aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2010-12-21 15:52:43 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2010-12-21 15:52:43 +0000
commit94314898aadfdfff71c453befb9d398d97157a63 (patch)
tree30b3c6ffc707196599eb3623b541ed224086ca4a
parent1c4cb8e9a83f8eda9743026cf5b7e5d9fbfdb7de (diff)
parente529b59aaf07b81fd60ba5ad649f6fdd5a03ffe7 (diff)
downloadalpine_aports-94314898aadfdfff71c453befb9d398d97157a63.tar.bz2
alpine_aports-94314898aadfdfff71c453befb9d398d97157a63.tar.xz
alpine_aports-94314898aadfdfff71c453befb9d398d97157a63.zip
Merge git://git.alpinelinux.org/aports-clandmeter
-rw-r--r--testing/iscsi-scst-grsec/2.6.35.patch11
-rw-r--r--testing/iscsi-scst-grsec/APKBUILD63
-rw-r--r--testing/iscsi-scst-grsec/config.c.patch12
-rw-r--r--testing/iscsi-scst-svn/APKBUILD41
-rw-r--r--testing/iscsi-scst-svn/iscsi-scst.initd23
-rw-r--r--testing/iscsi-scst/APKBUILD24
-rw-r--r--testing/iscsi-scst/iscsi-scst.initd2
-rw-r--r--testing/linux-scst/0004-arp-flush-arp-cache-on-device-change.patch29
-rw-r--r--testing/linux-scst/APKBUILD224
-rw-r--r--testing/linux-scst/arp.patch14
-rw-r--r--testing/linux-scst/kernelconfig.x86_64 (renamed from testing/linux-scst/kernelconfig.x86)786
-rw-r--r--testing/linux-scst/put_page_callback-2.6.34.patch390
-rw-r--r--testing/linux-scst/r8169-add-gro-support.patch52
-rw-r--r--testing/linux-scst/r8169-fix-rx-checksum-offload.patch62
-rw-r--r--testing/linux-scst/scst-2.6.35-svn-3161.patch76656
-rw-r--r--testing/linux-scst/scst_exec_req_fifo-2.6.34.patch529
-rw-r--r--testing/linux-scst/setlocalversion.patch11
-rw-r--r--testing/linux-scst/unionfs-2.5.7_for_2.6.35.8.patch11269
-rw-r--r--testing/scst-grsec/APKBUILD65
-rw-r--r--testing/scst-grsec/scst-kernel-2.6.32.patch17
-rw-r--r--testing/scst-svn-scst/APKBUILD83
-rw-r--r--testing/scstadmin-svn/APKBUILD31
-rw-r--r--testing/scstadmin/APKBUILD39
-rw-r--r--testing/scstadmin/scst-init-ash-comapt.patch35
24 files changed, 88699 insertions, 1769 deletions
diff --git a/testing/iscsi-scst-grsec/2.6.35.patch b/testing/iscsi-scst-grsec/2.6.35.patch
deleted file mode 100644
index 54fde38221..0000000000
--- a/testing/iscsi-scst-grsec/2.6.35.patch
+++ /dev/null
@@ -1,11 +0,0 @@
1--- ./kernel/conn.c.orig
2+++ ./kernel/conn.c
3@@ -86,7 +86,7 @@
4 switch (sk->sk_family) {
5 case AF_INET:
6 snprintf(buf, sizeof(buf),
7- "%u.%u.%u.%u", NIPQUAD(inet_sk(sk)->daddr));
8+ "%u.%u.%u.%u", NIPQUAD(inet_sk(sk)->inet_daddr));
9 break;
10 case AF_INET6:
11 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
diff --git a/testing/iscsi-scst-grsec/APKBUILD b/testing/iscsi-scst-grsec/APKBUILD
deleted file mode 100644
index e87b66c788..0000000000
--- a/testing/iscsi-scst-grsec/APKBUILD
+++ /dev/null
@@ -1,63 +0,0 @@
1# Contributor: Carlo Landmeter
2# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
3
4_flavor=${FLAVOR:-grsec}
5_realname=iscsi-scst
6# source the kernel version
7if [ -f ../../main/linux-$_flavor/APKBUILD ]; then
8 . ../../main/linux-$_flavor/APKBUILD
9fi
10_kver=$pkgver
11_kernelver=$pkgver-r$pkgrel
12_abi_release=$pkgver-${_flavor}
13_kpkgrel=$pkgrel
14
15_realver=1.0.1.1
16pkgname=${_realname}-${_flavor}
17pkgver=$_kver
18_mypkgrel=0
19pkgrel=$(($_kpkgrel + $_mypkgrel))
20pkgdesc="$_flavor ISCSI for SCST $_realver"
21url="http://scst.sourceforge.net/"
22arch="x86 x86_64"
23license="GPL-2"
24depends="linux-${_flavor}=${_kernelver}"
25install=
26makedepends="linux-${_flavor}-dev=${_kernelver} scst-grsec-dev"
27subpackages=
28source="http://downloads.sourceforge.net/scst/$_realname-$_realver.tar.gz
29 config.c.patch
30 2.6.35.patch
31 "
32_ksrc=/usr/src/linux-headers-${_abi_release}
33
34_builddir="$srcdir"/$_realname-$_realver
35prepare() {
36 cd "$_builddir"
37 for i in "$srcdir"/*.patch; do
38 [ -f "$i" ] || continue
39 msg "Applying $i"
40 patch -p1 -i $i || return 1
41 done
42 # to build mods we need the headre file. fix dependency in makefile
43 sed -i -e 's/^\(mods: .*\)/\1 include\/iscsi_scst_itf_ver.h/' Makefile
44}
45
46build() {
47 cd "$_builddir"
48 unset ARCH
49 make mods \
50 KDIR="$_ksrc" \
51 SCST_INC_DIR=/usr/include/scst \
52 || return 1
53}
54
55package() {
56 cd "$_builddir"
57 install -D -m 644 kernel/iscsi-scst.ko \
58 "$pkgdir"/lib/modules/$_abi_release/extra/iscsi-scst.ko
59}
60
61md5sums="56109c01e3d4421a36d6f47efa1fb0d5 iscsi-scst-1.0.1.1.tar.gz
6248e21e3466fd819418f29e3b2487f052 config.c.patch
63d2490c86d9138226ec674997817a163b 2.6.35.patch"
diff --git a/testing/iscsi-scst-grsec/config.c.patch b/testing/iscsi-scst-grsec/config.c.patch
deleted file mode 100644
index e3b1523218..0000000000
--- a/testing/iscsi-scst-grsec/config.c.patch
+++ /dev/null
@@ -1,12 +0,0 @@
1--- iscsi-scst/kernel/config.c 2009/05/11 17:24:51 841
2+++ iscsi-scst/kernel/config.c 2009/07/08 17:27:30 938
3@@ -203,7 +203,9 @@
4 goto out;
5 }
6
7+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
8 proc_iscsi_dir->owner = THIS_MODULE;
9+#endif
10
11 err = iscsi_proc_log_entry_build(&iscsi_template);
12 if (err < 0)
diff --git a/testing/iscsi-scst-svn/APKBUILD b/testing/iscsi-scst-svn/APKBUILD
deleted file mode 100644
index 61ccb248a4..0000000000
--- a/testing/iscsi-scst-svn/APKBUILD
+++ /dev/null
@@ -1,41 +0,0 @@
1# Contributor: Carlo Landmeter
2# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
3
4pkgname=iscsi-scst-svn
5pkgver=1713
6pkgrel=0
7pkgdesc="ISCSI target for SCST - userspace tools"
8url="http://iscsi-scst.sourceforge.net/"
9arch="x86 x86_64"
10license="GPL-2"
11depends=
12install=
13makedepends="openssl-dev scst-svn-scst-dev bash"
14subpackages=
15source="http://alpine.nethq.org/clandmeter/src/$pkgname-$pkgver.tar.gz
16 iscsi-scst.initd
17 "
18
19_builddir="$srcdir"/iscsi-scst
20prepare() {
21 cd "$_builddir"
22 # we need the headre file. fix dependency in makefile
23 sed -i -e 's/^\(progs:.*\)/\1 include\/iscsi_scst_itf_ver.h/' Makefile
24}
25
26build() {
27 cd "$_builddir"
28 make progs \
29 SCST_INC_DIR=/usr/include/scst
30}
31
32package() {
33 cd "$_builddir"
34 # make install is broken
35 install -D usr/iscsi-scstd "$pkgdir"/usr/sbin/iscsi-scstd
36 install -D usr/iscsi-scst-adm "$pkgdir"/usr/sbin/iscsi-scst-adm
37 install -D -m 755 "$srcdir"/iscsi-scst.initd "$pkgdir"/etc/init.d/iscsi-scst
38}
39
40md5sums="cf046db4f7cd9cf969b054dc055922d6 iscsi-scst-svn-1713.tar.gz
413132fae1ec2f9bcc72476d9e9f36d326 iscsi-scst.initd"
diff --git a/testing/iscsi-scst-svn/iscsi-scst.initd b/testing/iscsi-scst-svn/iscsi-scst.initd
deleted file mode 100644
index 4d4cd76b59..0000000000
--- a/testing/iscsi-scst-svn/iscsi-scst.initd
+++ /dev/null
@@ -1,23 +0,0 @@
1#!/sbin/runscript
2#
3# Start the iSCSI-SCST Target.
4#
5
6depend() {
7 need net
8 afer firewall
9}
10
11start() {
12 modprobe -q crc32c
13 modprobe -q iscsi-scst
14 ebegin "Starting iscsi-scstd"
15 start-stop-daemon --start --exec /usr/sbin/iscsi-scstd
16 eend 0
17}
18
19stop() {
20 ebegin "Stopping iscsi-scstd"
21 start-stop-daemon --stop --exec /usr/sbin/iscsi-scstd
22 eend 0
23}
diff --git a/testing/iscsi-scst/APKBUILD b/testing/iscsi-scst/APKBUILD
index b929731594..f6f6c85b1b 100644
--- a/testing/iscsi-scst/APKBUILD
+++ b/testing/iscsi-scst/APKBUILD
@@ -2,30 +2,31 @@
2# Maintainer: Natanael Copa <ncopa@alpinelinux.org> 2# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
3 3
4pkgname=iscsi-scst 4pkgname=iscsi-scst
5pkgver=1.0.1.1 5pkgver=2.0.0
6pkgrel=2 6pkgrel=0
7pkgdesc="ISCSI target for SCST - userspace tools" 7pkgdesc="ISCSI target for SCST - userspace tools"
8url="http://iscsi-scst.sourceforge.net/" 8url="http://iscsi-scst.sourceforge.net/"
9arch="x86 x86_64" 9arch="x86_64"
10license="GPL-2" 10license="GPL-2"
11depends= 11depends=
12install= 12install=
13makedepends="openssl-dev" 13makedepends="openssl-dev bash"
14subpackages= 14subpackages=
15source="http://downloads.sourceforge.net/scst/$pkgname-$pkgver.tar.gz 15_svn="3161"
16source="http://alpine.nethq.org/distfiles/$pkgname-$pkgver-svn-$_svn.tar.gz
17 http://alpine.nethq.org/distfiles/scst-$pkgver-svn-$_svn.tar.gz
16 iscsi-scst.initd 18 iscsi-scst.initd
17 " 19 "
18 20
19_builddir="$srcdir"/$pkgname-$pkgver 21_builddir="$srcdir"/$pkgname
20prepare() { 22prepare() {
21 cd "$_builddir" 23 cd "$_builddir"
22 # we need the headre file. fix dependency in makefile 24 cp Makefile_user_space_only Makefile
23 sed -i -e 's/^\(progs:.*\)/\1 include\/iscsi_scst_itf_ver.h/' Makefile
24} 25}
25 26
26build() { 27build() {
27 cd "$_builddir" 28 cd "$_builddir"
28 make progs 29 make all SCST_INC_DIR="$srcdir"/scst/include || return 1
29} 30}
30 31
31package() { 32package() {
@@ -36,5 +37,6 @@ package() {
36 install -D -m 755 "$srcdir"/iscsi-scst.initd "$pkgdir"/etc/init.d/iscsi-scst 37 install -D -m 755 "$srcdir"/iscsi-scst.initd "$pkgdir"/etc/init.d/iscsi-scst
37} 38}
38 39
39md5sums="56109c01e3d4421a36d6f47efa1fb0d5 iscsi-scst-1.0.1.1.tar.gz 40md5sums="0980e7f0cc57d3a09cc57ba4b127ef12 iscsi-scst-2.0.0-svn-3161.tar.gz
403132fae1ec2f9bcc72476d9e9f36d326 iscsi-scst.initd" 4173c1ec37231918e5183e78f1ec8f2302 scst-2.0.0-svn-3161.tar.gz
4205efba84051393bf22ff1f2c718afbe9 iscsi-scst.initd"
diff --git a/testing/iscsi-scst/iscsi-scst.initd b/testing/iscsi-scst/iscsi-scst.initd
index 4d4cd76b59..3563bafa7e 100644
--- a/testing/iscsi-scst/iscsi-scst.initd
+++ b/testing/iscsi-scst/iscsi-scst.initd
@@ -5,7 +5,7 @@
5 5
6depend() { 6depend() {
7 need net 7 need net
8 afer firewall 8 after firewall
9} 9}
10 10
11start() { 11start() {
diff --git a/testing/linux-scst/0004-arp-flush-arp-cache-on-device-change.patch b/testing/linux-scst/0004-arp-flush-arp-cache-on-device-change.patch
new file mode 100644
index 0000000000..85161ea3a3
--- /dev/null
+++ b/testing/linux-scst/0004-arp-flush-arp-cache-on-device-change.patch
@@ -0,0 +1,29 @@
1From 8a0e3ea4924059a7268446177d6869e3399adbb2 Mon Sep 17 00:00:00 2001
2From: Timo Teras <timo.teras@iki.fi>
3Date: Mon, 12 Apr 2010 13:46:45 +0000
4Subject: [PATCH 04/18] arp: flush arp cache on device change
5
6If IFF_NOARP is changed, we must flush the arp cache.
7
8Signed-off-by: Timo Teras <timo.teras@iki.fi>
9---
10 net/ipv4/arp.c | 3 +++
11 1 files changed, 3 insertions(+), 0 deletions(-)
12
13diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
14index 4e80f33..580bfc3 100644
15--- a/net/ipv4/arp.c
16+++ b/net/ipv4/arp.c
17@@ -1200,6 +1200,9 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo
18 neigh_changeaddr(&arp_tbl, dev);
19 rt_cache_flush(dev_net(dev), 0);
20 break;
21+ case NETDEV_CHANGE:
22+ neigh_changeaddr(&arp_tbl, dev);
23+ break;
24 default:
25 break;
26 }
27--
281.7.0.2
29
diff --git a/testing/linux-scst/APKBUILD b/testing/linux-scst/APKBUILD
index 0b16031504..6f494c17e9 100644
--- a/testing/linux-scst/APKBUILD
+++ b/testing/linux-scst/APKBUILD
@@ -1,123 +1,155 @@
1# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
2
1_flavor=scst 3_flavor=scst
2pkgname=linux-${_flavor} 4pkgname=linux-${_flavor}
3pkgver=2.6.34 5pkgver=2.6.35.9
4_kernver=$pkgver 6_kernver=2.6.35
5pkgrel=0 7pkgrel=0
6pkgdesc="Linux kernel with scst" 8pkgdesc="Linux kernel optimised for scst"
7url="http://www.kernel.org" 9url="http://scst.sourceforge.net"
8depends="mkinitfs linux-firmware" 10depends="mkinitfs linux-firmware"
9makedepends="perl installkernel" 11makedepends="perl installkernel bash"
10options="!strip" 12options="!strip"
11_config=${config:-kernelconfig.${CARCH:-x86}} 13_config=${config:-kernelconfig.${CARCH}}
12install= 14install=
13source="ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$pkgver.tar.bz2 15_scst_svn="3161"
14 arp.patch 16source="ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_kernver.tar.bz2
15 kernelconfig.x86 17 ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2
16 put_page_callback-2.6.34.patch 18 0004-arp-flush-arp-cache-on-device-change.patch
17 scst_exec_req_fifo-2.6.34.patch 19 r8169-fix-rx-checksum-offload.patch
18 " 20 r8169-add-gro-support.patch
19# no need to patch now 21 setlocalversion.patch
20#ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2 22 kernelconfig.x86_64
21subpackages="$pkgname-dev" 23 unionfs-2.5.7_for_2.6.35.8.patch
22arch="x86" 24 scst-2.6.35-svn-3161.patch
25 "
26subpackages="$pkgname-dev linux-firmware:firmware"
27arch="x86_64"
23license="GPL-2" 28license="GPL-2"
24 29
25_abi_release=${pkgver}-${_flavor} 30_abi_release=${pkgver}-${_flavor}
26 31
27prepare() { 32prepare() {
28 cd "$srcdir"/linux-$_kernver 33 local _patch_failed=
29 if [ "$_kernver" != "$pkgver" ]; then 34 cd "$srcdir"/linux-$_kernver
30 bunzip2 -c < ../patch-$pkgver.bz2 | patch -p1 -N || return 1 35 if [ "$_kernver" != "$pkgver" ]; then
31 fi 36 bunzip2 -c < ../patch-$pkgver.bz2 | patch -p1 -N || return 1
32 37 fi
33 for i in ../*.diff ../*.patch; do 38
34 [ -f $i ] || continue 39 # first apply patches in specified order
35 msg "Applying $i..." 40 for i in $source; do
36 patch -s -p1 -N < $i || return 1 41 case $i in
37 done 42 *.patch)
38 43 msg "Applying $i..."
39 mkdir -p "$srcdir"/build 44 if ! patch -s -p1 -N -i "$srcdir"/$i; then
40 cp "$srcdir"/$_config "$srcdir"/build/.config 45 echo $i >>failed
41 echo "-${_flavor}" > "$srcdir"/linux-$_kernver/localversion-${_flavor} 46 _patch_failed=1
42 make -C "$srcdir"/linux-$_kernver O="$srcdir"/build HOSTCC="$CC" \ 47 fi
43 silentoldconfig 48 ;;
49 esac
50 done
51
52 if ! [ -z "$_patch_failed" ]; then
53 error "The following patches failed:"
54 cat failed
55 return 1
56 fi
57
58 echo "-scst" > "$srcdir"/linux-$_kernver/localversion-scst
59
60 mkdir -p "$srcdir"/build
61 cp "$srcdir"/$_config "$srcdir"/build/.config || return 1
62 make -C "$srcdir"/linux-$_kernver O="$srcdir"/build HOSTCC="${CC:-gcc}" \
63 silentoldconfig
44} 64}
45 65
46# this is so we can do: 'abuild menuconfig' to reconfigure kernel 66# this is so we can do: 'abuild menuconfig' to reconfigure kernel
47menuconfig() { 67menuconfig() {
48 cd "$srcdir"/build || return 1 68 cd "$srcdir"/build || return 1
49 make menuconfig 69 make menuconfig
50 cp .config "$startdir"/$_config 70 cp .config "$startdir"/$_config
51} 71}
52 72
53build() { 73build() {
54 cd "$srcdir"/build 74 cd "$srcdir"/build
55 make CC="$CC" || return 1 75 make CC="${CC:-gcc}" \
76 KBUILD_BUILD_VERSION="$((pkgrel + 1 ))-Alpine" \
77 || return 1
56} 78}
57 79
58package() { 80package() {
59 cd "$srcdir"/build 81 cd "$srcdir"/build
60 mkdir -p "$pkgdir"/boot "$pkgdir"/lib/modules 82 mkdir -p "$pkgdir"/boot "$pkgdir"/lib/modules
61 make modules_install install \ 83 make -j1 modules_install firmware_install install \
62 INSTALL_MOD_PATH="$pkgdir" \ 84 INSTALL_MOD_PATH="$pkgdir" \
63 INSTALL_PATH="$pkgdir"/boot 85 INSTALL_PATH="$pkgdir"/boot \
64 86 || return 1
65 rm -f "$pkgdir"/lib/modules/${_abi_release}/build \ 87
66 "$pkgdir"/lib/modules/${_abi_release}/source 88 rm -f "$pkgdir"/lib/modules/${_abi_release}/build \
67 rm -rf "$pkgdir"/lib/firmware 89 "$pkgdir"/lib/modules/${_abi_release}/source
68 90 install -D include/config/kernel.release \
69 install -D include/config/kernel.release \ 91 "$pkgdir"/usr/share/kernel/$_flavor/kernel.release
70 "$pkgdir"/usr/share/kernel/$_flavor/kernel.release
71} 92}
72 93
73dev() { 94dev() {
74 # copy the only the parts that we really need for build 3rd party 95 # copy the only the parts that we really need for build 3rd party
75 # kernel modules and install those as /usr/src/linux-headers, 96 # kernel modules and install those as /usr/src/linux-headers,
76 # simlar to what ubuntu does 97 # simlar to what ubuntu does
77 # 98 #
78 # this way you dont need to install the 300-400 kernel sources to 99 # this way you dont need to install the 300-400 kernel sources to
79 # build a tiny kernel module 100 # build a tiny kernel module
80 # 101 #
81 pkgdesc="Headers and script for third party modules for $pkgname kernel" 102 pkgdesc="Headers and script for third party modules for grsec kernel"
82 local dir="$subpkgdir"/usr/src/linux-headers-${_abi_release} 103 local dir="$subpkgdir"/usr/src/linux-headers-${_abi_release}
83 104
84 # first we import config, run prepare to set up for building 105 # first we import config, run prepare to set up for building
85 # external modules, and create the scripts 106 # external modules, and create the scripts
86 mkdir -p "$dir" 107 mkdir -p "$dir"
87 cp "$srcdir"/$_config "$dir"/.config 108 cp "$srcdir"/$_config "$dir"/.config
88 make -j1 -C "$srcdir"/linux-$_kernver O="$dir" HOSTCC="$CC" \ 109 make -j1 -C "$srcdir"/linux-$_kernver O="$dir" HOSTCC="${CC:-gcc}" \
89 silentoldconfig prepare scripts 110 silentoldconfig prepare scripts
90 111
91 # remove the stuff that poits to real sources. we want 3rd party 112 # remove the stuff that poits to real sources. we want 3rd party
92 # modules to believe this is the soruces 113 # modules to believe this is the soruces
93 rm "$dir"/Makefile "$dir"/source 114 rm "$dir"/Makefile "$dir"/source
94 115
95 # copy the needed stuff from real sources 116 # copy the needed stuff from real sources
96 # 117 #
97 # this is taken from ubuntu kernel build script 118 # this is taken from ubuntu kernel build script
98 # http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-jaunty.git;a=blob;f=debian/rules.d/3-binary-indep.mk;hb=HEAD 119 # http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-jaunty.git;a=blob;f=debian/rules.d/3-binary-indep.mk;hb=HEAD
99 cd "$srcdir"/linux-$_kernver 120 cd "$srcdir"/linux-$_kernver
100 find . -path './include/*' -prune -o -path './scripts/*' -prune \ 121 find . -path './include/*' -prune -o -path './scripts/*' -prune \
101 -o -type f \( -name 'Makefile*' -o -name 'Kconfig*' \ 122 -o -type f \( -name 'Makefile*' -o -name 'Kconfig*' \
102 -o -name 'Kbuild*' -o -name '*.sh' -o -name '*.pl' \ 123 -o -name 'Kbuild*' -o -name '*.sh' -o -name '*.pl' \
103 -o -name '*.lds' \) | cpio -pdm "$dir" 124 -o -name '*.lds' \) | cpio -pdm "$dir"
104 cp -a drivers/media/dvb/dvb-core/*.h "$dir"/drivers/media/dvb/dvb-core 125 cp -a drivers/media/dvb/dvb-core/*.h "$dir"/drivers/media/dvb/dvb-core
105 cp -a drivers/media/video/*.h "$dir"/drivers/media/video 126 cp -a drivers/media/video/*.h "$dir"/drivers/media/video
106 cp -a drivers/media/dvb/frontends/*.h "$dir"/drivers/media/dvb/frontends 127 cp -a drivers/media/dvb/frontends/*.h "$dir"/drivers/media/dvb/frontends
107 cp -a scripts include "$dir" 128 cp -a scripts include "$dir"
108 find $(find arch -name include -type d -print) -type f \ 129 find $(find arch -name include -type d -print) -type f \
109 | cpio -pdm "$dir" 130 | cpio -pdm "$dir"
110 131
111 install -Dm644 "$srcdir"/build/Module.symvers \ 132 install -Dm644 "$srcdir"/build/Module.symvers \
112 "$dir"/Module.symvers 133 "$dir"/Module.symvers
113 134
114 mkdir -p "$subpkgdir"/lib/modules/${_abi_release} 135 mkdir -p "$subpkgdir"/lib/modules/${_abi_release}
115 ln -sf /usr/src/linux-headers-${_abi_release} \ 136 ln -sf /usr/src/linux-headers-${_abi_release} \
116 "$subpkgdir"/lib/modules/${_abi_release}/build 137 "$subpkgdir"/lib/modules/${_abi_release}/build
138}
139
140firmware() {
141 pkgdesc="Firmware for linux kernel"
142 replaces="linux-grsec linux-vserver"
143 mkdir -p "$subpkgdir"/lib
144 mv "$pkgdir"/lib/firmware "$subpkgdir"/lib/
117} 145}
118 146
119md5sums="10eebcb0178fb4540e2165bfd7efc7ad linux-2.6.34.tar.bz2 147md5sums="091abeb4684ce03d1d936851618687b6 linux-2.6.35.tar.bz2
1204c39a161d918e7f274292ecfd168b891 arp.patch 148eca407cf4872ad77ae23adc8242389c4 patch-2.6.35.9.bz2
1212a08789db4977397f529a2933bc7b787 kernelconfig.x86 149776adeeb5272093574f8836c5037dd7d 0004-arp-flush-arp-cache-on-device-change.patch
12206e9b200ec4fe252dc1478b5f8137e9e put_page_callback-2.6.34.patch 1500ccecafd4123dcad0b0cd7787553d734 r8169-fix-rx-checksum-offload.patch
123f9ea26d08807c41407a7758ce53fc633 scst_exec_req_fifo-2.6.34.patch" 151139b39da44ecb577275be53d7d365949 r8169-add-gro-support.patch
1528c224ba0cdf0aa572c7eb50379435be4 setlocalversion.patch
1538b50f527b834f693e9cfbcabf29b04f3 kernelconfig.x86_64
154e4185c1bb1d88594c67eb154d0c06692 unionfs-2.5.7_for_2.6.35.8.patch
155f8aa57373ab14ece95ecdaa15840fa25 scst-2.6.35-svn-3161.patch"
diff --git a/testing/linux-scst/arp.patch b/testing/linux-scst/arp.patch
deleted file mode 100644
index d2682690f5..0000000000
--- a/testing/linux-scst/arp.patch
+++ /dev/null
@@ -1,14 +0,0 @@
1diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
2index c95cd93..71ab56f 100644
3--- a/net/ipv4/arp.c
4+++ b/net/ipv4/arp.c
5@@ -1200,6 +1200,9 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo
6 neigh_changeaddr(&arp_tbl, dev);
7 rt_cache_flush(dev_net(dev), 0);
8 break;
9+ case NETDEV_CHANGE:
10+ neigh_changeaddr(&arp_tbl, dev);
11+ break;
12 default:
13 break;
14 }
diff --git a/testing/linux-scst/kernelconfig.x86 b/testing/linux-scst/kernelconfig.x86_64
index 84aa9734b1..6d9675b93a 100644
--- a/testing/linux-scst/kernelconfig.x86
+++ b/testing/linux-scst/kernelconfig.x86_64
@@ -1,14 +1,15 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.34 3# Linux kernel version: 2.6.35.9
4# Tue May 25 13:28:42 2010 4# Mon Dec 20 14:49:00 2010
5# 5#
6# CONFIG_64BIT is not set 6CONFIG_64BIT=y
7CONFIG_X86_32=y 7# CONFIG_X86_32 is not set
8# CONFIG_X86_64 is not set 8CONFIG_X86_64=y
9CONFIG_X86=y 9CONFIG_X86=y
10CONFIG_OUTPUT_FORMAT="elf32-i386" 10CONFIG_INSTRUCTION_DECODER=y
11CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig" 11CONFIG_OUTPUT_FORMAT="elf64-x86-64"
12CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
12CONFIG_GENERIC_TIME=y 13CONFIG_GENERIC_TIME=y
13CONFIG_GENERIC_CMOS_UPDATE=y 14CONFIG_GENERIC_CMOS_UPDATE=y
14CONFIG_CLOCKSOURCE_WATCHDOG=y 15CONFIG_CLOCKSOURCE_WATCHDOG=y
@@ -19,10 +20,12 @@ CONFIG_STACKTRACE_SUPPORT=y
19CONFIG_HAVE_LATENCYTOP_SUPPORT=y 20CONFIG_HAVE_LATENCYTOP_SUPPORT=y
20CONFIG_MMU=y 21CONFIG_MMU=y
21CONFIG_ZONE_DMA=y 22CONFIG_ZONE_DMA=y
22# CONFIG_NEED_DMA_MAP_STATE is not set 23CONFIG_NEED_DMA_MAP_STATE=y
24CONFIG_NEED_SG_DMA_LENGTH=y
23CONFIG_GENERIC_ISA_DMA=y 25CONFIG_GENERIC_ISA_DMA=y
24CONFIG_GENERIC_IOMAP=y 26CONFIG_GENERIC_IOMAP=y
25CONFIG_GENERIC_BUG=y 27CONFIG_GENERIC_BUG=y
28CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
26CONFIG_GENERIC_HWEIGHT=y 29CONFIG_GENERIC_HWEIGHT=y
27CONFIG_GENERIC_GPIO=y 30CONFIG_GENERIC_GPIO=y
28CONFIG_ARCH_MAY_HAVE_PC_FDC=y 31CONFIG_ARCH_MAY_HAVE_PC_FDC=y
@@ -30,19 +33,19 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
30CONFIG_RWSEM_XCHGADD_ALGORITHM=y 33CONFIG_RWSEM_XCHGADD_ALGORITHM=y
31CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y 34CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
32CONFIG_GENERIC_CALIBRATE_DELAY=y 35CONFIG_GENERIC_CALIBRATE_DELAY=y
33# CONFIG_GENERIC_TIME_VSYSCALL is not set 36CONFIG_GENERIC_TIME_VSYSCALL=y
34CONFIG_ARCH_HAS_CPU_RELAX=y 37CONFIG_ARCH_HAS_CPU_RELAX=y
35CONFIG_ARCH_HAS_DEFAULT_IDLE=y 38CONFIG_ARCH_HAS_DEFAULT_IDLE=y
36CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y 39CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
37CONFIG_HAVE_SETUP_PER_CPU_AREA=y 40CONFIG_HAVE_SETUP_PER_CPU_AREA=y
38CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y 41CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
39CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y 42CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
40# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set 43CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y
41CONFIG_ARCH_HIBERNATION_POSSIBLE=y 44CONFIG_ARCH_HIBERNATION_POSSIBLE=y
42CONFIG_ARCH_SUSPEND_POSSIBLE=y 45CONFIG_ARCH_SUSPEND_POSSIBLE=y
43# CONFIG_ZONE_DMA32 is not set 46CONFIG_ZONE_DMA32=y
44CONFIG_ARCH_POPULATES_NODE_MAP=y 47CONFIG_ARCH_POPULATES_NODE_MAP=y
45# CONFIG_AUDIT_ARCH is not set 48CONFIG_AUDIT_ARCH=y
46CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y 49CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
47CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y 50CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
48CONFIG_HAVE_EARLY_RES=y 51CONFIG_HAVE_EARLY_RES=y
@@ -51,11 +54,12 @@ CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
51CONFIG_GENERIC_IRQ_PROBE=y 54CONFIG_GENERIC_IRQ_PROBE=y
52CONFIG_GENERIC_PENDING_IRQ=y 55CONFIG_GENERIC_PENDING_IRQ=y
53CONFIG_USE_GENERIC_SMP_HELPERS=y 56CONFIG_USE_GENERIC_SMP_HELPERS=y
54CONFIG_X86_32_SMP=y 57CONFIG_X86_64_SMP=y
55CONFIG_X86_HT=y 58CONFIG_X86_HT=y
56CONFIG_X86_TRAMPOLINE=y 59CONFIG_X86_TRAMPOLINE=y
57CONFIG_X86_32_LAZY_GS=y 60CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11"
58CONFIG_KTIME_SCALAR=y 61# CONFIG_KTIME_SCALAR is not set
62CONFIG_ARCH_CPU_PROBE_RELEASE=y
59CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" 63CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
60CONFIG_CONSTRUCTORS=y 64CONFIG_CONSTRUCTORS=y
61 65
@@ -65,6 +69,7 @@ CONFIG_CONSTRUCTORS=y
65CONFIG_EXPERIMENTAL=y 69CONFIG_EXPERIMENTAL=y
66CONFIG_LOCK_KERNEL=y 70CONFIG_LOCK_KERNEL=y
67CONFIG_INIT_ENV_ARG_LIMIT=32 71CONFIG_INIT_ENV_ARG_LIMIT=32
72CONFIG_CROSS_COMPILE=""
68CONFIG_LOCALVERSION="" 73CONFIG_LOCALVERSION=""
69# CONFIG_LOCALVERSION_AUTO is not set 74# CONFIG_LOCALVERSION_AUTO is not set
70CONFIG_HAVE_KERNEL_GZIP=y 75CONFIG_HAVE_KERNEL_GZIP=y
@@ -93,7 +98,7 @@ CONFIG_TREE_RCU=y
93# CONFIG_RCU_TRACE is not set 98# CONFIG_RCU_TRACE is not set
94CONFIG_RCU_FANOUT=32 99CONFIG_RCU_FANOUT=32
95# CONFIG_RCU_FANOUT_EXACT is not set 100# CONFIG_RCU_FANOUT_EXACT is not set
96# CONFIG_RCU_FAST_NO_HZ is not set 101CONFIG_RCU_FAST_NO_HZ=y
97# CONFIG_TREE_RCU_TRACE is not set 102# CONFIG_TREE_RCU_TRACE is not set
98CONFIG_IKCONFIG=m 103CONFIG_IKCONFIG=m
99CONFIG_IKCONFIG_PROC=y 104CONFIG_IKCONFIG_PROC=y
@@ -108,12 +113,11 @@ CONFIG_INITRAMFS_SOURCE=""
108CONFIG_RD_GZIP=y 113CONFIG_RD_GZIP=y
109CONFIG_RD_BZIP2=y 114CONFIG_RD_BZIP2=y
110CONFIG_RD_LZMA=y 115CONFIG_RD_LZMA=y
111# CONFIG_RD_LZO is not set 116CONFIG_RD_LZO=y
112CONFIG_CC_OPTIMIZE_FOR_SIZE=y 117CONFIG_CC_OPTIMIZE_FOR_SIZE=y
113CONFIG_SYSCTL=y 118CONFIG_SYSCTL=y
114CONFIG_ANON_INODES=y 119CONFIG_ANON_INODES=y
115CONFIG_EMBEDDED=y 120CONFIG_EMBEDDED=y
116CONFIG_UID16=y
117CONFIG_SYSCTL_SYSCALL=y 121CONFIG_SYSCTL_SYSCALL=y
118# CONFIG_KALLSYMS is not set 122# CONFIG_KALLSYMS is not set
119CONFIG_HOTPLUG=y 123CONFIG_HOTPLUG=y
@@ -158,6 +162,7 @@ CONFIG_HAVE_DMA_ATTRS=y
158CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y 162CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
159CONFIG_HAVE_DMA_API_DEBUG=y 163CONFIG_HAVE_DMA_API_DEBUG=y
160CONFIG_HAVE_HW_BREAKPOINT=y 164CONFIG_HAVE_HW_BREAKPOINT=y
165CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
161CONFIG_HAVE_USER_RETURN_NOTIFIER=y 166CONFIG_HAVE_USER_RETURN_NOTIFIER=y
162 167
163# 168#
@@ -166,7 +171,7 @@ CONFIG_HAVE_USER_RETURN_NOTIFIER=y
166# CONFIG_GCOV_KERNEL is not set 171# CONFIG_GCOV_KERNEL is not set
167CONFIG_SLOW_WORK=y 172CONFIG_SLOW_WORK=y
168# CONFIG_SLOW_WORK_DEBUG is not set 173# CONFIG_SLOW_WORK_DEBUG is not set
169CONFIG_HAVE_GENERIC_DMA_COHERENT=y 174# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
170CONFIG_RT_MUTEXES=y 175CONFIG_RT_MUTEXES=y
171CONFIG_BASE_SMALL=0 176CONFIG_BASE_SMALL=0
172CONFIG_MODULES=y 177CONFIG_MODULES=y
@@ -177,7 +182,6 @@ CONFIG_MODVERSIONS=y
177# CONFIG_MODULE_SRCVERSION_ALL is not set 182# CONFIG_MODULE_SRCVERSION_ALL is not set
178CONFIG_STOP_MACHINE=y 183CONFIG_STOP_MACHINE=y
179CONFIG_BLOCK=y 184CONFIG_BLOCK=y
180CONFIG_LBDAF=y
181CONFIG_BLK_DEV_BSG=y 185CONFIG_BLK_DEV_BSG=y
182# CONFIG_BLK_DEV_INTEGRITY is not set 186# CONFIG_BLK_DEV_INTEGRITY is not set
183 187
@@ -234,22 +238,13 @@ CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
234CONFIG_SMP=y 238CONFIG_SMP=y
235# CONFIG_SPARSE_IRQ is not set 239# CONFIG_SPARSE_IRQ is not set
236CONFIG_X86_MPPARSE=y 240CONFIG_X86_MPPARSE=y
237# CONFIG_X86_BIGSMP is not set
238CONFIG_X86_EXTENDED_PLATFORM=y 241CONFIG_X86_EXTENDED_PLATFORM=y
239# CONFIG_X86_ELAN is not set 242# CONFIG_X86_VSMP is not set
240# CONFIG_X86_MRST is not set
241# CONFIG_X86_RDC321X is not set
242# CONFIG_X86_32_NON_STANDARD is not set
243CONFIG_SCHED_OMIT_FRAME_POINTER=y 243CONFIG_SCHED_OMIT_FRAME_POINTER=y
244CONFIG_PARAVIRT_GUEST=y 244CONFIG_PARAVIRT_GUEST=y
245CONFIG_XEN=y 245# CONFIG_XEN is not set
246CONFIG_XEN_MAX_DOMAIN_MEMORY=8
247CONFIG_XEN_SAVE_RESTORE=y
248# CONFIG_XEN_DEBUG_FS is not set
249CONFIG_VMI=y
250CONFIG_KVM_CLOCK=y 246CONFIG_KVM_CLOCK=y
251CONFIG_KVM_GUEST=y 247CONFIG_KVM_GUEST=y
252CONFIG_LGUEST_GUEST=y
253CONFIG_PARAVIRT=y 248CONFIG_PARAVIRT=y
254# CONFIG_PARAVIRT_SPINLOCKS is not set 249# CONFIG_PARAVIRT_SPINLOCKS is not set
255CONFIG_PARAVIRT_CLOCK=y 250CONFIG_PARAVIRT_CLOCK=y
@@ -258,7 +253,7 @@ CONFIG_NO_BOOTMEM=y
258# CONFIG_M386 is not set 253# CONFIG_M386 is not set
259# CONFIG_M486 is not set 254# CONFIG_M486 is not set
260# CONFIG_M586 is not set 255# CONFIG_M586 is not set
261CONFIG_M586TSC=y 256# CONFIG_M586TSC is not set
262# CONFIG_M586MMX is not set 257# CONFIG_M586MMX is not set
263# CONFIG_M686 is not set 258# CONFIG_M686 is not set
264# CONFIG_MPENTIUMII is not set 259# CONFIG_MPENTIUMII is not set
@@ -280,36 +275,33 @@ CONFIG_M586TSC=y
280# CONFIG_MPSC is not set 275# CONFIG_MPSC is not set
281# CONFIG_MCORE2 is not set 276# CONFIG_MCORE2 is not set
282# CONFIG_MATOM is not set 277# CONFIG_MATOM is not set
283# CONFIG_GENERIC_CPU is not set 278CONFIG_GENERIC_CPU=y
284CONFIG_X86_GENERIC=y
285CONFIG_X86_CPU=y 279CONFIG_X86_CPU=y
286CONFIG_X86_INTERNODE_CACHE_SHIFT=6 280CONFIG_X86_INTERNODE_CACHE_SHIFT=6
287CONFIG_X86_CMPXCHG=y 281CONFIG_X86_CMPXCHG=y
288CONFIG_X86_L1_CACHE_SHIFT=6 282CONFIG_X86_L1_CACHE_SHIFT=6
289CONFIG_X86_XADD=y 283CONFIG_X86_XADD=y
290# CONFIG_X86_PPRO_FENCE is not set
291CONFIG_X86_F00F_BUG=y
292CONFIG_X86_WP_WORKS_OK=y 284CONFIG_X86_WP_WORKS_OK=y
293CONFIG_X86_INVLPG=y
294CONFIG_X86_BSWAP=y
295CONFIG_X86_POPAD_OK=y
296CONFIG_X86_ALIGNMENT_16=y
297CONFIG_X86_INTEL_USERCOPY=y
298CONFIG_X86_TSC=y 285CONFIG_X86_TSC=y
299CONFIG_X86_CMPXCHG64=y 286CONFIG_X86_CMPXCHG64=y
300CONFIG_X86_MINIMUM_CPU_FAMILY=5 287CONFIG_X86_CMOV=y
288CONFIG_X86_MINIMUM_CPU_FAMILY=64
289CONFIG_X86_DEBUGCTLMSR=y
301# CONFIG_PROCESSOR_SELECT is not set 290# CONFIG_PROCESSOR_SELECT is not set
302CONFIG_CPU_SUP_INTEL=y 291CONFIG_CPU_SUP_INTEL=y
303CONFIG_CPU_SUP_CYRIX_32=y
304CONFIG_CPU_SUP_AMD=y 292CONFIG_CPU_SUP_AMD=y
305CONFIG_CPU_SUP_CENTAUR=y 293CONFIG_CPU_SUP_CENTAUR=y
306CONFIG_CPU_SUP_TRANSMETA_32=y
307CONFIG_CPU_SUP_UMC_32=y
308CONFIG_HPET_TIMER=y 294CONFIG_HPET_TIMER=y
309CONFIG_HPET_EMULATE_RTC=y 295CONFIG_HPET_EMULATE_RTC=y
310CONFIG_DMI=y 296CONFIG_DMI=y
311# CONFIG_IOMMU_HELPER is not set 297CONFIG_GART_IOMMU=y
312# CONFIG_IOMMU_API is not set 298CONFIG_CALGARY_IOMMU=y
299CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y
300CONFIG_AMD_IOMMU=y
301# CONFIG_AMD_IOMMU_STATS is not set
302CONFIG_SWIOTLB=y
303CONFIG_IOMMU_HELPER=y
304CONFIG_IOMMU_API=y
313CONFIG_NR_CPUS=8 305CONFIG_NR_CPUS=8
314CONFIG_SCHED_SMT=y 306CONFIG_SCHED_SMT=y
315CONFIG_SCHED_MC=y 307CONFIG_SCHED_MC=y
@@ -320,39 +312,31 @@ CONFIG_X86_LOCAL_APIC=y
320CONFIG_X86_IO_APIC=y 312CONFIG_X86_IO_APIC=y
321# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set 313# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
322# CONFIG_X86_MCE is not set 314# CONFIG_X86_MCE is not set
323CONFIG_VM86=y
324CONFIG_TOSHIBA=m
325CONFIG_I8K=m 315CONFIG_I8K=m
326CONFIG_X86_REBOOTFIXUPS=y
327CONFIG_MICROCODE=m 316CONFIG_MICROCODE=m
328CONFIG_MICROCODE_INTEL=y 317CONFIG_MICROCODE_INTEL=y
329CONFIG_MICROCODE_AMD=y 318CONFIG_MICROCODE_AMD=y
330CONFIG_MICROCODE_OLD_INTERFACE=y 319CONFIG_MICROCODE_OLD_INTERFACE=y
331CONFIG_X86_MSR=m 320CONFIG_X86_MSR=m
332CONFIG_X86_CPUID=m 321CONFIG_X86_CPUID=m
333# CONFIG_NOHIGHMEM is not set
334# CONFIG_HIGHMEM4G is not set
335CONFIG_HIGHMEM64G=y
336CONFIG_VMSPLIT_3G=y
337# CONFIG_VMSPLIT_3G_OPT is not set
338# CONFIG_VMSPLIT_2G is not set
339# CONFIG_VMSPLIT_2G_OPT is not set
340# CONFIG_VMSPLIT_1G is not set
341CONFIG_PAGE_OFFSET=0xC0000000
342CONFIG_HIGHMEM=y
343CONFIG_X86_PAE=y
344CONFIG_ARCH_PHYS_ADDR_T_64BIT=y 322CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
345CONFIG_ARCH_FLATMEM_ENABLE=y 323CONFIG_DIRECT_GBPAGES=y
324# CONFIG_NUMA is not set
325CONFIG_ARCH_SPARSEMEM_DEFAULT=y
346CONFIG_ARCH_SPARSEMEM_ENABLE=y 326CONFIG_ARCH_SPARSEMEM_ENABLE=y
347CONFIG_ARCH_SELECT_MEMORY_MODEL=y 327CONFIG_ARCH_SELECT_MEMORY_MODEL=y
348CONFIG_ILLEGAL_POINTER_VALUE=0 328CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
349CONFIG_SELECT_MEMORY_MODEL=y 329CONFIG_SELECT_MEMORY_MODEL=y
350CONFIG_FLATMEM_MANUAL=y 330# CONFIG_FLATMEM_MANUAL is not set
351# CONFIG_DISCONTIGMEM_MANUAL is not set 331# CONFIG_DISCONTIGMEM_MANUAL is not set
352# CONFIG_SPARSEMEM_MANUAL is not set 332CONFIG_SPARSEMEM_MANUAL=y
353CONFIG_FLATMEM=y 333CONFIG_SPARSEMEM=y
354CONFIG_FLAT_NODE_MEM_MAP=y 334CONFIG_HAVE_MEMORY_PRESENT=y
355CONFIG_SPARSEMEM_STATIC=y 335CONFIG_SPARSEMEM_EXTREME=y
336CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
337CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
338CONFIG_SPARSEMEM_VMEMMAP=y
339# CONFIG_MEMORY_HOTPLUG is not set
356CONFIG_PAGEFLAGS_EXTENDED=y 340CONFIG_PAGEFLAGS_EXTENDED=y
357CONFIG_SPLIT_PTLOCK_CPUS=4 341CONFIG_SPLIT_PTLOCK_CPUS=4
358CONFIG_PHYS_ADDR_T_64BIT=y 342CONFIG_PHYS_ADDR_T_64BIT=y
@@ -360,12 +344,10 @@ CONFIG_ZONE_DMA_FLAG=1
360CONFIG_BOUNCE=y 344CONFIG_BOUNCE=y
361CONFIG_VIRT_TO_BUS=y 345CONFIG_VIRT_TO_BUS=y
362CONFIG_MMU_NOTIFIER=y 346CONFIG_MMU_NOTIFIER=y
363# CONFIG_KSM is not set 347CONFIG_KSM=y
364CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 348CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
365# CONFIG_HIGHPTE is not set
366# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set 349# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
367CONFIG_X86_RESERVE_LOW_64K=y 350CONFIG_X86_RESERVE_LOW_64K=y
368CONFIG_MATH_EMULATION=y
369CONFIG_MTRR=y 351CONFIG_MTRR=y
370CONFIG_MTRR_SANITIZER=y 352CONFIG_MTRR_SANITIZER=y
371CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0 353CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
@@ -387,7 +369,6 @@ CONFIG_PHYSICAL_START=0x1000000
387# CONFIG_RELOCATABLE is not set 369# CONFIG_RELOCATABLE is not set
388CONFIG_PHYSICAL_ALIGN=0x1000000 370CONFIG_PHYSICAL_ALIGN=0x1000000
389CONFIG_HOTPLUG_CPU=y 371CONFIG_HOTPLUG_CPU=y
390CONFIG_COMPAT_VDSO=y
391# CONFIG_CMDLINE_BOOL is not set 372# CONFIG_CMDLINE_BOOL is not set
392CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y 373CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
393 374
@@ -398,6 +379,7 @@ CONFIG_PM=y
398# CONFIG_PM_DEBUG is not set 379# CONFIG_PM_DEBUG is not set
399CONFIG_PM_SLEEP_SMP=y 380CONFIG_PM_SLEEP_SMP=y
400CONFIG_PM_SLEEP=y 381CONFIG_PM_SLEEP=y
382CONFIG_SUSPEND_NVS=y
401CONFIG_SUSPEND=y 383CONFIG_SUSPEND=y
402CONFIG_SUSPEND_FREEZER=y 384CONFIG_SUSPEND_FREEZER=y
403# CONFIG_HIBERNATION is not set 385# CONFIG_HIBERNATION is not set
@@ -421,14 +403,17 @@ CONFIG_ACPI_HOTPLUG_CPU=y
421# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set 403# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
422CONFIG_ACPI_THERMAL=m 404CONFIG_ACPI_THERMAL=m
423# CONFIG_ACPI_CUSTOM_DSDT is not set 405# CONFIG_ACPI_CUSTOM_DSDT is not set
424CONFIG_ACPI_BLACKLIST_YEAR=2000 406CONFIG_ACPI_BLACKLIST_YEAR=0
425# CONFIG_ACPI_DEBUG is not set 407# CONFIG_ACPI_DEBUG is not set
426CONFIG_ACPI_PCI_SLOT=m 408CONFIG_ACPI_PCI_SLOT=m
427CONFIG_X86_PM_TIMER=y 409CONFIG_X86_PM_TIMER=y
428CONFIG_ACPI_CONTAINER=m 410CONFIG_ACPI_CONTAINER=m
429CONFIG_ACPI_SBS=m 411CONFIG_ACPI_SBS=m
412CONFIG_ACPI_HED=m
413CONFIG_ACPI_APEI=y
414CONFIG_ACPI_APEI_GHES=m
415CONFIG_ACPI_APEI_EINJ=m
430# CONFIG_SFI is not set 416# CONFIG_SFI is not set
431# CONFIG_APM is not set
432 417
433# 418#
434# CPU Frequency scaling 419# CPU Frequency scaling
@@ -452,63 +437,49 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
452# 437#
453# CPUFreq processor drivers 438# CPUFreq processor drivers
454# 439#
455# CONFIG_X86_PCC_CPUFREQ is not set 440CONFIG_X86_PCC_CPUFREQ=m
456CONFIG_X86_ACPI_CPUFREQ=m 441CONFIG_X86_ACPI_CPUFREQ=m
457CONFIG_X86_POWERNOW_K6=m
458CONFIG_X86_POWERNOW_K7=m
459CONFIG_X86_POWERNOW_K7_ACPI=y
460CONFIG_X86_POWERNOW_K8=m 442CONFIG_X86_POWERNOW_K8=m
461CONFIG_X86_GX_SUSPMOD=m
462CONFIG_X86_SPEEDSTEP_CENTRINO=m 443CONFIG_X86_SPEEDSTEP_CENTRINO=m
463CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y
464CONFIG_X86_SPEEDSTEP_ICH=m
465CONFIG_X86_SPEEDSTEP_SMI=m
466CONFIG_X86_P4_CLOCKMOD=m 444CONFIG_X86_P4_CLOCKMOD=m
467CONFIG_X86_CPUFREQ_NFORCE2=m
468CONFIG_X86_LONGRUN=m
469CONFIG_X86_LONGHAUL=m
470CONFIG_X86_E_POWERSAVER=m
471 445
472# 446#
473# shared options 447# shared options
474# 448#
475CONFIG_X86_SPEEDSTEP_LIB=m 449CONFIG_X86_SPEEDSTEP_LIB=m
476CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK=y
477CONFIG_CPU_IDLE=y 450CONFIG_CPU_IDLE=y
478CONFIG_CPU_IDLE_GOV_LADDER=y 451CONFIG_CPU_IDLE_GOV_LADDER=y
479CONFIG_CPU_IDLE_GOV_MENU=y 452CONFIG_CPU_IDLE_GOV_MENU=y
453CONFIG_INTEL_IDLE=m
454
455#
456# Memory power savings
457#
458CONFIG_I7300_IDLE_IOAT_CHANNEL=y
459CONFIG_I7300_IDLE=m
480 460
481# 461#
482# Bus options (PCI etc.) 462# Bus options (PCI etc.)
483# 463#
484CONFIG_PCI=y 464CONFIG_PCI=y
485# CONFIG_PCI_GOBIOS is not set
486# CONFIG_PCI_GOMMCONFIG is not set
487# CONFIG_PCI_GODIRECT is not set
488# CONFIG_PCI_GOOLPC is not set
489CONFIG_PCI_GOANY=y
490CONFIG_PCI_BIOS=y
491CONFIG_PCI_DIRECT=y 465CONFIG_PCI_DIRECT=y
492CONFIG_PCI_MMCONFIG=y 466CONFIG_PCI_MMCONFIG=y
493CONFIG_PCI_DOMAINS=y 467CONFIG_PCI_DOMAINS=y
468CONFIG_PCI_CNB20LE_QUIRK=y
469# CONFIG_DMAR is not set
470# CONFIG_INTR_REMAP is not set
494CONFIG_PCIEPORTBUS=y 471CONFIG_PCIEPORTBUS=y
495CONFIG_HOTPLUG_PCI_PCIE=m 472CONFIG_HOTPLUG_PCI_PCIE=m
496# CONFIG_PCIEAER is not set 473# CONFIG_PCIEAER is not set
497CONFIG_PCIEASPM=y 474CONFIG_PCIEASPM=y
498# CONFIG_PCIEASPM_DEBUG is not set 475# CONFIG_PCIEASPM_DEBUG is not set
499CONFIG_ARCH_SUPPORTS_MSI=y 476CONFIG_ARCH_SUPPORTS_MSI=y
500# CONFIG_PCI_MSI is not set 477CONFIG_PCI_MSI=y
501CONFIG_PCI_STUB=m 478CONFIG_PCI_STUB=m
502CONFIG_HT_IRQ=y 479CONFIG_HT_IRQ=y
503# CONFIG_PCI_IOV is not set 480# CONFIG_PCI_IOV is not set
504CONFIG_PCI_IOAPIC=y 481CONFIG_PCI_IOAPIC=y
505CONFIG_ISA_DMA_API=y 482CONFIG_ISA_DMA_API=y
506CONFIG_ISA=y
507# CONFIG_EISA is not set
508# CONFIG_MCA is not set
509CONFIG_SCx200=m
510CONFIG_SCx200HR_TIMER=m
511# CONFIG_OLPC is not set
512CONFIG_K8_NB=y 483CONFIG_K8_NB=y
513CONFIG_PCCARD=m 484CONFIG_PCCARD=m
514CONFIG_PCMCIA=m 485CONFIG_PCMCIA=m
@@ -526,15 +497,9 @@ CONFIG_YENTA_ENE_TUNE=y
526CONFIG_YENTA_TOSHIBA=y 497CONFIG_YENTA_TOSHIBA=y
527CONFIG_PD6729=m 498CONFIG_PD6729=m
528CONFIG_I82092=m 499CONFIG_I82092=m
529CONFIG_I82365=m 500CONFIG_PCCARD_NONSTATIC=y
530CONFIG_TCIC=m
531CONFIG_PCMCIA_PROBE=y
532CONFIG_PCCARD_NONSTATIC=m
533CONFIG_HOTPLUG_PCI=m 501CONFIG_HOTPLUG_PCI=m
534CONFIG_HOTPLUG_PCI_FAKE=m 502CONFIG_HOTPLUG_PCI_FAKE=m
535CONFIG_HOTPLUG_PCI_COMPAQ=m
536# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
537CONFIG_HOTPLUG_PCI_IBM=m
538CONFIG_HOTPLUG_PCI_ACPI=m 503CONFIG_HOTPLUG_PCI_ACPI=m
539CONFIG_HOTPLUG_PCI_ACPI_IBM=m 504CONFIG_HOTPLUG_PCI_ACPI_IBM=m
540CONFIG_HOTPLUG_PCI_CPCI=y 505CONFIG_HOTPLUG_PCI_CPCI=y
@@ -547,10 +512,10 @@ CONFIG_HOTPLUG_PCI_SHPC=m
547# 512#
548CONFIG_BINFMT_ELF=y 513CONFIG_BINFMT_ELF=y
549# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set 514# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
550CONFIG_HAVE_AOUT=y 515# CONFIG_HAVE_AOUT is not set
551CONFIG_BINFMT_AOUT=m
552CONFIG_BINFMT_MISC=m 516CONFIG_BINFMT_MISC=m
553CONFIG_HAVE_ATOMIC_IOMAP=y 517# CONFIG_IA32_EMULATION is not set
518# CONFIG_COMPAT_FOR_U64_ALIGNMENT is not set
554CONFIG_NET=y 519CONFIG_NET=y
555 520
556# 521#
@@ -584,6 +549,7 @@ CONFIG_NET_IPIP=m
584CONFIG_NET_IPGRE=m 549CONFIG_NET_IPGRE=m
585CONFIG_NET_IPGRE_BROADCAST=y 550CONFIG_NET_IPGRE_BROADCAST=y
586CONFIG_IP_MROUTE=y 551CONFIG_IP_MROUTE=y
552CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
587# CONFIG_IP_PIMSM_V1 is not set 553# CONFIG_IP_PIMSM_V1 is not set
588CONFIG_IP_PIMSM_V2=y 554CONFIG_IP_PIMSM_V2=y
589CONFIG_ARPD=y 555CONFIG_ARPD=y
@@ -615,7 +581,9 @@ CONFIG_TCP_CONG_ILLINOIS=m
615# CONFIG_DEFAULT_BIC is not set 581# CONFIG_DEFAULT_BIC is not set
616CONFIG_DEFAULT_CUBIC=y 582CONFIG_DEFAULT_CUBIC=y
617# CONFIG_DEFAULT_HTCP is not set 583# CONFIG_DEFAULT_HTCP is not set
584# CONFIG_DEFAULT_HYBLA is not set
618# CONFIG_DEFAULT_VEGAS is not set 585# CONFIG_DEFAULT_VEGAS is not set
586# CONFIG_DEFAULT_VENO is not set
619# CONFIG_DEFAULT_WESTWOOD is not set 587# CONFIG_DEFAULT_WESTWOOD is not set
620# CONFIG_DEFAULT_RENO is not set 588# CONFIG_DEFAULT_RENO is not set
621CONFIG_DEFAULT_TCP_CONG="cubic" 589CONFIG_DEFAULT_TCP_CONG="cubic"
@@ -636,12 +604,13 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m
636CONFIG_INET6_XFRM_MODE_BEET=m 604CONFIG_INET6_XFRM_MODE_BEET=m
637CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m 605CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
638CONFIG_IPV6_SIT=m 606CONFIG_IPV6_SIT=m
639# CONFIG_IPV6_SIT_6RD is not set 607CONFIG_IPV6_SIT_6RD=y
640CONFIG_IPV6_NDISC_NODETYPE=y 608CONFIG_IPV6_NDISC_NODETYPE=y
641CONFIG_IPV6_TUNNEL=m 609CONFIG_IPV6_TUNNEL=m
642CONFIG_IPV6_MULTIPLE_TABLES=y 610CONFIG_IPV6_MULTIPLE_TABLES=y
643CONFIG_IPV6_SUBTREES=y 611CONFIG_IPV6_SUBTREES=y
644CONFIG_IPV6_MROUTE=y 612CONFIG_IPV6_MROUTE=y
613CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
645CONFIG_IPV6_PIMSM_V2=y 614CONFIG_IPV6_PIMSM_V2=y
646CONFIG_NETLABEL=y 615CONFIG_NETLABEL=y
647CONFIG_NETWORK_SECMARK=y 616CONFIG_NETWORK_SECMARK=y
@@ -660,7 +629,7 @@ CONFIG_NF_CONNTRACK=m
660CONFIG_NF_CT_ACCT=y 629CONFIG_NF_CT_ACCT=y
661CONFIG_NF_CONNTRACK_MARK=y 630CONFIG_NF_CONNTRACK_MARK=y
662CONFIG_NF_CONNTRACK_SECMARK=y 631CONFIG_NF_CONNTRACK_SECMARK=y
663# CONFIG_NF_CONNTRACK_ZONES is not set 632CONFIG_NF_CONNTRACK_ZONES=y
664CONFIG_NF_CONNTRACK_EVENTS=y 633CONFIG_NF_CONNTRACK_EVENTS=y
665CONFIG_NF_CT_PROTO_DCCP=m 634CONFIG_NF_CT_PROTO_DCCP=m
666CONFIG_NF_CT_PROTO_GRE=m 635CONFIG_NF_CT_PROTO_GRE=m
@@ -678,6 +647,16 @@ CONFIG_NF_CONNTRACK_TFTP=m
678CONFIG_NF_CT_NETLINK=m 647CONFIG_NF_CT_NETLINK=m
679CONFIG_NETFILTER_TPROXY=m 648CONFIG_NETFILTER_TPROXY=m
680CONFIG_NETFILTER_XTABLES=m 649CONFIG_NETFILTER_XTABLES=m
650
651#
652# Xtables combined modules
653#
654CONFIG_NETFILTER_XT_MARK=m
655CONFIG_NETFILTER_XT_CONNMARK=m
656
657#
658# Xtables targets
659#
681CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m 660CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
682CONFIG_NETFILTER_XT_TARGET_CONNMARK=m 661CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
683CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m 662CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
@@ -690,11 +669,16 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
690CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m 669CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
691CONFIG_NETFILTER_XT_TARGET_NOTRACK=m 670CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
692CONFIG_NETFILTER_XT_TARGET_RATEEST=m 671CONFIG_NETFILTER_XT_TARGET_RATEEST=m
672CONFIG_NETFILTER_XT_TARGET_TEE=m
693CONFIG_NETFILTER_XT_TARGET_TPROXY=m 673CONFIG_NETFILTER_XT_TARGET_TPROXY=m
694CONFIG_NETFILTER_XT_TARGET_TRACE=m 674CONFIG_NETFILTER_XT_TARGET_TRACE=m
695CONFIG_NETFILTER_XT_TARGET_SECMARK=m 675CONFIG_NETFILTER_XT_TARGET_SECMARK=m
696CONFIG_NETFILTER_XT_TARGET_TCPMSS=m 676CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
697CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m 677CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
678
679#
680# Xtables matches
681#
698CONFIG_NETFILTER_XT_MATCH_CLUSTER=m 682CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
699CONFIG_NETFILTER_XT_MATCH_COMMENT=m 683CONFIG_NETFILTER_XT_MATCH_COMMENT=m
700CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m 684CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
@@ -713,6 +697,7 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
713CONFIG_NETFILTER_XT_MATCH_MAC=m 697CONFIG_NETFILTER_XT_MATCH_MAC=m
714CONFIG_NETFILTER_XT_MATCH_MARK=m 698CONFIG_NETFILTER_XT_MATCH_MARK=m
715CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m 699CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
700CONFIG_NETFILTER_XT_MATCH_OSF=m
716CONFIG_NETFILTER_XT_MATCH_OWNER=m 701CONFIG_NETFILTER_XT_MATCH_OWNER=m
717CONFIG_NETFILTER_XT_MATCH_POLICY=m 702CONFIG_NETFILTER_XT_MATCH_POLICY=m
718CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m 703CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
@@ -721,7 +706,6 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
721CONFIG_NETFILTER_XT_MATCH_RATEEST=m 706CONFIG_NETFILTER_XT_MATCH_RATEEST=m
722CONFIG_NETFILTER_XT_MATCH_REALM=m 707CONFIG_NETFILTER_XT_MATCH_REALM=m
723CONFIG_NETFILTER_XT_MATCH_RECENT=m 708CONFIG_NETFILTER_XT_MATCH_RECENT=m
724# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
725CONFIG_NETFILTER_XT_MATCH_SCTP=m 709CONFIG_NETFILTER_XT_MATCH_SCTP=m
726CONFIG_NETFILTER_XT_MATCH_SOCKET=m 710CONFIG_NETFILTER_XT_MATCH_SOCKET=m
727CONFIG_NETFILTER_XT_MATCH_STATE=m 711CONFIG_NETFILTER_XT_MATCH_STATE=m
@@ -730,7 +714,6 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
730CONFIG_NETFILTER_XT_MATCH_TCPMSS=m 714CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
731CONFIG_NETFILTER_XT_MATCH_TIME=m 715CONFIG_NETFILTER_XT_MATCH_TIME=m
732CONFIG_NETFILTER_XT_MATCH_U32=m 716CONFIG_NETFILTER_XT_MATCH_U32=m
733CONFIG_NETFILTER_XT_MATCH_OSF=m
734CONFIG_IP_VS=m 717CONFIG_IP_VS=m
735CONFIG_IP_VS_IPV6=y 718CONFIG_IP_VS_IPV6=y
736# CONFIG_IP_VS_DEBUG is not set 719# CONFIG_IP_VS_DEBUG is not set
@@ -744,7 +727,7 @@ CONFIG_IP_VS_PROTO_UDP=y
744CONFIG_IP_VS_PROTO_AH_ESP=y 727CONFIG_IP_VS_PROTO_AH_ESP=y
745CONFIG_IP_VS_PROTO_ESP=y 728CONFIG_IP_VS_PROTO_ESP=y
746CONFIG_IP_VS_PROTO_AH=y 729CONFIG_IP_VS_PROTO_AH=y
747# CONFIG_IP_VS_PROTO_SCTP is not set 730CONFIG_IP_VS_PROTO_SCTP=y
748 731
749# 732#
750# IPVS scheduler 733# IPVS scheduler
@@ -887,6 +870,11 @@ CONFIG_ATM_LANE=m
887CONFIG_ATM_MPOA=m 870CONFIG_ATM_MPOA=m
888CONFIG_ATM_BR2684=m 871CONFIG_ATM_BR2684=m
889# CONFIG_ATM_BR2684_IPFILTER is not set 872# CONFIG_ATM_BR2684_IPFILTER is not set
873CONFIG_L2TP=m
874CONFIG_L2TP_DEBUGFS=m
875CONFIG_L2TP_V3=y
876CONFIG_L2TP_IP=m
877CONFIG_L2TP_ETH=m
890CONFIG_STP=m 878CONFIG_STP=m
891CONFIG_BRIDGE=m 879CONFIG_BRIDGE=m
892CONFIG_BRIDGE_IGMP_SNOOPING=y 880CONFIG_BRIDGE_IGMP_SNOOPING=y
@@ -901,10 +889,6 @@ CONFIG_IPX=m
901# CONFIG_IPX_INTERN is not set 889# CONFIG_IPX_INTERN is not set
902CONFIG_ATALK=m 890CONFIG_ATALK=m
903CONFIG_DEV_APPLETALK=m 891CONFIG_DEV_APPLETALK=m
904CONFIG_LTPC=m
905CONFIG_COPS=m
906CONFIG_COPS_DAYNA=y
907CONFIG_COPS_TANGENT=y
908CONFIG_IPDDP=m 892CONFIG_IPDDP=m
909CONFIG_IPDDP_ENCAP=y 893CONFIG_IPDDP_ENCAP=y
910CONFIG_IPDDP_DECAP=y 894CONFIG_IPDDP_DECAP=y
@@ -972,6 +956,7 @@ CONFIG_NET_ACT_SKBEDIT=m
972# CONFIG_NET_CLS_IND is not set 956# CONFIG_NET_CLS_IND is not set
973CONFIG_NET_SCH_FIFO=y 957CONFIG_NET_SCH_FIFO=y
974# CONFIG_DCB is not set 958# CONFIG_DCB is not set
959CONFIG_RPS=y
975 960
976# 961#
977# Network testing 962# Network testing
@@ -989,8 +974,8 @@ CONFIG_CAN_VCAN=m
989CONFIG_CAN_DEV=m 974CONFIG_CAN_DEV=m
990# CONFIG_CAN_CALC_BITTIMING is not set 975# CONFIG_CAN_CALC_BITTIMING is not set
991CONFIG_CAN_MCP251X=m 976CONFIG_CAN_MCP251X=m
977CONFIG_CAN_JANZ_ICAN3=m
992CONFIG_CAN_SJA1000=m 978CONFIG_CAN_SJA1000=m
993# CONFIG_CAN_SJA1000_ISA is not set
994CONFIG_CAN_SJA1000_PLATFORM=m 979CONFIG_CAN_SJA1000_PLATFORM=m
995CONFIG_CAN_EMS_PCI=m 980CONFIG_CAN_EMS_PCI=m
996CONFIG_CAN_KVASER_PCI=m 981CONFIG_CAN_KVASER_PCI=m
@@ -1052,7 +1037,6 @@ CONFIG_USB_IRDA=m
1052CONFIG_SIGMATEL_FIR=m 1037CONFIG_SIGMATEL_FIR=m
1053CONFIG_NSC_FIR=m 1038CONFIG_NSC_FIR=m
1054CONFIG_WINBOND_FIR=m 1039CONFIG_WINBOND_FIR=m
1055CONFIG_TOSHIBA_FIR=m
1056CONFIG_SMC_IRCC_FIR=m 1040CONFIG_SMC_IRCC_FIR=m
1057CONFIG_ALI_FIR=m 1041CONFIG_ALI_FIR=m
1058CONFIG_VLSI_FIR=m 1042CONFIG_VLSI_FIR=m
@@ -1060,6 +1044,7 @@ CONFIG_VIA_FIR=m
1060CONFIG_MCS_FIR=m 1044CONFIG_MCS_FIR=m
1061CONFIG_BT=m 1045CONFIG_BT=m
1062CONFIG_BT_L2CAP=m 1046CONFIG_BT_L2CAP=m
1047# CONFIG_BT_L2CAP_EXT_FEATURES is not set
1063CONFIG_BT_SCO=m 1048CONFIG_BT_SCO=m
1064CONFIG_BT_RFCOMM=m 1049CONFIG_BT_RFCOMM=m
1065CONFIG_BT_RFCOMM_TTY=y 1050CONFIG_BT_RFCOMM_TTY=y
@@ -1113,6 +1098,7 @@ CONFIG_LIB80211_CRYPT_CCMP=m
1113CONFIG_LIB80211_CRYPT_TKIP=m 1098CONFIG_LIB80211_CRYPT_TKIP=m
1114# CONFIG_LIB80211_DEBUG is not set 1099# CONFIG_LIB80211_DEBUG is not set
1115CONFIG_MAC80211=m 1100CONFIG_MAC80211=m
1101CONFIG_MAC80211_HAS_RC=y
1116CONFIG_MAC80211_RC_PID=y 1102CONFIG_MAC80211_RC_PID=y
1117CONFIG_MAC80211_RC_MINSTREL=y 1103CONFIG_MAC80211_RC_MINSTREL=y
1118CONFIG_MAC80211_RC_DEFAULT_PID=y 1104CONFIG_MAC80211_RC_DEFAULT_PID=y
@@ -1131,6 +1117,9 @@ CONFIG_NET_9P=m
1131CONFIG_NET_9P_VIRTIO=m 1117CONFIG_NET_9P_VIRTIO=m
1132CONFIG_NET_9P_RDMA=m 1118CONFIG_NET_9P_RDMA=m
1133# CONFIG_NET_9P_DEBUG is not set 1119# CONFIG_NET_9P_DEBUG is not set
1120CONFIG_CAIF=m
1121# CONFIG_CAIF_DEBUG is not set
1122CONFIG_CAIF_NETDEV=m
1134 1123
1135# 1124#
1136# Device Drivers 1125# Device Drivers
@@ -1146,7 +1135,7 @@ CONFIG_STANDALONE=y
1146CONFIG_FW_LOADER=m 1135CONFIG_FW_LOADER=m
1147# CONFIG_FIRMWARE_IN_KERNEL is not set 1136# CONFIG_FIRMWARE_IN_KERNEL is not set
1148CONFIG_EXTRA_FIRMWARE="" 1137CONFIG_EXTRA_FIRMWARE=""
1149CONFIG_SYS_HYPERVISOR=y 1138# CONFIG_SYS_HYPERVISOR is not set
1150CONFIG_CONNECTOR=m 1139CONFIG_CONNECTOR=m
1151CONFIG_MTD=m 1140CONFIG_MTD=m
1152# CONFIG_MTD_DEBUG is not set 1141# CONFIG_MTD_DEBUG is not set
@@ -1173,6 +1162,7 @@ CONFIG_NFTL_RW=y
1173CONFIG_INFTL=m 1162CONFIG_INFTL=m
1174CONFIG_RFD_FTL=m 1163CONFIG_RFD_FTL=m
1175CONFIG_SSFDC=m 1164CONFIG_SSFDC=m
1165CONFIG_SM_FTL=m
1176CONFIG_MTD_OOPS=m 1166CONFIG_MTD_OOPS=m
1177 1167
1178# 1168#
@@ -1210,7 +1200,6 @@ CONFIG_MTD_SC520CDP=m
1210CONFIG_MTD_NETSC520=m 1200CONFIG_MTD_NETSC520=m
1211CONFIG_MTD_TS5500=m 1201CONFIG_MTD_TS5500=m
1212CONFIG_MTD_SBC_GXX=m 1202CONFIG_MTD_SBC_GXX=m
1213CONFIG_MTD_SCx200_DOCFLASH=m
1214CONFIG_MTD_AMD76XROM=m 1203CONFIG_MTD_AMD76XROM=m
1215CONFIG_MTD_ICHXROM=m 1204CONFIG_MTD_ICHXROM=m
1216CONFIG_MTD_ESB2ROM=m 1205CONFIG_MTD_ESB2ROM=m
@@ -1219,6 +1208,8 @@ CONFIG_MTD_SCB2_FLASH=m
1219CONFIG_MTD_NETtel=m 1208CONFIG_MTD_NETtel=m
1220CONFIG_MTD_L440GX=m 1209CONFIG_MTD_L440GX=m
1221CONFIG_MTD_PCI=m 1210CONFIG_MTD_PCI=m
1211CONFIG_MTD_PCMCIA=m
1212# CONFIG_MTD_PCMCIA_ANONYMOUS is not set
1222# CONFIG_MTD_GPIO_ADDR is not set 1213# CONFIG_MTD_GPIO_ADDR is not set
1223CONFIG_MTD_INTEL_VR_NOR=m 1214CONFIG_MTD_INTEL_VR_NOR=m
1224CONFIG_MTD_PLATRAM=m 1215CONFIG_MTD_PLATRAM=m
@@ -1254,17 +1245,21 @@ CONFIG_MTD_DOCPROBE_ADVANCED=y
1254CONFIG_MTD_DOCPROBE_ADDRESS=0x0000 1245CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
1255# CONFIG_MTD_DOCPROBE_HIGH is not set 1246# CONFIG_MTD_DOCPROBE_HIGH is not set
1256# CONFIG_MTD_DOCPROBE_55AA is not set 1247# CONFIG_MTD_DOCPROBE_55AA is not set
1248CONFIG_MTD_NAND_ECC=m
1249CONFIG_MTD_NAND_ECC_SMC=y
1257CONFIG_MTD_NAND=m 1250CONFIG_MTD_NAND=m
1258# CONFIG_MTD_NAND_VERIFY_WRITE is not set 1251# CONFIG_MTD_NAND_VERIFY_WRITE is not set
1259CONFIG_MTD_NAND_ECC_SMC=y 1252CONFIG_MTD_SM_COMMON=m
1260# CONFIG_MTD_NAND_MUSEUM_IDS is not set 1253# CONFIG_MTD_NAND_MUSEUM_IDS is not set
1254CONFIG_MTD_NAND_DENALI=m
1255CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018
1261CONFIG_MTD_NAND_IDS=m 1256CONFIG_MTD_NAND_IDS=m
1257CONFIG_MTD_NAND_RICOH=m
1262CONFIG_MTD_NAND_DISKONCHIP=m 1258CONFIG_MTD_NAND_DISKONCHIP=m
1263# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set 1259# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
1264CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 1260CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
1265# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set 1261# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
1266CONFIG_MTD_NAND_CAFE=m 1262CONFIG_MTD_NAND_CAFE=m
1267CONFIG_MTD_NAND_CS553X=m
1268CONFIG_MTD_NAND_NANDSIM=m 1263CONFIG_MTD_NAND_NANDSIM=m
1269CONFIG_MTD_NAND_PLATFORM=m 1264CONFIG_MTD_NAND_PLATFORM=m
1270CONFIG_MTD_ALAUDA=m 1265CONFIG_MTD_ALAUDA=m
@@ -1309,13 +1304,9 @@ CONFIG_PNP=y
1309# 1304#
1310# Protocols 1305# Protocols
1311# 1306#
1312CONFIG_ISAPNP=y
1313CONFIG_PNPBIOS=y
1314# CONFIG_PNPBIOS_PROC_FS is not set
1315CONFIG_PNPACPI=y 1307CONFIG_PNPACPI=y
1316CONFIG_BLK_DEV=y 1308CONFIG_BLK_DEV=y
1317CONFIG_BLK_DEV_FD=m 1309CONFIG_BLK_DEV_FD=m
1318CONFIG_BLK_DEV_XD=m
1319# CONFIG_PARIDE is not set 1310# CONFIG_PARIDE is not set
1320CONFIG_BLK_CPQ_DA=m 1311CONFIG_BLK_CPQ_DA=m
1321CONFIG_BLK_CPQ_CISS_DA=m 1312CONFIG_BLK_CPQ_CISS_DA=m
@@ -1325,8 +1316,7 @@ CONFIG_BLK_DEV_UMEM=m
1325# CONFIG_BLK_DEV_COW_COMMON is not set 1316# CONFIG_BLK_DEV_COW_COMMON is not set
1326CONFIG_BLK_DEV_LOOP=m 1317CONFIG_BLK_DEV_LOOP=m
1327CONFIG_BLK_DEV_CRYPTOLOOP=m 1318CONFIG_BLK_DEV_CRYPTOLOOP=m
1328CONFIG_BLK_DEV_DRBD=m 1319# CONFIG_BLK_DEV_DRBD is not set
1329# CONFIG_DRBD_FAULT_INJECTION is not set
1330CONFIG_BLK_DEV_NBD=m 1320CONFIG_BLK_DEV_NBD=m
1331CONFIG_BLK_DEV_OSD=m 1321CONFIG_BLK_DEV_OSD=m
1332CONFIG_BLK_DEV_SX8=m 1322CONFIG_BLK_DEV_SX8=m
@@ -1339,11 +1329,12 @@ CONFIG_CDROM_PKTCDVD=m
1339CONFIG_CDROM_PKTCDVD_BUFFERS=8 1329CONFIG_CDROM_PKTCDVD_BUFFERS=8
1340# CONFIG_CDROM_PKTCDVD_WCACHE is not set 1330# CONFIG_CDROM_PKTCDVD_WCACHE is not set
1341CONFIG_ATA_OVER_ETH=m 1331CONFIG_ATA_OVER_ETH=m
1342CONFIG_XEN_BLKDEV_FRONTEND=y
1343CONFIG_VIRTIO_BLK=m 1332CONFIG_VIRTIO_BLK=m
1344# CONFIG_BLK_DEV_HD is not set 1333# CONFIG_BLK_DEV_HD is not set
1345CONFIG_MISC_DEVICES=y 1334CONFIG_MISC_DEVICES=y
1346CONFIG_AD525X_DPOT=m 1335CONFIG_AD525X_DPOT=m
1336CONFIG_AD525X_DPOT_I2C=m
1337CONFIG_AD525X_DPOT_SPI=m
1347CONFIG_IBM_ASM=m 1338CONFIG_IBM_ASM=m
1348CONFIG_PHANTOM=m 1339CONFIG_PHANTOM=m
1349CONFIG_SGI_IOC4=m 1340CONFIG_SGI_IOC4=m
@@ -1431,10 +1422,7 @@ CONFIG_BLK_DEV_3W_XXXX_RAID=m
1431CONFIG_SCSI_HPSA=m 1422CONFIG_SCSI_HPSA=m
1432CONFIG_SCSI_3W_9XXX=m 1423CONFIG_SCSI_3W_9XXX=m
1433CONFIG_SCSI_3W_SAS=m 1424CONFIG_SCSI_3W_SAS=m
1434CONFIG_SCSI_7000FASST=m
1435CONFIG_SCSI_ACARD=m 1425CONFIG_SCSI_ACARD=m
1436CONFIG_SCSI_AHA152X=m
1437CONFIG_SCSI_AHA1542=m
1438CONFIG_SCSI_AACRAID=m 1426CONFIG_SCSI_AACRAID=m
1439CONFIG_SCSI_AIC7XXX=m 1427CONFIG_SCSI_AIC7XXX=m
1440CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 1428CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
@@ -1457,7 +1445,6 @@ CONFIG_SCSI_MVSAS=m
1457CONFIG_SCSI_MVSAS_DEBUG=y 1445CONFIG_SCSI_MVSAS_DEBUG=y
1458CONFIG_SCSI_DPT_I2O=m 1446CONFIG_SCSI_DPT_I2O=m
1459CONFIG_SCSI_ADVANSYS=m 1447CONFIG_SCSI_ADVANSYS=m
1460CONFIG_SCSI_IN2000=m
1461CONFIG_SCSI_ARCMSR=m 1448CONFIG_SCSI_ARCMSR=m
1462CONFIG_MEGARAID_NEWGEN=y 1449CONFIG_MEGARAID_NEWGEN=y
1463CONFIG_MEGARAID_MM=m 1450CONFIG_MEGARAID_MM=m
@@ -1469,23 +1456,18 @@ CONFIG_SCSI_MPT2SAS_MAX_SGE=128
1469# CONFIG_SCSI_MPT2SAS_LOGGING is not set 1456# CONFIG_SCSI_MPT2SAS_LOGGING is not set
1470CONFIG_SCSI_HPTIOP=m 1457CONFIG_SCSI_HPTIOP=m
1471CONFIG_SCSI_BUSLOGIC=m 1458CONFIG_SCSI_BUSLOGIC=m
1472CONFIG_SCSI_FLASHPOINT=y
1473CONFIG_VMWARE_PVSCSI=m 1459CONFIG_VMWARE_PVSCSI=m
1474CONFIG_LIBFC=m 1460CONFIG_LIBFC=m
1475CONFIG_LIBFCOE=m 1461CONFIG_LIBFCOE=m
1476CONFIG_FCOE=m 1462CONFIG_FCOE=m
1477CONFIG_FCOE_FNIC=m 1463CONFIG_FCOE_FNIC=m
1478CONFIG_SCSI_DMX3191D=m 1464CONFIG_SCSI_DMX3191D=m
1479CONFIG_SCSI_DTC3280=m
1480CONFIG_SCSI_EATA=m 1465CONFIG_SCSI_EATA=m
1481# CONFIG_SCSI_EATA_TAGGED_QUEUE is not set 1466# CONFIG_SCSI_EATA_TAGGED_QUEUE is not set
1482# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set 1467# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set
1483CONFIG_SCSI_EATA_MAX_TAGS=16 1468CONFIG_SCSI_EATA_MAX_TAGS=16
1484CONFIG_SCSI_FUTURE_DOMAIN=m 1469CONFIG_SCSI_FUTURE_DOMAIN=m
1485CONFIG_SCSI_GDTH=m 1470CONFIG_SCSI_GDTH=m
1486CONFIG_SCSI_GENERIC_NCR5380=m
1487CONFIG_SCSI_GENERIC_NCR5380_MMIO=m
1488CONFIG_SCSI_GENERIC_NCR53C400=y
1489CONFIG_SCSI_IPS=m 1471CONFIG_SCSI_IPS=m
1490CONFIG_SCSI_INITIO=m 1472CONFIG_SCSI_INITIO=m
1491CONFIG_SCSI_INIA100=m 1473CONFIG_SCSI_INIA100=m
@@ -1493,7 +1475,6 @@ CONFIG_SCSI_PPA=m
1493CONFIG_SCSI_IMM=m 1475CONFIG_SCSI_IMM=m
1494# CONFIG_SCSI_IZIP_EPP16 is not set 1476# CONFIG_SCSI_IZIP_EPP16 is not set
1495# CONFIG_SCSI_IZIP_SLOW_CTR is not set 1477# CONFIG_SCSI_IZIP_SLOW_CTR is not set
1496CONFIG_SCSI_NCR53C406A=m
1497CONFIG_SCSI_STEX=m 1478CONFIG_SCSI_STEX=m
1498CONFIG_SCSI_SYM53C8XX_2=m 1479CONFIG_SCSI_SYM53C8XX_2=m
1499CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 1480CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
@@ -1503,32 +1484,20 @@ CONFIG_SCSI_SYM53C8XX_MMIO=y
1503CONFIG_SCSI_IPR=m 1484CONFIG_SCSI_IPR=m
1504CONFIG_SCSI_IPR_TRACE=y 1485CONFIG_SCSI_IPR_TRACE=y
1505# CONFIG_SCSI_IPR_DUMP is not set 1486# CONFIG_SCSI_IPR_DUMP is not set
1506CONFIG_SCSI_PAS16=m
1507CONFIG_SCSI_QLOGIC_FAS=m
1508CONFIG_SCSI_QLOGIC_1280=m 1487CONFIG_SCSI_QLOGIC_1280=m
1509CONFIG_SCSI_QLA_FC=m 1488CONFIG_SCSI_QLA_FC=m
1510CONFIG_SCSI_QLA_ISCSI=m 1489CONFIG_SCSI_QLA_ISCSI=m
1511CONFIG_SCSI_LPFC=m 1490CONFIG_SCSI_LPFC=m
1512# CONFIG_SCSI_LPFC_DEBUG_FS is not set 1491# CONFIG_SCSI_LPFC_DEBUG_FS is not set
1513CONFIG_SCSI_SYM53C416=m
1514CONFIG_SCSI_DC395x=m 1492CONFIG_SCSI_DC395x=m
1515CONFIG_SCSI_DC390T=m 1493CONFIG_SCSI_DC390T=m
1516CONFIG_SCSI_T128=m
1517CONFIG_SCSI_U14_34F=m
1518# CONFIG_SCSI_U14_34F_TAGGED_QUEUE is not set
1519# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set
1520CONFIG_SCSI_U14_34F_MAX_TAGS=8
1521CONFIG_SCSI_ULTRASTOR=m
1522CONFIG_SCSI_NSP32=m
1523CONFIG_SCSI_DEBUG=m 1494CONFIG_SCSI_DEBUG=m
1524# CONFIG_SCSI_PMCRAID is not set 1495# CONFIG_SCSI_PMCRAID is not set
1525CONFIG_SCSI_PM8001=m 1496CONFIG_SCSI_PM8001=m
1526CONFIG_SCSI_SRP=m 1497CONFIG_SCSI_SRP=m
1527# CONFIG_SCSI_BFA_FC is not set 1498# CONFIG_SCSI_BFA_FC is not set
1528CONFIG_SCSI_LOWLEVEL_PCMCIA=y 1499CONFIG_SCSI_LOWLEVEL_PCMCIA=y
1529CONFIG_PCMCIA_AHA152X=m
1530CONFIG_PCMCIA_FDOMAIN=m 1500CONFIG_PCMCIA_FDOMAIN=m
1531CONFIG_PCMCIA_NINJA_SCSI=m
1532CONFIG_PCMCIA_QLOGIC=m 1501CONFIG_PCMCIA_QLOGIC=m
1533CONFIG_PCMCIA_SYM53C500=m 1502CONFIG_PCMCIA_SYM53C500=m
1534CONFIG_SCSI_DH=m 1503CONFIG_SCSI_DH=m
@@ -1540,80 +1509,131 @@ CONFIG_SCSI_OSD_INITIATOR=m
1540CONFIG_SCSI_OSD_ULD=m 1509CONFIG_SCSI_OSD_ULD=m
1541CONFIG_SCSI_OSD_DPRINT_SENSE=1 1510CONFIG_SCSI_OSD_DPRINT_SENSE=1
1542# CONFIG_SCSI_OSD_DEBUG is not set 1511# CONFIG_SCSI_OSD_DEBUG is not set
1512
1513#
1514# SCSI target (SCST) support
1515#
1516CONFIG_SCST=m
1517CONFIG_SCST_DISK=m
1518CONFIG_SCST_TAPE=m
1519CONFIG_SCST_CDROM=m
1520CONFIG_SCST_MODISK=m
1521CONFIG_SCST_CHANGER=m
1522CONFIG_SCST_PROCESSOR=m
1523CONFIG_SCST_RAID=m
1524CONFIG_SCST_VDISK=m
1525CONFIG_SCST_USER=m
1526# CONFIG_SCST_STRICT_SERIALIZING is not set
1527# CONFIG_SCST_STRICT_SECURITY is not set
1528# CONFIG_SCST_TEST_IO_IN_SIRQ is not set
1529# CONFIG_SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING is not set
1530# CONFIG_SCST_USE_EXPECTED_VALUES is not set
1531# CONFIG_SCST_EXTRACHECKS is not set
1532CONFIG_SCST_TRACING=y
1533# CONFIG_SCST_DEBUG is not set
1534# CONFIG_SCST_DEBUG_OOM is not set
1535# CONFIG_SCST_DEBUG_RETRY is not set
1536# CONFIG_SCST_DEBUG_SN is not set
1537# CONFIG_SCST_MEASURE_LATENCY is not set
1538CONFIG_FCST=m
1539CONFIG_SCST_ISCSI=m
1540# CONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES is not set
1541CONFIG_SCST_SRPT=m
1543CONFIG_ATA=m 1542CONFIG_ATA=m
1544# CONFIG_ATA_NONSTANDARD is not set 1543# CONFIG_ATA_NONSTANDARD is not set
1545CONFIG_ATA_VERBOSE_ERROR=y 1544CONFIG_ATA_VERBOSE_ERROR=y
1546CONFIG_ATA_ACPI=y 1545CONFIG_ATA_ACPI=y
1547CONFIG_SATA_PMP=y 1546CONFIG_SATA_PMP=y
1547
1548#
1549# Controllers with non-SFF native interface
1550#
1548CONFIG_SATA_AHCI=m 1551CONFIG_SATA_AHCI=m
1552CONFIG_SATA_AHCI_PLATFORM=m
1553CONFIG_SATA_INIC162X=m
1549CONFIG_SATA_SIL24=m 1554CONFIG_SATA_SIL24=m
1550CONFIG_ATA_SFF=y 1555CONFIG_ATA_SFF=y
1551CONFIG_SATA_SVW=m 1556
1557#
1558# SFF controllers with custom DMA interface
1559#
1560CONFIG_PDC_ADMA=m
1561CONFIG_SATA_QSTOR=m
1562CONFIG_SATA_SX4=m
1563CONFIG_ATA_BMDMA=y
1564
1565#
1566# SATA SFF controllers with BMDMA
1567#
1552CONFIG_ATA_PIIX=m 1568CONFIG_ATA_PIIX=m
1553CONFIG_SATA_MV=m 1569CONFIG_SATA_MV=m
1554CONFIG_SATA_NV=m 1570CONFIG_SATA_NV=m
1555CONFIG_PDC_ADMA=m
1556CONFIG_SATA_QSTOR=m
1557CONFIG_SATA_PROMISE=m 1571CONFIG_SATA_PROMISE=m
1558CONFIG_SATA_SX4=m
1559CONFIG_SATA_SIL=m 1572CONFIG_SATA_SIL=m
1560CONFIG_SATA_SIS=m 1573CONFIG_SATA_SIS=m
1574CONFIG_SATA_SVW=m
1561CONFIG_SATA_ULI=m 1575CONFIG_SATA_ULI=m
1562CONFIG_SATA_VIA=m 1576CONFIG_SATA_VIA=m
1563CONFIG_SATA_VITESSE=m 1577CONFIG_SATA_VITESSE=m
1564CONFIG_SATA_INIC162X=m 1578
1565CONFIG_PATA_ACPI=m 1579#
1580# PATA SFF controllers with BMDMA
1581#
1566CONFIG_PATA_ALI=m 1582CONFIG_PATA_ALI=m
1567CONFIG_PATA_AMD=m 1583CONFIG_PATA_AMD=m
1568CONFIG_PATA_ARTOP=m 1584CONFIG_PATA_ARTOP=m
1569CONFIG_PATA_ATP867X=m
1570CONFIG_PATA_ATIIXP=m 1585CONFIG_PATA_ATIIXP=m
1571CONFIG_PATA_CMD640_PCI=m 1586CONFIG_PATA_ATP867X=m
1572CONFIG_PATA_CMD64X=m 1587CONFIG_PATA_CMD64X=m
1573CONFIG_PATA_CS5520=m 1588CONFIG_PATA_CS5520=m
1574CONFIG_PATA_CS5530=m 1589CONFIG_PATA_CS5530=m
1575CONFIG_PATA_CS5535=m
1576CONFIG_PATA_CS5536=m
1577CONFIG_PATA_CYPRESS=m 1590CONFIG_PATA_CYPRESS=m
1578CONFIG_PATA_EFAR=m 1591CONFIG_PATA_EFAR=m
1579CONFIG_ATA_GENERIC=m
1580CONFIG_PATA_HPT366=m 1592CONFIG_PATA_HPT366=m
1581CONFIG_PATA_HPT37X=m 1593CONFIG_PATA_HPT37X=m
1582CONFIG_PATA_HPT3X2N=m 1594CONFIG_PATA_HPT3X2N=m
1583CONFIG_PATA_HPT3X3=m 1595CONFIG_PATA_HPT3X3=m
1584CONFIG_PATA_HPT3X3_DMA=y 1596CONFIG_PATA_HPT3X3_DMA=y
1585CONFIG_PATA_ISAPNP=m
1586CONFIG_PATA_IT821X=m
1587CONFIG_PATA_IT8213=m 1597CONFIG_PATA_IT8213=m
1598CONFIG_PATA_IT821X=m
1588CONFIG_PATA_JMICRON=m 1599CONFIG_PATA_JMICRON=m
1589CONFIG_PATA_LEGACY=m
1590CONFIG_PATA_TRIFLEX=m
1591CONFIG_PATA_MARVELL=m 1600CONFIG_PATA_MARVELL=m
1592CONFIG_PATA_MPIIX=m
1593CONFIG_PATA_OLDPIIX=m
1594CONFIG_PATA_NETCELL=m 1601CONFIG_PATA_NETCELL=m
1595CONFIG_PATA_NINJA32=m 1602CONFIG_PATA_NINJA32=m
1596CONFIG_PATA_NS87410=m
1597CONFIG_PATA_NS87415=m 1603CONFIG_PATA_NS87415=m
1598CONFIG_PATA_OPTI=m 1604CONFIG_PATA_OLDPIIX=m
1599CONFIG_PATA_OPTIDMA=m 1605CONFIG_PATA_OPTIDMA=m
1600CONFIG_PATA_PCMCIA=m
1601CONFIG_PATA_PDC2027X=m 1606CONFIG_PATA_PDC2027X=m
1602CONFIG_PATA_PDC_OLD=m 1607CONFIG_PATA_PDC_OLD=m
1603CONFIG_PATA_QDI=m
1604CONFIG_PATA_RADISYS=m 1608CONFIG_PATA_RADISYS=m
1605CONFIG_PATA_RDC=m 1609CONFIG_PATA_RDC=m
1606CONFIG_PATA_RZ1000=m
1607CONFIG_PATA_SC1200=m 1610CONFIG_PATA_SC1200=m
1611CONFIG_PATA_SCH=m
1608CONFIG_PATA_SERVERWORKS=m 1612CONFIG_PATA_SERVERWORKS=m
1609CONFIG_PATA_SIL680=m 1613CONFIG_PATA_SIL680=m
1610CONFIG_PATA_SIS=m 1614CONFIG_PATA_SIS=m
1611CONFIG_PATA_TOSHIBA=m 1615CONFIG_PATA_TOSHIBA=m
1616CONFIG_PATA_TRIFLEX=m
1612CONFIG_PATA_VIA=m 1617CONFIG_PATA_VIA=m
1613CONFIG_PATA_WINBOND=m 1618CONFIG_PATA_WINBOND=m
1614CONFIG_PATA_WINBOND_VLB=m 1619
1620#
1621# PIO-only SFF controllers
1622#
1623CONFIG_PATA_CMD640_PCI=m
1624CONFIG_PATA_MPIIX=m
1625CONFIG_PATA_NS87410=m
1626CONFIG_PATA_OPTI=m
1627CONFIG_PATA_PCMCIA=m
1615CONFIG_PATA_PLATFORM=m 1628CONFIG_PATA_PLATFORM=m
1616CONFIG_PATA_SCH=m 1629CONFIG_PATA_RZ1000=m
1630
1631#
1632# Generic fallback / legacy drivers
1633#
1634CONFIG_PATA_ACPI=m
1635CONFIG_ATA_GENERIC=m
1636CONFIG_PATA_LEGACY=m
1617CONFIG_MD=y 1637CONFIG_MD=y
1618CONFIG_BLK_DEV_MD=y 1638CONFIG_BLK_DEV_MD=y
1619# CONFIG_MD_AUTODETECT is not set 1639# CONFIG_MD_AUTODETECT is not set
@@ -1704,7 +1724,6 @@ CONFIG_ARCNET_COM90xx=m
1704CONFIG_ARCNET_COM90xxIO=m 1724CONFIG_ARCNET_COM90xxIO=m
1705CONFIG_ARCNET_RIM_I=m 1725CONFIG_ARCNET_RIM_I=m
1706CONFIG_ARCNET_COM20020=m 1726CONFIG_ARCNET_COM20020=m
1707CONFIG_ARCNET_COM20020_ISA=m
1708CONFIG_ARCNET_COM20020_PCI=m 1727CONFIG_ARCNET_COM20020_PCI=m
1709CONFIG_PHYLIB=m 1728CONFIG_PHYLIB=m
1710 1729
@@ -1733,25 +1752,11 @@ CONFIG_HAPPYMEAL=m
1733CONFIG_SUNGEM=m 1752CONFIG_SUNGEM=m
1734CONFIG_CASSINI=m 1753CONFIG_CASSINI=m
1735CONFIG_NET_VENDOR_3COM=y 1754CONFIG_NET_VENDOR_3COM=y
1736CONFIG_EL1=m
1737CONFIG_EL2=m
1738CONFIG_ELPLUS=m
1739CONFIG_EL16=m
1740CONFIG_EL3=m
1741CONFIG_3C515=m
1742CONFIG_VORTEX=m 1755CONFIG_VORTEX=m
1743CONFIG_TYPHOON=m 1756CONFIG_TYPHOON=m
1744CONFIG_LANCE=m
1745CONFIG_NET_VENDOR_SMC=y
1746CONFIG_WD80x3=m
1747CONFIG_ULTRA=m
1748CONFIG_SMC9194=m
1749CONFIG_ENC28J60=m 1757CONFIG_ENC28J60=m
1750# CONFIG_ENC28J60_WRITEVERIFY is not set 1758# CONFIG_ENC28J60_WRITEVERIFY is not set
1751CONFIG_ETHOC=m 1759CONFIG_ETHOC=m
1752CONFIG_NET_VENDOR_RACAL=y
1753CONFIG_NI52=m
1754CONFIG_NI65=m
1755CONFIG_DNET=m 1760CONFIG_DNET=m
1756CONFIG_NET_TULIP=y 1761CONFIG_NET_TULIP=y
1757CONFIG_DE2104X=m 1762CONFIG_DE2104X=m
@@ -1765,21 +1770,7 @@ CONFIG_WINBOND_840=m
1765CONFIG_DM9102=m 1770CONFIG_DM9102=m
1766CONFIG_ULI526X=m 1771CONFIG_ULI526X=m
1767CONFIG_PCMCIA_XIRCOM=m 1772CONFIG_PCMCIA_XIRCOM=m
1768CONFIG_AT1700=m
1769CONFIG_DEPCA=m
1770CONFIG_HP100=m 1773CONFIG_HP100=m
1771CONFIG_NET_ISA=y
1772CONFIG_E2100=m
1773CONFIG_EWRK3=m
1774CONFIG_EEXPRESS=m
1775CONFIG_EEXPRESS_PRO=m
1776CONFIG_HPLAN_PLUS=m
1777CONFIG_HPLAN=m
1778CONFIG_LP486E=m
1779CONFIG_ETH16I=m
1780CONFIG_NE2000=m
1781CONFIG_ZNET=m
1782CONFIG_SEEQ8005=m
1783# CONFIG_IBM_NEW_EMAC_ZMII is not set 1774# CONFIG_IBM_NEW_EMAC_ZMII is not set
1784# CONFIG_IBM_NEW_EMAC_RGMII is not set 1775# CONFIG_IBM_NEW_EMAC_RGMII is not set
1785# CONFIG_IBM_NEW_EMAC_TAH is not set 1776# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -1791,16 +1782,12 @@ CONFIG_NET_PCI=y
1791CONFIG_PCNET32=m 1782CONFIG_PCNET32=m
1792CONFIG_AMD8111_ETH=m 1783CONFIG_AMD8111_ETH=m
1793CONFIG_ADAPTEC_STARFIRE=m 1784CONFIG_ADAPTEC_STARFIRE=m
1794CONFIG_AC3200=m
1795CONFIG_KSZ884X_PCI=m 1785CONFIG_KSZ884X_PCI=m
1796CONFIG_APRICOT=m
1797CONFIG_B44=m 1786CONFIG_B44=m
1798CONFIG_B44_PCI_AUTOSELECT=y 1787CONFIG_B44_PCI_AUTOSELECT=y
1799CONFIG_B44_PCICORE_AUTOSELECT=y 1788CONFIG_B44_PCICORE_AUTOSELECT=y
1800CONFIG_B44_PCI=y 1789CONFIG_B44_PCI=y
1801CONFIG_FORCEDETH=m 1790CONFIG_FORCEDETH=m
1802# CONFIG_FORCEDETH_NAPI is not set
1803CONFIG_CS89x0=m
1804CONFIG_E100=m 1791CONFIG_E100=m
1805CONFIG_FEALNX=m 1792CONFIG_FEALNX=m
1806CONFIG_NATSEMI=m 1793CONFIG_NATSEMI=m
@@ -1869,6 +1856,7 @@ CONFIG_CHELSIO_T4=m
1869CONFIG_ENIC=m 1856CONFIG_ENIC=m
1870CONFIG_IXGBE=m 1857CONFIG_IXGBE=m
1871CONFIG_IXGBE_DCA=y 1858CONFIG_IXGBE_DCA=y
1859# CONFIG_IXGBEVF is not set
1872CONFIG_IXGB=m 1860CONFIG_IXGB=m
1873CONFIG_S2IO=m 1861CONFIG_S2IO=m
1874CONFIG_VXGE=m 1862CONFIG_VXGE=m
@@ -1891,6 +1879,7 @@ CONFIG_BE2NET=m
1891CONFIG_WLAN=y 1879CONFIG_WLAN=y
1892CONFIG_PCMCIA_RAYCS=m 1880CONFIG_PCMCIA_RAYCS=m
1893CONFIG_LIBERTAS_THINFIRM=m 1881CONFIG_LIBERTAS_THINFIRM=m
1882# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
1894CONFIG_LIBERTAS_THINFIRM_USB=m 1883CONFIG_LIBERTAS_THINFIRM_USB=m
1895CONFIG_AIRO=m 1884CONFIG_AIRO=m
1896CONFIG_ATMEL=m 1885CONFIG_ATMEL=m
@@ -1916,6 +1905,8 @@ CONFIG_ATH9K_HW=m
1916CONFIG_ATH9K_COMMON=m 1905CONFIG_ATH9K_COMMON=m
1917CONFIG_ATH9K=m 1906CONFIG_ATH9K=m
1918# CONFIG_ATH9K_DEBUGFS is not set 1907# CONFIG_ATH9K_DEBUGFS is not set
1908CONFIG_ATH9K_HTC=m
1909# CONFIG_ATH9K_HTC_DEBUGFS is not set
1919CONFIG_AR9170_USB=m 1910CONFIG_AR9170_USB=m
1920CONFIG_AR9170_LEDS=y 1911CONFIG_AR9170_LEDS=y
1921CONFIG_B43=m 1912CONFIG_B43=m
@@ -1970,15 +1961,16 @@ CONFIG_LIBERTAS_CS=m
1970CONFIG_LIBERTAS_SDIO=m 1961CONFIG_LIBERTAS_SDIO=m
1971CONFIG_LIBERTAS_SPI=m 1962CONFIG_LIBERTAS_SPI=m
1972# CONFIG_LIBERTAS_DEBUG is not set 1963# CONFIG_LIBERTAS_DEBUG is not set
1973# CONFIG_LIBERTAS_MESH is not set 1964CONFIG_LIBERTAS_MESH=y
1974CONFIG_HERMES=m 1965CONFIG_HERMES=m
1966# CONFIG_HERMES_PRISM is not set
1975CONFIG_HERMES_CACHE_FW_ON_INIT=y 1967CONFIG_HERMES_CACHE_FW_ON_INIT=y
1976CONFIG_PLX_HERMES=m 1968CONFIG_PLX_HERMES=m
1977CONFIG_TMD_HERMES=m 1969CONFIG_TMD_HERMES=m
1978CONFIG_NORTEL_HERMES=m 1970CONFIG_NORTEL_HERMES=m
1979CONFIG_PCI_HERMES=m
1980CONFIG_PCMCIA_HERMES=m 1971CONFIG_PCMCIA_HERMES=m
1981CONFIG_PCMCIA_SPECTRUM=m 1972CONFIG_PCMCIA_SPECTRUM=m
1973CONFIG_ORINOCO_USB=m
1982CONFIG_P54_COMMON=m 1974CONFIG_P54_COMMON=m
1983CONFIG_P54_USB=m 1975CONFIG_P54_USB=m
1984CONFIG_P54_PCI=m 1976CONFIG_P54_PCI=m
@@ -1990,14 +1982,14 @@ CONFIG_RT2500PCI=m
1990CONFIG_RT61PCI=m 1982CONFIG_RT61PCI=m
1991CONFIG_RT2800PCI_PCI=y 1983CONFIG_RT2800PCI_PCI=y
1992CONFIG_RT2800PCI=m 1984CONFIG_RT2800PCI=m
1993# CONFIG_RT2800PCI_RT30XX is not set 1985CONFIG_RT2800PCI_RT30XX=y
1994# CONFIG_RT2800PCI_RT35XX is not set 1986# CONFIG_RT2800PCI_RT35XX is not set
1995CONFIG_RT2500USB=m 1987CONFIG_RT2500USB=m
1996CONFIG_RT73USB=m 1988CONFIG_RT73USB=m
1997CONFIG_RT2800USB=m 1989CONFIG_RT2800USB=m
1998# CONFIG_RT2800USB_RT30XX is not set 1990CONFIG_RT2800USB_RT30XX=y
1999# CONFIG_RT2800USB_RT35XX is not set 1991# CONFIG_RT2800USB_RT35XX is not set
2000# CONFIG_RT2800USB_UNKNOWN is not set 1992CONFIG_RT2800USB_UNKNOWN=y
2001CONFIG_RT2800_LIB=m 1993CONFIG_RT2800_LIB=m
2002CONFIG_RT2X00_LIB_PCI=m 1994CONFIG_RT2X00_LIB_PCI=m
2003CONFIG_RT2X00_LIB_USB=m 1995CONFIG_RT2X00_LIB_USB=m
@@ -2012,6 +2004,7 @@ CONFIG_WL1251=m
2012CONFIG_WL1251_SPI=m 2004CONFIG_WL1251_SPI=m
2013CONFIG_WL1251_SDIO=m 2005CONFIG_WL1251_SDIO=m
2014CONFIG_WL1271=m 2006CONFIG_WL1271=m
2007CONFIG_WL1271_SPI=m
2015CONFIG_ZD1211RW=m 2008CONFIG_ZD1211RW=m
2016# CONFIG_ZD1211RW_DEBUG is not set 2009# CONFIG_ZD1211RW_DEBUG is not set
2017 2010
@@ -2021,7 +2014,7 @@ CONFIG_ZD1211RW=m
2021CONFIG_WIMAX_I2400M=m 2014CONFIG_WIMAX_I2400M=m
2022CONFIG_WIMAX_I2400M_USB=m 2015CONFIG_WIMAX_I2400M_USB=m
2023CONFIG_WIMAX_I2400M_SDIO=m 2016CONFIG_WIMAX_I2400M_SDIO=m
2024# CONFIG_WIMAX_IWMC3200_SDIO is not set 2017CONFIG_WIMAX_IWMC3200_SDIO=y
2025CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 2018CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8
2026 2019
2027# 2020#
@@ -2067,10 +2060,7 @@ CONFIG_PCMCIA_XIRC2PS=m
2067CONFIG_PCMCIA_AXNET=m 2060CONFIG_PCMCIA_AXNET=m
2068CONFIG_ARCNET_COM20020_CS=m 2061CONFIG_ARCNET_COM20020_CS=m
2069CONFIG_WAN=y 2062CONFIG_WAN=y
2070CONFIG_HOSTESS_SV11=m
2071CONFIG_COSA=m
2072CONFIG_LANMEDIA=m 2063CONFIG_LANMEDIA=m
2073CONFIG_SEALEVEL_4021=m
2074CONFIG_HDLC=m 2064CONFIG_HDLC=m
2075CONFIG_HDLC_RAW=m 2065CONFIG_HDLC_RAW=m
2076CONFIG_HDLC_RAW_ETH=m 2066CONFIG_HDLC_RAW_ETH=m
@@ -2082,15 +2072,12 @@ CONFIG_PCI200SYN=m
2082CONFIG_WANXL=m 2072CONFIG_WANXL=m
2083# CONFIG_WANXL_BUILD_FIRMWARE is not set 2073# CONFIG_WANXL_BUILD_FIRMWARE is not set
2084CONFIG_PC300TOO=m 2074CONFIG_PC300TOO=m
2085CONFIG_N2=m
2086CONFIG_C101=m
2087CONFIG_FARSYNC=m 2075CONFIG_FARSYNC=m
2088CONFIG_DSCC4=m 2076CONFIG_DSCC4=m
2089CONFIG_DSCC4_PCISYNC=y 2077CONFIG_DSCC4_PCISYNC=y
2090CONFIG_DSCC4_PCI_RST=y 2078CONFIG_DSCC4_PCI_RST=y
2091CONFIG_DLCI=m 2079CONFIG_DLCI=m
2092CONFIG_DLCI_MAX=8 2080CONFIG_DLCI_MAX=8
2093CONFIG_SDLA=m
2094CONFIG_WAN_ROUTER_DRIVERS=m 2081CONFIG_WAN_ROUTER_DRIVERS=m
2095CONFIG_CYCLADES_SYNC=m 2082CONFIG_CYCLADES_SYNC=m
2096CONFIG_CYCLOMX_X25=y 2083CONFIG_CYCLOMX_X25=y
@@ -2108,9 +2095,6 @@ CONFIG_ATM_ENI=m
2108CONFIG_ATM_FIRESTREAM=m 2095CONFIG_ATM_FIRESTREAM=m
2109CONFIG_ATM_ZATM=m 2096CONFIG_ATM_ZATM=m
2110# CONFIG_ATM_ZATM_DEBUG is not set 2097# CONFIG_ATM_ZATM_DEBUG is not set
2111CONFIG_ATM_NICSTAR=m
2112CONFIG_ATM_NICSTAR_USE_SUNI=y
2113CONFIG_ATM_NICSTAR_USE_IDT77105=y
2114CONFIG_ATM_IDT77252=m 2098CONFIG_ATM_IDT77252=m
2115# CONFIG_ATM_IDT77252_DEBUG is not set 2099# CONFIG_ATM_IDT77252_DEBUG is not set
2116# CONFIG_ATM_IDT77252_RCV_ALL is not set 2100# CONFIG_ATM_IDT77252_RCV_ALL is not set
@@ -2130,7 +2114,11 @@ CONFIG_ATM_HE_USE_SUNI=y
2130CONFIG_ATM_SOLOS=m 2114CONFIG_ATM_SOLOS=m
2131CONFIG_IEEE802154_DRIVERS=m 2115CONFIG_IEEE802154_DRIVERS=m
2132CONFIG_IEEE802154_FAKEHARD=m 2116CONFIG_IEEE802154_FAKEHARD=m
2133CONFIG_XEN_NETDEV_FRONTEND=y 2117
2118#
2119# CAIF transport drivers
2120#
2121CONFIG_CAIF_TTY=m
2134CONFIG_FDDI=y 2122CONFIG_FDDI=y
2135CONFIG_DEFXX=m 2123CONFIG_DEFXX=m
2136# CONFIG_DEFXX_MMIO is not set 2124# CONFIG_DEFXX_MMIO is not set
@@ -2177,10 +2165,8 @@ CONFIG_ISDN_CAPI_CAPIFS=m
2177# CAPI hardware drivers 2165# CAPI hardware drivers
2178# 2166#
2179CONFIG_CAPI_AVM=y 2167CONFIG_CAPI_AVM=y
2180CONFIG_ISDN_DRV_AVMB1_B1ISA=m
2181CONFIG_ISDN_DRV_AVMB1_B1PCI=m 2168CONFIG_ISDN_DRV_AVMB1_B1PCI=m
2182CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y 2169CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
2183CONFIG_ISDN_DRV_AVMB1_T1ISA=m
2184CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m 2170CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
2185CONFIG_ISDN_DRV_AVMB1_AVM_CS=m 2171CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
2186CONFIG_ISDN_DRV_AVMB1_T1PCI=m 2172CONFIG_ISDN_DRV_AVMB1_T1PCI=m
@@ -2200,7 +2186,7 @@ CONFIG_GIGASET_M105=m
2200CONFIG_GIGASET_M101=m 2186CONFIG_GIGASET_M101=m
2201# CONFIG_GIGASET_DEBUG is not set 2187# CONFIG_GIGASET_DEBUG is not set
2202CONFIG_HYSDN=m 2188CONFIG_HYSDN=m
2203# CONFIG_HYSDN_CAPI is not set 2189CONFIG_HYSDN_CAPI=y
2204CONFIG_MISDN=m 2190CONFIG_MISDN=m
2205CONFIG_MISDN_DSP=m 2191CONFIG_MISDN_DSP=m
2206CONFIG_MISDN_L1OIP=m 2192CONFIG_MISDN_L1OIP=m
@@ -2237,7 +2223,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
2237CONFIG_INPUT_JOYDEV=m 2223CONFIG_INPUT_JOYDEV=m
2238CONFIG_INPUT_EVDEV=m 2224CONFIG_INPUT_EVDEV=m
2239CONFIG_INPUT_EVBUG=m 2225CONFIG_INPUT_EVBUG=m
2240CONFIG_XEN_KBDDEV_FRONTEND=m
2241 2226
2242# 2227#
2243# Input Device Drivers 2228# Input Device Drivers
@@ -2245,9 +2230,10 @@ CONFIG_XEN_KBDDEV_FRONTEND=m
2245CONFIG_INPUT_KEYBOARD=y 2230CONFIG_INPUT_KEYBOARD=y
2246# CONFIG_KEYBOARD_ADP5588 is not set 2231# CONFIG_KEYBOARD_ADP5588 is not set
2247CONFIG_KEYBOARD_ATKBD=y 2232CONFIG_KEYBOARD_ATKBD=y
2248CONFIG_QT2160=m 2233# CONFIG_KEYBOARD_QT2160 is not set
2249CONFIG_KEYBOARD_LKKBD=m 2234CONFIG_KEYBOARD_LKKBD=m
2250CONFIG_KEYBOARD_GPIO=m 2235CONFIG_KEYBOARD_GPIO=m
2236CONFIG_KEYBOARD_TCA6416=m
2251CONFIG_KEYBOARD_MATRIX=m 2237CONFIG_KEYBOARD_MATRIX=m
2252CONFIG_KEYBOARD_LM8323=m 2238CONFIG_KEYBOARD_LM8323=m
2253# CONFIG_KEYBOARD_MAX7359 is not set 2239# CONFIG_KEYBOARD_MAX7359 is not set
@@ -2269,10 +2255,6 @@ CONFIG_MOUSE_PS2_TRACKPOINT=y
2269CONFIG_MOUSE_SERIAL=m 2255CONFIG_MOUSE_SERIAL=m
2270CONFIG_MOUSE_APPLETOUCH=m 2256CONFIG_MOUSE_APPLETOUCH=m
2271CONFIG_MOUSE_BCM5974=m 2257CONFIG_MOUSE_BCM5974=m
2272CONFIG_MOUSE_INPORT=m
2273# CONFIG_MOUSE_ATIXL is not set
2274CONFIG_MOUSE_LOGIBM=m
2275CONFIG_MOUSE_PC110PAD=m
2276CONFIG_MOUSE_VSXXXAA=m 2258CONFIG_MOUSE_VSXXXAA=m
2277CONFIG_MOUSE_GPIO=m 2259CONFIG_MOUSE_GPIO=m
2278CONFIG_MOUSE_SYNAPTICS_I2C=m 2260CONFIG_MOUSE_SYNAPTICS_I2C=m
@@ -2284,6 +2266,7 @@ CONFIG_TOUCHSCREEN_AD7877=m
2284CONFIG_TOUCHSCREEN_AD7879_I2C=m 2266CONFIG_TOUCHSCREEN_AD7879_I2C=m
2285CONFIG_TOUCHSCREEN_AD7879=m 2267CONFIG_TOUCHSCREEN_AD7879=m
2286CONFIG_TOUCHSCREEN_DYNAPRO=m 2268CONFIG_TOUCHSCREEN_DYNAPRO=m
2269CONFIG_TOUCHSCREEN_HAMPSHIRE=m
2287CONFIG_TOUCHSCREEN_EETI=m 2270CONFIG_TOUCHSCREEN_EETI=m
2288CONFIG_TOUCHSCREEN_FUJITSU=m 2271CONFIG_TOUCHSCREEN_FUJITSU=m
2289CONFIG_TOUCHSCREEN_GUNZE=m 2272CONFIG_TOUCHSCREEN_GUNZE=m
@@ -2293,7 +2276,6 @@ CONFIG_TOUCHSCREEN_WACOM_W8001=m
2293CONFIG_TOUCHSCREEN_MTOUCH=m 2276CONFIG_TOUCHSCREEN_MTOUCH=m
2294CONFIG_TOUCHSCREEN_INEXIO=m 2277CONFIG_TOUCHSCREEN_INEXIO=m
2295CONFIG_TOUCHSCREEN_MK712=m 2278CONFIG_TOUCHSCREEN_MK712=m
2296CONFIG_TOUCHSCREEN_HTCPEN=m
2297CONFIG_TOUCHSCREEN_PENMOUNT=m 2279CONFIG_TOUCHSCREEN_PENMOUNT=m
2298CONFIG_TOUCHSCREEN_TOUCHRIGHT=m 2280CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
2299CONFIG_TOUCHSCREEN_TOUCHWIN=m 2281CONFIG_TOUCHSCREEN_TOUCHWIN=m
@@ -2321,10 +2303,13 @@ CONFIG_TOUCHSCREEN_USB_ETT_TC5UH=y
2321CONFIG_TOUCHSCREEN_USB_NEXIO=y 2303CONFIG_TOUCHSCREEN_USB_NEXIO=y
2322CONFIG_TOUCHSCREEN_TOUCHIT213=m 2304CONFIG_TOUCHSCREEN_TOUCHIT213=m
2323CONFIG_TOUCHSCREEN_TSC2007=m 2305CONFIG_TOUCHSCREEN_TSC2007=m
2306CONFIG_TOUCHSCREEN_TPS6507X=m
2324CONFIG_INPUT_MISC=y 2307CONFIG_INPUT_MISC=y
2308CONFIG_INPUT_AD714X=m
2309CONFIG_INPUT_AD714X_I2C=m
2310CONFIG_INPUT_AD714X_SPI=m
2325CONFIG_INPUT_PCSPKR=m 2311CONFIG_INPUT_PCSPKR=m
2326CONFIG_INPUT_APANEL=m 2312CONFIG_INPUT_APANEL=m
2327CONFIG_INPUT_WISTRON_BTNS=m
2328CONFIG_INPUT_ATLAS_BTNS=m 2313CONFIG_INPUT_ATLAS_BTNS=m
2329CONFIG_INPUT_ATI_REMOTE=m 2314CONFIG_INPUT_ATI_REMOTE=m
2330CONFIG_INPUT_ATI_REMOTE2=m 2315CONFIG_INPUT_ATI_REMOTE2=m
@@ -2335,6 +2320,7 @@ CONFIG_INPUT_CM109=m
2335CONFIG_INPUT_UINPUT=m 2320CONFIG_INPUT_UINPUT=m
2336CONFIG_INPUT_WINBOND_CIR=m 2321CONFIG_INPUT_WINBOND_CIR=m
2337CONFIG_INPUT_PCF50633_PMU=m 2322CONFIG_INPUT_PCF50633_PMU=m
2323CONFIG_INPUT_PCF8574=m
2338CONFIG_INPUT_GPIO_ROTARY_ENCODER=m 2324CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
2339 2325
2340# 2326#
@@ -2373,6 +2359,7 @@ CONFIG_SYNCLINK=m
2373CONFIG_SYNCLINKMP=m 2359CONFIG_SYNCLINKMP=m
2374CONFIG_SYNCLINK_GT=m 2360CONFIG_SYNCLINK_GT=m
2375CONFIG_N_HDLC=m 2361CONFIG_N_HDLC=m
2362# CONFIG_N_GSM is not set
2376CONFIG_RISCOM8=m 2363CONFIG_RISCOM8=m
2377CONFIG_SPECIALIX=m 2364CONFIG_SPECIALIX=m
2378CONFIG_STALDRV=y 2365CONFIG_STALDRV=y
@@ -2393,11 +2380,6 @@ CONFIG_SERIAL_8250_NR_UARTS=16
2393CONFIG_SERIAL_8250_RUNTIME_UARTS=4 2380CONFIG_SERIAL_8250_RUNTIME_UARTS=4
2394CONFIG_SERIAL_8250_EXTENDED=y 2381CONFIG_SERIAL_8250_EXTENDED=y
2395CONFIG_SERIAL_8250_MANY_PORTS=y 2382CONFIG_SERIAL_8250_MANY_PORTS=y
2396CONFIG_SERIAL_8250_FOURPORT=m
2397CONFIG_SERIAL_8250_ACCENT=m
2398CONFIG_SERIAL_8250_BOCA=m
2399CONFIG_SERIAL_8250_EXAR_ST16C554=m
2400CONFIG_SERIAL_8250_HUB6=m
2401CONFIG_SERIAL_8250_SHARE_IRQ=y 2383CONFIG_SERIAL_8250_SHARE_IRQ=y
2402# CONFIG_SERIAL_8250_DETECT_IRQ is not set 2384# CONFIG_SERIAL_8250_DETECT_IRQ is not set
2403CONFIG_SERIAL_8250_RSA=y 2385CONFIG_SERIAL_8250_RSA=y
@@ -2411,6 +2393,10 @@ CONFIG_SERIAL_CORE=y
2411CONFIG_SERIAL_CORE_CONSOLE=y 2393CONFIG_SERIAL_CORE_CONSOLE=y
2412CONFIG_SERIAL_JSM=m 2394CONFIG_SERIAL_JSM=m
2413CONFIG_SERIAL_TIMBERDALE=m 2395CONFIG_SERIAL_TIMBERDALE=m
2396CONFIG_SERIAL_ALTERA_JTAGUART=m
2397CONFIG_SERIAL_ALTERA_UART=m
2398CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4
2399CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200
2414CONFIG_UNIX98_PTYS=y 2400CONFIG_UNIX98_PTYS=y
2415# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set 2401# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
2416# CONFIG_LEGACY_PTYS is not set 2402# CONFIG_LEGACY_PTYS is not set
@@ -2418,9 +2404,7 @@ CONFIG_PRINTER=m
2418# CONFIG_LP_CONSOLE is not set 2404# CONFIG_LP_CONSOLE is not set
2419CONFIG_PPDEV=m 2405CONFIG_PPDEV=m
2420CONFIG_HVC_DRIVER=y 2406CONFIG_HVC_DRIVER=y
2421CONFIG_HVC_IRQ=y 2407CONFIG_VIRTIO_CONSOLE=m
2422CONFIG_HVC_XEN=y
2423CONFIG_VIRTIO_CONSOLE=y
2424CONFIG_IPMI_HANDLER=m 2408CONFIG_IPMI_HANDLER=m
2425# CONFIG_IPMI_PANIC_EVENT is not set 2409# CONFIG_IPMI_PANIC_EVENT is not set
2426CONFIG_IPMI_DEVICE_INTERFACE=m 2410CONFIG_IPMI_DEVICE_INTERFACE=m
@@ -2431,14 +2415,11 @@ CONFIG_HW_RANDOM=m
2431CONFIG_HW_RANDOM_TIMERIOMEM=m 2415CONFIG_HW_RANDOM_TIMERIOMEM=m
2432CONFIG_HW_RANDOM_INTEL=m 2416CONFIG_HW_RANDOM_INTEL=m
2433CONFIG_HW_RANDOM_AMD=m 2417CONFIG_HW_RANDOM_AMD=m
2434CONFIG_HW_RANDOM_GEODE=m
2435CONFIG_HW_RANDOM_VIA=m 2418CONFIG_HW_RANDOM_VIA=m
2436CONFIG_HW_RANDOM_VIRTIO=m 2419CONFIG_HW_RANDOM_VIRTIO=m
2437CONFIG_NVRAM=m 2420CONFIG_NVRAM=m
2438CONFIG_DTLK=m
2439CONFIG_R3964=m 2421CONFIG_R3964=m
2440CONFIG_APPLICOM=m 2422CONFIG_APPLICOM=m
2441CONFIG_SONYPI=m
2442 2423
2443# 2424#
2444# PCMCIA character devices 2425# PCMCIA character devices
@@ -2448,10 +2429,8 @@ CONFIG_CARDMAN_4000=m
2448CONFIG_CARDMAN_4040=m 2429CONFIG_CARDMAN_4040=m
2449CONFIG_IPWIRELESS=m 2430CONFIG_IPWIRELESS=m
2450CONFIG_MWAVE=m 2431CONFIG_MWAVE=m
2451CONFIG_SCx200_GPIO=m
2452CONFIG_PC8736x_GPIO=m 2432CONFIG_PC8736x_GPIO=m
2453CONFIG_NSC_GPIO=m 2433CONFIG_NSC_GPIO=m
2454CONFIG_CS5535_GPIO=m
2455CONFIG_RAW_DRIVER=m 2434CONFIG_RAW_DRIVER=m
2456CONFIG_MAX_RAW_DEVS=256 2435CONFIG_MAX_RAW_DEVS=256
2457CONFIG_HPET=y 2436CONFIG_HPET=y
@@ -2464,6 +2443,7 @@ CONFIG_TCG_ATMEL=m
2464CONFIG_TCG_INFINEON=m 2443CONFIG_TCG_INFINEON=m
2465CONFIG_TELCLOCK=m 2444CONFIG_TELCLOCK=m
2466CONFIG_DEVPORT=y 2445CONFIG_DEVPORT=y
2446CONFIG_RAMOOPS=m
2467CONFIG_I2C=m 2447CONFIG_I2C=m
2468CONFIG_I2C_BOARDINFO=y 2448CONFIG_I2C_BOARDINFO=y
2469CONFIG_I2C_COMPAT=y 2449CONFIG_I2C_COMPAT=y
@@ -2507,6 +2487,7 @@ CONFIG_I2C_SCMI=m
2507# 2487#
2508CONFIG_I2C_GPIO=m 2488CONFIG_I2C_GPIO=m
2509CONFIG_I2C_OCORES=m 2489CONFIG_I2C_OCORES=m
2490CONFIG_I2C_PCA_PLATFORM=m
2510CONFIG_I2C_SIMTEC=m 2491CONFIG_I2C_SIMTEC=m
2511CONFIG_I2C_XILINX=m 2492CONFIG_I2C_XILINX=m
2512 2493
@@ -2521,13 +2502,7 @@ CONFIG_I2C_TINY_USB=m
2521# 2502#
2522# Other I2C/SMBus bus drivers 2503# Other I2C/SMBus bus drivers
2523# 2504#
2524CONFIG_I2C_PCA_ISA=m
2525CONFIG_I2C_PCA_PLATFORM=m
2526CONFIG_I2C_STUB=m 2505CONFIG_I2C_STUB=m
2527CONFIG_SCx200_I2C=m
2528CONFIG_SCx200_I2C_SCL=12
2529CONFIG_SCx200_I2C_SDA=13
2530CONFIG_SCx200_ACB=m
2531# CONFIG_I2C_DEBUG_CORE is not set 2506# CONFIG_I2C_DEBUG_CORE is not set
2532# CONFIG_I2C_DEBUG_ALGO is not set 2507# CONFIG_I2C_DEBUG_ALGO is not set
2533# CONFIG_I2C_DEBUG_BUS is not set 2508# CONFIG_I2C_DEBUG_BUS is not set
@@ -2541,8 +2516,7 @@ CONFIG_SPI_BITBANG=m
2541CONFIG_SPI_BUTTERFLY=m 2516CONFIG_SPI_BUTTERFLY=m
2542CONFIG_SPI_GPIO=m 2517CONFIG_SPI_GPIO=m
2543CONFIG_SPI_LM70_LLP=m 2518CONFIG_SPI_LM70_LLP=m
2544CONFIG_SPI_XILINX=m 2519# CONFIG_SPI_XILINX is not set
2545CONFIG_SPI_XILINX_PLTFM=m
2546CONFIG_SPI_DESIGNWARE=m 2520CONFIG_SPI_DESIGNWARE=m
2547CONFIG_SPI_DW_PCI=m 2521CONFIG_SPI_DW_PCI=m
2548 2522
@@ -2574,7 +2548,6 @@ CONFIG_GPIO_MAX7300=m
2574CONFIG_GPIO_MAX732X=m 2548CONFIG_GPIO_MAX732X=m
2575CONFIG_GPIO_PCA953X=m 2549CONFIG_GPIO_PCA953X=m
2576CONFIG_GPIO_PCF857X=m 2550CONFIG_GPIO_PCF857X=m
2577CONFIG_GPIO_WM8994=m
2578CONFIG_GPIO_ADP5588=m 2551CONFIG_GPIO_ADP5588=m
2579 2552
2580# 2553#
@@ -2582,7 +2555,8 @@ CONFIG_GPIO_ADP5588=m
2582# 2555#
2583CONFIG_GPIO_CS5535=m 2556CONFIG_GPIO_CS5535=m
2584# CONFIG_GPIO_LANGWELL is not set 2557# CONFIG_GPIO_LANGWELL is not set
2585# CONFIG_GPIO_TIMBERDALE is not set 2558CONFIG_GPIO_TIMBERDALE=y
2559CONFIG_GPIO_RDC321X=m
2586 2560
2587# 2561#
2588# SPI GPIO expanders: 2562# SPI GPIO expanders:
@@ -2595,6 +2569,11 @@ CONFIG_GPIO_MCP23S08=m
2595# AC97 GPIO expanders: 2569# AC97 GPIO expanders:
2596# 2570#
2597# CONFIG_GPIO_UCB1400 is not set 2571# CONFIG_GPIO_UCB1400 is not set
2572
2573#
2574# MODULbus GPIO expanders:
2575#
2576CONFIG_GPIO_JANZ_TTL=m
2598CONFIG_W1=m 2577CONFIG_W1=m
2599CONFIG_W1_CON=y 2578CONFIG_W1_CON=y
2600 2579
@@ -2619,6 +2598,7 @@ CONFIG_W1_SLAVE_BQ27000=m
2619CONFIG_POWER_SUPPLY=y 2598CONFIG_POWER_SUPPLY=y
2620# CONFIG_POWER_SUPPLY_DEBUG is not set 2599# CONFIG_POWER_SUPPLY_DEBUG is not set
2621CONFIG_PDA_POWER=m 2600CONFIG_PDA_POWER=m
2601CONFIG_TEST_POWER=m
2622CONFIG_BATTERY_DS2760=m 2602CONFIG_BATTERY_DS2760=m
2623CONFIG_BATTERY_DS2782=m 2603CONFIG_BATTERY_DS2782=m
2624CONFIG_BATTERY_BQ27x00=m 2604CONFIG_BATTERY_BQ27x00=m
@@ -2689,12 +2669,15 @@ CONFIG_SENSORS_PCF8591=m
2689CONFIG_SENSORS_SHT15=m 2669CONFIG_SENSORS_SHT15=m
2690CONFIG_SENSORS_SIS5595=m 2670CONFIG_SENSORS_SIS5595=m
2691CONFIG_SENSORS_DME1737=m 2671CONFIG_SENSORS_DME1737=m
2672CONFIG_SENSORS_EMC1403=m
2692CONFIG_SENSORS_SMSC47M1=m 2673CONFIG_SENSORS_SMSC47M1=m
2693CONFIG_SENSORS_SMSC47M192=m 2674CONFIG_SENSORS_SMSC47M192=m
2694CONFIG_SENSORS_SMSC47B397=m 2675CONFIG_SENSORS_SMSC47B397=m
2695CONFIG_SENSORS_ADS7828=m 2676CONFIG_SENSORS_ADS7828=m
2677CONFIG_SENSORS_ADS7871=m
2696CONFIG_SENSORS_AMC6821=m 2678CONFIG_SENSORS_AMC6821=m
2697CONFIG_SENSORS_THMC50=m 2679CONFIG_SENSORS_THMC50=m
2680CONFIG_SENSORS_TMP102=m
2698CONFIG_SENSORS_TMP401=m 2681CONFIG_SENSORS_TMP401=m
2699CONFIG_SENSORS_TMP421=m 2682CONFIG_SENSORS_TMP421=m
2700CONFIG_SENSORS_VIA_CPUTEMP=m 2683CONFIG_SENSORS_VIA_CPUTEMP=m
@@ -2744,11 +2727,9 @@ CONFIG_IT8712F_WDT=m
2744CONFIG_IT87_WDT=m 2727CONFIG_IT87_WDT=m
2745# CONFIG_HP_WATCHDOG is not set 2728# CONFIG_HP_WATCHDOG is not set
2746CONFIG_SC1200_WDT=m 2729CONFIG_SC1200_WDT=m
2747CONFIG_SCx200_WDT=m
2748CONFIG_PC87413_WDT=m 2730CONFIG_PC87413_WDT=m
2749CONFIG_60XX_WDT=m 2731CONFIG_60XX_WDT=m
2750CONFIG_SBC8360_WDT=m 2732CONFIG_SBC8360_WDT=m
2751CONFIG_SBC7240_WDT=m
2752CONFIG_CPU5_WDT=m 2733CONFIG_CPU5_WDT=m
2753CONFIG_SMSC_SCH311X_WDT=m 2734CONFIG_SMSC_SCH311X_WDT=m
2754CONFIG_SMSC37B787_WDT=m 2735CONFIG_SMSC37B787_WDT=m
@@ -2761,13 +2742,6 @@ CONFIG_MACHZ_WDT=m
2761CONFIG_SBC_EPX_C3_WATCHDOG=m 2742CONFIG_SBC_EPX_C3_WATCHDOG=m
2762 2743
2763# 2744#
2764# ISA-based Watchdog Cards
2765#
2766CONFIG_PCWATCHDOG=m
2767CONFIG_MIXCOMWD=m
2768CONFIG_WDT=m
2769
2770#
2771# PCI-based Watchdog Cards 2745# PCI-based Watchdog Cards
2772# 2746#
2773CONFIG_PCIPCWATCHDOG=m 2747CONFIG_PCIPCWATCHDOG=m
@@ -2796,27 +2770,27 @@ CONFIG_SSB_SDIOHOST=y
2796# CONFIG_SSB_DEBUG is not set 2770# CONFIG_SSB_DEBUG is not set
2797CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y 2771CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
2798CONFIG_SSB_DRIVER_PCICORE=y 2772CONFIG_SSB_DRIVER_PCICORE=y
2799 2773CONFIG_MFD_SUPPORT=y
2800# 2774CONFIG_MFD_CORE=y
2801# Multifunction device drivers
2802#
2803CONFIG_MFD_CORE=m
2804CONFIG_MFD_SM501=m 2775CONFIG_MFD_SM501=m
2805# CONFIG_MFD_SM501_GPIO is not set 2776# CONFIG_MFD_SM501_GPIO is not set
2806CONFIG_HTC_PASIC3=m 2777CONFIG_HTC_PASIC3=m
2807CONFIG_UCB1400_CORE=m 2778CONFIG_UCB1400_CORE=m
2808CONFIG_TPS65010=m 2779CONFIG_TPS65010=m
2780CONFIG_TPS6507X=m
2809# CONFIG_MFD_TMIO is not set 2781# CONFIG_MFD_TMIO is not set
2810CONFIG_MFD_WM8400=m 2782CONFIG_MFD_WM8400=m
2811CONFIG_MFD_WM8994=m
2812CONFIG_MFD_PCF50633=m 2783CONFIG_MFD_PCF50633=m
2813# CONFIG_MFD_MC13783 is not set 2784# CONFIG_MFD_MC13783 is not set
2814CONFIG_PCF50633_ADC=m 2785CONFIG_PCF50633_ADC=m
2815CONFIG_PCF50633_GPIO=m 2786CONFIG_PCF50633_GPIO=m
2787CONFIG_ABX500_CORE=y
2816# CONFIG_EZX_PCAP is not set 2788# CONFIG_EZX_PCAP is not set
2817CONFIG_AB4500_CORE=m 2789CONFIG_AB8500_CORE=y
2818CONFIG_MFD_TIMBERDALE=m 2790CONFIG_MFD_TIMBERDALE=m
2819CONFIG_LPC_SCH=m 2791CONFIG_LPC_SCH=m
2792CONFIG_MFD_RDC321X=m
2793CONFIG_MFD_JANZ_CMODIO=m
2820CONFIG_REGULATOR=y 2794CONFIG_REGULATOR=y
2821# CONFIG_REGULATOR_DEBUG is not set 2795# CONFIG_REGULATOR_DEBUG is not set
2822# CONFIG_REGULATOR_DUMMY is not set 2796# CONFIG_REGULATOR_DUMMY is not set
@@ -2828,7 +2802,6 @@ CONFIG_REGULATOR_MAX1586=m
2828CONFIG_REGULATOR_MAX8649=m 2802CONFIG_REGULATOR_MAX8649=m
2829CONFIG_REGULATOR_MAX8660=m 2803CONFIG_REGULATOR_MAX8660=m
2830CONFIG_REGULATOR_WM8400=m 2804CONFIG_REGULATOR_WM8400=m
2831CONFIG_REGULATOR_WM8994=m
2832CONFIG_REGULATOR_PCF50633=m 2805CONFIG_REGULATOR_PCF50633=m
2833CONFIG_REGULATOR_LP3971=m 2806CONFIG_REGULATOR_LP3971=m
2834# CONFIG_REGULATOR_TPS65023 is not set 2807# CONFIG_REGULATOR_TPS65023 is not set
@@ -2852,6 +2825,13 @@ CONFIG_VIDEO_SAA7146=m
2852CONFIG_VIDEO_SAA7146_VV=m 2825CONFIG_VIDEO_SAA7146_VV=m
2853CONFIG_IR_CORE=m 2826CONFIG_IR_CORE=m
2854CONFIG_VIDEO_IR=m 2827CONFIG_VIDEO_IR=m
2828CONFIG_RC_MAP=m
2829CONFIG_IR_NEC_DECODER=m
2830CONFIG_IR_RC5_DECODER=m
2831CONFIG_IR_RC6_DECODER=m
2832CONFIG_IR_JVC_DECODER=m
2833CONFIG_IR_SONY_DECODER=m
2834CONFIG_IR_IMON=m
2855# CONFIG_MEDIA_ATTACH is not set 2835# CONFIG_MEDIA_ATTACH is not set
2856CONFIG_MEDIA_TUNER=m 2836CONFIG_MEDIA_TUNER=m
2857# CONFIG_MEDIA_TUNER_CUSTOMISE is not set 2837# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -2881,6 +2861,7 @@ CONFIG_VIDEOBUF_DVB=m
2881CONFIG_VIDEO_BTCX=m 2861CONFIG_VIDEO_BTCX=m
2882CONFIG_VIDEO_TVEEPROM=m 2862CONFIG_VIDEO_TVEEPROM=m
2883CONFIG_VIDEO_TUNER=m 2863CONFIG_VIDEO_TUNER=m
2864CONFIG_V4L2_MEM2MEM_DEV=m
2884CONFIG_VIDEO_CAPTURE_DRIVERS=y 2865CONFIG_VIDEO_CAPTURE_DRIVERS=y
2885# CONFIG_VIDEO_ADV_DEBUG is not set 2866# CONFIG_VIDEO_ADV_DEBUG is not set
2886# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set 2867# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
@@ -2953,16 +2934,17 @@ CONFIG_VIDEO_ADV7170=m
2953CONFIG_VIDEO_ADV7175=m 2934CONFIG_VIDEO_ADV7175=m
2954CONFIG_VIDEO_THS7303=m 2935CONFIG_VIDEO_THS7303=m
2955CONFIG_VIDEO_ADV7343=m 2936CONFIG_VIDEO_ADV7343=m
2937CONFIG_VIDEO_AK881X=m
2956 2938
2957# 2939#
2958# Video improvement chips 2940# Video improvement chips
2959# 2941#
2960CONFIG_VIDEO_UPD64031A=m 2942CONFIG_VIDEO_UPD64031A=m
2961CONFIG_VIDEO_UPD64083=m 2943CONFIG_VIDEO_UPD64083=m
2962CONFIG_VIDEO_VIVI=m
2963CONFIG_VIDEO_BT848=m 2944CONFIG_VIDEO_BT848=m
2964CONFIG_VIDEO_BT848_DVB=y 2945CONFIG_VIDEO_BT848_DVB=y
2965CONFIG_VIDEO_PMS=m 2946CONFIG_VIDEO_BWQCAM=m
2947CONFIG_VIDEO_CQCAM=m
2966CONFIG_VIDEO_SAA5246A=m 2948CONFIG_VIDEO_SAA5246A=m
2967CONFIG_VIDEO_SAA5249=m 2949CONFIG_VIDEO_SAA5249=m
2968CONFIG_VIDEO_ZORAN=m 2950CONFIG_VIDEO_ZORAN=m
@@ -2973,6 +2955,7 @@ CONFIG_VIDEO_ZORAN_DC10=m
2973CONFIG_VIDEO_ZORAN_LML33=m 2955CONFIG_VIDEO_ZORAN_LML33=m
2974CONFIG_VIDEO_ZORAN_LML33R10=m 2956CONFIG_VIDEO_ZORAN_LML33R10=m
2975CONFIG_VIDEO_ZORAN_AVS6EYES=m 2957CONFIG_VIDEO_ZORAN_AVS6EYES=m
2958CONFIG_VIDEO_MEYE=m
2976CONFIG_VIDEO_SAA7134=m 2959CONFIG_VIDEO_SAA7134=m
2977CONFIG_VIDEO_SAA7134_ALSA=m 2960CONFIG_VIDEO_SAA7134_ALSA=m
2978CONFIG_VIDEO_SAA7134_DVB=m 2961CONFIG_VIDEO_SAA7134_DVB=m
@@ -3027,7 +3010,6 @@ CONFIG_USB_GSPCA_PAC7302=m
3027CONFIG_USB_GSPCA_PAC7311=m 3010CONFIG_USB_GSPCA_PAC7311=m
3028CONFIG_USB_GSPCA_SN9C2028=m 3011CONFIG_USB_GSPCA_SN9C2028=m
3029CONFIG_USB_GSPCA_SN9C20X=m 3012CONFIG_USB_GSPCA_SN9C20X=m
3030CONFIG_USB_GSPCA_SN9C20X_EVDEV=y
3031CONFIG_USB_GSPCA_SONIXB=m 3013CONFIG_USB_GSPCA_SONIXB=m
3032CONFIG_USB_GSPCA_SONIXJ=m 3014CONFIG_USB_GSPCA_SONIXJ=m
3033CONFIG_USB_GSPCA_SPCA500=m 3015CONFIG_USB_GSPCA_SPCA500=m
@@ -3061,26 +3043,15 @@ CONFIG_VIDEO_USBVISION=m
3061CONFIG_USB_ET61X251=m 3043CONFIG_USB_ET61X251=m
3062CONFIG_USB_SN9C102=m 3044CONFIG_USB_SN9C102=m
3063CONFIG_USB_ZC0301=m 3045CONFIG_USB_ZC0301=m
3064CONFIG_USB_PWC_INPUT_EVDEV=y
3065CONFIG_USB_ZR364XX=m 3046CONFIG_USB_ZR364XX=m
3066CONFIG_USB_STKWEBCAM=m 3047CONFIG_USB_STKWEBCAM=m
3067CONFIG_USB_S2255=m 3048CONFIG_USB_S2255=m
3049CONFIG_V4L_MEM2MEM_DRIVERS=y
3050CONFIG_VIDEO_MEM2MEM_TESTDEV=m
3068CONFIG_RADIO_ADAPTERS=y 3051CONFIG_RADIO_ADAPTERS=y
3069CONFIG_RADIO_CADET=m
3070CONFIG_RADIO_RTRACK=m
3071CONFIG_RADIO_RTRACK2=m
3072CONFIG_RADIO_AZTECH=m
3073CONFIG_RADIO_GEMTEK=m
3074CONFIG_RADIO_GEMTEK_PCI=m 3052CONFIG_RADIO_GEMTEK_PCI=m
3075CONFIG_RADIO_MAXIRADIO=m 3053CONFIG_RADIO_MAXIRADIO=m
3076CONFIG_RADIO_MAESTRO=m 3054CONFIG_RADIO_MAESTRO=m
3077CONFIG_RADIO_MIROPCM20=m
3078CONFIG_RADIO_SF16FMI=m
3079CONFIG_RADIO_SF16FMR2=m
3080CONFIG_RADIO_TERRATEC=m
3081CONFIG_RADIO_TRUST=m
3082CONFIG_RADIO_TYPHOON=m
3083CONFIG_RADIO_ZOLTRIX=m
3084# CONFIG_I2C_SI4713 is not set 3055# CONFIG_I2C_SI4713 is not set
3085# CONFIG_RADIO_SI4713 is not set 3056# CONFIG_RADIO_SI4713 is not set
3086CONFIG_USB_DSBR=m 3057CONFIG_USB_DSBR=m
@@ -3261,9 +3232,11 @@ CONFIG_DVB_S5H1411=m
3261CONFIG_DVB_DIB8000=m 3232CONFIG_DVB_DIB8000=m
3262CONFIG_DVB_PLL=m 3233CONFIG_DVB_PLL=m
3263CONFIG_DVB_TUNER_DIB0070=m 3234CONFIG_DVB_TUNER_DIB0070=m
3235CONFIG_DVB_TUNER_DIB0090=m
3264CONFIG_DVB_LNBP21=m 3236CONFIG_DVB_LNBP21=m
3265CONFIG_DVB_ISL6405=m 3237CONFIG_DVB_ISL6405=m
3266CONFIG_DVB_ISL6421=m 3238CONFIG_DVB_ISL6421=m
3239CONFIG_DVB_ISL6423=m
3267CONFIG_DVB_LGS8GXX=m 3240CONFIG_DVB_LGS8GXX=m
3268CONFIG_DVB_ATBM8830=m 3241CONFIG_DVB_ATBM8830=m
3269CONFIG_DAB=y 3242CONFIG_DAB=y
@@ -3273,18 +3246,12 @@ CONFIG_USB_DABUSB=m
3273# Graphics support 3246# Graphics support
3274# 3247#
3275CONFIG_AGP=m 3248CONFIG_AGP=m
3276CONFIG_AGP_ALI=m
3277CONFIG_AGP_ATI=m
3278CONFIG_AGP_AMD=m
3279CONFIG_AGP_AMD64=m 3249CONFIG_AGP_AMD64=m
3280CONFIG_AGP_INTEL=m 3250CONFIG_AGP_INTEL=m
3281CONFIG_AGP_NVIDIA=m
3282CONFIG_AGP_SIS=m 3251CONFIG_AGP_SIS=m
3283CONFIG_AGP_SWORKS=m
3284CONFIG_AGP_VIA=m 3252CONFIG_AGP_VIA=m
3285CONFIG_AGP_EFFICEON=m
3286# CONFIG_VGA_ARB is not set 3253# CONFIG_VGA_ARB is not set
3287# CONFIG_VGA_SWITCHEROO is not set 3254CONFIG_VGA_SWITCHEROO=y
3288CONFIG_DRM=m 3255CONFIG_DRM=m
3289CONFIG_DRM_KMS_HELPER=m 3256CONFIG_DRM_KMS_HELPER=m
3290CONFIG_DRM_TTM=m 3257CONFIG_DRM_TTM=m
@@ -3345,9 +3312,6 @@ CONFIG_FB_RIVA=m
3345CONFIG_FB_RIVA_I2C=y 3312CONFIG_FB_RIVA_I2C=y
3346# CONFIG_FB_RIVA_DEBUG is not set 3313# CONFIG_FB_RIVA_DEBUG is not set
3347CONFIG_FB_RIVA_BACKLIGHT=y 3314CONFIG_FB_RIVA_BACKLIGHT=y
3348CONFIG_FB_I810=m
3349CONFIG_FB_I810_GTF=y
3350CONFIG_FB_I810_I2C=y
3351CONFIG_FB_LE80578=m 3315CONFIG_FB_LE80578=m
3352CONFIG_FB_CARILLO_RANCH=m 3316CONFIG_FB_CARILLO_RANCH=m
3353CONFIG_FB_INTEL=m 3317CONFIG_FB_INTEL=m
@@ -3378,6 +3342,7 @@ CONFIG_FB_SIS=m
3378CONFIG_FB_SIS_300=y 3342CONFIG_FB_SIS_300=y
3379CONFIG_FB_SIS_315=y 3343CONFIG_FB_SIS_315=y
3380CONFIG_FB_VIA=m 3344CONFIG_FB_VIA=m
3345# CONFIG_FB_VIA_DIRECT_PROCFS is not set
3381CONFIG_FB_NEOMAGIC=m 3346CONFIG_FB_NEOMAGIC=m
3382CONFIG_FB_KYRO=m 3347CONFIG_FB_KYRO=m
3383CONFIG_FB_3DFX=m 3348CONFIG_FB_3DFX=m
@@ -3399,7 +3364,6 @@ CONFIG_FB_TMIO=m
3399CONFIG_FB_TMIO_ACCELL=y 3364CONFIG_FB_TMIO_ACCELL=y
3400CONFIG_FB_SM501=m 3365CONFIG_FB_SM501=m
3401# CONFIG_FB_VIRTUAL is not set 3366# CONFIG_FB_VIRTUAL is not set
3402CONFIG_XEN_FBDEV_FRONTEND=m
3403CONFIG_FB_METRONOME=m 3367CONFIG_FB_METRONOME=m
3404CONFIG_FB_MB862XX=m 3368CONFIG_FB_MB862XX=m
3405# CONFIG_FB_MB862XX_PCI_GDC is not set 3369# CONFIG_FB_MB862XX_PCI_GDC is not set
@@ -3413,12 +3377,15 @@ CONFIG_LCD_ILI9320=m
3413CONFIG_LCD_TDO24M=m 3377CONFIG_LCD_TDO24M=m
3414CONFIG_LCD_VGG2432A4=m 3378CONFIG_LCD_VGG2432A4=m
3415CONFIG_LCD_PLATFORM=m 3379CONFIG_LCD_PLATFORM=m
3380CONFIG_LCD_S6E63M0=m
3416CONFIG_BACKLIGHT_CLASS_DEVICE=m 3381CONFIG_BACKLIGHT_CLASS_DEVICE=m
3417CONFIG_BACKLIGHT_GENERIC=m 3382CONFIG_BACKLIGHT_GENERIC=m
3418CONFIG_BACKLIGHT_PROGEAR=m 3383CONFIG_BACKLIGHT_PROGEAR=m
3419CONFIG_BACKLIGHT_CARILLO_RANCH=m 3384CONFIG_BACKLIGHT_CARILLO_RANCH=m
3420CONFIG_BACKLIGHT_MBP_NVIDIA=m 3385CONFIG_BACKLIGHT_MBP_NVIDIA=m
3421CONFIG_BACKLIGHT_SAHARA=m 3386CONFIG_BACKLIGHT_SAHARA=m
3387CONFIG_BACKLIGHT_ADP8860=m
3388CONFIG_BACKLIGHT_PCF50633=m
3422 3389
3423# 3390#
3424# Display device support 3391# Display device support
@@ -3434,7 +3401,6 @@ CONFIG_DISPLAY_SUPPORT=m
3434# 3401#
3435CONFIG_VGA_CONSOLE=y 3402CONFIG_VGA_CONSOLE=y
3436# CONFIG_VGACON_SOFT_SCROLLBACK is not set 3403# CONFIG_VGACON_SOFT_SCROLLBACK is not set
3437CONFIG_MDA_CONSOLE=m
3438CONFIG_DUMMY_CONSOLE=y 3404CONFIG_DUMMY_CONSOLE=y
3439CONFIG_FRAMEBUFFER_CONSOLE=m 3405CONFIG_FRAMEBUFFER_CONSOLE=m
3440CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y 3406CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
@@ -3470,12 +3436,11 @@ CONFIG_SND_VMASTER=y
3470CONFIG_SND_DMA_SGBUF=y 3436CONFIG_SND_DMA_SGBUF=y
3471CONFIG_SND_RAWMIDI_SEQ=m 3437CONFIG_SND_RAWMIDI_SEQ=m
3472CONFIG_SND_OPL3_LIB_SEQ=m 3438CONFIG_SND_OPL3_LIB_SEQ=m
3473CONFIG_SND_OPL4_LIB_SEQ=m 3439# CONFIG_SND_OPL4_LIB_SEQ is not set
3474CONFIG_SND_SBAWE_SEQ=m 3440# CONFIG_SND_SBAWE_SEQ is not set
3475CONFIG_SND_EMU10K1_SEQ=m 3441CONFIG_SND_EMU10K1_SEQ=m
3476CONFIG_SND_MPU401_UART=m 3442CONFIG_SND_MPU401_UART=m
3477CONFIG_SND_OPL3_LIB=m 3443CONFIG_SND_OPL3_LIB=m
3478CONFIG_SND_OPL4_LIB=m
3479CONFIG_SND_VX_LIB=m 3444CONFIG_SND_VX_LIB=m
3480CONFIG_SND_AC97_CODEC=m 3445CONFIG_SND_AC97_CODEC=m
3481CONFIG_SND_DRIVERS=y 3446CONFIG_SND_DRIVERS=y
@@ -3489,48 +3454,14 @@ CONFIG_SND_MPU401=m
3489CONFIG_SND_PORTMAN2X4=m 3454CONFIG_SND_PORTMAN2X4=m
3490CONFIG_SND_AC97_POWER_SAVE=y 3455CONFIG_SND_AC97_POWER_SAVE=y
3491CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 3456CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
3492CONFIG_SND_WSS_LIB=m
3493CONFIG_SND_SB_COMMON=m 3457CONFIG_SND_SB_COMMON=m
3494CONFIG_SND_SB8_DSP=m
3495CONFIG_SND_SB16_DSP=m 3458CONFIG_SND_SB16_DSP=m
3496CONFIG_SND_ISA=y
3497CONFIG_SND_ADLIB=m
3498CONFIG_SND_AD1816A=m
3499CONFIG_SND_AD1848=m
3500CONFIG_SND_ALS100=m
3501CONFIG_SND_AZT2320=m
3502CONFIG_SND_CMI8330=m
3503CONFIG_SND_CS4231=m
3504CONFIG_SND_CS4236=m
3505CONFIG_SND_ES968=m
3506CONFIG_SND_ES1688=m
3507CONFIG_SND_ES18XX=m
3508CONFIG_SND_SC6000=m
3509CONFIG_SND_GUSCLASSIC=m
3510CONFIG_SND_GUSEXTREME=m
3511CONFIG_SND_GUSMAX=m
3512CONFIG_SND_INTERWAVE=m
3513CONFIG_SND_INTERWAVE_STB=m
3514CONFIG_SND_JAZZ16=m
3515CONFIG_SND_OPL3SA2=m
3516CONFIG_SND_OPTI92X_AD1848=m
3517CONFIG_SND_OPTI92X_CS4231=m
3518CONFIG_SND_OPTI93X=m
3519CONFIG_SND_MIRO=m
3520CONFIG_SND_SB8=m
3521CONFIG_SND_SB16=m
3522CONFIG_SND_SBAWE=m
3523CONFIG_SND_SB16_CSP=y
3524CONFIG_SND_SGALAXY=m
3525CONFIG_SND_SSCAPE=m
3526CONFIG_SND_WAVEFRONT=m
3527CONFIG_SND_MSND_PINNACLE=m
3528CONFIG_SND_MSND_CLASSIC=m
3529CONFIG_SND_PCI=y 3459CONFIG_SND_PCI=y
3530CONFIG_SND_AD1889=m 3460CONFIG_SND_AD1889=m
3531CONFIG_SND_ALS300=m 3461CONFIG_SND_ALS300=m
3532CONFIG_SND_ALS4000=m 3462CONFIG_SND_ALS4000=m
3533CONFIG_SND_ALI5451=m 3463CONFIG_SND_ALI5451=m
3464CONFIG_SND_ASIHPI=m
3534CONFIG_SND_ATIIXP=m 3465CONFIG_SND_ATIIXP=m
3535CONFIG_SND_ATIIXP_MODEM=m 3466CONFIG_SND_ATIIXP_MODEM=m
3536CONFIG_SND_AU8810=m 3467CONFIG_SND_AU8810=m
@@ -3570,13 +3501,14 @@ CONFIG_SND_ENS1370=m
3570CONFIG_SND_ENS1371=m 3501CONFIG_SND_ENS1371=m
3571CONFIG_SND_ES1938=m 3502CONFIG_SND_ES1938=m
3572CONFIG_SND_ES1968=m 3503CONFIG_SND_ES1968=m
3504CONFIG_SND_ES1968_INPUT=y
3573CONFIG_SND_FM801=m 3505CONFIG_SND_FM801=m
3574# CONFIG_SND_FM801_TEA575X_BOOL is not set 3506# CONFIG_SND_FM801_TEA575X_BOOL is not set
3575CONFIG_SND_HDA_INTEL=m 3507CONFIG_SND_HDA_INTEL=m
3576CONFIG_SND_HDA_HWDEP=y 3508CONFIG_SND_HDA_HWDEP=y
3577# CONFIG_SND_HDA_RECONFIG is not set 3509# CONFIG_SND_HDA_RECONFIG is not set
3578CONFIG_SND_HDA_INPUT_BEEP=y 3510CONFIG_SND_HDA_INPUT_BEEP=y
3579CONFIG_SND_HDA_INPUT_BEEP_MODE=1 3511CONFIG_SND_HDA_INPUT_BEEP_MODE=0
3580CONFIG_SND_HDA_INPUT_JACK=y 3512CONFIG_SND_HDA_INPUT_JACK=y
3581# CONFIG_SND_HDA_PATCH_LOADER is not set 3513# CONFIG_SND_HDA_PATCH_LOADER is not set
3582CONFIG_SND_HDA_CODEC_REALTEK=y 3514CONFIG_SND_HDA_CODEC_REALTEK=y
@@ -3604,6 +3536,7 @@ CONFIG_SND_INTEL8X0M=m
3604CONFIG_SND_KORG1212=m 3536CONFIG_SND_KORG1212=m
3605CONFIG_SND_LX6464ES=m 3537CONFIG_SND_LX6464ES=m
3606CONFIG_SND_MAESTRO3=m 3538CONFIG_SND_MAESTRO3=m
3539CONFIG_SND_MAESTRO3_INPUT=y
3607CONFIG_SND_MIXART=m 3540CONFIG_SND_MIXART=m
3608CONFIG_SND_NM256=m 3541CONFIG_SND_NM256=m
3609CONFIG_SND_PCXHR=m 3542CONFIG_SND_PCXHR=m
@@ -3611,7 +3544,6 @@ CONFIG_SND_RIPTIDE=m
3611CONFIG_SND_RME32=m 3544CONFIG_SND_RME32=m
3612CONFIG_SND_RME96=m 3545CONFIG_SND_RME96=m
3613CONFIG_SND_RME9652=m 3546CONFIG_SND_RME9652=m
3614CONFIG_SND_SIS7019=m
3615CONFIG_SND_SONICVIBES=m 3547CONFIG_SND_SONICVIBES=m
3616CONFIG_SND_TRIDENT=m 3548CONFIG_SND_TRIDENT=m
3617CONFIG_SND_VIA82XX=m 3549CONFIG_SND_VIA82XX=m
@@ -3635,7 +3567,7 @@ CONFIG_SND_SOC_I2C_AND_SPI=m
3635CONFIG_SND_SOC_ALL_CODECS=m 3567CONFIG_SND_SOC_ALL_CODECS=m
3636CONFIG_SND_SOC_WM_HUBS=m 3568CONFIG_SND_SOC_WM_HUBS=m
3637CONFIG_SND_SOC_AD1836=m 3569CONFIG_SND_SOC_AD1836=m
3638CONFIG_SND_SOC_AD1938=m 3570CONFIG_SND_SOC_AD193X=m
3639CONFIG_SND_SOC_AD73311=m 3571CONFIG_SND_SOC_AD73311=m
3640CONFIG_SND_SOC_ADS117X=m 3572CONFIG_SND_SOC_ADS117X=m
3641CONFIG_SND_SOC_AK4104=m 3573CONFIG_SND_SOC_AK4104=m
@@ -3678,11 +3610,11 @@ CONFIG_SND_SOC_WM8978=m
3678CONFIG_SND_SOC_WM8988=m 3610CONFIG_SND_SOC_WM8988=m
3679CONFIG_SND_SOC_WM8990=m 3611CONFIG_SND_SOC_WM8990=m
3680CONFIG_SND_SOC_WM8993=m 3612CONFIG_SND_SOC_WM8993=m
3681CONFIG_SND_SOC_WM8994=m
3682CONFIG_SND_SOC_WM9081=m 3613CONFIG_SND_SOC_WM9081=m
3683CONFIG_SND_SOC_MAX9877=m 3614CONFIG_SND_SOC_MAX9877=m
3684CONFIG_SND_SOC_TPA6130A2=m 3615CONFIG_SND_SOC_TPA6130A2=m
3685CONFIG_SND_SOC_WM2000=m 3616CONFIG_SND_SOC_WM2000=m
3617CONFIG_SND_SOC_WM9090=m
3686# CONFIG_SOUND_PRIME is not set 3618# CONFIG_SOUND_PRIME is not set
3687CONFIG_AC97_BUS=m 3619CONFIG_AC97_BUS=m
3688CONFIG_HID_SUPPORT=y 3620CONFIG_HID_SUPPORT=y
@@ -3709,10 +3641,13 @@ CONFIG_HID_3M_PCT=m
3709# CONFIG_HID_A4TECH is not set 3641# CONFIG_HID_A4TECH is not set
3710# CONFIG_HID_APPLE is not set 3642# CONFIG_HID_APPLE is not set
3711# CONFIG_HID_BELKIN is not set 3643# CONFIG_HID_BELKIN is not set
3644CONFIG_HID_CANDO=m
3712# CONFIG_HID_CHERRY is not set 3645# CONFIG_HID_CHERRY is not set
3713# CONFIG_HID_CHICONY is not set 3646# CONFIG_HID_CHICONY is not set
3647CONFIG_HID_PRODIKEYS=m
3714# CONFIG_HID_CYPRESS is not set 3648# CONFIG_HID_CYPRESS is not set
3715# CONFIG_HID_DRAGONRISE is not set 3649# CONFIG_HID_DRAGONRISE is not set
3650CONFIG_HID_EGALAX=m
3716# CONFIG_HID_EZKEY is not set 3651# CONFIG_HID_EZKEY is not set
3717# CONFIG_HID_KYE is not set 3652# CONFIG_HID_KYE is not set
3718# CONFIG_HID_GYRATION is not set 3653# CONFIG_HID_GYRATION is not set
@@ -3727,7 +3662,14 @@ CONFIG_HID_MOSART=m
3727CONFIG_HID_ORTEK=m 3662CONFIG_HID_ORTEK=m
3728# CONFIG_HID_PANTHERLORD is not set 3663# CONFIG_HID_PANTHERLORD is not set
3729# CONFIG_HID_PETALYNX is not set 3664# CONFIG_HID_PETALYNX is not set
3665CONFIG_HID_PICOLCD=m
3666CONFIG_HID_PICOLCD_FB=y
3667CONFIG_HID_PICOLCD_BACKLIGHT=y
3668CONFIG_HID_PICOLCD_LCD=y
3669CONFIG_HID_PICOLCD_LEDS=y
3730CONFIG_HID_QUANTA=m 3670CONFIG_HID_QUANTA=m
3671CONFIG_HID_ROCCAT=m
3672CONFIG_HID_ROCCAT_KONE=m
3731# CONFIG_HID_SAMSUNG is not set 3673# CONFIG_HID_SAMSUNG is not set
3732# CONFIG_HID_SONY is not set 3674# CONFIG_HID_SONY is not set
3733CONFIG_HID_STANTUM=m 3675CONFIG_HID_STANTUM=m
@@ -3738,6 +3680,7 @@ CONFIG_HID_STANTUM=m
3738# CONFIG_HID_THRUSTMASTER is not set 3680# CONFIG_HID_THRUSTMASTER is not set
3739# CONFIG_HID_WACOM is not set 3681# CONFIG_HID_WACOM is not set
3740# CONFIG_HID_ZEROPLUS is not set 3682# CONFIG_HID_ZEROPLUS is not set
3683CONFIG_HID_ZYDACRON=m
3741CONFIG_USB_SUPPORT=y 3684CONFIG_USB_SUPPORT=y
3742CONFIG_USB_ARCH_HAS_HCD=y 3685CONFIG_USB_ARCH_HAS_HCD=y
3743CONFIG_USB_ARCH_HAS_OHCI=y 3686CONFIG_USB_ARCH_HAS_OHCI=y
@@ -3857,6 +3800,7 @@ CONFIG_USB_SERIAL_KLSI=m
3857CONFIG_USB_SERIAL_KOBIL_SCT=m 3800CONFIG_USB_SERIAL_KOBIL_SCT=m
3858CONFIG_USB_SERIAL_MCT_U232=m 3801CONFIG_USB_SERIAL_MCT_U232=m
3859CONFIG_USB_SERIAL_MOS7720=m 3802CONFIG_USB_SERIAL_MOS7720=m
3803CONFIG_USB_SERIAL_MOS7715_PARPORT=y
3860CONFIG_USB_SERIAL_MOS7840=m 3804CONFIG_USB_SERIAL_MOS7840=m
3861CONFIG_USB_SERIAL_MOTOROLA=m 3805CONFIG_USB_SERIAL_MOTOROLA=m
3862CONFIG_USB_SERIAL_NAVMAN=m 3806CONFIG_USB_SERIAL_NAVMAN=m
@@ -3874,10 +3818,12 @@ CONFIG_USB_SERIAL_SYMBOL=m
3874CONFIG_USB_SERIAL_TI=m 3818CONFIG_USB_SERIAL_TI=m
3875CONFIG_USB_SERIAL_CYBERJACK=m 3819CONFIG_USB_SERIAL_CYBERJACK=m
3876CONFIG_USB_SERIAL_XIRCOM=m 3820CONFIG_USB_SERIAL_XIRCOM=m
3821CONFIG_USB_SERIAL_WWAN=m
3877CONFIG_USB_SERIAL_OPTION=m 3822CONFIG_USB_SERIAL_OPTION=m
3878CONFIG_USB_SERIAL_OMNINET=m 3823CONFIG_USB_SERIAL_OMNINET=m
3879CONFIG_USB_SERIAL_OPTICON=m 3824CONFIG_USB_SERIAL_OPTICON=m
3880CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m 3825CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
3826CONFIG_USB_SERIAL_ZIO=m
3881CONFIG_USB_SERIAL_DEBUG=m 3827CONFIG_USB_SERIAL_DEBUG=m
3882 3828
3883# 3829#
@@ -3939,10 +3885,11 @@ CONFIG_MMC_TEST=m
3939# 3885#
3940CONFIG_MMC_SDHCI=m 3886CONFIG_MMC_SDHCI=m
3941CONFIG_MMC_SDHCI_PCI=m 3887CONFIG_MMC_SDHCI_PCI=m
3942# CONFIG_MMC_RICOH_MMC is not set 3888CONFIG_MMC_RICOH_MMC=y
3943CONFIG_MMC_SDHCI_PLTFM=m 3889CONFIG_MMC_SDHCI_PLTFM=m
3944CONFIG_MMC_WBSD=m 3890CONFIG_MMC_WBSD=m
3945CONFIG_MMC_TIFM_SD=m 3891CONFIG_MMC_TIFM_SD=m
3892# CONFIG_MMC_SPI is not set
3946CONFIG_MMC_SDRICOH_CS=m 3893CONFIG_MMC_SDRICOH_CS=m
3947CONFIG_MMC_CB710=m 3894CONFIG_MMC_CB710=m
3948CONFIG_MMC_VIA_SDMMC=m 3895CONFIG_MMC_VIA_SDMMC=m
@@ -3966,8 +3913,7 @@ CONFIG_LEDS_CLASS=m
3966# 3913#
3967# LED drivers 3914# LED drivers
3968# 3915#
3969CONFIG_LEDS_NET48XX=m 3916CONFIG_LEDS_NET5501=m
3970CONFIG_LEDS_WRAP=m
3971CONFIG_LEDS_ALIX2=m 3917CONFIG_LEDS_ALIX2=m
3972CONFIG_LEDS_PCA9532=m 3918CONFIG_LEDS_PCA9532=m
3973CONFIG_LEDS_GPIO=m 3919CONFIG_LEDS_GPIO=m
@@ -4004,10 +3950,13 @@ CONFIG_INFINIBAND_USER_MEM=y
4004CONFIG_INFINIBAND_ADDR_TRANS=y 3950CONFIG_INFINIBAND_ADDR_TRANS=y
4005CONFIG_INFINIBAND_MTHCA=m 3951CONFIG_INFINIBAND_MTHCA=m
4006# CONFIG_INFINIBAND_MTHCA_DEBUG is not set 3952# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
3953# CONFIG_INFINIBAND_IPATH is not set
3954# CONFIG_INFINIBAND_QIB is not set
4007CONFIG_INFINIBAND_AMSO1100=m 3955CONFIG_INFINIBAND_AMSO1100=m
4008# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set 3956# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set
4009CONFIG_INFINIBAND_CXGB3=m 3957CONFIG_INFINIBAND_CXGB3=m
4010# CONFIG_INFINIBAND_CXGB3_DEBUG is not set 3958# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
3959CONFIG_INFINIBAND_CXGB4=m
4011CONFIG_MLX4_INFINIBAND=m 3960CONFIG_MLX4_INFINIBAND=m
4012CONFIG_INFINIBAND_NES=m 3961CONFIG_INFINIBAND_NES=m
4013# CONFIG_INFINIBAND_NES_DEBUG is not set 3962# CONFIG_INFINIBAND_NES_DEBUG is not set
@@ -4078,6 +4027,7 @@ CONFIG_RTC_DRV_BQ4802=m
4078CONFIG_RTC_DRV_RP5C01=m 4027CONFIG_RTC_DRV_RP5C01=m
4079CONFIG_RTC_DRV_V3020=m 4028CONFIG_RTC_DRV_V3020=m
4080CONFIG_RTC_DRV_PCF50633=m 4029CONFIG_RTC_DRV_PCF50633=m
4030CONFIG_RTC_DRV_AB8500=m
4081 4031
4082# 4032#
4083# on-CPU RTC drivers 4033# on-CPU RTC drivers
@@ -4090,6 +4040,7 @@ CONFIG_DMADEVICES=y
4090# 4040#
4091CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH=y 4041CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH=y
4092CONFIG_INTEL_IOATDMA=m 4042CONFIG_INTEL_IOATDMA=m
4043CONFIG_TIMB_DMA=m
4093CONFIG_DMA_ENGINE=y 4044CONFIG_DMA_ENGINE=y
4094 4045
4095# 4046#
@@ -4113,21 +4064,73 @@ CONFIG_UIO_AEC=m
4113CONFIG_UIO_SERCOS3=m 4064CONFIG_UIO_SERCOS3=m
4114# CONFIG_UIO_PCI_GENERIC is not set 4065# CONFIG_UIO_PCI_GENERIC is not set
4115CONFIG_UIO_NETX=m 4066CONFIG_UIO_NETX=m
4116 4067CONFIG_STAGING=y
4117# 4068# CONFIG_STAGING_EXCLUDE_BUILD is not set
4118# TI VLYNQ 4069# CONFIG_ET131X is not set
4119# 4070# CONFIG_SLICOSS is not set
4120 4071# CONFIG_VIDEO_GO7007 is not set
4121# 4072# CONFIG_VIDEO_CX25821 is not set
4122# Xen driver support 4073# CONFIG_VIDEO_TM6000 is not set
4123# 4074# CONFIG_USB_IP_COMMON is not set
4124CONFIG_XEN_BALLOON=y 4075# CONFIG_W35UND is not set
4125CONFIG_XEN_SCRUB_PAGES=y 4076# CONFIG_PRISM2_USB is not set
4126CONFIG_XEN_DEV_EVTCHN=y 4077# CONFIG_ECHO is not set
4127CONFIG_XENFS=y 4078# CONFIG_OTUS is not set
4128CONFIG_XEN_COMPAT_XENFS=y 4079# CONFIG_RT2860 is not set
4129CONFIG_XEN_SYS_HYPERVISOR=y 4080# CONFIG_RT2870 is not set
4130# CONFIG_STAGING is not set 4081# CONFIG_COMEDI is not set
4082# CONFIG_ASUS_OLED is not set
4083# CONFIG_PANEL is not set
4084# CONFIG_R8187SE is not set
4085# CONFIG_RTL8192SU is not set
4086# CONFIG_RTL8192U is not set
4087# CONFIG_RTL8192E is not set
4088# CONFIG_TRANZPORT is not set
4089# CONFIG_POHMELFS is not set
4090# CONFIG_IDE_PHISON is not set
4091# CONFIG_LINE6_USB is not set
4092# CONFIG_DRM_VMWGFX is not set
4093# CONFIG_DRM_NOUVEAU is not set
4094
4095#
4096# I2C encoder or helper chips
4097#
4098# CONFIG_DRM_I2C_CH7006 is not set
4099# CONFIG_USB_SERIAL_QUATECH2 is not set
4100# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
4101# CONFIG_VT6655 is not set
4102# CONFIG_VT6656 is not set
4103# CONFIG_FB_UDL is not set
4104CONFIG_HYPERV=m
4105CONFIG_HYPERV_STORAGE=m
4106CONFIG_HYPERV_BLOCK=m
4107CONFIG_HYPERV_NET=m
4108CONFIG_HYPERV_UTILS=m
4109# CONFIG_VME_BUS is not set
4110
4111#
4112# RAR Register Driver
4113#
4114# CONFIG_RAR_REGISTER is not set
4115# CONFIG_IIO is not set
4116# CONFIG_RAMZSWAP is not set
4117# CONFIG_WLAGS49_H2 is not set
4118# CONFIG_WLAGS49_H25 is not set
4119# CONFIG_BATMAN_ADV is not set
4120# CONFIG_SAMSUNG_LAPTOP is not set
4121# CONFIG_FB_SM7XX is not set
4122# CONFIG_DT3155 is not set
4123# CONFIG_VIDEO_DT3155 is not set
4124# CONFIG_CRYSTALHD is not set
4125# CONFIG_CXT1E1 is not set
4126
4127#
4128# Texas Instruments shared transport line discipline
4129#
4130# CONFIG_TI_ST is not set
4131# CONFIG_ST_BT is not set
4132# CONFIG_ADIS16255 is not set
4133# CONFIG_FB_XGI is not set
4131CONFIG_X86_PLATFORM_DEVICES=y 4134CONFIG_X86_PLATFORM_DEVICES=y
4132CONFIG_ACER_WMI=m 4135CONFIG_ACER_WMI=m
4133CONFIG_ASUS_LAPTOP=m 4136CONFIG_ASUS_LAPTOP=m
@@ -4135,7 +4138,6 @@ CONFIG_DELL_LAPTOP=m
4135CONFIG_DELL_WMI=m 4138CONFIG_DELL_WMI=m
4136CONFIG_FUJITSU_LAPTOP=m 4139CONFIG_FUJITSU_LAPTOP=m
4137# CONFIG_FUJITSU_LAPTOP_DEBUG is not set 4140# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
4138CONFIG_TC1100_WMI=m
4139CONFIG_HP_WMI=m 4141CONFIG_HP_WMI=m
4140CONFIG_MSI_LAPTOP=m 4142CONFIG_MSI_LAPTOP=m
4141CONFIG_PANASONIC_LAPTOP=m 4143CONFIG_PANASONIC_LAPTOP=m
@@ -4291,6 +4293,9 @@ CONFIG_MISC_FILESYSTEMS=y
4291# CONFIG_ADFS_FS is not set 4293# CONFIG_ADFS_FS is not set
4292# CONFIG_AFFS_FS is not set 4294# CONFIG_AFFS_FS is not set
4293CONFIG_ECRYPT_FS=m 4295CONFIG_ECRYPT_FS=m
4296CONFIG_UNION_FS=m
4297# CONFIG_UNION_FS_XATTR is not set
4298# CONFIG_UNION_FS_DEBUG is not set
4294CONFIG_HFS_FS=m 4299CONFIG_HFS_FS=m
4295CONFIG_HFSPLUS_FS=m 4300CONFIG_HFSPLUS_FS=m
4296# CONFIG_BEFS_FS is not set 4301# CONFIG_BEFS_FS is not set
@@ -4322,6 +4327,7 @@ CONFIG_UBIFS_FS_ZLIB=y
4322CONFIG_LOGFS=m 4327CONFIG_LOGFS=m
4323CONFIG_CRAMFS=m 4328CONFIG_CRAMFS=m
4324CONFIG_SQUASHFS=m 4329CONFIG_SQUASHFS=m
4330# CONFIG_SQUASHFS_XATTRS is not set
4325# CONFIG_SQUASHFS_EMBEDDED is not set 4331# CONFIG_SQUASHFS_EMBEDDED is not set
4326CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 4332CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
4327# CONFIG_VXFS_FS is not set 4333# CONFIG_VXFS_FS is not set
@@ -4380,8 +4386,24 @@ CONFIG_CIFS_EXPERIMENTAL=y
4380# 4386#
4381# Partition Types 4387# Partition Types
4382# 4388#
4383# CONFIG_PARTITION_ADVANCED is not set 4389CONFIG_PARTITION_ADVANCED=y
4390# CONFIG_ACORN_PARTITION is not set
4391# CONFIG_OSF_PARTITION is not set
4392# CONFIG_AMIGA_PARTITION is not set
4393# CONFIG_ATARI_PARTITION is not set
4394# CONFIG_MAC_PARTITION is not set
4384CONFIG_MSDOS_PARTITION=y 4395CONFIG_MSDOS_PARTITION=y
4396# CONFIG_BSD_DISKLABEL is not set
4397# CONFIG_MINIX_SUBPARTITION is not set
4398# CONFIG_SOLARIS_X86_PARTITION is not set
4399# CONFIG_UNIXWARE_DISKLABEL is not set
4400# CONFIG_LDM_PARTITION is not set
4401# CONFIG_SGI_PARTITION is not set
4402# CONFIG_ULTRIX_PARTITION is not set
4403# CONFIG_SUN_PARTITION is not set
4404# CONFIG_KARMA_PARTITION is not set
4405CONFIG_EFI_PARTITION=y
4406# CONFIG_SYSV68_PARTITION is not set
4385CONFIG_NLS=m 4407CONFIG_NLS=m
4386CONFIG_NLS_DEFAULT="iso8859-1" 4408CONFIG_NLS_DEFAULT="iso8859-1"
4387CONFIG_NLS_CODEPAGE_437=m 4409CONFIG_NLS_CODEPAGE_437=m
@@ -4444,7 +4466,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
4444CONFIG_ARCH_WANT_FRAME_POINTERS=y 4466CONFIG_ARCH_WANT_FRAME_POINTERS=y
4445CONFIG_FRAME_POINTER=y 4467CONFIG_FRAME_POINTER=y
4446# CONFIG_RCU_CPU_STALL_DETECTOR is not set 4468# CONFIG_RCU_CPU_STALL_DETECTOR is not set
4447CONFIG_LKDTM=m 4469# CONFIG_LKDTM is not set
4448# CONFIG_LATENCYTOP is not set 4470# CONFIG_LATENCYTOP is not set
4449CONFIG_SYSCTL_SYSCALL_CHECK=y 4471CONFIG_SYSCTL_SYSCALL_CHECK=y
4450CONFIG_USER_STACKTRACE_SUPPORT=y 4472CONFIG_USER_STACKTRACE_SUPPORT=y
@@ -4463,14 +4485,13 @@ CONFIG_TRACING_SUPPORT=y
4463# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set 4485# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set
4464# CONFIG_DYNAMIC_DEBUG is not set 4486# CONFIG_DYNAMIC_DEBUG is not set
4465# CONFIG_DMA_API_DEBUG is not set 4487# CONFIG_DMA_API_DEBUG is not set
4488# CONFIG_ATOMIC64_SELFTEST is not set
4466# CONFIG_SAMPLES is not set 4489# CONFIG_SAMPLES is not set
4467CONFIG_HAVE_ARCH_KGDB=y 4490CONFIG_HAVE_ARCH_KGDB=y
4468CONFIG_HAVE_ARCH_KMEMCHECK=y 4491CONFIG_HAVE_ARCH_KMEMCHECK=y
4469CONFIG_STRICT_DEVMEM=y 4492CONFIG_STRICT_DEVMEM=y
4470# CONFIG_X86_VERBOSE_BOOTUP is not set 4493# CONFIG_X86_VERBOSE_BOOTUP is not set
4471# CONFIG_EARLY_PRINTK is not set 4494# CONFIG_EARLY_PRINTK is not set
4472# CONFIG_4KSTACKS is not set
4473# CONFIG_DOUBLEFAULT is not set
4474# CONFIG_IOMMU_STRESS is not set 4495# CONFIG_IOMMU_STRESS is not set
4475CONFIG_HAVE_MMIOTRACE_SUPPORT=y 4496CONFIG_HAVE_MMIOTRACE_SUPPORT=y
4476CONFIG_IO_DELAY_TYPE_0X80=0 4497CONFIG_IO_DELAY_TYPE_0X80=0
@@ -4527,6 +4548,7 @@ CONFIG_CRYPTO_RNG2=y
4527CONFIG_CRYPTO_PCOMP=y 4548CONFIG_CRYPTO_PCOMP=y
4528CONFIG_CRYPTO_MANAGER=m 4549CONFIG_CRYPTO_MANAGER=m
4529CONFIG_CRYPTO_MANAGER2=y 4550CONFIG_CRYPTO_MANAGER2=y
4551CONFIG_CRYPTO_MANAGER_TESTS=y
4530CONFIG_CRYPTO_GF128MUL=m 4552CONFIG_CRYPTO_GF128MUL=m
4531CONFIG_CRYPTO_NULL=m 4553CONFIG_CRYPTO_NULL=m
4532CONFIG_CRYPTO_PCRYPT=m 4554CONFIG_CRYPTO_PCRYPT=m
@@ -4578,12 +4600,14 @@ CONFIG_CRYPTO_SHA256=y
4578CONFIG_CRYPTO_SHA512=m 4600CONFIG_CRYPTO_SHA512=m
4579CONFIG_CRYPTO_TGR192=m 4601CONFIG_CRYPTO_TGR192=m
4580CONFIG_CRYPTO_WP512=m 4602CONFIG_CRYPTO_WP512=m
4603# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set
4581 4604
4582# 4605#
4583# Ciphers 4606# Ciphers
4584# 4607#
4585CONFIG_CRYPTO_AES=m 4608CONFIG_CRYPTO_AES=m
4586CONFIG_CRYPTO_AES_586=m 4609# CONFIG_CRYPTO_AES_X86_64 is not set
4610# CONFIG_CRYPTO_AES_NI_INTEL is not set
4587CONFIG_CRYPTO_ANUBIS=m 4611CONFIG_CRYPTO_ANUBIS=m
4588CONFIG_CRYPTO_ARC4=m 4612CONFIG_CRYPTO_ARC4=m
4589CONFIG_CRYPTO_BLOWFISH=m 4613CONFIG_CRYPTO_BLOWFISH=m
@@ -4594,13 +4618,13 @@ CONFIG_CRYPTO_DES=m
4594CONFIG_CRYPTO_FCRYPT=m 4618CONFIG_CRYPTO_FCRYPT=m
4595CONFIG_CRYPTO_KHAZAD=m 4619CONFIG_CRYPTO_KHAZAD=m
4596CONFIG_CRYPTO_SALSA20=m 4620CONFIG_CRYPTO_SALSA20=m
4597CONFIG_CRYPTO_SALSA20_586=m 4621# CONFIG_CRYPTO_SALSA20_X86_64 is not set
4598CONFIG_CRYPTO_SEED=m 4622CONFIG_CRYPTO_SEED=m
4599CONFIG_CRYPTO_SERPENT=m 4623CONFIG_CRYPTO_SERPENT=m
4600CONFIG_CRYPTO_TEA=m 4624CONFIG_CRYPTO_TEA=m
4601CONFIG_CRYPTO_TWOFISH=m 4625CONFIG_CRYPTO_TWOFISH=m
4602CONFIG_CRYPTO_TWOFISH_COMMON=m 4626CONFIG_CRYPTO_TWOFISH_COMMON=m
4603CONFIG_CRYPTO_TWOFISH_586=m 4627# CONFIG_CRYPTO_TWOFISH_X86_64 is not set
4604 4628
4605# 4629#
4606# Compression 4630# Compression
@@ -4617,7 +4641,6 @@ CONFIG_CRYPTO_HW=y
4617CONFIG_CRYPTO_DEV_PADLOCK=m 4641CONFIG_CRYPTO_DEV_PADLOCK=m
4618CONFIG_CRYPTO_DEV_PADLOCK_AES=m 4642CONFIG_CRYPTO_DEV_PADLOCK_AES=m
4619CONFIG_CRYPTO_DEV_PADLOCK_SHA=m 4643CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
4620CONFIG_CRYPTO_DEV_GEODE=m
4621CONFIG_CRYPTO_DEV_HIFN_795X=m 4644CONFIG_CRYPTO_DEV_HIFN_795X=m
4622CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y 4645CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
4623CONFIG_HAVE_KVM=y 4646CONFIG_HAVE_KVM=y
@@ -4630,9 +4653,8 @@ CONFIG_KVM=m
4630CONFIG_KVM_INTEL=m 4653CONFIG_KVM_INTEL=m
4631CONFIG_KVM_AMD=m 4654CONFIG_KVM_AMD=m
4632CONFIG_VHOST_NET=m 4655CONFIG_VHOST_NET=m
4633CONFIG_LGUEST=m 4656CONFIG_VIRTIO=m
4634CONFIG_VIRTIO=y 4657CONFIG_VIRTIO_RING=m
4635CONFIG_VIRTIO_RING=y
4636CONFIG_VIRTIO_PCI=m 4658CONFIG_VIRTIO_PCI=m
4637CONFIG_VIRTIO_BALLOON=m 4659CONFIG_VIRTIO_BALLOON=m
4638# CONFIG_BINARY_PRINTF is not set 4660# CONFIG_BINARY_PRINTF is not set
@@ -4640,7 +4662,7 @@ CONFIG_VIRTIO_BALLOON=m
4640# 4662#
4641# Library routines 4663# Library routines
4642# 4664#
4643CONFIG_BITREVERSE=m 4665CONFIG_BITREVERSE=y
4644CONFIG_GENERIC_FIND_FIRST_BIT=y 4666CONFIG_GENERIC_FIND_FIRST_BIT=y
4645CONFIG_GENERIC_FIND_NEXT_BIT=y 4667CONFIG_GENERIC_FIND_NEXT_BIT=y
4646CONFIG_GENERIC_FIND_LAST_BIT=y 4668CONFIG_GENERIC_FIND_LAST_BIT=y
@@ -4648,16 +4670,17 @@ CONFIG_CRC_CCITT=m
4648CONFIG_CRC16=m 4670CONFIG_CRC16=m
4649CONFIG_CRC_T10DIF=m 4671CONFIG_CRC_T10DIF=m
4650CONFIG_CRC_ITU_T=m 4672CONFIG_CRC_ITU_T=m
4651CONFIG_CRC32=m 4673CONFIG_CRC32=y
4652CONFIG_CRC7=m 4674CONFIG_CRC7=m
4653CONFIG_LIBCRC32C=m 4675CONFIG_LIBCRC32C=m
4654CONFIG_ZLIB_INFLATE=y 4676CONFIG_ZLIB_INFLATE=y
4655CONFIG_ZLIB_DEFLATE=m 4677CONFIG_ZLIB_DEFLATE=m
4656CONFIG_LZO_COMPRESS=m 4678CONFIG_LZO_COMPRESS=m
4657CONFIG_LZO_DECOMPRESS=m 4679CONFIG_LZO_DECOMPRESS=y
4658CONFIG_DECOMPRESS_GZIP=y 4680CONFIG_DECOMPRESS_GZIP=y
4659CONFIG_DECOMPRESS_BZIP2=y 4681CONFIG_DECOMPRESS_BZIP2=y
4660CONFIG_DECOMPRESS_LZMA=y 4682CONFIG_DECOMPRESS_LZMA=y
4683CONFIG_DECOMPRESS_LZO=y
4661CONFIG_GENERIC_ALLOCATOR=y 4684CONFIG_GENERIC_ALLOCATOR=y
4662CONFIG_REED_SOLOMON=m 4685CONFIG_REED_SOLOMON=m
4663CONFIG_REED_SOLOMON_DEC16=y 4686CONFIG_REED_SOLOMON_DEC16=y
@@ -4671,4 +4694,3 @@ CONFIG_HAS_IOPORT=y
4671CONFIG_HAS_DMA=y 4694CONFIG_HAS_DMA=y
4672CONFIG_CHECK_SIGNATURE=y 4695CONFIG_CHECK_SIGNATURE=y
4673CONFIG_NLATTR=y 4696CONFIG_NLATTR=y
4674CONFIG_LRU_CACHE=m
diff --git a/testing/linux-scst/put_page_callback-2.6.34.patch b/testing/linux-scst/put_page_callback-2.6.34.patch
deleted file mode 100644
index 97d6f7f0af..0000000000
--- a/testing/linux-scst/put_page_callback-2.6.34.patch
+++ /dev/null
@@ -1,390 +0,0 @@
1diff -upkr linux-2.6.34/include/linux/mm_types.h linux-2.6.34/include/linux/mm_types.h
2--- linux-2.6.34/include/linux/mm_types.h 2010-05-17 01:17:36.000000000 +0400
3+++ linux-2.6.34/include/linux/mm_types.h 2010-05-24 14:51:40.000000000 +0400
4@@ -100,6 +100,18 @@ struct page {
5 */
6 void *shadow;
7 #endif
8+
9+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
10+ /*
11+ * Used to implement support for notification on zero-copy TCP transfer
12+ * completion. It might look as not good to have this field here and
13+ * it's better to have it in struct sk_buff, but it would make the code
14+ * much more complicated and fragile, since all skb then would have to
15+ * contain only pages with the same value in this field.
16+ */
17+ void *net_priv;
18+#endif
19+
20 };
21
22 /*
23diff -upkr linux-2.6.34/include/linux/net.h linux-2.6.34/include/linux/net.h
24--- linux-2.6.34/include/linux/net.h 2010-05-17 01:17:36.000000000 +0400
25+++ linux-2.6.34/include/linux/net.h 2010-05-24 14:51:40.000000000 +0400
26@@ -20,6 +20,7 @@
27
28 #include <linux/socket.h>
29 #include <asm/socket.h>
30+#include <linux/mm.h>
31
32 #define NPROTO AF_MAX
33
34@@ -288,5 +289,44 @@ extern int kernel_sock_shutdown(struct s
35 extern struct ratelimit_state net_ratelimit_state;
36 #endif
37
38+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
39+/* Support for notification on zero-copy TCP transfer completion */
40+typedef void (*net_get_page_callback_t)(struct page *page);
41+typedef void (*net_put_page_callback_t)(struct page *page);
42+
43+extern net_get_page_callback_t net_get_page_callback;
44+extern net_put_page_callback_t net_put_page_callback;
45+
46+extern int net_set_get_put_page_callbacks(
47+ net_get_page_callback_t get_callback,
48+ net_put_page_callback_t put_callback);
49+
50+/*
51+ * See comment for net_set_get_put_page_callbacks() why those functions
52+ * don't need any protection.
53+ */
54+static inline void net_get_page(struct page *page)
55+{
56+ if (page->net_priv != 0)
57+ net_get_page_callback(page);
58+ get_page(page);
59+}
60+static inline void net_put_page(struct page *page)
61+{
62+ if (page->net_priv != 0)
63+ net_put_page_callback(page);
64+ put_page(page);
65+}
66+#else
67+static inline void net_get_page(struct page *page)
68+{
69+ get_page(page);
70+}
71+static inline void net_put_page(struct page *page)
72+{
73+ put_page(page);
74+}
75+#endif /* CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION */
76+
77 #endif /* __KERNEL__ */
78 #endif /* _LINUX_NET_H */
79diff -upkr linux-2.6.34/net/core/dev.c linux-2.6.34/net/core/dev.c
80--- linux-2.6.34/net/core/dev.c 2010-05-17 01:17:36.000000000 +0400
81+++ linux-2.6.34/net/core/dev.c 2010-05-24 14:51:40.000000000 +0400
82@@ -2732,7 +2732,7 @@ pull:
83 skb_shinfo(skb)->frags[0].size -= grow;
84
85 if (unlikely(!skb_shinfo(skb)->frags[0].size)) {
86- put_page(skb_shinfo(skb)->frags[0].page);
87+ net_put_page(skb_shinfo(skb)->frags[0].page);
88 memmove(skb_shinfo(skb)->frags,
89 skb_shinfo(skb)->frags + 1,
90 --skb_shinfo(skb)->nr_frags);
91diff -upkr linux-2.6.34/net/core/skbuff.c linux-2.6.34/net/core/skbuff.c
92--- linux-2.6.34/net/core/skbuff.c 2010-05-17 01:17:36.000000000 +0400
93+++ linux-2.6.34/net/core/skbuff.c 2010-05-24 14:51:40.000000000 +0400
94@@ -76,13 +76,13 @@ static struct kmem_cache *skbuff_fclone_
95 static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
96 struct pipe_buffer *buf)
97 {
98- put_page(buf->page);
99+ net_put_page(buf->page);
100 }
101
102 static void sock_pipe_buf_get(struct pipe_inode_info *pipe,
103 struct pipe_buffer *buf)
104 {
105- get_page(buf->page);
106+ net_get_page(buf->page);
107 }
108
109 static int sock_pipe_buf_steal(struct pipe_inode_info *pipe,
110@@ -344,7 +344,7 @@ static void skb_release_data(struct sk_b
111 if (skb_shinfo(skb)->nr_frags) {
112 int i;
113 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
114- put_page(skb_shinfo(skb)->frags[i].page);
115+ net_put_page(skb_shinfo(skb)->frags[i].page);
116 }
117
118 if (skb_has_frags(skb))
119@@ -765,7 +765,7 @@ struct sk_buff *pskb_copy(struct sk_buff
120
121 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
122 skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
123- get_page(skb_shinfo(n)->frags[i].page);
124+ net_get_page(skb_shinfo(n)->frags[i].page);
125 }
126 skb_shinfo(n)->nr_frags = i;
127 }
128@@ -831,7 +831,7 @@ int pskb_expand_head(struct sk_buff *skb
129 sizeof(struct skb_shared_info));
130
131 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
132- get_page(skb_shinfo(skb)->frags[i].page);
133+ net_get_page(skb_shinfo(skb)->frags[i].page);
134
135 if (skb_has_frags(skb))
136 skb_clone_fraglist(skb);
137@@ -1105,7 +1105,7 @@ drop_pages:
138 skb_shinfo(skb)->nr_frags = i;
139
140 for (; i < nfrags; i++)
141- put_page(skb_shinfo(skb)->frags[i].page);
142+ net_put_page(skb_shinfo(skb)->frags[i].page);
143
144 if (skb_has_frags(skb))
145 skb_drop_fraglist(skb);
146@@ -1274,7 +1274,7 @@ pull_pages:
147 k = 0;
148 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
149 if (skb_shinfo(skb)->frags[i].size <= eat) {
150- put_page(skb_shinfo(skb)->frags[i].page);
151+ net_put_page(skb_shinfo(skb)->frags[i].page);
152 eat -= skb_shinfo(skb)->frags[i].size;
153 } else {
154 skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
155@@ -1375,7 +1375,7 @@ EXPORT_SYMBOL(skb_copy_bits);
156 */
157 static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i)
158 {
159- put_page(spd->pages[i]);
160+ net_put_page(spd->pages[i]);
161 }
162
163 static inline struct page *linear_to_page(struct page *page, unsigned int *len,
164@@ -1399,7 +1399,7 @@ new_page:
165 off = sk->sk_sndmsg_off;
166 mlen = PAGE_SIZE - off;
167 if (mlen < 64 && mlen < *len) {
168- put_page(p);
169+ net_put_page(p);
170 goto new_page;
171 }
172
173@@ -1409,7 +1409,7 @@ new_page:
174 memcpy(page_address(p) + off, page_address(page) + *offset, *len);
175 sk->sk_sndmsg_off += *len;
176 *offset = off;
177- get_page(p);
178+ net_get_page(p);
179
180 return p;
181 }
182@@ -1430,7 +1430,7 @@ static inline int spd_fill_page(struct s
183 if (!page)
184 return 1;
185 } else
186- get_page(page);
187+ net_get_page(page);
188
189 spd->pages[spd->nr_pages] = page;
190 spd->partial[spd->nr_pages].len = *len;
191@@ -2060,7 +2060,7 @@ static inline void skb_split_no_header(s
192 * where splitting is expensive.
193 * 2. Split is accurately. We make this.
194 */
195- get_page(skb_shinfo(skb)->frags[i].page);
196+ net_get_page(skb_shinfo(skb)->frags[i].page);
197 skb_shinfo(skb1)->frags[0].page_offset += len - pos;
198 skb_shinfo(skb1)->frags[0].size -= len - pos;
199 skb_shinfo(skb)->frags[i].size = len - pos;
200@@ -2182,7 +2182,7 @@ int skb_shift(struct sk_buff *tgt, struc
201 to++;
202
203 } else {
204- get_page(fragfrom->page);
205+ net_get_page(fragfrom->page);
206 fragto->page = fragfrom->page;
207 fragto->page_offset = fragfrom->page_offset;
208 fragto->size = todo;
209@@ -2204,7 +2204,7 @@ int skb_shift(struct sk_buff *tgt, struc
210 fragto = &skb_shinfo(tgt)->frags[merge];
211
212 fragto->size += fragfrom->size;
213- put_page(fragfrom->page);
214+ net_put_page(fragfrom->page);
215 }
216
217 /* Reposition in the original skb */
218@@ -2602,7 +2602,7 @@ struct sk_buff *skb_segment(struct sk_bu
219
220 while (pos < offset + len && i < nfrags) {
221 *frag = skb_shinfo(skb)->frags[i];
222- get_page(frag->page);
223+ net_get_page(frag->page);
224 size = frag->size;
225
226 if (pos < offset) {
227diff -upkr linux-2.6.34/net/ipv4/ip_output.c linux-2.6.34/net/ipv4/ip_output.c
228--- linux-2.6.34/net/ipv4/ip_output.c 2010-05-17 01:17:36.000000000 +0400
229+++ linux-2.6.34/net/ipv4/ip_output.c 2010-05-24 14:51:40.000000000 +0400
230@@ -1024,7 +1024,7 @@ alloc_new_skb:
231 err = -EMSGSIZE;
232 goto error;
233 }
234- get_page(page);
235+ net_get_page(page);
236 skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
237 frag = &skb_shinfo(skb)->frags[i];
238 }
239@@ -1182,7 +1182,7 @@ ssize_t ip_append_page(struct sock *sk,
240 if (skb_can_coalesce(skb, i, page, offset)) {
241 skb_shinfo(skb)->frags[i-1].size += len;
242 } else if (i < MAX_SKB_FRAGS) {
243- get_page(page);
244+ net_get_page(page);
245 skb_fill_page_desc(skb, i, page, offset, len);
246 } else {
247 err = -EMSGSIZE;
248diff -upkr linux-2.6.34/net/ipv4/Makefile linux-2.6.34/net/ipv4/Makefile
249--- linux-2.6.34/net/ipv4/Makefile 2010-05-17 01:17:36.000000000 +0400
250+++ linux-2.6.34/net/ipv4/Makefile 2010-05-24 14:51:40.000000000 +0400
251@@ -49,6 +49,7 @@ obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
252 obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o
253 obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o
254 obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
255+obj-$(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) += tcp_zero_copy.o
256
257 obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
258 xfrm4_output.o
259diff -upkr linux-2.6.34/net/ipv4/tcp.c linux-2.6.34/net/ipv4/tcp.c
260--- linux-2.6.34/net/ipv4/tcp.c 2010-05-17 01:17:36.000000000 +0400
261+++ linux-2.6.34/net/ipv4/tcp.c 2010-05-24 14:51:40.000000000 +0400
262@@ -800,7 +800,7 @@ new_segment:
263 if (can_coalesce) {
264 skb_shinfo(skb)->frags[i - 1].size += copy;
265 } else {
266- get_page(page);
267+ net_get_page(page);
268 skb_fill_page_desc(skb, i, page, offset, copy);
269 }
270
271@@ -1009,7 +1009,7 @@ new_segment:
272 goto new_segment;
273 } else if (page) {
274 if (off == PAGE_SIZE) {
275- put_page(page);
276+ net_put_page(page);
277 TCP_PAGE(sk) = page = NULL;
278 off = 0;
279 }
280@@ -1050,9 +1050,9 @@ new_segment:
281 } else {
282 skb_fill_page_desc(skb, i, page, off, copy);
283 if (TCP_PAGE(sk)) {
284- get_page(page);
285+ net_get_page(page);
286 } else if (off + copy < PAGE_SIZE) {
287- get_page(page);
288+ net_get_page(page);
289 TCP_PAGE(sk) = page;
290 }
291 }
292diff -upkr linux-2.6.34/net/ipv4/tcp_output.c linux-2.6.34/net/ipv4/tcp_output.c
293--- linux-2.6.34/net/ipv4/tcp_output.c 2010-05-17 01:17:36.000000000 +0400
294+++ linux-2.6.34/net/ipv4/tcp_output.c 2010-05-24 14:51:40.000000000 +0400
295@@ -1084,7 +1084,7 @@ static void __pskb_trim_head(struct sk_b
296 k = 0;
297 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
298 if (skb_shinfo(skb)->frags[i].size <= eat) {
299- put_page(skb_shinfo(skb)->frags[i].page);
300+ net_put_page(skb_shinfo(skb)->frags[i].page);
301 eat -= skb_shinfo(skb)->frags[i].size;
302 } else {
303 skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
304diff -upkr linux-2.6.34/net/ipv4/tcp_zero_copy.c linux-2.6.34/net/ipv4/tcp_zero_copy.c
305--- linux-2.6.34/net/ipv4/tcp_zero_copy.c 2010-03-01 17:30:31.000000000 +0300
306+++ linux-2.6.34/net/ipv4/tcp_zero_copy.c 2010-05-24 14:51:40.000000000 +0400
307@@ -0,0 +1,49 @@
308+/*
309+ * Support routines for TCP zero copy transmit
310+ *
311+ * Created by Vladislav Bolkhovitin
312+ *
313+ * This program is free software; you can redistribute it and/or
314+ * modify it under the terms of the GNU General Public License
315+ * version 2 as published by the Free Software Foundation.
316+ */
317+
318+#include <linux/skbuff.h>
319+
320+net_get_page_callback_t net_get_page_callback __read_mostly;
321+EXPORT_SYMBOL(net_get_page_callback);
322+
323+net_put_page_callback_t net_put_page_callback __read_mostly;
324+EXPORT_SYMBOL(net_put_page_callback);
325+
326+/*
327+ * Caller of this function must ensure that at the moment when it's called
328+ * there are no pages in the system with net_priv field set to non-zero
329+ * value. Hence, this function, as well as net_get_page() and net_put_page(),
330+ * don't need any protection.
331+ */
332+int net_set_get_put_page_callbacks(
333+ net_get_page_callback_t get_callback,
334+ net_put_page_callback_t put_callback)
335+{
336+ int res = 0;
337+
338+ if ((net_get_page_callback != NULL) && (get_callback != NULL) &&
339+ (net_get_page_callback != get_callback)) {
340+ res = -EBUSY;
341+ goto out;
342+ }
343+
344+ if ((net_put_page_callback != NULL) && (put_callback != NULL) &&
345+ (net_put_page_callback != put_callback)) {
346+ res = -EBUSY;
347+ goto out;
348+ }
349+
350+ net_get_page_callback = get_callback;
351+ net_put_page_callback = put_callback;
352+
353+out:
354+ return res;
355+}
356+EXPORT_SYMBOL(net_set_get_put_page_callbacks);
357diff -upkr linux-2.6.34/net/ipv6/ip6_output.c linux-2.6.34/net/ipv6/ip6_output.c
358--- linux-2.6.34/net/ipv6/ip6_output.c 2010-05-17 01:17:36.000000000 +0400
359+++ linux-2.6.34/net/ipv6/ip6_output.c 2010-05-24 14:51:40.000000000 +0400
360@@ -1382,7 +1382,7 @@ alloc_new_skb:
361 err = -EMSGSIZE;
362 goto error;
363 }
364- get_page(page);
365+ net_get_page(page);
366 skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
367 frag = &skb_shinfo(skb)->frags[i];
368 }
369diff -upkr linux-2.6.34/net/Kconfig linux-2.6.34/net/Kconfig
370--- linux-2.6.34/net/Kconfig 2010-05-17 01:17:36.000000000 +0400
371+++ linux-2.6.34/net/Kconfig 2010-05-24 14:51:40.000000000 +0400
372@@ -72,6 +72,18 @@ config INET
373
374 Short answer: say Y.
375
376+config TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION
377+ bool "TCP/IP zero-copy transfer completion notification"
378+ depends on INET
379+ default SCST_ISCSI
380+ ---help---
381+ Adds support for sending a notification upon completion of a
382+ zero-copy TCP/IP transfer. This can speed up certain TCP/IP
383+ software. Currently this is only used by the iSCSI target driver
384+ iSCSI-SCST.
385+
386+ If unsure, say N.
387+
388 if INET
389 source "net/ipv4/Kconfig"
390 source "net/ipv6/Kconfig"
diff --git a/testing/linux-scst/r8169-add-gro-support.patch b/testing/linux-scst/r8169-add-gro-support.patch
new file mode 100644
index 0000000000..d8ca8d3ad6
--- /dev/null
+++ b/testing/linux-scst/r8169-add-gro-support.patch
@@ -0,0 +1,52 @@
1- Use napi_gro_receive() and vlan_gro_receive()
2- Enable GRO by default
3
4Tested on a RTL8111/8168 adapter
5
6Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
7CC: Francois Romieu <romieu@fr.zoreil.com>
8---
9 drivers/net/r8169.c | 10 ++++++++--
10 1 file changed, 8 insertions(+), 2 deletions(-)
11
12diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
13index 56a11e2..ddff42b 100644
14--- a/drivers/net/r8169.c
15+++ b/drivers/net/r8169.c
16@@ -1076,7 +1076,12 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
17 int ret;
18
19 if (vlgrp && (opts2 & RxVlanTag)) {
20- __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling);
21+ u16 vtag = swab16(opts2 & 0xffff);
22+
23+ if (polling)
24+ vlan_gro_receive(&tp->napi, vlgrp, vtag, skb);
25+ else
26+ __vlan_hwaccel_rx(skb, vlgrp, vtag, polling);
27 ret = 0;
28 } else
29 ret = -1;
30@@ -3186,6 +3191,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
31 #ifdef CONFIG_R8169_VLAN
32 dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
33 #endif
34+ dev->features |= NETIF_F_GRO;
35
36 tp->intr_mask = 0xffff;
37 tp->align = cfg->align;
38@@ -4561,7 +4567,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
39
40 if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) {
41 if (likely(polling))
42- netif_receive_skb(skb);
43+ napi_gro_receive(&tp->napi, skb);
44 else
45 netif_rx(skb);
46 }
47
48
49--
50To unsubscribe from this list: send the line "unsubscribe netdev" in
51the body of a message to majordomo@vger.kernel.org
52More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file
diff --git a/testing/linux-scst/r8169-fix-rx-checksum-offload.patch b/testing/linux-scst/r8169-fix-rx-checksum-offload.patch
new file mode 100644
index 0000000000..d979caac63
--- /dev/null
+++ b/testing/linux-scst/r8169-fix-rx-checksum-offload.patch
@@ -0,0 +1,62 @@
1From adea1ac7effbddbe60a9de6d63462bfe79289e59 Mon Sep 17 00:00:00 2001
2From: Eric Dumazet <eric.dumazet@gmail.com>
3Date: Sun, 5 Sep 2010 20:04:05 -0700
4Subject: [PATCH] r8169: fix rx checksum offload
5
6While porting GRO to r8169, I found this driver has a bug in its rx
7path.
8
9All skbs given to network stack had their ip_summed set to
10CHECKSUM_NONE, while hardware said they had correct TCP/UDP checksums.
11
12The reason is driver sets skb->ip_summed on the original skb before the
13copy eventually done by copybreak. The fresh skb gets the ip_summed =
14CHECKSUM_NONE value, forcing network stack to recompute checksum, and
15preventing my GRO patch to work.
16
17Fix is to make the ip_summed setting after skb copy.
18
19Note : rx_copybreak current value is 16383, so all frames are copied...
20
21Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
22Acked-by: Francois Romieu <romieu@fr.zoreil.com>
23Signed-off-by: David S. Miller <davem@davemloft.net>
24---
25 drivers/net/r8169.c | 6 ++----
26 1 files changed, 2 insertions(+), 4 deletions(-)
27
28diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
29index 07b3fb5..56a11e2 100644
30--- a/drivers/net/r8169.c
31+++ b/drivers/net/r8169.c
32@@ -4450,9 +4450,8 @@ static inline int rtl8169_fragmented_frame(u32 status)
33 return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
34 }
35
36-static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
37+static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
38 {
39- u32 opts1 = le32_to_cpu(desc->opts1);
40 u32 status = opts1 & RxProtoMask;
41
42 if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
43@@ -4546,8 +4545,6 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
44 continue;
45 }
46
47- rtl8169_rx_csum(skb, desc);
48-
49 if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) {
50 pci_dma_sync_single_for_device(pdev, addr,
51 pkt_size, PCI_DMA_FROMDEVICE);
52@@ -4558,6 +4555,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
53 tp->Rx_skbuff[entry] = NULL;
54 }
55
56+ rtl8169_rx_csum(skb, status);
57 skb_put(skb, pkt_size);
58 skb->protocol = eth_type_trans(skb, dev);
59
60--
611.7.2.3
62
diff --git a/testing/linux-scst/scst-2.6.35-svn-3161.patch b/testing/linux-scst/scst-2.6.35-svn-3161.patch
new file mode 100644
index 0000000000..6b1904a45d
--- /dev/null
+++ b/testing/linux-scst/scst-2.6.35-svn-3161.patch
@@ -0,0 +1,76656 @@
1Signed-off-by:
2
3diff -upkr linux-2.6.35/block/blk-map.c linux-2.6.35/block/blk-map.c
4--- linux-2.6.35/block/blk-map.c 2010-08-02 02:11:14.000000000 +0400
5+++ linux-2.6.35/block/blk-map.c 2010-11-26 18:03:58.107693773 +0300
6@@ -5,6 +5,8 @@
7 #include <linux/module.h>
8 #include <linux/bio.h>
9 #include <linux/blkdev.h>
10+#include <linux/scatterlist.h>
11+#include <linux/slab.h>
12 #include <scsi/sg.h> /* for struct sg_iovec */
13
14 #include "blk.h"
15@@ -271,6 +273,335 @@ int blk_rq_unmap_user(struct bio *bio)
16 }
17 EXPORT_SYMBOL(blk_rq_unmap_user);
18
19+struct blk_kern_sg_work {
20+ atomic_t bios_inflight;
21+ struct sg_table sg_table;
22+ struct scatterlist *src_sgl;
23+};
24+
25+static void blk_free_kern_sg_work(struct blk_kern_sg_work *bw)
26+{
27+ sg_free_table(&bw->sg_table);
28+ kfree(bw);
29+ return;
30+}
31+
32+static void blk_bio_map_kern_endio(struct bio *bio, int err)
33+{
34+ struct blk_kern_sg_work *bw = bio->bi_private;
35+
36+ if (bw != NULL) {
37+ /* Decrement the bios in processing and, if zero, free */
38+ BUG_ON(atomic_read(&bw->bios_inflight) <= 0);
39+ if (atomic_dec_and_test(&bw->bios_inflight)) {
40+ if ((bio_data_dir(bio) == READ) && (err == 0)) {
41+ unsigned long flags;
42+
43+ local_irq_save(flags); /* to protect KMs */
44+ sg_copy(bw->src_sgl, bw->sg_table.sgl, 0, 0,
45+ KM_BIO_DST_IRQ, KM_BIO_SRC_IRQ);
46+ local_irq_restore(flags);
47+ }
48+ blk_free_kern_sg_work(bw);
49+ }
50+ }
51+
52+ bio_put(bio);
53+ return;
54+}
55+
56+static int blk_rq_copy_kern_sg(struct request *rq, struct scatterlist *sgl,
57+ int nents, struct blk_kern_sg_work **pbw,
58+ gfp_t gfp, gfp_t page_gfp)
59+{
60+ int res = 0, i;
61+ struct scatterlist *sg;
62+ struct scatterlist *new_sgl;
63+ int new_sgl_nents;
64+ size_t len = 0, to_copy;
65+ struct blk_kern_sg_work *bw;
66+
67+ bw = kzalloc(sizeof(*bw), gfp);
68+ if (bw == NULL)
69+ goto out;
70+
71+ bw->src_sgl = sgl;
72+
73+ for_each_sg(sgl, sg, nents, i)
74+ len += sg->length;
75+ to_copy = len;
76+
77+ new_sgl_nents = PFN_UP(len);
78+
79+ res = sg_alloc_table(&bw->sg_table, new_sgl_nents, gfp);
80+ if (res != 0)
81+ goto out_free_bw;
82+
83+ new_sgl = bw->sg_table.sgl;
84+
85+ for_each_sg(new_sgl, sg, new_sgl_nents, i) {
86+ struct page *pg;
87+
88+ pg = alloc_page(page_gfp);
89+ if (pg == NULL)
90+ goto err_free_new_sgl;
91+
92+ sg_assign_page(sg, pg);
93+ sg->length = min_t(size_t, PAGE_SIZE, len);
94+
95+ len -= PAGE_SIZE;
96+ }
97+
98+ if (rq_data_dir(rq) == WRITE) {
99+ /*
100+ * We need to limit amount of copied data to to_copy, because
101+ * sgl might have the last element in sgl not marked as last in
102+ * SG chaining.
103+ */
104+ sg_copy(new_sgl, sgl, 0, to_copy,
105+ KM_USER0, KM_USER1);
106+ }
107+
108+ *pbw = bw;
109+ /*
110+ * REQ_COPY_USER name is misleading. It should be something like
111+ * REQ_HAS_TAIL_SPACE_FOR_PADDING.
112+ */
113+ rq->cmd_flags |= REQ_COPY_USER;
114+
115+out:
116+ return res;
117+
118+err_free_new_sgl:
119+ for_each_sg(new_sgl, sg, new_sgl_nents, i) {
120+ struct page *pg = sg_page(sg);
121+ if (pg == NULL)
122+ break;
123+ __free_page(pg);
124+ }
125+ sg_free_table(&bw->sg_table);
126+
127+out_free_bw:
128+ kfree(bw);
129+ res = -ENOMEM;
130+ goto out;
131+}
132+
133+static int __blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
134+ int nents, struct blk_kern_sg_work *bw, gfp_t gfp)
135+{
136+ int res;
137+ struct request_queue *q = rq->q;
138+ int rw = rq_data_dir(rq);
139+ int max_nr_vecs, i;
140+ size_t tot_len;
141+ bool need_new_bio;
142+ struct scatterlist *sg, *prev_sg = NULL;
143+ struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
144+ int bios;
145+
146+ if (unlikely((sgl == NULL) || (sgl->length == 0) || (nents <= 0))) {
147+ WARN_ON(1);
148+ res = -EINVAL;
149+ goto out;
150+ }
151+
152+ /*
153+ * Let's keep each bio allocation inside a single page to decrease
154+ * probability of failure.
155+ */
156+ max_nr_vecs = min_t(size_t,
157+ ((PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec)),
158+ BIO_MAX_PAGES);
159+
160+ need_new_bio = true;
161+ tot_len = 0;
162+ bios = 0;
163+ for_each_sg(sgl, sg, nents, i) {
164+ struct page *page = sg_page(sg);
165+ void *page_addr = page_address(page);
166+ size_t len = sg->length, l;
167+ size_t offset = sg->offset;
168+
169+ tot_len += len;
170+ prev_sg = sg;
171+
172+ /*
173+ * Each segment must be aligned on DMA boundary and
174+ * not on stack. The last one may have unaligned
175+ * length as long as the total length is aligned to
176+ * DMA padding alignment.
177+ */
178+ if (i == nents - 1)
179+ l = 0;
180+ else
181+ l = len;
182+ if (((sg->offset | l) & queue_dma_alignment(q)) ||
183+ (page_addr && object_is_on_stack(page_addr + sg->offset))) {
184+ res = -EINVAL;
185+ goto out_free_bios;
186+ }
187+
188+ while (len > 0) {
189+ size_t bytes;
190+ int rc;
191+
192+ if (need_new_bio) {
193+ bio = bio_kmalloc(gfp, max_nr_vecs);
194+ if (bio == NULL) {
195+ res = -ENOMEM;
196+ goto out_free_bios;
197+ }
198+
199+ if (rw == WRITE)
200+ bio->bi_rw |= 1 << BIO_RW;
201+
202+ bios++;
203+ bio->bi_private = bw;
204+ bio->bi_end_io = blk_bio_map_kern_endio;
205+
206+ if (hbio == NULL)
207+ hbio = tbio = bio;
208+ else
209+ tbio = tbio->bi_next = bio;
210+ }
211+
212+ bytes = min_t(size_t, len, PAGE_SIZE - offset);
213+
214+ rc = bio_add_pc_page(q, bio, page, bytes, offset);
215+ if (rc < bytes) {
216+ if (unlikely(need_new_bio || (rc < 0))) {
217+ if (rc < 0)
218+ res = rc;
219+ else
220+ res = -EIO;
221+ goto out_free_bios;
222+ } else {
223+ need_new_bio = true;
224+ len -= rc;
225+ offset += rc;
226+ continue;
227+ }
228+ }
229+
230+ need_new_bio = false;
231+ offset = 0;
232+ len -= bytes;
233+ page = nth_page(page, 1);
234+ }
235+ }
236+
237+ if (hbio == NULL) {
238+ res = -EINVAL;
239+ goto out_free_bios;
240+ }
241+
242+ /* Total length must be aligned on DMA padding alignment */
243+ if ((tot_len & q->dma_pad_mask) &&
244+ !(rq->cmd_flags & REQ_COPY_USER)) {
245+ res = -EINVAL;
246+ goto out_free_bios;
247+ }
248+
249+ if (bw != NULL)
250+ atomic_set(&bw->bios_inflight, bios);
251+
252+ while (hbio != NULL) {
253+ bio = hbio;
254+ hbio = hbio->bi_next;
255+ bio->bi_next = NULL;
256+
257+ blk_queue_bounce(q, &bio);
258+
259+ res = blk_rq_append_bio(q, rq, bio);
260+ if (unlikely(res != 0)) {
261+ bio->bi_next = hbio;
262+ hbio = bio;
263+ /* We can have one or more bios bounced */
264+ goto out_unmap_bios;
265+ }
266+ }
267+
268+ rq->buffer = NULL;
269+out:
270+ return res;
271+
272+out_unmap_bios:
273+ blk_rq_unmap_kern_sg(rq, res);
274+
275+out_free_bios:
276+ while (hbio != NULL) {
277+ bio = hbio;
278+ hbio = hbio->bi_next;
279+ bio_put(bio);
280+ }
281+ goto out;
282+}
283+
284+/**
285+ * blk_rq_map_kern_sg - map kernel data to a request, for REQ_TYPE_BLOCK_PC
286+ * @rq: request to fill
287+ * @sgl: area to map
288+ * @nents: number of elements in @sgl
289+ * @gfp: memory allocation flags
290+ *
291+ * Description:
292+ * Data will be mapped directly if possible. Otherwise a bounce
293+ * buffer will be used.
294+ */
295+int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
296+ int nents, gfp_t gfp)
297+{
298+ int res;
299+
300+ res = __blk_rq_map_kern_sg(rq, sgl, nents, NULL, gfp);
301+ if (unlikely(res != 0)) {
302+ struct blk_kern_sg_work *bw = NULL;
303+
304+ res = blk_rq_copy_kern_sg(rq, sgl, nents, &bw,
305+ gfp, rq->q->bounce_gfp | gfp);
306+ if (unlikely(res != 0))
307+ goto out;
308+
309+ res = __blk_rq_map_kern_sg(rq, bw->sg_table.sgl,
310+ bw->sg_table.nents, bw, gfp);
311+ if (res != 0) {
312+ blk_free_kern_sg_work(bw);
313+ goto out;
314+ }
315+ }
316+
317+ rq->buffer = NULL;
318+
319+out:
320+ return res;
321+}
322+EXPORT_SYMBOL(blk_rq_map_kern_sg);
323+
324+/**
325+ * blk_rq_unmap_kern_sg - unmap a request with kernel sg
326+ * @rq: request to unmap
327+ * @err: non-zero error code
328+ *
329+ * Description:
330+ * Unmap a rq previously mapped by blk_rq_map_kern_sg(). Must be called
331+ * only in case of an error!
332+ */
333+void blk_rq_unmap_kern_sg(struct request *rq, int err)
334+{
335+ struct bio *bio = rq->bio;
336+
337+ while (bio) {
338+ struct bio *b = bio;
339+ bio = bio->bi_next;
340+ b->bi_end_io(b, err);
341+ }
342+ rq->bio = NULL;
343+
344+ return;
345+}
346+EXPORT_SYMBOL(blk_rq_unmap_kern_sg);
347+
348 /**
349 * blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage
350 * @q: request queue where request should be inserted
351diff -upkr linux-2.6.35/include/linux/blkdev.h linux-2.6.35/include/linux/blkdev.h
352--- linux-2.6.35/include/linux/blkdev.h 2010-08-02 02:11:14.000000000 +0400
353+++ linux-2.6.35/include/linux/blkdev.h 2010-08-04 12:21:59.737128732 +0400
354@@ -832,6 +834,9 @@ extern int blk_rq_map_kern(struct reques
355 extern int blk_rq_map_user_iov(struct request_queue *, struct request *,
356 struct rq_map_data *, struct sg_iovec *, int,
357 unsigned int, gfp_t);
358+extern int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
359+ int nents, gfp_t gfp);
360+extern void blk_rq_unmap_kern_sg(struct request *rq, int err);
361 extern int blk_execute_rq(struct request_queue *, struct gendisk *,
362 struct request *, int);
363 extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *,
364diff -upkr linux-2.6.35/include/linux/scatterlist.h linux-2.6.35/include/linux/scatterlist.h
365--- linux-2.6.35/include/linux/scatterlist.h 2010-08-02 02:11:14.000000000 +0400
366+++ linux-2.6.35/include/linux/scatterlist.h 2010-08-04 12:21:59.741129485 +0400
367@@ -3,6 +3,7 @@
368
369 #include <asm/types.h>
370 #include <asm/scatterlist.h>
371+#include <asm/kmap_types.h>
372 #include <linux/mm.h>
373 #include <linux/string.h>
374 #include <asm/io.h>
375@@ -218,6 +219,10 @@ size_t sg_copy_from_buffer(struct scatte
376 size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
377 void *buf, size_t buflen);
378
379+int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg,
380+ int nents_to_copy, size_t copy_len,
381+ enum km_type d_km_type, enum km_type s_km_type);
382+
383 /*
384 * Maximum number of entries that will be allocated in one piece, if
385 * a list larger than this is required then chaining will be utilized.
386diff -upkr linux-2.6.35/lib/scatterlist.c linux-2.6.35/lib/scatterlist.c
387--- linux-2.6.35/lib/scatterlist.c 2010-08-02 02:11:14.000000000 +0400
388+++ linux-2.6.35/lib/scatterlist.c 2010-08-04 12:21:59.741129485 +0400
389@@ -494,3 +494,132 @@ size_t sg_copy_to_buffer(struct scatterl
390 return sg_copy_buffer(sgl, nents, buf, buflen, 1);
391 }
392 EXPORT_SYMBOL(sg_copy_to_buffer);
393+
394+/*
395+ * Can switch to the next dst_sg element, so, to copy to strictly only
396+ * one dst_sg element, it must be either last in the chain, or
397+ * copy_len == dst_sg->length.
398+ */
399+static int sg_copy_elem(struct scatterlist **pdst_sg, size_t *pdst_len,
400+ size_t *pdst_offs, struct scatterlist *src_sg,
401+ size_t copy_len,
402+ enum km_type d_km_type, enum km_type s_km_type)
403+{
404+ int res = 0;
405+ struct scatterlist *dst_sg;
406+ size_t src_len, dst_len, src_offs, dst_offs;
407+ struct page *src_page, *dst_page;
408+
409+ dst_sg = *pdst_sg;
410+ dst_len = *pdst_len;
411+ dst_offs = *pdst_offs;
412+ dst_page = sg_page(dst_sg);
413+
414+ src_page = sg_page(src_sg);
415+ src_len = src_sg->length;
416+ src_offs = src_sg->offset;
417+
418+ do {
419+ void *saddr, *daddr;
420+ size_t n;
421+
422+ saddr = kmap_atomic(src_page +
423+ (src_offs >> PAGE_SHIFT), s_km_type) +
424+ (src_offs & ~PAGE_MASK);
425+ daddr = kmap_atomic(dst_page +
426+ (dst_offs >> PAGE_SHIFT), d_km_type) +
427+ (dst_offs & ~PAGE_MASK);
428+
429+ if (((src_offs & ~PAGE_MASK) == 0) &&
430+ ((dst_offs & ~PAGE_MASK) == 0) &&
431+ (src_len >= PAGE_SIZE) && (dst_len >= PAGE_SIZE) &&
432+ (copy_len >= PAGE_SIZE)) {
433+ copy_page(daddr, saddr);
434+ n = PAGE_SIZE;
435+ } else {
436+ n = min_t(size_t, PAGE_SIZE - (dst_offs & ~PAGE_MASK),
437+ PAGE_SIZE - (src_offs & ~PAGE_MASK));
438+ n = min(n, src_len);
439+ n = min(n, dst_len);
440+ n = min_t(size_t, n, copy_len);
441+ memcpy(daddr, saddr, n);
442+ }
443+ dst_offs += n;
444+ src_offs += n;
445+
446+ kunmap_atomic(saddr, s_km_type);
447+ kunmap_atomic(daddr, d_km_type);
448+
449+ res += n;
450+ copy_len -= n;
451+ if (copy_len == 0)
452+ goto out;
453+
454+ src_len -= n;
455+ dst_len -= n;
456+ if (dst_len == 0) {
457+ dst_sg = sg_next(dst_sg);
458+ if (dst_sg == NULL)
459+ goto out;
460+ dst_page = sg_page(dst_sg);
461+ dst_len = dst_sg->length;
462+ dst_offs = dst_sg->offset;
463+ }
464+ } while (src_len > 0);
465+
466+out:
467+ *pdst_sg = dst_sg;
468+ *pdst_len = dst_len;
469+ *pdst_offs = dst_offs;
470+ return res;
471+}
472+
473+/**
474+ * sg_copy - copy one SG vector to another
475+ * @dst_sg: destination SG
476+ * @src_sg: source SG
477+ * @nents_to_copy: maximum number of entries to copy
478+ * @copy_len: maximum amount of data to copy. If 0, then copy all.
479+ * @d_km_type: kmap_atomic type for the destination SG
480+ * @s_km_type: kmap_atomic type for the source SG
481+ *
482+ * Description:
483+ * Data from the source SG vector will be copied to the destination SG
484+ * vector. End of the vectors will be determined by sg_next() returning
485+ * NULL. Returns number of bytes copied.
486+ */
487+int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg,
488+ int nents_to_copy, size_t copy_len,
489+ enum km_type d_km_type, enum km_type s_km_type)
490+{
491+ int res = 0;
492+ size_t dst_len, dst_offs;
493+
494+ if (copy_len == 0)
495+ copy_len = 0x7FFFFFFF; /* copy all */
496+
497+ if (nents_to_copy == 0)
498+ nents_to_copy = 0x7FFFFFFF; /* copy all */
499+
500+ dst_len = dst_sg->length;
501+ dst_offs = dst_sg->offset;
502+
503+ do {
504+ int copied = sg_copy_elem(&dst_sg, &dst_len, &dst_offs,
505+ src_sg, copy_len, d_km_type, s_km_type);
506+ copy_len -= copied;
507+ res += copied;
508+ if ((copy_len == 0) || (dst_sg == NULL))
509+ goto out;
510+
511+ nents_to_copy--;
512+ if (nents_to_copy == 0)
513+ goto out;
514+
515+ src_sg = sg_next(src_sg);
516+ } while (src_sg != NULL);
517+
518+out:
519+ return res;
520+}
521+EXPORT_SYMBOL(sg_copy);
522
523diff -upkr linux-2.6.35/include/linux/mm_types.h linux-2.6.35/include/linux/mm_types.h
524--- linux-2.6.35/include/linux/mm_types.h 2010-05-17 01:17:36.000000000 +0400
525+++ linux-2.6.35/include/linux/mm_types.h 2010-05-24 14:51:40.000000000 +0400
526@@ -100,6 +100,18 @@ struct page {
527 */
528 void *shadow;
529 #endif
530+
531+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
532+ /*
533+ * Used to implement support for notification on zero-copy TCP transfer
534+ * completion. It might look as not good to have this field here and
535+ * it's better to have it in struct sk_buff, but it would make the code
536+ * much more complicated and fragile, since all skb then would have to
537+ * contain only pages with the same value in this field.
538+ */
539+ void *net_priv;
540+#endif
541+
542 };
543
544 /*
545diff -upkr linux-2.6.35/include/linux/net.h linux-2.6.35/include/linux/net.h
546--- linux-2.6.35/include/linux/net.h 2010-05-17 01:17:36.000000000 +0400
547+++ linux-2.6.35/include/linux/net.h 2010-05-24 14:51:40.000000000 +0400
548@@ -20,6 +20,7 @@
549
550 #include <linux/socket.h>
551 #include <asm/socket.h>
552+#include <linux/mm.h>
553
554 #define NPROTO AF_MAX
555
556@@ -291,5 +292,44 @@ extern int kernel_sock_shutdown(struct s
557 extern struct ratelimit_state net_ratelimit_state;
558 #endif
559
560+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
561+/* Support for notification on zero-copy TCP transfer completion */
562+typedef void (*net_get_page_callback_t)(struct page *page);
563+typedef void (*net_put_page_callback_t)(struct page *page);
564+
565+extern net_get_page_callback_t net_get_page_callback;
566+extern net_put_page_callback_t net_put_page_callback;
567+
568+extern int net_set_get_put_page_callbacks(
569+ net_get_page_callback_t get_callback,
570+ net_put_page_callback_t put_callback);
571+
572+/*
573+ * See comment for net_set_get_put_page_callbacks() why those functions
574+ * don't need any protection.
575+ */
576+static inline void net_get_page(struct page *page)
577+{
578+ if (page->net_priv != 0)
579+ net_get_page_callback(page);
580+ get_page(page);
581+}
582+static inline void net_put_page(struct page *page)
583+{
584+ if (page->net_priv != 0)
585+ net_put_page_callback(page);
586+ put_page(page);
587+}
588+#else
589+static inline void net_get_page(struct page *page)
590+{
591+ get_page(page);
592+}
593+static inline void net_put_page(struct page *page)
594+{
595+ put_page(page);
596+}
597+#endif /* CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION */
598+
599 #endif /* __KERNEL__ */
600 #endif /* _LINUX_NET_H */
601diff -upkr linux-2.6.35/net/core/dev.c linux-2.6.35/net/core/dev.c
602--- linux-2.6.35/net/core/dev.c 2010-05-17 01:17:36.000000000 +0400
603+++ linux-2.6.35/net/core/dev.c 2010-05-24 14:51:40.000000000 +0400
604@@ -3130,7 +3130,7 @@ pull:
605 skb_shinfo(skb)->frags[0].size -= grow;
606
607 if (unlikely(!skb_shinfo(skb)->frags[0].size)) {
608- put_page(skb_shinfo(skb)->frags[0].page);
609+ net_put_page(skb_shinfo(skb)->frags[0].page);
610 memmove(skb_shinfo(skb)->frags,
611 skb_shinfo(skb)->frags + 1,
612 --skb_shinfo(skb)->nr_frags);
613diff -upkr linux-2.6.35/net/core/skbuff.c linux-2.6.35/net/core/skbuff.c
614--- linux-2.6.35/net/core/skbuff.c 2010-05-17 01:17:36.000000000 +0400
615+++ linux-2.6.35/net/core/skbuff.c 2010-05-24 14:51:40.000000000 +0400
616@@ -76,13 +76,13 @@ static struct kmem_cache *skbuff_fclone_
617 static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
618 struct pipe_buffer *buf)
619 {
620- put_page(buf->page);
621+ net_put_page(buf->page);
622 }
623
624 static void sock_pipe_buf_get(struct pipe_inode_info *pipe,
625 struct pipe_buffer *buf)
626 {
627- get_page(buf->page);
628+ net_get_page(buf->page);
629 }
630
631 static int sock_pipe_buf_steal(struct pipe_inode_info *pipe,
632@@ -337,7 +337,7 @@ static void skb_release_data(struct sk_b
633 if (skb_shinfo(skb)->nr_frags) {
634 int i;
635 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
636- put_page(skb_shinfo(skb)->frags[i].page);
637+ net_put_page(skb_shinfo(skb)->frags[i].page);
638 }
639
640 if (skb_has_frags(skb))
641@@ -754,7 +754,7 @@ struct sk_buff *pskb_copy(struct sk_buff
642
643 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
644 skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
645- get_page(skb_shinfo(n)->frags[i].page);
646+ net_get_page(skb_shinfo(n)->frags[i].page);
647 }
648 skb_shinfo(n)->nr_frags = i;
649 }
650@@ -820,7 +820,7 @@ int pskb_expand_head(struct sk_buff *skb
651 sizeof(struct skb_shared_info));
652
653 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
654- get_page(skb_shinfo(skb)->frags[i].page);
655+ net_get_page(skb_shinfo(skb)->frags[i].page);
656
657 if (skb_has_frags(skb))
658 skb_clone_fraglist(skb);
659@@ -1097,7 +1097,7 @@ drop_pages:
660 skb_shinfo(skb)->nr_frags = i;
661
662 for (; i < nfrags; i++)
663- put_page(skb_shinfo(skb)->frags[i].page);
664+ net_put_page(skb_shinfo(skb)->frags[i].page);
665
666 if (skb_has_frags(skb))
667 skb_drop_fraglist(skb);
668@@ -1266,7 +1266,7 @@ pull_pages:
669 k = 0;
670 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
671 if (skb_shinfo(skb)->frags[i].size <= eat) {
672- put_page(skb_shinfo(skb)->frags[i].page);
673+ net_put_page(skb_shinfo(skb)->frags[i].page);
674 eat -= skb_shinfo(skb)->frags[i].size;
675 } else {
676 skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
677@@ -1367,7 +1367,7 @@ EXPORT_SYMBOL(skb_copy_bits);
678 */
679 static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i)
680 {
681- put_page(spd->pages[i]);
682+ net_put_page(spd->pages[i]);
683 }
684
685 static inline struct page *linear_to_page(struct page *page, unsigned int *len,
686@@ -1391,7 +1391,7 @@ new_page:
687 off = sk->sk_sndmsg_off;
688 mlen = PAGE_SIZE - off;
689 if (mlen < 64 && mlen < *len) {
690- put_page(p);
691+ net_put_page(p);
692 goto new_page;
693 }
694
695@@ -1401,7 +1401,7 @@ new_page:
696 memcpy(page_address(p) + off, page_address(page) + *offset, *len);
697 sk->sk_sndmsg_off += *len;
698 *offset = off;
699- get_page(p);
700+ net_get_page(p);
701
702 return p;
703 }
704@@ -1423,7 +1423,7 @@ static inline int spd_fill_page(struct s
705 if (!page)
706 return 1;
707 } else
708- get_page(page);
709+ net_get_page(page);
710
711 spd->pages[spd->nr_pages] = page;
712 spd->partial[spd->nr_pages].len = *len;
713@@ -2056,7 +2056,7 @@ static inline void skb_split_no_header(s
714 * where splitting is expensive.
715 * 2. Split is accurately. We make this.
716 */
717- get_page(skb_shinfo(skb)->frags[i].page);
718+ net_get_page(skb_shinfo(skb)->frags[i].page);
719 skb_shinfo(skb1)->frags[0].page_offset += len - pos;
720 skb_shinfo(skb1)->frags[0].size -= len - pos;
721 skb_shinfo(skb)->frags[i].size = len - pos;
722@@ -2178,7 +2178,7 @@ int skb_shift(struct sk_buff *tgt, struc
723 to++;
724
725 } else {
726- get_page(fragfrom->page);
727+ net_get_page(fragfrom->page);
728 fragto->page = fragfrom->page;
729 fragto->page_offset = fragfrom->page_offset;
730 fragto->size = todo;
731@@ -2200,7 +2200,7 @@ int skb_shift(struct sk_buff *tgt, struc
732 fragto = &skb_shinfo(tgt)->frags[merge];
733
734 fragto->size += fragfrom->size;
735- put_page(fragfrom->page);
736+ net_put_page(fragfrom->page);
737 }
738
739 /* Reposition in the original skb */
740@@ -2598,7 +2598,7 @@ struct sk_buff *skb_segment(struct sk_bu
741
742 while (pos < offset + len && i < nfrags) {
743 *frag = skb_shinfo(skb)->frags[i];
744- get_page(frag->page);
745+ net_get_page(frag->page);
746 size = frag->size;
747
748 if (pos < offset) {
749diff -upkr linux-2.6.35/net/ipv4/ip_output.c linux-2.6.35/net/ipv4/ip_output.c
750--- linux-2.6.35/net/ipv4/ip_output.c 2010-05-17 01:17:36.000000000 +0400
751+++ linux-2.6.35/net/ipv4/ip_output.c 2010-05-24 14:51:40.000000000 +0400
752@@ -1035,7 +1035,7 @@ alloc_new_skb:
753 err = -EMSGSIZE;
754 goto error;
755 }
756- get_page(page);
757+ net_get_page(page);
758 skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
759 frag = &skb_shinfo(skb)->frags[i];
760 }
761@@ -1194,7 +1194,7 @@ ssize_t ip_append_page(struct sock *sk,
762 if (skb_can_coalesce(skb, i, page, offset)) {
763 skb_shinfo(skb)->frags[i-1].size += len;
764 } else if (i < MAX_SKB_FRAGS) {
765- get_page(page);
766+ net_get_page(page);
767 skb_fill_page_desc(skb, i, page, offset, len);
768 } else {
769 err = -EMSGSIZE;
770diff -upkr linux-2.6.35/net/ipv4/Makefile linux-2.6.35/net/ipv4/Makefile
771--- linux-2.6.35/net/ipv4/Makefile 2010-05-17 01:17:36.000000000 +0400
772+++ linux-2.6.35/net/ipv4/Makefile 2010-05-24 14:51:40.000000000 +0400
773@@ -49,6 +49,7 @@ obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
774 obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o
775 obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o
776 obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
777+obj-$(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) += tcp_zero_copy.o
778
779 obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
780 xfrm4_output.o
781diff -upkr linux-2.6.35/net/ipv4/tcp.c linux-2.6.35/net/ipv4/tcp.c
782--- linux-2.6.35/net/ipv4/tcp.c 2010-05-17 01:17:36.000000000 +0400
783+++ linux-2.6.35/net/ipv4/tcp.c 2010-05-24 14:51:40.000000000 +0400
784@@ -801,7 +801,7 @@ new_segment:
785 if (can_coalesce) {
786 skb_shinfo(skb)->frags[i - 1].size += copy;
787 } else {
788- get_page(page);
789+ net_get_page(page);
790 skb_fill_page_desc(skb, i, page, offset, copy);
791 }
792
793@@ -1010,7 +1010,7 @@ new_segment:
794 goto new_segment;
795 } else if (page) {
796 if (off == PAGE_SIZE) {
797- put_page(page);
798+ net_put_page(page);
799 TCP_PAGE(sk) = page = NULL;
800 off = 0;
801 }
802@@ -1051,9 +1051,9 @@ new_segment:
803 } else {
804 skb_fill_page_desc(skb, i, page, off, copy);
805 if (TCP_PAGE(sk)) {
806- get_page(page);
807+ net_get_page(page);
808 } else if (off + copy < PAGE_SIZE) {
809- get_page(page);
810+ net_get_page(page);
811 TCP_PAGE(sk) = page;
812 }
813 }
814diff -upkr linux-2.6.35/net/ipv4/tcp_output.c linux-2.6.35/net/ipv4/tcp_output.c
815--- linux-2.6.35/net/ipv4/tcp_output.c 2010-05-17 01:17:36.000000000 +0400
816+++ linux-2.6.35/net/ipv4/tcp_output.c 2010-05-24 14:51:40.000000000 +0400
817@@ -1085,7 +1085,7 @@ static void __pskb_trim_head(struct sk_b
818 k = 0;
819 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
820 if (skb_shinfo(skb)->frags[i].size <= eat) {
821- put_page(skb_shinfo(skb)->frags[i].page);
822+ net_put_page(skb_shinfo(skb)->frags[i].page);
823 eat -= skb_shinfo(skb)->frags[i].size;
824 } else {
825 skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
826diff -upkr linux-2.6.35/net/ipv4/tcp_zero_copy.c linux-2.6.35/net/ipv4/tcp_zero_copy.c
827--- linux-2.6.35/net/ipv4/tcp_zero_copy.c 2010-03-01 17:30:31.000000000 +0300
828+++ linux-2.6.35/net/ipv4/tcp_zero_copy.c 2010-05-24 14:51:40.000000000 +0400
829@@ -0,0 +1,49 @@
830+/*
831+ * Support routines for TCP zero copy transmit
832+ *
833+ * Created by Vladislav Bolkhovitin
834+ *
835+ * This program is free software; you can redistribute it and/or
836+ * modify it under the terms of the GNU General Public License
837+ * version 2 as published by the Free Software Foundation.
838+ */
839+
840+#include <linux/skbuff.h>
841+
842+net_get_page_callback_t net_get_page_callback __read_mostly;
843+EXPORT_SYMBOL(net_get_page_callback);
844+
845+net_put_page_callback_t net_put_page_callback __read_mostly;
846+EXPORT_SYMBOL(net_put_page_callback);
847+
848+/*
849+ * Caller of this function must ensure that at the moment when it's called
850+ * there are no pages in the system with net_priv field set to non-zero
851+ * value. Hence, this function, as well as net_get_page() and net_put_page(),
852+ * don't need any protection.
853+ */
854+int net_set_get_put_page_callbacks(
855+ net_get_page_callback_t get_callback,
856+ net_put_page_callback_t put_callback)
857+{
858+ int res = 0;
859+
860+ if ((net_get_page_callback != NULL) && (get_callback != NULL) &&
861+ (net_get_page_callback != get_callback)) {
862+ res = -EBUSY;
863+ goto out;
864+ }
865+
866+ if ((net_put_page_callback != NULL) && (put_callback != NULL) &&
867+ (net_put_page_callback != put_callback)) {
868+ res = -EBUSY;
869+ goto out;
870+ }
871+
872+ net_get_page_callback = get_callback;
873+ net_put_page_callback = put_callback;
874+
875+out:
876+ return res;
877+}
878+EXPORT_SYMBOL(net_set_get_put_page_callbacks);
879diff -upkr linux-2.6.35/net/ipv6/ip6_output.c linux-2.6.35/net/ipv6/ip6_output.c
880--- linux-2.6.35/net/ipv6/ip6_output.c 2010-05-17 01:17:36.000000000 +0400
881+++ linux-2.6.35/net/ipv6/ip6_output.c 2010-05-24 14:51:40.000000000 +0400
882@@ -1383,7 +1383,7 @@ alloc_new_skb:
883 err = -EMSGSIZE;
884 goto error;
885 }
886- get_page(page);
887+ net_get_page(page);
888 skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
889 frag = &skb_shinfo(skb)->frags[i];
890 }
891diff -upkr linux-2.6.35/net/Kconfig linux-2.6.35/net/Kconfig
892--- linux-2.6.35/net/Kconfig 2010-05-17 01:17:36.000000000 +0400
893+++ linux-2.6.35/net/Kconfig 2010-05-24 14:51:40.000000000 +0400
894@@ -72,6 +72,18 @@ config INET
895
896 Short answer: say Y.
897
898+config TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION
899+ bool "TCP/IP zero-copy transfer completion notification"
900+ depends on INET
901+ default SCST_ISCSI
902+ ---help---
903+ Adds support for sending a notification upon completion of a
904+ zero-copy TCP/IP transfer. This can speed up certain TCP/IP
905+ software. Currently this is only used by the iSCSI target driver
906+ iSCSI-SCST.
907+
908+ If unsure, say N.
909+
910 if INET
911 source "net/ipv4/Kconfig"
912 source "net/ipv6/Kconfig"
913diff -uprN orig/linux-2.6.35/include/scst/scst.h linux-2.6.35/include/scst/scst.h
914--- orig/linux-2.6.35/include/scst/scst.h
915+++ linux-2.6.35/include/scst/scst.h
916@@ -0,0 +1,3511 @@
917+/*
918+ * include/scst.h
919+ *
920+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
921+ * Copyright (C) 2004 - 2005 Leonid Stoljar
922+ * Copyright (C) 2007 - 2010 ID7 Ltd.
923+ *
924+ * Main SCSI target mid-level include file.
925+ *
926+ * This program is free software; you can redistribute it and/or
927+ * modify it under the terms of the GNU General Public License
928+ * as published by the Free Software Foundation, version 2
929+ * of the License.
930+ *
931+ * This program is distributed in the hope that it will be useful,
932+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
933+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
934+ * GNU General Public License for more details.
935+ */
936+
937+#ifndef __SCST_H
938+#define __SCST_H
939+
940+#include <linux/types.h>
941+#include <linux/version.h>
942+#include <linux/blkdev.h>
943+#include <linux/interrupt.h>
944+#include <linux/wait.h>
945+
946+/* #define CONFIG_SCST_PROC */
947+
948+#include <scsi/scsi_cmnd.h>
949+#include <scsi/scsi_device.h>
950+#include <scsi/scsi_eh.h>
951+#include <scsi/scsi.h>
952+
953+#include <scst/scst_const.h>
954+
955+#include <scst/scst_sgv.h>
956+
957+/*
958+ * Version numbers, the same as for the kernel.
959+ *
960+ * Changing it don't forget to change SCST_FIO_REV in scst_vdisk.c
961+ * and FIO_REV in usr/fileio/common.h as well.
962+ */
963+#define SCST_VERSION(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + d)
964+#define SCST_VERSION_CODE SCST_VERSION(2, 0, 0, 0)
965+#define SCST_VERSION_STRING_SUFFIX
966+#define SCST_VERSION_STRING "2.0.0-rc3" SCST_VERSION_STRING_SUFFIX
967+#define SCST_INTERFACE_VERSION \
968+ SCST_VERSION_STRING "$Revision: 3153 $" SCST_CONST_VERSION
969+
970+#define SCST_LOCAL_NAME "scst_local"
971+
972+/*************************************************************
973+ ** States of command processing state machine. At first,
974+ ** "active" states, then - "passive" ones. This is to have
975+ ** more efficient generated code of the corresponding
976+ ** "switch" statements.
977+ *************************************************************/
978+
979+/* Dev handler's parse() is going to be called */
980+#define SCST_CMD_STATE_PARSE 0
981+
982+/* Allocation of the cmd's data buffer */
983+#define SCST_CMD_STATE_PREPARE_SPACE 1
984+
985+/* Calling preprocessing_done() */
986+#define SCST_CMD_STATE_PREPROCESSING_DONE 2
987+
988+/* Target driver's rdy_to_xfer() is going to be called */
989+#define SCST_CMD_STATE_RDY_TO_XFER 3
990+
991+/* Target driver's pre_exec() is going to be called */
992+#define SCST_CMD_STATE_TGT_PRE_EXEC 4
993+
994+/* Cmd is going to be sent for execution */
995+#define SCST_CMD_STATE_SEND_FOR_EXEC 5
996+
997+/* Cmd is being checked if it should be executed locally */
998+#define SCST_CMD_STATE_LOCAL_EXEC 6
999+
1000+/* Cmd is ready for execution */
1001+#define SCST_CMD_STATE_REAL_EXEC 7
1002+
1003+/* Internal post-exec checks */
1004+#define SCST_CMD_STATE_PRE_DEV_DONE 8
1005+
1006+/* Internal MODE SELECT pages related checks */
1007+#define SCST_CMD_STATE_MODE_SELECT_CHECKS 9
1008+
1009+/* Dev handler's dev_done() is going to be called */
1010+#define SCST_CMD_STATE_DEV_DONE 10
1011+
1012+/* Target driver's xmit_response() is going to be called */
1013+#define SCST_CMD_STATE_PRE_XMIT_RESP 11
1014+
1015+/* Target driver's xmit_response() is going to be called */
1016+#define SCST_CMD_STATE_XMIT_RESP 12
1017+
1018+/* Cmd finished */
1019+#define SCST_CMD_STATE_FINISHED 13
1020+
1021+/* Internal cmd finished */
1022+#define SCST_CMD_STATE_FINISHED_INTERNAL 14
1023+
1024+#define SCST_CMD_STATE_LAST_ACTIVE (SCST_CMD_STATE_FINISHED_INTERNAL+100)
1025+
1026+/* A cmd is created, but scst_cmd_init_done() not called */
1027+#define SCST_CMD_STATE_INIT_WAIT (SCST_CMD_STATE_LAST_ACTIVE+1)
1028+
1029+/* LUN translation (cmd->tgt_dev assignment) */
1030+#define SCST_CMD_STATE_INIT (SCST_CMD_STATE_LAST_ACTIVE+2)
1031+
1032+/* Waiting for scst_restart_cmd() */
1033+#define SCST_CMD_STATE_PREPROCESSING_DONE_CALLED (SCST_CMD_STATE_LAST_ACTIVE+3)
1034+
1035+/* Waiting for data from the initiator (until scst_rx_data() called) */
1036+#define SCST_CMD_STATE_DATA_WAIT (SCST_CMD_STATE_LAST_ACTIVE+4)
1037+
1038+/* Waiting for CDB's execution finish */
1039+#define SCST_CMD_STATE_REAL_EXECUTING (SCST_CMD_STATE_LAST_ACTIVE+5)
1040+
1041+/* Waiting for response's transmission finish */
1042+#define SCST_CMD_STATE_XMIT_WAIT (SCST_CMD_STATE_LAST_ACTIVE+6)
1043+
1044+/*************************************************************
1045+ * Can be retuned instead of cmd's state by dev handlers'
1046+ * functions, if the command's state should be set by default
1047+ *************************************************************/
1048+#define SCST_CMD_STATE_DEFAULT 500
1049+
1050+/*************************************************************
1051+ * Can be retuned instead of cmd's state by dev handlers'
1052+ * functions, if it is impossible to complete requested
1053+ * task in atomic context. The cmd will be restarted in thread
1054+ * context.
1055+ *************************************************************/
1056+#define SCST_CMD_STATE_NEED_THREAD_CTX 1000
1057+
1058+/*************************************************************
1059+ * Can be retuned instead of cmd's state by dev handlers'
1060+ * parse function, if the cmd processing should be stopped
1061+ * for now. The cmd will be restarted by dev handlers itself.
1062+ *************************************************************/
1063+#define SCST_CMD_STATE_STOP 1001
1064+
1065+/*************************************************************
1066+ ** States of mgmt command processing state machine
1067+ *************************************************************/
1068+
1069+/* LUN translation (mcmd->tgt_dev assignment) */
1070+#define SCST_MCMD_STATE_INIT 0
1071+
1072+/* Mgmt cmd is being processed */
1073+#define SCST_MCMD_STATE_EXEC 1
1074+
1075+/* Waiting for affected commands done */
1076+#define SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_DONE 2
1077+
1078+/* Post actions when affected commands done */
1079+#define SCST_MCMD_STATE_AFFECTED_CMDS_DONE 3
1080+
1081+/* Waiting for affected local commands finished */
1082+#define SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_FINISHED 4
1083+
1084+/* Target driver's task_mgmt_fn_done() is going to be called */
1085+#define SCST_MCMD_STATE_DONE 5
1086+
1087+/* The mcmd finished */
1088+#define SCST_MCMD_STATE_FINISHED 6
1089+
1090+/*************************************************************
1091+ ** Constants for "atomic" parameter of SCST's functions
1092+ *************************************************************/
1093+#define SCST_NON_ATOMIC 0
1094+#define SCST_ATOMIC 1
1095+
1096+/*************************************************************
1097+ ** Values for pref_context parameter of scst_cmd_init_done(),
1098+ ** scst_rx_data(), scst_restart_cmd(), scst_tgt_cmd_done()
1099+ ** and scst_cmd_done()
1100+ *************************************************************/
1101+
1102+enum scst_exec_context {
1103+ /*
1104+ * Direct cmd's processing (i.e. regular function calls in the current
1105+ * context) sleeping is not allowed
1106+ */
1107+ SCST_CONTEXT_DIRECT_ATOMIC,
1108+
1109+ /*
1110+ * Direct cmd's processing (i.e. regular function calls in the current
1111+ * context), sleeping is allowed, no restrictions
1112+ */
1113+ SCST_CONTEXT_DIRECT,
1114+
1115+ /* Tasklet or thread context required for cmd's processing */
1116+ SCST_CONTEXT_TASKLET,
1117+
1118+ /* Thread context required for cmd's processing */
1119+ SCST_CONTEXT_THREAD,
1120+
1121+ /*
1122+ * Context is the same as it was in previous call of the corresponding
1123+ * callback. For example, if dev handler's exec() does sync. data
1124+ * reading this value should be used for scst_cmd_done(). The same is
1125+ * true if scst_tgt_cmd_done() called directly from target driver's
1126+ * xmit_response(). Not allowed in scst_cmd_init_done() and
1127+ * scst_cmd_init_stage1_done().
1128+ */
1129+ SCST_CONTEXT_SAME
1130+};
1131+
1132+/*************************************************************
1133+ ** Values for status parameter of scst_rx_data()
1134+ *************************************************************/
1135+
1136+/* Success */
1137+#define SCST_RX_STATUS_SUCCESS 0
1138+
1139+/*
1140+ * Data receiving finished with error, so set the sense and
1141+ * finish the command, including xmit_response() call
1142+ */
1143+#define SCST_RX_STATUS_ERROR 1
1144+
1145+/*
1146+ * Data receiving finished with error and the sense is set,
1147+ * so finish the command, including xmit_response() call
1148+ */
1149+#define SCST_RX_STATUS_ERROR_SENSE_SET 2
1150+
1151+/*
1152+ * Data receiving finished with fatal error, so finish the command,
1153+ * but don't call xmit_response()
1154+ */
1155+#define SCST_RX_STATUS_ERROR_FATAL 3
1156+
1157+/*************************************************************
1158+ ** Values for status parameter of scst_restart_cmd()
1159+ *************************************************************/
1160+
1161+/* Success */
1162+#define SCST_PREPROCESS_STATUS_SUCCESS 0
1163+
1164+/*
1165+ * Command's processing finished with error, so set the sense and
1166+ * finish the command, including xmit_response() call
1167+ */
1168+#define SCST_PREPROCESS_STATUS_ERROR 1
1169+
1170+/*
1171+ * Command's processing finished with error and the sense is set,
1172+ * so finish the command, including xmit_response() call
1173+ */
1174+#define SCST_PREPROCESS_STATUS_ERROR_SENSE_SET 2
1175+
1176+/*
1177+ * Command's processing finished with fatal error, so finish the command,
1178+ * but don't call xmit_response()
1179+ */
1180+#define SCST_PREPROCESS_STATUS_ERROR_FATAL 3
1181+
1182+/*************************************************************
1183+ ** Values for AEN functions
1184+ *************************************************************/
1185+
1186+/*
1187+ * SCSI Asynchronous Event. Parameter contains SCSI sense
1188+ * (Unit Attention). AENs generated only for 2 the following UAs:
1189+ * CAPACITY DATA HAS CHANGED and REPORTED LUNS DATA HAS CHANGED.
1190+ * Other UAs reported regularly as CHECK CONDITION status,
1191+ * because it doesn't look safe to report them using AENs, since
1192+ * reporting using AENs opens delivery race windows even in case of
1193+ * untagged commands.
1194+ */
1195+#define SCST_AEN_SCSI 0
1196+
1197+/*************************************************************
1198+ ** Allowed return/status codes for report_aen() callback and
1199+ ** scst_set_aen_delivery_status() function
1200+ *************************************************************/
1201+
1202+/* Success */
1203+#define SCST_AEN_RES_SUCCESS 0
1204+
1205+/* Not supported */
1206+#define SCST_AEN_RES_NOT_SUPPORTED -1
1207+
1208+/* Failure */
1209+#define SCST_AEN_RES_FAILED -2
1210+
1211+/*************************************************************
1212+ ** Allowed return codes for xmit_response(), rdy_to_xfer()
1213+ *************************************************************/
1214+
1215+/* Success */
1216+#define SCST_TGT_RES_SUCCESS 0
1217+
1218+/* Internal device queue is full, retry again later */
1219+#define SCST_TGT_RES_QUEUE_FULL -1
1220+
1221+/*
1222+ * It is impossible to complete requested task in atomic context.
1223+ * The cmd will be restarted in thread context.
1224+ */
1225+#define SCST_TGT_RES_NEED_THREAD_CTX -2
1226+
1227+/*
1228+ * Fatal error, if returned by xmit_response() the cmd will
1229+ * be destroyed, if by any other function, xmit_response()
1230+ * will be called with HARDWARE ERROR sense data
1231+ */
1232+#define SCST_TGT_RES_FATAL_ERROR -3
1233+
1234+/*************************************************************
1235+ ** Allowed return codes for dev handler's exec()
1236+ *************************************************************/
1237+
1238+/* The cmd is done, go to other ones */
1239+#define SCST_EXEC_COMPLETED 0
1240+
1241+/* The cmd should be sent to SCSI mid-level */
1242+#define SCST_EXEC_NOT_COMPLETED 1
1243+
1244+/*
1245+ * Set if cmd is finished and there is status/sense to be sent.
1246+ * The status should be not sent (i.e. the flag not set) if the
1247+ * possibility to perform a command in "chunks" (i.e. with multiple
1248+ * xmit_response()/rdy_to_xfer()) is used (not implemented yet).
1249+ * Obsolete, use scst_cmd_get_is_send_status() instead.
1250+ */
1251+#define SCST_TSC_FLAG_STATUS 0x2
1252+
1253+/*************************************************************
1254+ ** Additional return code for dev handler's task_mgmt_fn()
1255+ *************************************************************/
1256+
1257+/* Regular standard actions for the command should be done */
1258+#define SCST_DEV_TM_NOT_COMPLETED 1
1259+
1260+/*************************************************************
1261+ ** Session initialization phases
1262+ *************************************************************/
1263+
1264+/* Set if session is being initialized */
1265+#define SCST_SESS_IPH_INITING 0
1266+
1267+/* Set if the session is successfully initialized */
1268+#define SCST_SESS_IPH_SUCCESS 1
1269+
1270+/* Set if the session initialization failed */
1271+#define SCST_SESS_IPH_FAILED 2
1272+
1273+/* Set if session is initialized and ready */
1274+#define SCST_SESS_IPH_READY 3
1275+
1276+/*************************************************************
1277+ ** Session shutdown phases
1278+ *************************************************************/
1279+
1280+/* Set if session is initialized and ready */
1281+#define SCST_SESS_SPH_READY 0
1282+
1283+/* Set if session is shutting down */
1284+#define SCST_SESS_SPH_SHUTDOWN 1
1285+
1286+/* Set if session is shutting down */
1287+#define SCST_SESS_SPH_UNREG_DONE_CALLING 2
1288+
1289+/*************************************************************
1290+ ** Session's async (atomic) flags
1291+ *************************************************************/
1292+
1293+/* Set if the sess's hw pending work is scheduled */
1294+#define SCST_SESS_HW_PENDING_WORK_SCHEDULED 0
1295+
1296+/*************************************************************
1297+ ** Cmd's async (atomic) flags
1298+ *************************************************************/
1299+
1300+/* Set if the cmd is aborted and ABORTED sense will be sent as the result */
1301+#define SCST_CMD_ABORTED 0
1302+
1303+/* Set if the cmd is aborted by other initiator */
1304+#define SCST_CMD_ABORTED_OTHER 1
1305+
1306+/* Set if no response should be sent to the target about this cmd */
1307+#define SCST_CMD_NO_RESP 2
1308+
1309+/* Set if the cmd is dead and can be destroyed at any time */
1310+#define SCST_CMD_CAN_BE_DESTROYED 3
1311+
1312+/*
1313+ * Set if the cmd's device has TAS flag set. Used only when aborted by
1314+ * other initiator.
1315+ */
1316+#define SCST_CMD_DEVICE_TAS 4
1317+
1318+/*************************************************************
1319+ ** Tgt_dev's async. flags (tgt_dev_flags)
1320+ *************************************************************/
1321+
1322+/* Set if tgt_dev has Unit Attention sense */
1323+#define SCST_TGT_DEV_UA_PENDING 0
1324+
1325+/* Set if tgt_dev is RESERVED by another session */
1326+#define SCST_TGT_DEV_RESERVED 1
1327+
1328+/* Set if the corresponding context is atomic */
1329+#define SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC 5
1330+#define SCST_TGT_DEV_AFTER_EXEC_ATOMIC 6
1331+
1332+#define SCST_TGT_DEV_CLUST_POOL 11
1333+
1334+/*************************************************************
1335+ ** I/O groupping types. Changing them don't forget to change
1336+ ** the corresponding *_STR values in scst_const.h!
1337+ *************************************************************/
1338+
1339+/*
1340+ * All initiators with the same name connected to this group will have
1341+ * shared IO context, for each name own context. All initiators with
1342+ * different names will have own IO context.
1343+ */
1344+#define SCST_IO_GROUPING_AUTO 0
1345+
1346+/* All initiators connected to this group will have shared IO context */
1347+#define SCST_IO_GROUPING_THIS_GROUP_ONLY -1
1348+
1349+/* Each initiator connected to this group will have own IO context */
1350+#define SCST_IO_GROUPING_NEVER -2
1351+
1352+/*************************************************************
1353+ ** Kernel cache creation helper
1354+ *************************************************************/
1355+#ifndef KMEM_CACHE
1356+#define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\
1357+ sizeof(struct __struct), __alignof__(struct __struct),\
1358+ (__flags), NULL, NULL)
1359+#endif
1360+
1361+/*************************************************************
1362+ ** Vlaid_mask constants for scst_analyze_sense()
1363+ *************************************************************/
1364+
1365+#define SCST_SENSE_KEY_VALID 1
1366+#define SCST_SENSE_ASC_VALID 2
1367+#define SCST_SENSE_ASCQ_VALID 4
1368+
1369+#define SCST_SENSE_ASCx_VALID (SCST_SENSE_ASC_VALID | \
1370+ SCST_SENSE_ASCQ_VALID)
1371+
1372+#define SCST_SENSE_ALL_VALID (SCST_SENSE_KEY_VALID | \
1373+ SCST_SENSE_ASC_VALID | \
1374+ SCST_SENSE_ASCQ_VALID)
1375+
1376+/*************************************************************
1377+ * TYPES
1378+ *************************************************************/
1379+
1380+struct scst_tgt;
1381+struct scst_session;
1382+struct scst_cmd;
1383+struct scst_mgmt_cmd;
1384+struct scst_device;
1385+struct scst_tgt_dev;
1386+struct scst_dev_type;
1387+struct scst_acg;
1388+struct scst_acg_dev;
1389+struct scst_acn;
1390+struct scst_aen;
1391+
1392+/*
1393+ * SCST uses 64-bit numbers to represent LUN's internally. The value
1394+ * NO_SUCH_LUN is guaranteed to be different of every valid LUN.
1395+ */
1396+#define NO_SUCH_LUN ((uint64_t)-1)
1397+
1398+typedef enum dma_data_direction scst_data_direction;
1399+
1400+/*
1401+ * SCST target template: defines target driver's parameters and callback
1402+ * functions.
1403+ *
1404+ * MUST HAVEs define functions that are expected to be defined in order to
1405+ * work. OPTIONAL says that there is a choice.
1406+ */
1407+struct scst_tgt_template {
1408+ /* public: */
1409+
1410+ /*
1411+ * SG tablesize allows to check whether scatter/gather can be used
1412+ * or not.
1413+ */
1414+ int sg_tablesize;
1415+
1416+ /*
1417+ * True, if this target adapter uses unchecked DMA onto an ISA bus.
1418+ */
1419+ unsigned unchecked_isa_dma:1;
1420+
1421+ /*
1422+ * True, if this target adapter can benefit from using SG-vector
1423+ * clustering (i.e. smaller number of segments).
1424+ */
1425+ unsigned use_clustering:1;
1426+
1427+ /*
1428+ * True, if this target adapter doesn't support SG-vector clustering
1429+ */
1430+ unsigned no_clustering:1;
1431+
1432+ /*
1433+ * True, if corresponding function supports execution in
1434+ * the atomic (non-sleeping) context
1435+ */
1436+ unsigned xmit_response_atomic:1;
1437+ unsigned rdy_to_xfer_atomic:1;
1438+
1439+ /* True, if this target doesn't need "enabled" attribute */
1440+ unsigned enabled_attr_not_needed:1;
1441+
1442+ /*
1443+ * The maximum time in seconds cmd can stay inside the target
1444+ * hardware, i.e. after rdy_to_xfer() and xmit_response(), before
1445+ * on_hw_pending_cmd_timeout() will be called, if defined.
1446+ *
1447+ * In the current implementation a cmd will be aborted in time t
1448+ * max_hw_pending_time <= t < 2*max_hw_pending_time.
1449+ */
1450+ int max_hw_pending_time;
1451+
1452+ /*
1453+ * This function is equivalent to the SCSI
1454+ * queuecommand. The target should transmit the response
1455+ * buffer and the status in the scst_cmd struct.
1456+ * The expectation is that this executing this command is NON-BLOCKING.
1457+ * If it is blocking, consider to set threads_num to some none 0 number.
1458+ *
1459+ * After the response is actually transmitted, the target
1460+ * should call the scst_tgt_cmd_done() function of the
1461+ * mid-level, which will allow it to free up the command.
1462+ * Returns one of the SCST_TGT_RES_* constants.
1463+ *
1464+ * Pay attention to "atomic" attribute of the cmd, which can be get
1465+ * by scst_cmd_atomic(): it is true if the function called in the
1466+ * atomic (non-sleeping) context.
1467+ *
1468+ * MUST HAVE
1469+ */
1470+ int (*xmit_response) (struct scst_cmd *cmd);
1471+
1472+ /*
1473+ * This function informs the driver that data
1474+ * buffer corresponding to the said command have now been
1475+ * allocated and it is OK to receive data for this command.
1476+ * This function is necessary because a SCSI target does not
1477+ * have any control over the commands it receives. Most lower
1478+ * level protocols have a corresponding function which informs
1479+ * the initiator that buffers have been allocated e.g., XFER_
1480+ * RDY in Fibre Channel. After the data is actually received
1481+ * the low-level driver needs to call scst_rx_data() in order to
1482+ * continue processing this command.
1483+ * Returns one of the SCST_TGT_RES_* constants.
1484+ *
1485+ * This command is expected to be NON-BLOCKING.
1486+ * If it is blocking, consider to set threads_num to some none 0 number.
1487+ *
1488+ * Pay attention to "atomic" attribute of the cmd, which can be get
1489+ * by scst_cmd_atomic(): it is true if the function called in the
1490+ * atomic (non-sleeping) context.
1491+ *
1492+ * OPTIONAL
1493+ */
1494+ int (*rdy_to_xfer) (struct scst_cmd *cmd);
1495+
1496+ /*
1497+ * Called if cmd stays inside the target hardware, i.e. after
1498+ * rdy_to_xfer() and xmit_response(), more than max_hw_pending_time
1499+ * time. The target driver supposed to cleanup this command and
1500+ * resume cmd's processing.
1501+ *
1502+ * OPTIONAL
1503+ */
1504+ void (*on_hw_pending_cmd_timeout) (struct scst_cmd *cmd);
1505+
1506+ /*
1507+ * Called to notify the driver that the command is about to be freed.
1508+ * Necessary, because for aborted commands xmit_response() could not
1509+ * be called. Could be called on IRQ context.
1510+ *
1511+ * OPTIONAL
1512+ */
1513+ void (*on_free_cmd) (struct scst_cmd *cmd);
1514+
1515+ /*
1516+ * This function allows target driver to handle data buffer
1517+ * allocations on its own.
1518+ *
1519+ * Target driver doesn't have to always allocate buffer in this
1520+ * function, but if it decide to do it, it must check that
1521+ * scst_cmd_get_data_buff_alloced() returns 0, otherwise to avoid
1522+ * double buffer allocation and memory leaks alloc_data_buf() shall
1523+ * fail.
1524+ *
1525+ * Shall return 0 in case of success or < 0 (preferrably -ENOMEM)
1526+ * in case of error, or > 0 if the regular SCST allocation should be
1527+ * done. In case of returning successfully,
1528+ * scst_cmd->tgt_data_buf_alloced will be set by SCST.
1529+ *
1530+ * It is possible that both target driver and dev handler request own
1531+ * memory allocation. In this case, data will be memcpy() between
1532+ * buffers, where necessary.
1533+ *
1534+ * If allocation in atomic context - cf. scst_cmd_atomic() - is not
1535+ * desired or fails and consequently < 0 is returned, this function
1536+ * will be re-called in thread context.
1537+ *
1538+ * Please note that the driver will have to handle itself all relevant
1539+ * details such as scatterlist setup, highmem, freeing the allocated
1540+ * memory, etc.
1541+ *
1542+ * OPTIONAL.
1543+ */
1544+ int (*alloc_data_buf) (struct scst_cmd *cmd);
1545+
1546+ /*
1547+ * This function informs the driver that data
1548+ * buffer corresponding to the said command have now been
1549+ * allocated and other preprocessing tasks have been done.
1550+ * A target driver could need to do some actions at this stage.
1551+ * After the target driver done the needed actions, it shall call
1552+ * scst_restart_cmd() in order to continue processing this command.
1553+ * In case of preliminary the command completion, this function will
1554+ * also be called before xmit_response().
1555+ *
1556+ * Called only if the cmd is queued using scst_cmd_init_stage1_done()
1557+ * instead of scst_cmd_init_done().
1558+ *
1559+ * Returns void, the result is expected to be returned using
1560+ * scst_restart_cmd().
1561+ *
1562+ * This command is expected to be NON-BLOCKING.
1563+ * If it is blocking, consider to set threads_num to some none 0 number.
1564+ *
1565+ * Pay attention to "atomic" attribute of the cmd, which can be get
1566+ * by scst_cmd_atomic(): it is true if the function called in the
1567+ * atomic (non-sleeping) context.
1568+ *
1569+ * OPTIONAL.
1570+ */
1571+ void (*preprocessing_done) (struct scst_cmd *cmd);
1572+
1573+ /*
1574+ * This function informs the driver that the said command is about
1575+ * to be executed.
1576+ *
1577+ * Returns one of the SCST_PREPROCESS_* constants.
1578+ *
1579+ * This command is expected to be NON-BLOCKING.
1580+ * If it is blocking, consider to set threads_num to some none 0 number.
1581+ *
1582+ * OPTIONAL
1583+ */
1584+ int (*pre_exec) (struct scst_cmd *cmd);
1585+
1586+ /*
1587+ * This function informs the driver that all affected by the
1588+ * corresponding task management function commands have beed completed.
1589+ * No return value expected.
1590+ *
1591+ * This function is expected to be NON-BLOCKING.
1592+ *
1593+ * Called without any locks held from a thread context.
1594+ *
1595+ * OPTIONAL
1596+ */
1597+ void (*task_mgmt_affected_cmds_done) (struct scst_mgmt_cmd *mgmt_cmd);
1598+
1599+ /*
1600+ * This function informs the driver that the corresponding task
1601+ * management function has been completed, i.e. all the corresponding
1602+ * commands completed and freed. No return value expected.
1603+ *
1604+ * This function is expected to be NON-BLOCKING.
1605+ *
1606+ * Called without any locks held from a thread context.
1607+ *
1608+ * MUST HAVE if the target supports task management.
1609+ */
1610+ void (*task_mgmt_fn_done) (struct scst_mgmt_cmd *mgmt_cmd);
1611+
1612+ /*
1613+ * This function should detect the target adapters that
1614+ * are present in the system. The function should return a value
1615+ * >= 0 to signify the number of detected target adapters.
1616+ * A negative value should be returned whenever there is
1617+ * an error.
1618+ *
1619+ * MUST HAVE
1620+ */
1621+ int (*detect) (struct scst_tgt_template *tgt_template);
1622+
1623+ /*
1624+ * This function should free up the resources allocated to the device.
1625+ * The function should return 0 to indicate successful release
1626+ * or a negative value if there are some issues with the release.
1627+ * In the current version the return value is ignored.
1628+ *
1629+ * MUST HAVE
1630+ */
1631+ int (*release) (struct scst_tgt *tgt);
1632+
1633+ /*
1634+ * This function is used for Asynchronous Event Notifications.
1635+ *
1636+ * Returns one of the SCST_AEN_RES_* constants.
1637+ * After AEN is sent, target driver must call scst_aen_done() and,
1638+ * optionally, scst_set_aen_delivery_status().
1639+ *
1640+ * This function is expected to be NON-BLOCKING, but can sleep.
1641+ *
1642+ * This function must be prepared to handle AENs between calls for the
1643+ * corresponding session of scst_unregister_session() and
1644+ * unreg_done_fn() callback called or before scst_unregister_session()
1645+ * returned, if its called in the blocking mode. AENs for such sessions
1646+ * should be ignored.
1647+ *
1648+ * MUST HAVE, if low-level protocol supports AENs.
1649+ */
1650+ int (*report_aen) (struct scst_aen *aen);
1651+
1652+ /*
1653+ * This function returns in tr_id the corresponding to sess initiator
1654+ * port TransporID in the form as it's used by PR commands, see
1655+ * "Transport Identifiers" in SPC. Space for the initiator port
1656+ * TransporID must be allocated via kmalloc(). Caller supposed to
1657+ * kfree() it, when it isn't needed anymore.
1658+ *
1659+ * If sess is NULL, this function must return TransportID PROTOCOL
1660+ * IDENTIFIER of this transport.
1661+ *
1662+ * Returns 0 on success or negative error code otherwise.
1663+ *
1664+ * SHOULD HAVE, because it's required for Persistent Reservations.
1665+ */
1666+ int (*get_initiator_port_transport_id) (struct scst_session *sess,
1667+ uint8_t **transport_id);
1668+
1669+ /*
1670+ * This function allows to enable or disable particular target.
1671+ * A disabled target doesn't receive and process any SCSI commands.
1672+ *
1673+ * SHOULD HAVE to avoid race when there are connected initiators,
1674+ * while target not yet completed the initial configuration. In this
1675+ * case the too early connected initiators would see not those devices,
1676+ * which they intended to see.
1677+ *
1678+ * If you are sure your target driver doesn't need enabling target,
1679+ * you should set enabled_attr_not_needed in 1.
1680+ */
1681+ int (*enable_target) (struct scst_tgt *tgt, bool enable);
1682+
1683+ /*
1684+ * This function shows if particular target is enabled or not.
1685+ *
1686+ * SHOULD HAVE, see above why.
1687+ */
1688+ bool (*is_target_enabled) (struct scst_tgt *tgt);
1689+
1690+ /*
1691+ * This function adds a virtual target.
1692+ *
1693+ * If both add_target and del_target callbacks defined, then this
1694+ * target driver supposed to support virtual targets. In this case
1695+ * an "mgmt" entry will be created in the sysfs root for this driver.
1696+ * The "mgmt" entry will support 2 commands: "add_target" and
1697+ * "del_target", for which the corresponding callbacks will be called.
1698+ * Also target driver can define own commands for the "mgmt" entry, see
1699+ * mgmt_cmd and mgmt_cmd_help below.
1700+ *
1701+ * This approach allows uniform targets management to simplify external
1702+ * management tools like scstadmin. See README for more details.
1703+ *
1704+ * Either both add_target and del_target must be defined, or none.
1705+ *
1706+ * MUST HAVE if virtual targets are supported.
1707+ */
1708+ ssize_t (*add_target) (const char *target_name, char *params);
1709+
1710+ /*
1711+ * This function deletes a virtual target. See comment for add_target
1712+ * above.
1713+ *
1714+ * MUST HAVE if virtual targets are supported.
1715+ */
1716+ ssize_t (*del_target) (const char *target_name);
1717+
1718+ /*
1719+ * This function called if not "add_target" or "del_target" command is
1720+ * sent to the mgmt entry (see comment for add_target above). In this
1721+ * case the command passed to this function as is in a string form.
1722+ *
1723+ * OPTIONAL.
1724+ */
1725+ ssize_t (*mgmt_cmd) (char *cmd);
1726+
1727+ /*
1728+ * Should return physical transport version. Used in the corresponding
1729+ * INQUIRY version descriptor. See SPC for the list of available codes.
1730+ *
1731+ * OPTIONAL
1732+ */
1733+ uint16_t (*get_phys_transport_version) (struct scst_tgt *tgt);
1734+
1735+ /*
1736+ * Should return SCSI transport version. Used in the corresponding
1737+ * INQUIRY version descriptor. See SPC for the list of available codes.
1738+ *
1739+ * OPTIONAL
1740+ */
1741+ uint16_t (*get_scsi_transport_version) (struct scst_tgt *tgt);
1742+
1743+ /*
1744+ * Name of the template. Must be unique to identify
1745+ * the template. MUST HAVE
1746+ */
1747+ const char name[SCST_MAX_NAME];
1748+
1749+ /*
1750+ * Number of additional threads to the pool of dedicated threads.
1751+ * Used if xmit_response() or rdy_to_xfer() is blocking.
1752+ * It is the target driver's duty to ensure that not more, than that
1753+ * number of threads, are blocked in those functions at any time.
1754+ */
1755+ int threads_num;
1756+
1757+ /* Optional default log flags */
1758+ const unsigned long default_trace_flags;
1759+
1760+ /* Optional pointer to trace flags */
1761+ unsigned long *trace_flags;
1762+
1763+ /* Optional local trace table */
1764+ struct scst_trace_log *trace_tbl;
1765+
1766+ /* Optional local trace table help string */
1767+ const char *trace_tbl_help;
1768+
1769+ /* sysfs attributes, if any */
1770+ const struct attribute **tgtt_attrs;
1771+
1772+ /* sysfs target attributes, if any */
1773+ const struct attribute **tgt_attrs;
1774+
1775+ /* sysfs session attributes, if any */
1776+ const struct attribute **sess_attrs;
1777+
1778+ /* Optional help string for mgmt_cmd commands */
1779+ const char *mgmt_cmd_help;
1780+
1781+ /* List of parameters for add_target command, if any */
1782+ const char *add_target_parameters;
1783+
1784+ /*
1785+ * List of optional, i.e. which could be added by add_attribute command
1786+ * and deleted by del_attribute command, sysfs attributes, if any.
1787+ * Helpful for scstadmin to work correctly.
1788+ */
1789+ const char *tgtt_optional_attributes;
1790+
1791+ /*
1792+ * List of optional, i.e. which could be added by add_target_attribute
1793+ * command and deleted by del_target_attribute command, sysfs
1794+ * attributes, if any. Helpful for scstadmin to work correctly.
1795+ */
1796+ const char *tgt_optional_attributes;
1797+
1798+ /** Private, must be inited to 0 by memset() **/
1799+
1800+ /* List of targets per template, protected by scst_mutex */
1801+ struct list_head tgt_list;
1802+
1803+ /* List entry of global templates list */
1804+ struct list_head scst_template_list_entry;
1805+
1806+ struct kobject tgtt_kobj; /* kobject for this struct */
1807+
1808+ /* Number of currently active sysfs mgmt works (scst_sysfs_work_item) */
1809+ int tgtt_active_sysfs_works_count;
1810+
1811+ /* sysfs release completion */
1812+ struct completion tgtt_kobj_release_cmpl;
1813+
1814+};
1815+
1816+/*
1817+ * Threads pool types. Changing them don't forget to change
1818+ * the corresponding *_STR values in scst_const.h!
1819+ */
1820+enum scst_dev_type_threads_pool_type {
1821+ /* Each initiator will have dedicated threads pool. */
1822+ SCST_THREADS_POOL_PER_INITIATOR = 0,
1823+
1824+ /* All connected initiators will use shared threads pool */
1825+ SCST_THREADS_POOL_SHARED,
1826+
1827+ /* Invalid value for scst_parse_threads_pool_type() */
1828+ SCST_THREADS_POOL_TYPE_INVALID,
1829+};
1830+
1831+/*
1832+ * SCST dev handler template: defines dev handler's parameters and callback
1833+ * functions.
1834+ *
1835+ * MUST HAVEs define functions that are expected to be defined in order to
1836+ * work. OPTIONAL says that there is a choice.
1837+ */
1838+struct scst_dev_type {
1839+ /* SCSI type of the supported device. MUST HAVE */
1840+ int type;
1841+
1842+ /*
1843+ * True, if corresponding function supports execution in
1844+ * the atomic (non-sleeping) context
1845+ */
1846+ unsigned parse_atomic:1;
1847+ unsigned alloc_data_buf_atomic:1;
1848+ unsigned dev_done_atomic:1;
1849+
1850+ /*
1851+ * Should be true, if exec() is synchronous. This is a hint to SCST core
1852+ * to optimize commands order management.
1853+ */
1854+ unsigned exec_sync:1;
1855+
1856+ /*
1857+ * Should be set if the device wants to receive notification of
1858+ * Persistent Reservation commands (PR OUT only)
1859+ * Note: The notification will not be send if the command failed
1860+ */
1861+ unsigned pr_cmds_notifications:1;
1862+
1863+ /*
1864+ * Called to parse CDB from the cmd and initialize
1865+ * cmd->bufflen and cmd->data_direction (both - REQUIRED).
1866+ *
1867+ * Returns the command's next state or SCST_CMD_STATE_DEFAULT,
1868+ * if the next default state should be used, or
1869+ * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic
1870+ * context, but requires sleeping, or SCST_CMD_STATE_STOP if the
1871+ * command should not be further processed for now. In the
1872+ * SCST_CMD_STATE_NEED_THREAD_CTX case the function
1873+ * will be recalled in the thread context, where sleeping is allowed.
1874+ *
1875+ * Pay attention to "atomic" attribute of the cmd, which can be get
1876+ * by scst_cmd_atomic(): it is true if the function called in the
1877+ * atomic (non-sleeping) context.
1878+ *
1879+ * MUST HAVE
1880+ */
1881+ int (*parse) (struct scst_cmd *cmd);
1882+
1883+ /*
1884+ * This function allows dev handler to handle data buffer
1885+ * allocations on its own.
1886+ *
1887+ * Returns the command's next state or SCST_CMD_STATE_DEFAULT,
1888+ * if the next default state should be used, or
1889+ * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic
1890+ * context, but requires sleeping, or SCST_CMD_STATE_STOP if the
1891+ * command should not be further processed for now. In the
1892+ * SCST_CMD_STATE_NEED_THREAD_CTX case the function
1893+ * will be recalled in the thread context, where sleeping is allowed.
1894+ *
1895+ * Pay attention to "atomic" attribute of the cmd, which can be get
1896+ * by scst_cmd_atomic(): it is true if the function called in the
1897+ * atomic (non-sleeping) context.
1898+ *
1899+ * OPTIONAL
1900+ */
1901+ int (*alloc_data_buf) (struct scst_cmd *cmd);
1902+
1903+ /*
1904+ * Called to execute CDB. Useful, for instance, to implement
1905+ * data caching. The result of CDB execution is reported via
1906+ * cmd->scst_cmd_done() callback.
1907+ * Returns:
1908+ * - SCST_EXEC_COMPLETED - the cmd is done, go to other ones
1909+ * - SCST_EXEC_NOT_COMPLETED - the cmd should be sent to SCSI
1910+ * mid-level.
1911+ *
1912+ * If this function provides sync execution, you should set
1913+ * exec_sync flag and consider to setup dedicated threads by
1914+ * setting threads_num > 0.
1915+ *
1916+ * !! If this function is implemented, scst_check_local_events() !!
1917+ * !! shall be called inside it just before the actual command's !!
1918+ * !! execution. !!
1919+ *
1920+ * OPTIONAL, if not set, the commands will be sent directly to SCSI
1921+ * device.
1922+ */
1923+ int (*exec) (struct scst_cmd *cmd);
1924+
1925+ /*
1926+ * Called to notify dev handler about the result of cmd execution
1927+ * and perform some post processing. Cmd's fields is_send_status and
1928+ * resp_data_len should be set by this function, but SCST offers good
1929+ * defaults.
1930+ * Returns the command's next state or SCST_CMD_STATE_DEFAULT,
1931+ * if the next default state should be used, or
1932+ * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic
1933+ * context, but requires sleeping. In the last case, the function
1934+ * will be recalled in the thread context, where sleeping is allowed.
1935+ *
1936+ * Pay attention to "atomic" attribute of the cmd, which can be get
1937+ * by scst_cmd_atomic(): it is true if the function called in the
1938+ * atomic (non-sleeping) context.
1939+ */
1940+ int (*dev_done) (struct scst_cmd *cmd);
1941+
1942+ /*
1943+ * Called to notify dev hander that the command is about to be freed.
1944+ * Could be called on IRQ context.
1945+ */
1946+ void (*on_free_cmd) (struct scst_cmd *cmd);
1947+
1948+ /*
1949+ * Called to execute a task management command.
1950+ * Returns:
1951+ * - SCST_MGMT_STATUS_SUCCESS - the command is done with success,
1952+ * no firther actions required
1953+ * - The SCST_MGMT_STATUS_* error code if the command is failed and
1954+ * no further actions required
1955+ * - SCST_DEV_TM_NOT_COMPLETED - regular standard actions for the
1956+ * command should be done
1957+ *
1958+ * Called without any locks held from a thread context.
1959+ */
1960+ int (*task_mgmt_fn) (struct scst_mgmt_cmd *mgmt_cmd,
1961+ struct scst_tgt_dev *tgt_dev);
1962+
1963+ /*
1964+ * Called when new device is attaching to the dev handler
1965+ * Returns 0 on success, error code otherwise.
1966+ */
1967+ int (*attach) (struct scst_device *dev);
1968+
1969+ /* Called when a device is detaching from the dev handler */
1970+ void (*detach) (struct scst_device *dev);
1971+
1972+ /*
1973+ * Called when new tgt_dev (session) is attaching to the dev handler.
1974+ * Returns 0 on success, error code otherwise.
1975+ */
1976+ int (*attach_tgt) (struct scst_tgt_dev *tgt_dev);
1977+
1978+ /* Called when tgt_dev (session) is detaching from the dev handler */
1979+ void (*detach_tgt) (struct scst_tgt_dev *tgt_dev);
1980+
1981+ /*
1982+ * This function adds a virtual device.
1983+ *
1984+ * If both add_device and del_device callbacks defined, then this
1985+ * dev handler supposed to support adding/deleting virtual devices.
1986+ * In this case an "mgmt" entry will be created in the sysfs root for
1987+ * this handler. The "mgmt" entry will support 2 commands: "add_device"
1988+ * and "del_device", for which the corresponding callbacks will be called.
1989+ * Also dev handler can define own commands for the "mgmt" entry, see
1990+ * mgmt_cmd and mgmt_cmd_help below.
1991+ *
1992+ * This approach allows uniform devices management to simplify external
1993+ * management tools like scstadmin. See README for more details.
1994+ *
1995+ * Either both add_device and del_device must be defined, or none.
1996+ *
1997+ * MUST HAVE if virtual devices are supported.
1998+ */
1999+ ssize_t (*add_device) (const char *device_name, char *params);
2000+
2001+ /*
2002+ * This function deletes a virtual device. See comment for add_device
2003+ * above.
2004+ *
2005+ * MUST HAVE if virtual devices are supported.
2006+ */
2007+ ssize_t (*del_device) (const char *device_name);
2008+
2009+ /*
2010+ * This function called if not "add_device" or "del_device" command is
2011+ * sent to the mgmt entry (see comment for add_device above). In this
2012+ * case the command passed to this function as is in a string form.
2013+ *
2014+ * OPTIONAL.
2015+ */
2016+ ssize_t (*mgmt_cmd) (char *cmd);
2017+
2018+ /*
2019+ * Name of the dev handler. Must be unique. MUST HAVE.
2020+ *
2021+ * It's SCST_MAX_NAME + few more bytes to match scst_user expectations.
2022+ */
2023+ char name[SCST_MAX_NAME + 10];
2024+
2025+ /*
2026+ * Number of threads in this handler's devices' threads pools.
2027+ * If 0 - no threads will be created, if <0 - creation of the threads
2028+ * pools is prohibited. Also pay attention to threads_pool_type below.
2029+ */
2030+ int threads_num;
2031+
2032+ /* Threads pool type. Valid only if threads_num > 0. */
2033+ enum scst_dev_type_threads_pool_type threads_pool_type;
2034+
2035+ /* Optional default log flags */
2036+ const unsigned long default_trace_flags;
2037+
2038+ /* Optional pointer to trace flags */
2039+ unsigned long *trace_flags;
2040+
2041+ /* Optional local trace table */
2042+ struct scst_trace_log *trace_tbl;
2043+
2044+ /* Optional local trace table help string */
2045+ const char *trace_tbl_help;
2046+
2047+ /* Optional help string for mgmt_cmd commands */
2048+ const char *mgmt_cmd_help;
2049+
2050+ /* List of parameters for add_device command, if any */
2051+ const char *add_device_parameters;
2052+
2053+ /*
2054+ * List of optional, i.e. which could be added by add_attribute command
2055+ * and deleted by del_attribute command, sysfs attributes, if any.
2056+ * Helpful for scstadmin to work correctly.
2057+ */
2058+ const char *devt_optional_attributes;
2059+
2060+ /*
2061+ * List of optional, i.e. which could be added by add_device_attribute
2062+ * command and deleted by del_device_attribute command, sysfs
2063+ * attributes, if any. Helpful for scstadmin to work correctly.
2064+ */
2065+ const char *dev_optional_attributes;
2066+
2067+ /* sysfs attributes, if any */
2068+ const struct attribute **devt_attrs;
2069+
2070+ /* sysfs device attributes, if any */
2071+ const struct attribute **dev_attrs;
2072+
2073+ /* Pointer to dev handler's private data */
2074+ void *devt_priv;
2075+
2076+ /* Pointer to parent dev type in the sysfs hierarchy */
2077+ struct scst_dev_type *parent;
2078+
2079+ struct module *module;
2080+
2081+ /** Private, must be inited to 0 by memset() **/
2082+
2083+ /* list entry in scst_(virtual_)dev_type_list */
2084+ struct list_head dev_type_list_entry;
2085+
2086+ struct kobject devt_kobj; /* main handlers/driver */
2087+
2088+ /* Number of currently active sysfs mgmt works (scst_sysfs_work_item) */
2089+ int devt_active_sysfs_works_count;
2090+
2091+ /* To wait until devt_kobj released */
2092+ struct completion devt_kobj_release_compl;
2093+};
2094+
2095+/*
2096+ * An SCST target, analog of SCSI target port.
2097+ */
2098+struct scst_tgt {
2099+ /* List of remote sessions per target, protected by scst_mutex */
2100+ struct list_head sess_list;
2101+
2102+ /* List entry of targets per template (tgts_list) */
2103+ struct list_head tgt_list_entry;
2104+
2105+ struct scst_tgt_template *tgtt; /* corresponding target template */
2106+
2107+ struct scst_acg *default_acg; /* default acg for this target */
2108+
2109+ struct list_head tgt_acg_list; /* target ACG groups */
2110+
2111+ /*
2112+ * Maximum SG table size. Needed here, since different cards on the
2113+ * same target template can have different SG table limitations.
2114+ */
2115+ int sg_tablesize;
2116+
2117+ /* Used for storage of target driver private stuff */
2118+ void *tgt_priv;
2119+
2120+ /*
2121+ * The following fields used to store and retry cmds if target's
2122+ * internal queue is full, so the target is unable to accept
2123+ * the cmd returning QUEUE FULL.
2124+ * They protected by tgt_lock, where necessary.
2125+ */
2126+ bool retry_timer_active;
2127+ struct timer_list retry_timer;
2128+ atomic_t finished_cmds;
2129+ int retry_cmds;
2130+ spinlock_t tgt_lock;
2131+ struct list_head retry_cmd_list;
2132+
2133+ /* Used to wait until session finished to unregister */
2134+ wait_queue_head_t unreg_waitQ;
2135+
2136+ /* Name of the target */
2137+ char *tgt_name;
2138+
2139+ uint16_t rel_tgt_id;
2140+
2141+ /* sysfs release completion */
2142+ struct completion tgt_kobj_release_cmpl;
2143+
2144+ struct kobject tgt_kobj; /* main targets/target kobject */
2145+ struct kobject *tgt_sess_kobj; /* target/sessions/ */
2146+ struct kobject *tgt_luns_kobj; /* target/luns/ */
2147+ struct kobject *tgt_ini_grp_kobj; /* target/ini_groups/ */
2148+};
2149+
2150+/* Hash size and hash fn for hash based lun translation */
2151+#define TGT_DEV_HASH_SHIFT 5
2152+#define TGT_DEV_HASH_SIZE (1 << TGT_DEV_HASH_SHIFT)
2153+#define HASH_VAL(_val) (_val & (TGT_DEV_HASH_SIZE - 1))
2154+
2155+#ifdef CONFIG_SCST_MEASURE_LATENCY
2156+
2157+/* Defines extended latency statistics */
2158+struct scst_ext_latency_stat {
2159+ uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
2160+ unsigned int processed_cmds_rd;
2161+ uint64_t min_scst_time_rd, min_tgt_time_rd, min_dev_time_rd;
2162+ uint64_t max_scst_time_rd, max_tgt_time_rd, max_dev_time_rd;
2163+
2164+ uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
2165+ unsigned int processed_cmds_wr;
2166+ uint64_t min_scst_time_wr, min_tgt_time_wr, min_dev_time_wr;
2167+ uint64_t max_scst_time_wr, max_tgt_time_wr, max_dev_time_wr;
2168+};
2169+
2170+#define SCST_IO_SIZE_THRESHOLD_SMALL (8*1024)
2171+#define SCST_IO_SIZE_THRESHOLD_MEDIUM (32*1024)
2172+#define SCST_IO_SIZE_THRESHOLD_LARGE (128*1024)
2173+#define SCST_IO_SIZE_THRESHOLD_VERY_LARGE (512*1024)
2174+
2175+#define SCST_LATENCY_STAT_INDEX_SMALL 0
2176+#define SCST_LATENCY_STAT_INDEX_MEDIUM 1
2177+#define SCST_LATENCY_STAT_INDEX_LARGE 2
2178+#define SCST_LATENCY_STAT_INDEX_VERY_LARGE 3
2179+#define SCST_LATENCY_STAT_INDEX_OTHER 4
2180+#define SCST_LATENCY_STATS_NUM (SCST_LATENCY_STAT_INDEX_OTHER + 1)
2181+
2182+#endif /* CONFIG_SCST_MEASURE_LATENCY */
2183+
2184+/*
2185+ * SCST session, analog of SCSI I_T nexus
2186+ */
2187+struct scst_session {
2188+ /*
2189+ * Initialization phase, one of SCST_SESS_IPH_* constants, protected by
2190+ * sess_list_lock
2191+ */
2192+ int init_phase;
2193+
2194+ struct scst_tgt *tgt; /* corresponding target */
2195+
2196+ /* Used for storage of target driver private stuff */
2197+ void *tgt_priv;
2198+
2199+ /* session's async flags */
2200+ unsigned long sess_aflags;
2201+
2202+ /*
2203+ * Hash list of tgt_dev's for this session, protected by scst_mutex
2204+ * and suspended activity
2205+ */
2206+ struct list_head sess_tgt_dev_list_hash[TGT_DEV_HASH_SIZE];
2207+
2208+ /*
2209+ * List of cmds in this session. Protected by sess_list_lock.
2210+ *
2211+ * We must always keep commands in the sess list from the
2212+ * very beginning, because otherwise they can be missed during
2213+ * TM processing.
2214+ */
2215+ struct list_head sess_cmd_list;
2216+
2217+ spinlock_t sess_list_lock; /* protects sess_cmd_list, etc */
2218+
2219+ atomic_t refcnt; /* get/put counter */
2220+
2221+ /*
2222+ * Alive commands for this session. ToDo: make it part of the common
2223+ * IO flow control.
2224+ */
2225+ atomic_t sess_cmd_count;
2226+
2227+ /* Access control for this session and list entry there */
2228+ struct scst_acg *acg;
2229+
2230+ /* Initiator port transport id */
2231+ uint8_t *transport_id;
2232+
2233+ /* List entry for the sessions list inside ACG */
2234+ struct list_head acg_sess_list_entry;
2235+
2236+ struct delayed_work hw_pending_work;
2237+
2238+ /* Name of attached initiator */
2239+ const char *initiator_name;
2240+
2241+ /* List entry of sessions per target */
2242+ struct list_head sess_list_entry;
2243+
2244+ /* List entry for the list that keeps session, waiting for the init */
2245+ struct list_head sess_init_list_entry;
2246+
2247+ /*
2248+ * List entry for the list that keeps session, waiting for the shutdown
2249+ */
2250+ struct list_head sess_shut_list_entry;
2251+
2252+ /*
2253+ * Lists of deferred during session initialization commands.
2254+ * Protected by sess_list_lock.
2255+ */
2256+ struct list_head init_deferred_cmd_list;
2257+ struct list_head init_deferred_mcmd_list;
2258+
2259+ /*
2260+ * Shutdown phase, one of SCST_SESS_SPH_* constants, unprotected.
2261+ * Async. relating to init_phase, must be a separate variable, because
2262+ * session could be unregistered before async. registration is finished.
2263+ */
2264+ unsigned long shut_phase;
2265+
2266+ /* Used if scst_unregister_session() called in wait mode */
2267+ struct completion *shutdown_compl;
2268+
2269+ /* sysfs release completion */
2270+ struct completion sess_kobj_release_cmpl;
2271+
2272+ unsigned int sess_kobj_ready:1;
2273+
2274+ struct kobject sess_kobj; /* kobject for this struct */
2275+
2276+ /*
2277+ * Functions and data for user callbacks from scst_register_session()
2278+ * and scst_unregister_session()
2279+ */
2280+ void *reg_sess_data;
2281+ void (*init_result_fn) (struct scst_session *sess, void *data,
2282+ int result);
2283+ void (*unreg_done_fn) (struct scst_session *sess);
2284+
2285+#ifdef CONFIG_SCST_MEASURE_LATENCY
2286+ /*
2287+ * Must be the last to allow to work with drivers who don't know
2288+ * about this config time option.
2289+ */
2290+ spinlock_t lat_lock;
2291+ uint64_t scst_time, tgt_time, dev_time;
2292+ unsigned int processed_cmds;
2293+ uint64_t min_scst_time, min_tgt_time, min_dev_time;
2294+ uint64_t max_scst_time, max_tgt_time, max_dev_time;
2295+ struct scst_ext_latency_stat sess_latency_stat[SCST_LATENCY_STATS_NUM];
2296+#endif
2297+};
2298+
2299+/*
2300+ * SCST_PR_ABORT_ALL TM function helper structure
2301+ */
2302+struct scst_pr_abort_all_pending_mgmt_cmds_counter {
2303+ /*
2304+ * How many there are pending for this cmd SCST_PR_ABORT_ALL TM
2305+ * commands.
2306+ */
2307+ atomic_t pr_abort_pending_cnt;
2308+
2309+ /* Saved completition routine */
2310+ void (*saved_cmd_done) (struct scst_cmd *cmd, int next_state,
2311+ enum scst_exec_context pref_context);
2312+
2313+ /*
2314+ * How many there are pending for this cmd SCST_PR_ABORT_ALL TM
2315+ * commands, which not yet aborted all affected commands and
2316+ * a completion to signal, when it's done.
2317+ */
2318+ atomic_t pr_aborting_cnt;
2319+ struct completion pr_aborting_cmpl;
2320+};
2321+
2322+/*
2323+ * Structure to control commands' queuing and threads pool processing the queue
2324+ */
2325+struct scst_cmd_threads {
2326+ spinlock_t cmd_list_lock;
2327+ struct list_head active_cmd_list; /* commands queue */
2328+ wait_queue_head_t cmd_list_waitQ;
2329+
2330+ struct io_context *io_context; /* IO context of the threads pool */
2331+ int io_context_refcnt;
2332+
2333+ bool io_context_ready;
2334+
2335+ /* io_context_mutex protects io_context and io_context_refcnt. */
2336+ struct mutex io_context_mutex;
2337+
2338+ int nr_threads; /* number of processing threads */
2339+ struct list_head threads_list; /* processing threads */
2340+
2341+ struct list_head lists_list_entry;
2342+};
2343+
2344+/*
2345+ * SCST command, analog of I_T_L_Q nexus or task
2346+ */
2347+struct scst_cmd {
2348+ /* List entry for below *_cmd_threads */
2349+ struct list_head cmd_list_entry;
2350+
2351+ /* Pointer to lists of commands with the lock */
2352+ struct scst_cmd_threads *cmd_threads;
2353+
2354+ atomic_t cmd_ref;
2355+
2356+ struct scst_session *sess; /* corresponding session */
2357+
2358+ /* Cmd state, one of SCST_CMD_STATE_* constants */
2359+ int state;
2360+
2361+ /*************************************************************
2362+ ** Cmd's flags
2363+ *************************************************************/
2364+
2365+ /*
2366+ * Set if expected_sn should be incremented, i.e. cmd was sent
2367+ * for execution
2368+ */
2369+ unsigned int sent_for_exec:1;
2370+
2371+ /* Set if the cmd's action is completed */
2372+ unsigned int completed:1;
2373+
2374+ /* Set if we should ignore Unit Attention in scst_check_sense() */
2375+ unsigned int ua_ignore:1;
2376+
2377+ /* Set if cmd is being processed in atomic context */
2378+ unsigned int atomic:1;
2379+
2380+ /* Set if this command was sent in double UA possible state */
2381+ unsigned int double_ua_possible:1;
2382+
2383+ /* Set if this command contains status */
2384+ unsigned int is_send_status:1;
2385+
2386+ /* Set if cmd is being retried */
2387+ unsigned int retry:1;
2388+
2389+ /* Set if cmd is internally generated */
2390+ unsigned int internal:1;
2391+
2392+ /* Set if the device was blocked by scst_check_blocked_dev() */
2393+ unsigned int unblock_dev:1;
2394+
2395+ /* Set if cmd is queued as hw pending */
2396+ unsigned int cmd_hw_pending:1;
2397+
2398+ /*
2399+ * Set if the target driver wants to alloc data buffers on its own.
2400+ * In this case alloc_data_buf() must be provided in the target driver
2401+ * template.
2402+ */
2403+ unsigned int tgt_need_alloc_data_buf:1;
2404+
2405+ /*
2406+ * Set by SCST if the custom data buffer allocation by the target driver
2407+ * succeeded.
2408+ */
2409+ unsigned int tgt_data_buf_alloced:1;
2410+
2411+ /* Set if custom data buffer allocated by dev handler */
2412+ unsigned int dh_data_buf_alloced:1;
2413+
2414+ /* Set if the target driver called scst_set_expected() */
2415+ unsigned int expected_values_set:1;
2416+
2417+ /*
2418+ * Set if the SG buffer was modified by scst_adjust_sg()
2419+ */
2420+ unsigned int sg_buff_modified:1;
2421+
2422+ /*
2423+ * Set if cmd buffer was vmallocated and copied from more
2424+ * then one sg chunk
2425+ */
2426+ unsigned int sg_buff_vmallocated:1;
2427+
2428+ /*
2429+ * Set if scst_cmd_init_stage1_done() called and the target
2430+ * want that preprocessing_done() will be called
2431+ */
2432+ unsigned int preprocessing_only:1;
2433+
2434+ /* Set if cmd's SN was set */
2435+ unsigned int sn_set:1;
2436+
2437+ /* Set if hq_cmd_count was incremented */
2438+ unsigned int hq_cmd_inced:1;
2439+
2440+ /*
2441+ * Set if scst_cmd_init_stage1_done() called and the target wants
2442+ * that the SN for the cmd won't be assigned until scst_restart_cmd()
2443+ */
2444+ unsigned int set_sn_on_restart_cmd:1;
2445+
2446+ /* Set if the cmd's must not use sgv cache for data buffer */
2447+ unsigned int no_sgv:1;
2448+
2449+ /*
2450+ * Set if target driver may need to call dma_sync_sg() or similar
2451+ * function before transferring cmd' data to the target device
2452+ * via DMA.
2453+ */
2454+ unsigned int may_need_dma_sync:1;
2455+
2456+ /* Set if the cmd was done or aborted out of its SN */
2457+ unsigned int out_of_sn:1;
2458+
2459+ /* Set if increment expected_sn in cmd->scst_cmd_done() */
2460+ unsigned int inc_expected_sn_on_done:1;
2461+
2462+ /* Set if tgt_sn field is valid */
2463+ unsigned int tgt_sn_set:1;
2464+
2465+ /* Set if any direction residual is possible */
2466+ unsigned int resid_possible:1;
2467+
2468+ /* Set if cmd is done */
2469+ unsigned int done:1;
2470+
2471+ /* Set if cmd is finished */
2472+ unsigned int finished:1;
2473+
2474+#ifdef CONFIG_SCST_DEBUG_TM
2475+ /* Set if the cmd was delayed by task management debugging code */
2476+ unsigned int tm_dbg_delayed:1;
2477+
2478+ /* Set if the cmd must be ignored by task management debugging code */
2479+ unsigned int tm_dbg_immut:1;
2480+#endif
2481+
2482+ /**************************************************************/
2483+
2484+ /* cmd's async flags */
2485+ unsigned long cmd_flags;
2486+
2487+ /* Keeps status of cmd's status/data delivery to remote initiator */
2488+ int delivery_status;
2489+
2490+ struct scst_tgt_template *tgtt; /* to save extra dereferences */
2491+ struct scst_tgt *tgt; /* to save extra dereferences */
2492+ struct scst_device *dev; /* to save extra dereferences */
2493+
2494+ struct scst_tgt_dev *tgt_dev; /* corresponding device for this cmd */
2495+
2496+ uint64_t lun; /* LUN for this cmd */
2497+
2498+ unsigned long start_time;
2499+
2500+ /* List entry for tgt_dev's SN related lists */
2501+ struct list_head sn_cmd_list_entry;
2502+
2503+ /* Cmd's serial number, used to execute cmd's in order of arrival */
2504+ unsigned int sn;
2505+
2506+ /* The corresponding sn_slot in tgt_dev->sn_slots */
2507+ atomic_t *sn_slot;
2508+
2509+ /* List entry for sess's sess_cmd_list */
2510+ struct list_head sess_cmd_list_entry;
2511+
2512+ /*
2513+ * Used to found the cmd by scst_find_cmd_by_tag(). Set by the
2514+ * target driver on the cmd's initialization time
2515+ */
2516+ uint64_t tag;
2517+
2518+ uint32_t tgt_sn; /* SN set by target driver (for TM purposes) */
2519+
2520+ /* CDB and its len */
2521+ uint8_t cdb[SCST_MAX_CDB_SIZE];
2522+ unsigned short cdb_len;
2523+ unsigned short ext_cdb_len;
2524+ uint8_t *ext_cdb;
2525+
2526+ enum scst_cdb_flags op_flags;
2527+ const char *op_name;
2528+
2529+ enum scst_cmd_queue_type queue_type;
2530+
2531+ int timeout; /* CDB execution timeout in seconds */
2532+ int retries; /* Amount of retries that will be done by SCSI mid-level */
2533+
2534+ /* SCSI data direction, one of SCST_DATA_* constants */
2535+ scst_data_direction data_direction;
2536+
2537+ /* Remote initiator supplied values, if any */
2538+ scst_data_direction expected_data_direction;
2539+ int expected_transfer_len;
2540+ int expected_out_transfer_len; /* for bidi writes */
2541+
2542+ /*
2543+ * Cmd data length. Could be different from bufflen for commands like
2544+ * VERIFY, which transfer different amount of data (if any), than
2545+ * processed.
2546+ */
2547+ int data_len;
2548+
2549+ /* Completition routine */
2550+ void (*scst_cmd_done) (struct scst_cmd *cmd, int next_state,
2551+ enum scst_exec_context pref_context);
2552+
2553+ struct sgv_pool_obj *sgv; /* sgv object */
2554+ int bufflen; /* cmd buffer length */
2555+ struct scatterlist *sg; /* cmd data buffer SG vector */
2556+ int sg_cnt; /* SG segments count */
2557+
2558+ /*
2559+ * Response data length in data buffer. Must not be set
2560+ * directly, use scst_set_resp_data_len() for that.
2561+ */
2562+ int resp_data_len;
2563+
2564+ /*
2565+ * Response data length adjusted on residual, i.e.
2566+ * min(expected_len, resp_len), if expected len set.
2567+ */
2568+ int adjusted_resp_data_len;
2569+
2570+ /*
2571+ * Data length to write, i.e. transfer from the initiator. Might be
2572+ * different from (out_)bufflen, if the initiator asked too big or too
2573+ * small expected(_out_)transfer_len.
2574+ */
2575+ int write_len;
2576+
2577+ /*
2578+ * Write sg and sg_cnt to point out either on sg/sg_cnt, or on
2579+ * out_sg/out_sg_cnt.
2580+ */
2581+ struct scatterlist **write_sg;
2582+ int *write_sg_cnt;
2583+
2584+ /* scst_get_sg_buf_[first,next]() support */
2585+ int get_sg_buf_entry_num;
2586+
2587+ /* Bidirectional transfers support */
2588+ int out_bufflen; /* WRITE buffer length */
2589+ struct sgv_pool_obj *out_sgv; /* WRITE sgv object */
2590+ struct scatterlist *out_sg; /* WRITE data buffer SG vector */
2591+ int out_sg_cnt; /* WRITE SG segments count */
2592+
2593+ /*
2594+ * Used if both target driver and dev handler request own memory
2595+ * allocation. In other cases, both are equal to sg and sg_cnt
2596+ * correspondingly.
2597+ *
2598+ * If target driver requests own memory allocations, it MUST use
2599+ * functions scst_cmd_get_tgt_sg*() to get sg and sg_cnt! Otherwise,
2600+ * it may use functions scst_cmd_get_sg*().
2601+ */
2602+ struct scatterlist *tgt_sg;
2603+ int tgt_sg_cnt;
2604+ struct scatterlist *tgt_out_sg; /* bidirectional */
2605+ int tgt_out_sg_cnt; /* bidirectional */
2606+
2607+ /*
2608+ * The status fields in case of errors must be set using
2609+ * scst_set_cmd_error_status()!
2610+ */
2611+ uint8_t status; /* status byte from target device */
2612+ uint8_t msg_status; /* return status from host adapter itself */
2613+ uint8_t host_status; /* set by low-level driver to indicate status */
2614+ uint8_t driver_status; /* set by mid-level */
2615+
2616+ uint8_t *sense; /* pointer to sense buffer */
2617+ unsigned short sense_valid_len; /* length of valid sense data */
2618+ unsigned short sense_buflen; /* length of the sense buffer, if any */
2619+
2620+ /* Start time when cmd was sent to rdy_to_xfer() or xmit_response() */
2621+ unsigned long hw_pending_start;
2622+
2623+ /* Used for storage of target driver private stuff */
2624+ void *tgt_priv;
2625+
2626+ /* Used for storage of dev handler private stuff */
2627+ void *dh_priv;
2628+
2629+ /* Used to restore sg if it was modified by scst_adjust_sg() */
2630+ struct scatterlist *orig_sg;
2631+ int *p_orig_sg_cnt;
2632+ int orig_sg_cnt, orig_sg_entry, orig_entry_len;
2633+
2634+ /* Used to retry commands in case of double UA */
2635+ int dbl_ua_orig_resp_data_len, dbl_ua_orig_data_direction;
2636+
2637+ /*
2638+ * List of the corresponding mgmt cmds, if any. Protected by
2639+ * sess_list_lock.
2640+ */
2641+ struct list_head mgmt_cmd_list;
2642+
2643+ /* List entry for dev's blocked_cmd_list */
2644+ struct list_head blocked_cmd_list_entry;
2645+
2646+ /* Counter of the corresponding SCST_PR_ABORT_ALL TM commands */
2647+ struct scst_pr_abort_all_pending_mgmt_cmds_counter *pr_abort_counter;
2648+
2649+ struct scst_cmd *orig_cmd; /* Used to issue REQUEST SENSE */
2650+
2651+#ifdef CONFIG_SCST_MEASURE_LATENCY
2652+ /*
2653+ * Must be the last to allow to work with drivers who don't know
2654+ * about this config time option.
2655+ */
2656+ uint64_t start, curr_start, parse_time, alloc_buf_time;
2657+ uint64_t restart_waiting_time, rdy_to_xfer_time;
2658+ uint64_t pre_exec_time, exec_time, dev_done_time;
2659+ uint64_t xmit_time, tgt_on_free_time, dev_on_free_time;
2660+#endif
2661+};
2662+
2663+/*
2664+ * Parameters for SCST management commands
2665+ */
2666+struct scst_rx_mgmt_params {
2667+ int fn;
2668+ uint64_t tag;
2669+ const uint8_t *lun;
2670+ int lun_len;
2671+ uint32_t cmd_sn;
2672+ int atomic;
2673+ void *tgt_priv;
2674+ unsigned char tag_set;
2675+ unsigned char lun_set;
2676+ unsigned char cmd_sn_set;
2677+};
2678+
2679+/*
2680+ * A stub structure to link an management command and affected regular commands
2681+ */
2682+struct scst_mgmt_cmd_stub {
2683+ struct scst_mgmt_cmd *mcmd;
2684+
2685+ /* List entry in cmd->mgmt_cmd_list */
2686+ struct list_head cmd_mgmt_cmd_list_entry;
2687+
2688+ /* Set if the cmd was counted in mcmd->cmd_done_wait_count */
2689+ unsigned int done_counted:1;
2690+
2691+ /* Set if the cmd was counted in mcmd->cmd_finish_wait_count */
2692+ unsigned int finish_counted:1;
2693+};
2694+
2695+/*
2696+ * SCST task management structure
2697+ */
2698+struct scst_mgmt_cmd {
2699+ /* List entry for *_mgmt_cmd_list */
2700+ struct list_head mgmt_cmd_list_entry;
2701+
2702+ struct scst_session *sess;
2703+
2704+ /* Mgmt cmd state, one of SCST_MCMD_STATE_* constants */
2705+ int state;
2706+
2707+ int fn; /* task management function */
2708+
2709+ /* Set if device(s) should be unblocked after mcmd's finish */
2710+ unsigned int needs_unblocking:1;
2711+ unsigned int lun_set:1; /* set, if lun field is valid */
2712+ unsigned int cmd_sn_set:1; /* set, if cmd_sn field is valid */
2713+
2714+ /*
2715+ * Number of commands to finish before sending response,
2716+ * protected by scst_mcmd_lock
2717+ */
2718+ int cmd_finish_wait_count;
2719+
2720+ /*
2721+ * Number of commands to complete (done) before resetting reservation,
2722+ * protected by scst_mcmd_lock
2723+ */
2724+ int cmd_done_wait_count;
2725+
2726+ /* Number of completed commands, protected by scst_mcmd_lock */
2727+ int completed_cmd_count;
2728+
2729+ uint64_t lun; /* LUN for this mgmt cmd */
2730+ /* or (and for iSCSI) */
2731+ uint64_t tag; /* tag of the corresponding cmd */
2732+
2733+ uint32_t cmd_sn; /* affected command's highest SN */
2734+
2735+ /* corresponding cmd (to be aborted, found by tag) */
2736+ struct scst_cmd *cmd_to_abort;
2737+
2738+ /* corresponding device for this mgmt cmd (found by lun) */
2739+ struct scst_tgt_dev *mcmd_tgt_dev;
2740+
2741+ /* completition status, one of the SCST_MGMT_STATUS_* constants */
2742+ int status;
2743+
2744+ /* Used for storage of target driver private stuff or origin PR cmd */
2745+ union {
2746+ void *tgt_priv;
2747+ struct scst_cmd *origin_pr_cmd;
2748+ };
2749+};
2750+
2751+/*
2752+ * Persistent reservations registrant
2753+ */
2754+struct scst_dev_registrant {
2755+ uint8_t *transport_id;
2756+ uint16_t rel_tgt_id;
2757+ __be64 key;
2758+
2759+ /* tgt_dev (I_T nexus) for this registrant, if any */
2760+ struct scst_tgt_dev *tgt_dev;
2761+
2762+ /* List entry for dev_registrants_list */
2763+ struct list_head dev_registrants_list_entry;
2764+
2765+ /* 2 auxiliary fields used to rollback changes for errors, etc. */
2766+ struct list_head aux_list_entry;
2767+ __be64 rollback_key;
2768+};
2769+
2770+/*
2771+ * SCST device
2772+ */
2773+struct scst_device {
2774+ unsigned short type; /* SCSI type of the device */
2775+
2776+ /*************************************************************
2777+ ** Dev's flags. Updates serialized by dev_lock or suspended
2778+ ** activity
2779+ *************************************************************/
2780+
2781+ /* Set if dev is RESERVED */
2782+ unsigned short dev_reserved:1;
2783+
2784+ /* Set if double reset UA is possible */
2785+ unsigned short dev_double_ua_possible:1;
2786+
2787+ /* If set, dev is read only */
2788+ unsigned short rd_only:1;
2789+
2790+ /**************************************************************/
2791+
2792+ /*************************************************************
2793+ ** Dev's control mode page related values. Updates serialized
2794+ ** by scst_block_dev(). Modified independently to the above and
2795+ ** below fields, hence the alignment.
2796+ *************************************************************/
2797+
2798+ unsigned int queue_alg:4 __attribute__((aligned(sizeof(long))));
2799+ unsigned int tst:3;
2800+ unsigned int tas:1;
2801+ unsigned int swp:1;
2802+ unsigned int d_sense:1;
2803+
2804+ /*
2805+ * Set if device implements own ordered commands management. If not set
2806+ * and queue_alg is SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER,
2807+ * expected_sn will be incremented only after commands finished.
2808+ */
2809+ unsigned int has_own_order_mgmt:1;
2810+
2811+ /**************************************************************/
2812+
2813+ /*
2814+ * How many times device was blocked for new cmds execution.
2815+ * Protected by dev_lock
2816+ */
2817+ int block_count;
2818+
2819+ /* How many cmds alive on this dev */
2820+ atomic_t dev_cmd_count;
2821+
2822+ /*
2823+ * Set if dev is persistently reserved. Protected by dev_pr_mutex.
2824+ * Modified independently to the above field, hence the alignment.
2825+ */
2826+ unsigned int pr_is_set:1 __attribute__((aligned(sizeof(long))));
2827+
2828+ /*
2829+ * Set if there is a thread changing or going to change PR state(s).
2830+ * Protected by dev_pr_mutex.
2831+ */
2832+ unsigned int pr_writer_active:1;
2833+
2834+ /*
2835+ * How many threads are checking commands for PR allowance. Used to
2836+ * implement lockless read-only fast path.
2837+ */
2838+ atomic_t pr_readers_count;
2839+
2840+ struct scst_dev_type *handler; /* corresponding dev handler */
2841+
2842+ /* Used for storage of dev handler private stuff */
2843+ void *dh_priv;
2844+
2845+ /* Corresponding real SCSI device, could be NULL for virtual devices */
2846+ struct scsi_device *scsi_dev;
2847+
2848+ /* List of commands with lock, if dedicated threads are used */
2849+ struct scst_cmd_threads dev_cmd_threads;
2850+
2851+ /* Memory limits for this device */
2852+ struct scst_mem_lim dev_mem_lim;
2853+
2854+ /* How many write cmds alive on this dev. Temporary, ToDo */
2855+ atomic_t write_cmd_count;
2856+
2857+ /*************************************************************
2858+ ** Persistent reservation fields. Protected by dev_pr_mutex.
2859+ *************************************************************/
2860+
2861+ /*
2862+ * True if persist through power loss is activated. Modified
2863+ * independently to the above field, hence the alignment.
2864+ */
2865+ unsigned short pr_aptpl:1 __attribute__((aligned(sizeof(long))));
2866+
2867+ /* Persistent reservation type */
2868+ uint8_t pr_type;
2869+
2870+ /* Persistent reservation scope */
2871+ uint8_t pr_scope;
2872+
2873+ /* Mutex to protect PR operations */
2874+ struct mutex dev_pr_mutex;
2875+
2876+ /* Persistent reservation generation value */
2877+ uint32_t pr_generation;
2878+
2879+ /* Reference to registrant - persistent reservation holder */
2880+ struct scst_dev_registrant *pr_holder;
2881+
2882+ /* List of dev's registrants */
2883+ struct list_head dev_registrants_list;
2884+
2885+ /*
2886+ * Count of connected tgt_devs from transports, which don't support
2887+ * PRs, i.e. don't have get_initiator_port_transport_id(). Protected
2888+ * by scst_mutex.
2889+ */
2890+ int not_pr_supporting_tgt_devs_num;
2891+
2892+ /* Persist through power loss files */
2893+ char *pr_file_name;
2894+ char *pr_file_name1;
2895+
2896+ /**************************************************************/
2897+
2898+ spinlock_t dev_lock; /* device lock */
2899+
2900+ struct list_head blocked_cmd_list; /* protected by dev_lock */
2901+
2902+ /* A list entry used during TM, protected by scst_mutex */
2903+ struct list_head tm_dev_list_entry;
2904+
2905+ /* Virtual device internal ID */
2906+ int virt_id;
2907+
2908+ /* Pointer to virtual device name, for convenience only */
2909+ char *virt_name;
2910+
2911+ /* List entry in global devices list */
2912+ struct list_head dev_list_entry;
2913+
2914+ /*
2915+ * List of tgt_dev's, one per session, protected by scst_mutex or
2916+ * dev_lock for reads and both for writes
2917+ */
2918+ struct list_head dev_tgt_dev_list;
2919+
2920+ /* List of acg_dev's, one per acg, protected by scst_mutex */
2921+ struct list_head dev_acg_dev_list;
2922+
2923+ /* Number of threads in the device's threads pools */
2924+ int threads_num;
2925+
2926+ /* Threads pool type of the device. Valid only if threads_num > 0. */
2927+ enum scst_dev_type_threads_pool_type threads_pool_type;
2928+
2929+ /* sysfs release completion */
2930+ struct completion dev_kobj_release_cmpl;
2931+
2932+ struct kobject dev_kobj; /* kobject for this struct */
2933+ struct kobject *dev_exp_kobj; /* exported groups */
2934+
2935+ /* Export number in the dev's sysfs list. Protected by scst_mutex */
2936+ int dev_exported_lun_num;
2937+};
2938+
2939+/*
2940+ * Used to store threads local tgt_dev specific data
2941+ */
2942+struct scst_thr_data_hdr {
2943+ /* List entry in tgt_dev->thr_data_list */
2944+ struct list_head thr_data_list_entry;
2945+ struct task_struct *owner_thr; /* the owner thread */
2946+ atomic_t ref;
2947+ /* Function that will be called on the tgt_dev destruction */
2948+ void (*free_fn) (struct scst_thr_data_hdr *data);
2949+};
2950+
2951+/*
2952+ * Used to clearly dispose async io_context
2953+ */
2954+struct scst_async_io_context_keeper {
2955+ struct kref aic_keeper_kref;
2956+ bool aic_ready;
2957+ struct io_context *aic;
2958+ struct task_struct *aic_keeper_thr;
2959+ wait_queue_head_t aic_keeper_waitQ;
2960+};
2961+
2962+/*
2963+ * Used to store per-session specific device information, analog of
2964+ * SCSI I_T_L nexus.
2965+ */
2966+struct scst_tgt_dev {
2967+ /* List entry in sess->sess_tgt_dev_list_hash */
2968+ struct list_head sess_tgt_dev_list_entry;
2969+
2970+ struct scst_device *dev; /* to save extra dereferences */
2971+ uint64_t lun; /* to save extra dereferences */
2972+
2973+ gfp_t gfp_mask;
2974+ struct sgv_pool *pool;
2975+ int max_sg_cnt;
2976+
2977+ /*
2978+ * Tgt_dev's async flags. Modified independently to the neighbour
2979+ * fields.
2980+ */
2981+ unsigned long tgt_dev_flags;
2982+
2983+ /* Used for storage of dev handler private stuff */
2984+ void *dh_priv;
2985+
2986+ /* How many cmds alive on this dev in this session */
2987+ atomic_t tgt_dev_cmd_count;
2988+
2989+ /*
2990+ * Used to execute cmd's in order of arrival, honoring SCSI task
2991+ * attributes.
2992+ *
2993+ * Protected by sn_lock, except expected_sn, which is protected by
2994+ * itself. Curr_sn must have the same size as expected_sn to
2995+ * overflow simultaneously.
2996+ */
2997+ int def_cmd_count;
2998+ spinlock_t sn_lock;
2999+ unsigned int expected_sn;
3000+ unsigned int curr_sn;
3001+ int hq_cmd_count;
3002+ struct list_head deferred_cmd_list;
3003+ struct list_head skipped_sn_list;
3004+
3005+ /*
3006+ * Set if the prev cmd was ORDERED. Size and, hence, alignment must
3007+ * allow unprotected modifications independently to the neighbour fields.
3008+ */
3009+ unsigned long prev_cmd_ordered;
3010+
3011+ int num_free_sn_slots; /* if it's <0, then all slots are busy */
3012+ atomic_t *cur_sn_slot;
3013+ atomic_t sn_slots[15];
3014+
3015+ /* List of scst_thr_data_hdr and lock */
3016+ spinlock_t thr_data_lock;
3017+ struct list_head thr_data_list;
3018+
3019+ /* Pointer to lists of commands with the lock */
3020+ struct scst_cmd_threads *active_cmd_threads;
3021+
3022+ /* Union to save some CPU cache footprint */
3023+ union {
3024+ struct {
3025+ /* Copy to save fast path dereference */
3026+ struct io_context *async_io_context;
3027+
3028+ struct scst_async_io_context_keeper *aic_keeper;
3029+ };
3030+
3031+ /* Lists of commands with lock, if dedicated threads are used */
3032+ struct scst_cmd_threads tgt_dev_cmd_threads;
3033+ };
3034+
3035+ spinlock_t tgt_dev_lock; /* per-session device lock */
3036+
3037+ /* List of UA's for this device, protected by tgt_dev_lock */
3038+ struct list_head UA_list;
3039+
3040+ struct scst_session *sess; /* corresponding session */
3041+ struct scst_acg_dev *acg_dev; /* corresponding acg_dev */
3042+
3043+ /* Reference to registrant to find quicker */
3044+ struct scst_dev_registrant *registrant;
3045+
3046+ /* List entry in dev->dev_tgt_dev_list */
3047+ struct list_head dev_tgt_dev_list_entry;
3048+
3049+ /* Internal tmp list entry */
3050+ struct list_head extra_tgt_dev_list_entry;
3051+
3052+ /* Set if INQUIRY DATA HAS CHANGED UA is needed */
3053+ unsigned int inq_changed_ua_needed:1;
3054+
3055+ /*
3056+ * Stored Unit Attention sense and its length for possible
3057+ * subsequent REQUEST SENSE. Both protected by tgt_dev_lock.
3058+ */
3059+ unsigned short tgt_dev_valid_sense_len;
3060+ uint8_t tgt_dev_sense[SCST_SENSE_BUFFERSIZE];
3061+
3062+ /* sysfs release completion */
3063+ struct completion tgt_dev_kobj_release_cmpl;
3064+
3065+ struct kobject tgt_dev_kobj; /* kobject for this struct */
3066+
3067+#ifdef CONFIG_SCST_MEASURE_LATENCY
3068+ /*
3069+ * Must be the last to allow to work with drivers who don't know
3070+ * about this config time option.
3071+ *
3072+ * Protected by sess->lat_lock.
3073+ */
3074+ uint64_t scst_time, tgt_time, dev_time;
3075+ unsigned int processed_cmds;
3076+ struct scst_ext_latency_stat dev_latency_stat[SCST_LATENCY_STATS_NUM];
3077+#endif
3078+};
3079+
3080+/*
3081+ * Used to store ACG-specific device information, like LUN
3082+ */
3083+struct scst_acg_dev {
3084+ struct scst_device *dev; /* corresponding device */
3085+
3086+ uint64_t lun; /* device's LUN in this acg */
3087+
3088+ /* If set, the corresponding LU is read only */
3089+ unsigned int rd_only:1;
3090+
3091+ struct scst_acg *acg; /* parent acg */
3092+
3093+ /* List entry in dev->dev_acg_dev_list */
3094+ struct list_head dev_acg_dev_list_entry;
3095+
3096+ /* List entry in acg->acg_dev_list */
3097+ struct list_head acg_dev_list_entry;
3098+
3099+ /* kobject for this structure */
3100+ struct kobject acg_dev_kobj;
3101+
3102+ /* sysfs release completion */
3103+ struct completion acg_dev_kobj_release_cmpl;
3104+
3105+ /* Name of the link to the corresponding LUN */
3106+ char acg_dev_link_name[20];
3107+};
3108+
3109+/*
3110+ * ACG - access control group. Used to store group related
3111+ * control information.
3112+ */
3113+struct scst_acg {
3114+ /* Owner target */
3115+ struct scst_tgt *tgt;
3116+
3117+ /* List of acg_dev's in this acg, protected by scst_mutex */
3118+ struct list_head acg_dev_list;
3119+
3120+ /* List of attached sessions, protected by scst_mutex */
3121+ struct list_head acg_sess_list;
3122+
3123+ /* List of attached acn's, protected by scst_mutex */
3124+ struct list_head acn_list;
3125+
3126+ /* List entry in acg_lists */
3127+ struct list_head acg_list_entry;
3128+
3129+ /* Name of this acg */
3130+ const char *acg_name;
3131+
3132+ /* Type of I/O initiators groupping */
3133+ int acg_io_grouping_type;
3134+
3135+ unsigned int tgt_acg:1;
3136+
3137+ /* sysfs release completion */
3138+ struct completion acg_kobj_release_cmpl;
3139+
3140+ /* kobject for this structure */
3141+ struct kobject acg_kobj;
3142+
3143+ struct kobject *luns_kobj;
3144+ struct kobject *initiators_kobj;
3145+
3146+ unsigned int addr_method;
3147+};
3148+
3149+/*
3150+ * ACN - access control name. Used to store names, by which
3151+ * incoming sessions will be assigned to appropriate ACG.
3152+ */
3153+struct scst_acn {
3154+ struct scst_acg *acg; /* owner ACG */
3155+
3156+ const char *name; /* initiator's name */
3157+
3158+ /* List entry in acg->acn_list */
3159+ struct list_head acn_list_entry;
3160+
3161+ /* sysfs file attributes */
3162+ struct kobj_attribute *acn_attr;
3163+};
3164+
3165+/*
3166+ * Used to store per-session UNIT ATTENTIONs
3167+ */
3168+struct scst_tgt_dev_UA {
3169+ /* List entry in tgt_dev->UA_list */
3170+ struct list_head UA_list_entry;
3171+
3172+ /* Set if UA is global for session */
3173+ unsigned short global_UA:1;
3174+
3175+ /* Unit Attention valid sense len */
3176+ unsigned short UA_valid_sense_len;
3177+ /* Unit Attention sense buf */
3178+ uint8_t UA_sense_buffer[SCST_SENSE_BUFFERSIZE];
3179+};
3180+
3181+/* Used to deliver AENs */
3182+struct scst_aen {
3183+ int event_fn; /* AEN fn */
3184+
3185+ struct scst_session *sess; /* corresponding session */
3186+ __be64 lun; /* corresponding LUN in SCSI form */
3187+
3188+ union {
3189+ /* SCSI AEN data */
3190+ struct {
3191+ int aen_sense_len;
3192+ uint8_t aen_sense[SCST_STANDARD_SENSE_LEN];
3193+ };
3194+ };
3195+
3196+ /* Keeps status of AEN's delivery to remote initiator */
3197+ int delivery_status;
3198+};
3199+
3200+#ifndef smp_mb__after_set_bit
3201+/* There is no smp_mb__after_set_bit() in the kernel */
3202+#define smp_mb__after_set_bit() smp_mb()
3203+#endif
3204+
3205+/*
3206+ * Registers target template.
3207+ * Returns 0 on success or appropriate error code otherwise.
3208+ */
3209+int __scst_register_target_template(struct scst_tgt_template *vtt,
3210+ const char *version);
3211+static inline int scst_register_target_template(struct scst_tgt_template *vtt)
3212+{
3213+ return __scst_register_target_template(vtt, SCST_INTERFACE_VERSION);
3214+}
3215+
3216+/*
3217+ * Registers target template, non-GPL version.
3218+ * Returns 0 on success or appropriate error code otherwise.
3219+ *
3220+ * Note: *vtt must be static!
3221+ */
3222+int __scst_register_target_template_non_gpl(struct scst_tgt_template *vtt,
3223+ const char *version);
3224+static inline int scst_register_target_template_non_gpl(
3225+ struct scst_tgt_template *vtt)
3226+{
3227+ return __scst_register_target_template_non_gpl(vtt,
3228+ SCST_INTERFACE_VERSION);
3229+}
3230+
3231+void scst_unregister_target_template(struct scst_tgt_template *vtt);
3232+
3233+struct scst_tgt *scst_register_target(struct scst_tgt_template *vtt,
3234+ const char *target_name);
3235+void scst_unregister_target(struct scst_tgt *tgt);
3236+
3237+struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
3238+ const char *initiator_name, void *tgt_priv, void *result_fn_data,
3239+ void (*result_fn) (struct scst_session *sess, void *data, int result));
3240+struct scst_session *scst_register_session_non_gpl(struct scst_tgt *tgt,
3241+ const char *initiator_name, void *tgt_priv);
3242+void scst_unregister_session(struct scst_session *sess, int wait,
3243+ void (*unreg_done_fn) (struct scst_session *sess));
3244+void scst_unregister_session_non_gpl(struct scst_session *sess);
3245+
3246+int __scst_register_dev_driver(struct scst_dev_type *dev_type,
3247+ const char *version);
3248+static inline int scst_register_dev_driver(struct scst_dev_type *dev_type)
3249+{
3250+ return __scst_register_dev_driver(dev_type, SCST_INTERFACE_VERSION);
3251+}
3252+void scst_unregister_dev_driver(struct scst_dev_type *dev_type);
3253+
3254+int __scst_register_virtual_dev_driver(struct scst_dev_type *dev_type,
3255+ const char *version);
3256+/*
3257+ * Registers dev handler driver for virtual devices (eg VDISK).
3258+ * Returns 0 on success or appropriate error code otherwise.
3259+ */
3260+static inline int scst_register_virtual_dev_driver(
3261+ struct scst_dev_type *dev_type)
3262+{
3263+ return __scst_register_virtual_dev_driver(dev_type,
3264+ SCST_INTERFACE_VERSION);
3265+}
3266+
3267+void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type);
3268+
3269+bool scst_initiator_has_luns(struct scst_tgt *tgt, const char *initiator_name);
3270+
3271+struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
3272+ const uint8_t *lun, int lun_len, const uint8_t *cdb,
3273+ unsigned int cdb_len, int atomic);
3274+void scst_cmd_init_done(struct scst_cmd *cmd,
3275+ enum scst_exec_context pref_context);
3276+
3277+/*
3278+ * Notifies SCST that the driver finished the first stage of the command
3279+ * initialization, and the command is ready for execution, but after
3280+ * SCST done the command's preprocessing preprocessing_done() function
3281+ * should be called. The second argument sets preferred command execition
3282+ * context. See SCST_CONTEXT_* constants for details.
3283+ *
3284+ * See comment for scst_cmd_init_done() for the serialization requirements.
3285+ */
3286+static inline void scst_cmd_init_stage1_done(struct scst_cmd *cmd,
3287+ enum scst_exec_context pref_context, int set_sn)
3288+{
3289+ cmd->preprocessing_only = 1;
3290+ cmd->set_sn_on_restart_cmd = !set_sn;
3291+ scst_cmd_init_done(cmd, pref_context);
3292+}
3293+
3294+void scst_restart_cmd(struct scst_cmd *cmd, int status,
3295+ enum scst_exec_context pref_context);
3296+
3297+void scst_rx_data(struct scst_cmd *cmd, int status,
3298+ enum scst_exec_context pref_context);
3299+
3300+void scst_tgt_cmd_done(struct scst_cmd *cmd,
3301+ enum scst_exec_context pref_context);
3302+
3303+int scst_rx_mgmt_fn(struct scst_session *sess,
3304+ const struct scst_rx_mgmt_params *params);
3305+
3306+/*
3307+ * Creates new management command using tag and sends it for execution.
3308+ * Can be used for SCST_ABORT_TASK only.
3309+ * Must not be called in parallel with scst_unregister_session() for the
3310+ * same sess. Returns 0 for success, error code otherwise.
3311+ *
3312+ * Obsolete in favor of scst_rx_mgmt_fn()
3313+ */
3314+static inline int scst_rx_mgmt_fn_tag(struct scst_session *sess, int fn,
3315+ uint64_t tag, int atomic, void *tgt_priv)
3316+{
3317+ struct scst_rx_mgmt_params params;
3318+
3319+ BUG_ON(fn != SCST_ABORT_TASK);
3320+
3321+ memset(&params, 0, sizeof(params));
3322+ params.fn = fn;
3323+ params.tag = tag;
3324+ params.tag_set = 1;
3325+ params.atomic = atomic;
3326+ params.tgt_priv = tgt_priv;
3327+ return scst_rx_mgmt_fn(sess, &params);
3328+}
3329+
3330+/*
3331+ * Creates new management command using LUN and sends it for execution.
3332+ * Currently can be used for any fn, except SCST_ABORT_TASK.
3333+ * Must not be called in parallel with scst_unregister_session() for the
3334+ * same sess. Returns 0 for success, error code otherwise.
3335+ *
3336+ * Obsolete in favor of scst_rx_mgmt_fn()
3337+ */
3338+static inline int scst_rx_mgmt_fn_lun(struct scst_session *sess, int fn,
3339+ const uint8_t *lun, int lun_len, int atomic, void *tgt_priv)
3340+{
3341+ struct scst_rx_mgmt_params params;
3342+
3343+ BUG_ON(fn == SCST_ABORT_TASK);
3344+
3345+ memset(&params, 0, sizeof(params));
3346+ params.fn = fn;
3347+ params.lun = lun;
3348+ params.lun_len = lun_len;
3349+ params.lun_set = 1;
3350+ params.atomic = atomic;
3351+ params.tgt_priv = tgt_priv;
3352+ return scst_rx_mgmt_fn(sess, &params);
3353+}
3354+
3355+int scst_get_cdb_info(struct scst_cmd *cmd);
3356+
3357+int scst_set_cmd_error_status(struct scst_cmd *cmd, int status);
3358+int scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq);
3359+void scst_set_busy(struct scst_cmd *cmd);
3360+
3361+void scst_check_convert_sense(struct scst_cmd *cmd);
3362+
3363+void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq);
3364+
3365+void scst_capacity_data_changed(struct scst_device *dev);
3366+
3367+struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess, uint64_t tag);
3368+struct scst_cmd *scst_find_cmd(struct scst_session *sess, void *data,
3369+ int (*cmp_fn) (struct scst_cmd *cmd,
3370+ void *data));
3371+
3372+enum dma_data_direction scst_to_dma_dir(int scst_dir);
3373+enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir);
3374+
3375+/*
3376+ * Returns true, if cmd's CDB is fully locally handled by SCST and false
3377+ * otherwise. Dev handlers parse() and dev_done() not called for such commands.
3378+ */
3379+static inline bool scst_is_cmd_fully_local(struct scst_cmd *cmd)
3380+{
3381+ return (cmd->op_flags & SCST_FULLY_LOCAL_CMD) != 0;
3382+}
3383+
3384+/*
3385+ * Returns true, if cmd's CDB is locally handled by SCST and
3386+ * false otherwise.
3387+ */
3388+static inline bool scst_is_cmd_local(struct scst_cmd *cmd)
3389+{
3390+ return (cmd->op_flags & SCST_LOCAL_CMD) != 0;
3391+}
3392+
3393+/* Returns true, if cmd can deliver UA */
3394+static inline bool scst_is_ua_command(struct scst_cmd *cmd)
3395+{
3396+ return (cmd->op_flags & SCST_SKIP_UA) == 0;
3397+}
3398+
3399+int scst_register_virtual_device(struct scst_dev_type *dev_handler,
3400+ const char *dev_name);
3401+void scst_unregister_virtual_device(int id);
3402+
3403+/*
3404+ * Get/Set functions for tgt's sg_tablesize
3405+ */
3406+static inline int scst_tgt_get_sg_tablesize(struct scst_tgt *tgt)
3407+{
3408+ return tgt->sg_tablesize;
3409+}
3410+
3411+static inline void scst_tgt_set_sg_tablesize(struct scst_tgt *tgt, int val)
3412+{
3413+ tgt->sg_tablesize = val;
3414+}
3415+
3416+/*
3417+ * Get/Set functions for tgt's target private data
3418+ */
3419+static inline void *scst_tgt_get_tgt_priv(struct scst_tgt *tgt)
3420+{
3421+ return tgt->tgt_priv;
3422+}
3423+
3424+static inline void scst_tgt_set_tgt_priv(struct scst_tgt *tgt, void *val)
3425+{
3426+ tgt->tgt_priv = val;
3427+}
3428+
3429+void scst_update_hw_pending_start(struct scst_cmd *cmd);
3430+
3431+/*
3432+ * Get/Set functions for session's target private data
3433+ */
3434+static inline void *scst_sess_get_tgt_priv(struct scst_session *sess)
3435+{
3436+ return sess->tgt_priv;
3437+}
3438+
3439+static inline void scst_sess_set_tgt_priv(struct scst_session *sess,
3440+ void *val)
3441+{
3442+ sess->tgt_priv = val;
3443+}
3444+
3445+/**
3446+ * Returns TRUE if cmd is being executed in atomic context.
3447+ *
3448+ * Note: checkpatch will complain on the use of in_atomic() below. You can
3449+ * safely ignore this warning since in_atomic() is used here only for debugging
3450+ * purposes.
3451+ */
3452+static inline bool scst_cmd_atomic(struct scst_cmd *cmd)
3453+{
3454+ int res = cmd->atomic;
3455+#ifdef CONFIG_SCST_EXTRACHECKS
3456+ if (unlikely((in_atomic() || in_interrupt() || irqs_disabled()) &&
3457+ !res)) {
3458+ printk(KERN_ERR "ERROR: atomic context and non-atomic cmd\n");
3459+ dump_stack();
3460+ cmd->atomic = 1;
3461+ res = 1;
3462+ }
3463+#endif
3464+ return res;
3465+}
3466+
3467+/*
3468+ * Returns TRUE if cmd has been preliminary completed, i.e. completed or
3469+ * aborted.
3470+ */
3471+static inline bool scst_cmd_prelim_completed(struct scst_cmd *cmd)
3472+{
3473+ return cmd->completed || test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags);
3474+}
3475+
3476+static inline enum scst_exec_context __scst_estimate_context(bool direct)
3477+{
3478+ if (in_irq())
3479+ return SCST_CONTEXT_TASKLET;
3480+ else if (irqs_disabled())
3481+ return SCST_CONTEXT_THREAD;
3482+ else
3483+ return direct ? SCST_CONTEXT_DIRECT :
3484+ SCST_CONTEXT_DIRECT_ATOMIC;
3485+}
3486+
3487+static inline enum scst_exec_context scst_estimate_context(void)
3488+{
3489+ return __scst_estimate_context(0);
3490+}
3491+
3492+static inline enum scst_exec_context scst_estimate_context_direct(void)
3493+{
3494+ return __scst_estimate_context(1);
3495+}
3496+
3497+/* Returns cmd's CDB */
3498+static inline const uint8_t *scst_cmd_get_cdb(struct scst_cmd *cmd)
3499+{
3500+ return cmd->cdb;
3501+}
3502+
3503+/* Returns cmd's CDB length */
3504+static inline unsigned int scst_cmd_get_cdb_len(struct scst_cmd *cmd)
3505+{
3506+ return cmd->cdb_len;
3507+}
3508+
3509+/* Returns cmd's extended CDB */
3510+static inline const uint8_t *scst_cmd_get_ext_cdb(struct scst_cmd *cmd)
3511+{
3512+ return cmd->ext_cdb;
3513+}
3514+
3515+/* Returns cmd's extended CDB length */
3516+static inline unsigned int scst_cmd_get_ext_cdb_len(struct scst_cmd *cmd)
3517+{
3518+ return cmd->ext_cdb_len;
3519+}
3520+
3521+/* Sets cmd's extended CDB and its length */
3522+static inline void scst_cmd_set_ext_cdb(struct scst_cmd *cmd,
3523+ uint8_t *ext_cdb, unsigned int ext_cdb_len)
3524+{
3525+ cmd->ext_cdb = ext_cdb;
3526+ cmd->ext_cdb_len = ext_cdb_len;
3527+}
3528+
3529+/* Returns cmd's session */
3530+static inline struct scst_session *scst_cmd_get_session(struct scst_cmd *cmd)
3531+{
3532+ return cmd->sess;
3533+}
3534+
3535+/* Returns cmd's response data length */
3536+static inline int scst_cmd_get_resp_data_len(struct scst_cmd *cmd)
3537+{
3538+ return cmd->resp_data_len;
3539+}
3540+
3541+/* Returns cmd's adjusted response data length */
3542+static inline int scst_cmd_get_adjusted_resp_data_len(struct scst_cmd *cmd)
3543+{
3544+ return cmd->adjusted_resp_data_len;
3545+}
3546+
3547+/* Returns if status should be sent for cmd */
3548+static inline int scst_cmd_get_is_send_status(struct scst_cmd *cmd)
3549+{
3550+ return cmd->is_send_status;
3551+}
3552+
3553+/*
3554+ * Returns pointer to cmd's SG data buffer.
3555+ *
3556+ * Usage of this function is not recommended, use scst_get_buf_*()
3557+ * family of functions instead.
3558+ */
3559+static inline struct scatterlist *scst_cmd_get_sg(struct scst_cmd *cmd)
3560+{
3561+ return cmd->sg;
3562+}
3563+
3564+/*
3565+ * Returns cmd's sg_cnt.
3566+ *
3567+ * Usage of this function is not recommended, use scst_get_buf_*()
3568+ * family of functions instead.
3569+ */
3570+static inline int scst_cmd_get_sg_cnt(struct scst_cmd *cmd)
3571+{
3572+ return cmd->sg_cnt;
3573+}
3574+
3575+/*
3576+ * Returns cmd's data buffer length.
3577+ *
3578+ * In case if you need to iterate over data in the buffer, usage of
3579+ * this function is not recommended, use scst_get_buf_*()
3580+ * family of functions instead.
3581+ */
3582+static inline unsigned int scst_cmd_get_bufflen(struct scst_cmd *cmd)
3583+{
3584+ return cmd->bufflen;
3585+}
3586+
3587+/*
3588+ * Returns pointer to cmd's bidirectional in (WRITE) SG data buffer.
3589+ *
3590+ * Usage of this function is not recommended, use scst_get_out_buf_*()
3591+ * family of functions instead.
3592+ */
3593+static inline struct scatterlist *scst_cmd_get_out_sg(struct scst_cmd *cmd)
3594+{
3595+ return cmd->out_sg;
3596+}
3597+
3598+/*
3599+ * Returns cmd's bidirectional in (WRITE) sg_cnt.
3600+ *
3601+ * Usage of this function is not recommended, use scst_get_out_buf_*()
3602+ * family of functions instead.
3603+ */
3604+static inline int scst_cmd_get_out_sg_cnt(struct scst_cmd *cmd)
3605+{
3606+ return cmd->out_sg_cnt;
3607+}
3608+
3609+void scst_restore_sg_buff(struct scst_cmd *cmd);
3610+
3611+/* Restores modified sg buffer in the original state, if necessary */
3612+static inline void scst_check_restore_sg_buff(struct scst_cmd *cmd)
3613+{
3614+ if (unlikely(cmd->sg_buff_modified))
3615+ scst_restore_sg_buff(cmd);
3616+}
3617+
3618+/*
3619+ * Returns cmd's bidirectional in (WRITE) data buffer length.
3620+ *
3621+ * In case if you need to iterate over data in the buffer, usage of
3622+ * this function is not recommended, use scst_get_out_buf_*()
3623+ * family of functions instead.
3624+ */
3625+static inline unsigned int scst_cmd_get_out_bufflen(struct scst_cmd *cmd)
3626+{
3627+ return cmd->out_bufflen;
3628+}
3629+
3630+/* Returns pointer to cmd's target's SG data buffer */
3631+static inline struct scatterlist *scst_cmd_get_tgt_sg(struct scst_cmd *cmd)
3632+{
3633+ return cmd->tgt_sg;
3634+}
3635+
3636+/* Returns cmd's target's sg_cnt */
3637+static inline int scst_cmd_get_tgt_sg_cnt(struct scst_cmd *cmd)
3638+{
3639+ return cmd->tgt_sg_cnt;
3640+}
3641+
3642+/* Sets cmd's target's SG data buffer */
3643+static inline void scst_cmd_set_tgt_sg(struct scst_cmd *cmd,
3644+ struct scatterlist *sg, int sg_cnt)
3645+{
3646+ cmd->tgt_sg = sg;
3647+ cmd->tgt_sg_cnt = sg_cnt;
3648+ cmd->tgt_data_buf_alloced = 1;
3649+}
3650+
3651+/* Returns pointer to cmd's target's OUT SG data buffer */
3652+static inline struct scatterlist *scst_cmd_get_out_tgt_sg(struct scst_cmd *cmd)
3653+{
3654+ return cmd->tgt_out_sg;
3655+}
3656+
3657+/* Returns cmd's target's OUT sg_cnt */
3658+static inline int scst_cmd_get_tgt_out_sg_cnt(struct scst_cmd *cmd)
3659+{
3660+ return cmd->tgt_out_sg_cnt;
3661+}
3662+
3663+/* Sets cmd's target's OUT SG data buffer */
3664+static inline void scst_cmd_set_tgt_out_sg(struct scst_cmd *cmd,
3665+ struct scatterlist *sg, int sg_cnt)
3666+{
3667+ WARN_ON(!cmd->tgt_data_buf_alloced);
3668+
3669+ cmd->tgt_out_sg = sg;
3670+ cmd->tgt_out_sg_cnt = sg_cnt;
3671+}
3672+
3673+/* Returns cmd's data direction */
3674+static inline scst_data_direction scst_cmd_get_data_direction(
3675+ struct scst_cmd *cmd)
3676+{
3677+ return cmd->data_direction;
3678+}
3679+
3680+/* Returns cmd's write len as well as write SG and sg_cnt */
3681+static inline int scst_cmd_get_write_fields(struct scst_cmd *cmd,
3682+ struct scatterlist **sg, int *sg_cnt)
3683+{
3684+ *sg = *cmd->write_sg;
3685+ *sg_cnt = *cmd->write_sg_cnt;
3686+ return cmd->write_len;
3687+}
3688+
3689+void scst_cmd_set_write_not_received_data_len(struct scst_cmd *cmd,
3690+ int not_received);
3691+
3692+bool __scst_get_resid(struct scst_cmd *cmd, int *resid, int *bidi_out_resid);
3693+
3694+/*
3695+ * Returns true if cmd has residual(s) and returns them in the corresponding
3696+ * parameters(s).
3697+ */
3698+static inline bool scst_get_resid(struct scst_cmd *cmd,
3699+ int *resid, int *bidi_out_resid)
3700+{
3701+ if (likely(!cmd->resid_possible))
3702+ return false;
3703+ return __scst_get_resid(cmd, resid, bidi_out_resid);
3704+}
3705+
3706+/* Returns cmd's status byte from host device */
3707+static inline uint8_t scst_cmd_get_status(struct scst_cmd *cmd)
3708+{
3709+ return cmd->status;
3710+}
3711+
3712+/* Returns cmd's status from host adapter itself */
3713+static inline uint8_t scst_cmd_get_msg_status(struct scst_cmd *cmd)
3714+{
3715+ return cmd->msg_status;
3716+}
3717+
3718+/* Returns cmd's status set by low-level driver to indicate its status */
3719+static inline uint8_t scst_cmd_get_host_status(struct scst_cmd *cmd)
3720+{
3721+ return cmd->host_status;
3722+}
3723+
3724+/* Returns cmd's status set by SCSI mid-level */
3725+static inline uint8_t scst_cmd_get_driver_status(struct scst_cmd *cmd)
3726+{
3727+ return cmd->driver_status;
3728+}
3729+
3730+/* Returns pointer to cmd's sense buffer */
3731+static inline uint8_t *scst_cmd_get_sense_buffer(struct scst_cmd *cmd)
3732+{
3733+ return cmd->sense;
3734+}
3735+
3736+/* Returns cmd's valid sense length */
3737+static inline int scst_cmd_get_sense_buffer_len(struct scst_cmd *cmd)
3738+{
3739+ return cmd->sense_valid_len;
3740+}
3741+
3742+/*
3743+ * Get/Set functions for cmd's queue_type
3744+ */
3745+static inline enum scst_cmd_queue_type scst_cmd_get_queue_type(
3746+ struct scst_cmd *cmd)
3747+{
3748+ return cmd->queue_type;
3749+}
3750+
3751+static inline void scst_cmd_set_queue_type(struct scst_cmd *cmd,
3752+ enum scst_cmd_queue_type queue_type)
3753+{
3754+ cmd->queue_type = queue_type;
3755+}
3756+
3757+/*
3758+ * Get/Set functions for cmd's target SN
3759+ */
3760+static inline uint64_t scst_cmd_get_tag(struct scst_cmd *cmd)
3761+{
3762+ return cmd->tag;
3763+}
3764+
3765+static inline void scst_cmd_set_tag(struct scst_cmd *cmd, uint64_t tag)
3766+{
3767+ cmd->tag = tag;
3768+}
3769+
3770+/*
3771+ * Get/Set functions for cmd's target private data.
3772+ * Variant with *_lock must be used if target driver uses
3773+ * scst_find_cmd() to avoid race with it, except inside scst_find_cmd()'s
3774+ * callback, where lock is already taken.
3775+ */
3776+static inline void *scst_cmd_get_tgt_priv(struct scst_cmd *cmd)
3777+{
3778+ return cmd->tgt_priv;
3779+}
3780+
3781+static inline void scst_cmd_set_tgt_priv(struct scst_cmd *cmd, void *val)
3782+{
3783+ cmd->tgt_priv = val;
3784+}
3785+
3786+/*
3787+ * Get/Set functions for tgt_need_alloc_data_buf flag
3788+ */
3789+static inline int scst_cmd_get_tgt_need_alloc_data_buf(struct scst_cmd *cmd)
3790+{
3791+ return cmd->tgt_need_alloc_data_buf;
3792+}
3793+
3794+static inline void scst_cmd_set_tgt_need_alloc_data_buf(struct scst_cmd *cmd)
3795+{
3796+ cmd->tgt_need_alloc_data_buf = 1;
3797+}
3798+
3799+/*
3800+ * Get/Set functions for tgt_data_buf_alloced flag
3801+ */
3802+static inline int scst_cmd_get_tgt_data_buff_alloced(struct scst_cmd *cmd)
3803+{
3804+ return cmd->tgt_data_buf_alloced;
3805+}
3806+
3807+static inline void scst_cmd_set_tgt_data_buff_alloced(struct scst_cmd *cmd)
3808+{
3809+ cmd->tgt_data_buf_alloced = 1;
3810+}
3811+
3812+/*
3813+ * Get/Set functions for dh_data_buf_alloced flag
3814+ */
3815+static inline int scst_cmd_get_dh_data_buff_alloced(struct scst_cmd *cmd)
3816+{
3817+ return cmd->dh_data_buf_alloced;
3818+}
3819+
3820+static inline void scst_cmd_set_dh_data_buff_alloced(struct scst_cmd *cmd)
3821+{
3822+ cmd->dh_data_buf_alloced = 1;
3823+}
3824+
3825+/*
3826+ * Get/Set functions for no_sgv flag
3827+ */
3828+static inline int scst_cmd_get_no_sgv(struct scst_cmd *cmd)
3829+{
3830+ return cmd->no_sgv;
3831+}
3832+
3833+static inline void scst_cmd_set_no_sgv(struct scst_cmd *cmd)
3834+{
3835+ cmd->no_sgv = 1;
3836+}
3837+
3838+/*
3839+ * Get/Set functions for tgt_sn
3840+ */
3841+static inline int scst_cmd_get_tgt_sn(struct scst_cmd *cmd)
3842+{
3843+ BUG_ON(!cmd->tgt_sn_set);
3844+ return cmd->tgt_sn;
3845+}
3846+
3847+static inline void scst_cmd_set_tgt_sn(struct scst_cmd *cmd, uint32_t tgt_sn)
3848+{
3849+ cmd->tgt_sn_set = 1;
3850+ cmd->tgt_sn = tgt_sn;
3851+}
3852+
3853+/*
3854+ * Returns 1 if the cmd was aborted, so its status is invalid and no
3855+ * reply shall be sent to the remote initiator. A target driver should
3856+ * only clear internal resources, associated with cmd.
3857+ */
3858+static inline int scst_cmd_aborted(struct scst_cmd *cmd)
3859+{
3860+ return test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags) &&
3861+ !test_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags);
3862+}
3863+
3864+/* Returns sense data format for cmd's dev */
3865+static inline bool scst_get_cmd_dev_d_sense(struct scst_cmd *cmd)
3866+{
3867+ return (cmd->dev != NULL) ? cmd->dev->d_sense : 0;
3868+}
3869+
3870+/*
3871+ * Get/Set functions for expected data direction, transfer length
3872+ * and its validity flag
3873+ */
3874+static inline int scst_cmd_is_expected_set(struct scst_cmd *cmd)
3875+{
3876+ return cmd->expected_values_set;
3877+}
3878+
3879+static inline scst_data_direction scst_cmd_get_expected_data_direction(
3880+ struct scst_cmd *cmd)
3881+{
3882+ return cmd->expected_data_direction;
3883+}
3884+
3885+static inline int scst_cmd_get_expected_transfer_len(
3886+ struct scst_cmd *cmd)
3887+{
3888+ return cmd->expected_transfer_len;
3889+}
3890+
3891+static inline int scst_cmd_get_expected_out_transfer_len(
3892+ struct scst_cmd *cmd)
3893+{
3894+ return cmd->expected_out_transfer_len;
3895+}
3896+
3897+static inline void scst_cmd_set_expected(struct scst_cmd *cmd,
3898+ scst_data_direction expected_data_direction,
3899+ int expected_transfer_len)
3900+{
3901+ cmd->expected_data_direction = expected_data_direction;
3902+ cmd->expected_transfer_len = expected_transfer_len;
3903+ cmd->expected_values_set = 1;
3904+}
3905+
3906+static inline void scst_cmd_set_expected_out_transfer_len(struct scst_cmd *cmd,
3907+ int expected_out_transfer_len)
3908+{
3909+ WARN_ON(!cmd->expected_values_set);
3910+ cmd->expected_out_transfer_len = expected_out_transfer_len;
3911+}
3912+
3913+/*
3914+ * Get/clear functions for cmd's may_need_dma_sync
3915+ */
3916+static inline int scst_get_may_need_dma_sync(struct scst_cmd *cmd)
3917+{
3918+ return cmd->may_need_dma_sync;
3919+}
3920+
3921+static inline void scst_clear_may_need_dma_sync(struct scst_cmd *cmd)
3922+{
3923+ cmd->may_need_dma_sync = 0;
3924+}
3925+
3926+/*
3927+ * Get/set functions for cmd's delivery_status. It is one of
3928+ * SCST_CMD_DELIVERY_* constants. It specifies the status of the
3929+ * command's delivery to initiator.
3930+ */
3931+static inline int scst_get_delivery_status(struct scst_cmd *cmd)
3932+{
3933+ return cmd->delivery_status;
3934+}
3935+
3936+static inline void scst_set_delivery_status(struct scst_cmd *cmd,
3937+ int delivery_status)
3938+{
3939+ cmd->delivery_status = delivery_status;
3940+}
3941+
3942+static inline unsigned int scst_get_active_cmd_count(struct scst_cmd *cmd)
3943+{
3944+ if (likely(cmd->tgt_dev != NULL))
3945+ return atomic_read(&cmd->tgt_dev->tgt_dev_cmd_count);
3946+ else
3947+ return (unsigned int)-1;
3948+}
3949+
3950+/*
3951+ * Get/Set function for mgmt cmd's target private data
3952+ */
3953+static inline void *scst_mgmt_cmd_get_tgt_priv(struct scst_mgmt_cmd *mcmd)
3954+{
3955+ return mcmd->tgt_priv;
3956+}
3957+
3958+static inline void scst_mgmt_cmd_set_tgt_priv(struct scst_mgmt_cmd *mcmd,
3959+ void *val)
3960+{
3961+ mcmd->tgt_priv = val;
3962+}
3963+
3964+/* Returns mgmt cmd's completition status (SCST_MGMT_STATUS_* constants) */
3965+static inline int scst_mgmt_cmd_get_status(struct scst_mgmt_cmd *mcmd)
3966+{
3967+ return mcmd->status;
3968+}
3969+
3970+/* Returns mgmt cmd's TM fn */
3971+static inline int scst_mgmt_cmd_get_fn(struct scst_mgmt_cmd *mcmd)
3972+{
3973+ return mcmd->fn;
3974+}
3975+
3976+/*
3977+ * Called by dev handler's task_mgmt_fn() to notify SCST core that mcmd
3978+ * is going to complete asynchronously.
3979+ */
3980+void scst_prepare_async_mcmd(struct scst_mgmt_cmd *mcmd);
3981+
3982+/*
3983+ * Called by dev handler to notify SCST core that async. mcmd is completed
3984+ * with status "status".
3985+ */
3986+void scst_async_mcmd_completed(struct scst_mgmt_cmd *mcmd, int status);
3987+
3988+/* Returns AEN's fn */
3989+static inline int scst_aen_get_event_fn(struct scst_aen *aen)
3990+{
3991+ return aen->event_fn;
3992+}
3993+
3994+/* Returns AEN's session */
3995+static inline struct scst_session *scst_aen_get_sess(struct scst_aen *aen)
3996+{
3997+ return aen->sess;
3998+}
3999+
4000+/* Returns AEN's LUN */
4001+static inline __be64 scst_aen_get_lun(struct scst_aen *aen)
4002+{
4003+ return aen->lun;
4004+}
4005+
4006+/* Returns SCSI AEN's sense */
4007+static inline const uint8_t *scst_aen_get_sense(struct scst_aen *aen)
4008+{
4009+ return aen->aen_sense;
4010+}
4011+
4012+/* Returns SCSI AEN's sense length */
4013+static inline int scst_aen_get_sense_len(struct scst_aen *aen)
4014+{
4015+ return aen->aen_sense_len;
4016+}
4017+
4018+/*
4019+ * Get/set functions for AEN's delivery_status. It is one of
4020+ * SCST_AEN_RES_* constants. It specifies the status of the
4021+ * command's delivery to initiator.
4022+ */
4023+static inline int scst_get_aen_delivery_status(struct scst_aen *aen)
4024+{
4025+ return aen->delivery_status;
4026+}
4027+
4028+static inline void scst_set_aen_delivery_status(struct scst_aen *aen,
4029+ int status)
4030+{
4031+ aen->delivery_status = status;
4032+}
4033+
4034+void scst_aen_done(struct scst_aen *aen);
4035+
4036+static inline void sg_clear(struct scatterlist *sg)
4037+{
4038+ memset(sg, 0, sizeof(*sg));
4039+#ifdef CONFIG_DEBUG_SG
4040+ sg->sg_magic = SG_MAGIC;
4041+#endif
4042+}
4043+
4044+enum scst_sg_copy_dir {
4045+ SCST_SG_COPY_FROM_TARGET,
4046+ SCST_SG_COPY_TO_TARGET
4047+};
4048+
4049+void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir copy_dir);
4050+
4051+/*
4052+ * Functions for access to the commands data (SG) buffer,
4053+ * including HIGHMEM environment. Should be used instead of direct
4054+ * access. Returns the mapped buffer length for success, 0 for EOD,
4055+ * negative error code otherwise.
4056+ *
4057+ * "Buf" argument returns the mapped buffer
4058+ *
4059+ * The "put" function unmaps the buffer.
4060+ */
4061+static inline int __scst_get_buf(struct scst_cmd *cmd, struct scatterlist *sg,
4062+ int sg_cnt, uint8_t **buf)
4063+{
4064+ int res = 0;
4065+ int i = cmd->get_sg_buf_entry_num;
4066+
4067+ *buf = NULL;
4068+
4069+ if ((i >= sg_cnt) || unlikely(sg == NULL))
4070+ goto out;
4071+
4072+ *buf = page_address(sg_page(&sg[i]));
4073+ *buf += sg[i].offset;
4074+
4075+ res = sg[i].length;
4076+ cmd->get_sg_buf_entry_num++;
4077+
4078+out:
4079+ return res;
4080+}
4081+
4082+static inline int scst_get_buf_first(struct scst_cmd *cmd, uint8_t **buf)
4083+{
4084+ cmd->get_sg_buf_entry_num = 0;
4085+ cmd->may_need_dma_sync = 1;
4086+ return __scst_get_buf(cmd, cmd->sg, cmd->sg_cnt, buf);
4087+}
4088+
4089+static inline int scst_get_buf_next(struct scst_cmd *cmd, uint8_t **buf)
4090+{
4091+ return __scst_get_buf(cmd, cmd->sg, cmd->sg_cnt, buf);
4092+}
4093+
4094+static inline void scst_put_buf(struct scst_cmd *cmd, void *buf)
4095+{
4096+ /* Nothing to do */
4097+}
4098+
4099+static inline int scst_get_out_buf_first(struct scst_cmd *cmd, uint8_t **buf)
4100+{
4101+ cmd->get_sg_buf_entry_num = 0;
4102+ cmd->may_need_dma_sync = 1;
4103+ return __scst_get_buf(cmd, cmd->out_sg, cmd->out_sg_cnt, buf);
4104+}
4105+
4106+static inline int scst_get_out_buf_next(struct scst_cmd *cmd, uint8_t **buf)
4107+{
4108+ return __scst_get_buf(cmd, cmd->out_sg, cmd->out_sg_cnt, buf);
4109+}
4110+
4111+static inline void scst_put_out_buf(struct scst_cmd *cmd, void *buf)
4112+{
4113+ /* Nothing to do */
4114+}
4115+
4116+static inline int scst_get_sg_buf_first(struct scst_cmd *cmd, uint8_t **buf,
4117+ struct scatterlist *sg, int sg_cnt)
4118+{
4119+ cmd->get_sg_buf_entry_num = 0;
4120+ cmd->may_need_dma_sync = 1;
4121+ return __scst_get_buf(cmd, sg, sg_cnt, buf);
4122+}
4123+
4124+static inline int scst_get_sg_buf_next(struct scst_cmd *cmd, uint8_t **buf,
4125+ struct scatterlist *sg, int sg_cnt)
4126+{
4127+ return __scst_get_buf(cmd, sg, sg_cnt, buf);
4128+}
4129+
4130+static inline void scst_put_sg_buf(struct scst_cmd *cmd, void *buf,
4131+ struct scatterlist *sg, int sg_cnt)
4132+{
4133+ /* Nothing to do */
4134+}
4135+
4136+/*
4137+ * Returns approximate higher rounded buffers count that
4138+ * scst_get_buf_[first|next]() return.
4139+ */
4140+static inline int scst_get_buf_count(struct scst_cmd *cmd)
4141+{
4142+ return (cmd->sg_cnt == 0) ? 1 : cmd->sg_cnt;
4143+}
4144+
4145+/*
4146+ * Returns approximate higher rounded buffers count that
4147+ * scst_get_out_buf_[first|next]() return.
4148+ */
4149+static inline int scst_get_out_buf_count(struct scst_cmd *cmd)
4150+{
4151+ return (cmd->out_sg_cnt == 0) ? 1 : cmd->out_sg_cnt;
4152+}
4153+
4154+int scst_suspend_activity(bool interruptible);
4155+void scst_resume_activity(void);
4156+
4157+void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic);
4158+
4159+void scst_post_parse(struct scst_cmd *cmd);
4160+void scst_post_alloc_data_buf(struct scst_cmd *cmd);
4161+
4162+int scst_check_local_events(struct scst_cmd *cmd);
4163+
4164+int scst_set_cmd_abnormal_done_state(struct scst_cmd *cmd);
4165+
4166+struct scst_trace_log {
4167+ unsigned int val;
4168+ const char *token;
4169+};
4170+
4171+extern struct mutex scst_mutex;
4172+
4173+const struct sysfs_ops *scst_sysfs_get_sysfs_ops(void);
4174+
4175+/*
4176+ * Returns target driver's root sysfs kobject.
4177+ * The driver can create own files/directories/links here.
4178+ */
4179+static inline struct kobject *scst_sysfs_get_tgtt_kobj(
4180+ struct scst_tgt_template *tgtt)
4181+{
4182+ return &tgtt->tgtt_kobj;
4183+}
4184+
4185+/*
4186+ * Returns target's root sysfs kobject.
4187+ * The driver can create own files/directories/links here.
4188+ */
4189+static inline struct kobject *scst_sysfs_get_tgt_kobj(
4190+ struct scst_tgt *tgt)
4191+{
4192+ return &tgt->tgt_kobj;
4193+}
4194+
4195+/*
4196+ * Returns device handler's root sysfs kobject.
4197+ * The driver can create own files/directories/links here.
4198+ */
4199+static inline struct kobject *scst_sysfs_get_devt_kobj(
4200+ struct scst_dev_type *devt)
4201+{
4202+ return &devt->devt_kobj;
4203+}
4204+
4205+/*
4206+ * Returns device's root sysfs kobject.
4207+ * The driver can create own files/directories/links here.
4208+ */
4209+static inline struct kobject *scst_sysfs_get_dev_kobj(
4210+ struct scst_device *dev)
4211+{
4212+ return &dev->dev_kobj;
4213+}
4214+
4215+/*
4216+ * Returns session's root sysfs kobject.
4217+ * The driver can create own files/directories/links here.
4218+ */
4219+static inline struct kobject *scst_sysfs_get_sess_kobj(
4220+ struct scst_session *sess)
4221+{
4222+ return &sess->sess_kobj;
4223+}
4224+
4225+/* Returns target name */
4226+static inline const char *scst_get_tgt_name(const struct scst_tgt *tgt)
4227+{
4228+ return tgt->tgt_name;
4229+}
4230+
4231+int scst_alloc_sense(struct scst_cmd *cmd, int atomic);
4232+int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic,
4233+ const uint8_t *sense, unsigned int len);
4234+
4235+int scst_set_sense(uint8_t *buffer, int len, bool d_sense,
4236+ int key, int asc, int ascq);
4237+
4238+bool scst_is_ua_sense(const uint8_t *sense, int len);
4239+
4240+bool scst_analyze_sense(const uint8_t *sense, int len,
4241+ unsigned int valid_mask, int key, int asc, int ascq);
4242+
4243+unsigned long scst_random(void);
4244+
4245+void scst_set_resp_data_len(struct scst_cmd *cmd, int resp_data_len);
4246+
4247+void scst_get(void);
4248+void scst_put(void);
4249+
4250+void scst_cmd_get(struct scst_cmd *cmd);
4251+void scst_cmd_put(struct scst_cmd *cmd);
4252+
4253+struct scatterlist *scst_alloc(int size, gfp_t gfp_mask, int *count);
4254+void scst_free(struct scatterlist *sg, int count);
4255+
4256+void scst_add_thr_data(struct scst_tgt_dev *tgt_dev,
4257+ struct scst_thr_data_hdr *data,
4258+ void (*free_fn) (struct scst_thr_data_hdr *data));
4259+void scst_del_all_thr_data(struct scst_tgt_dev *tgt_dev);
4260+void scst_dev_del_all_thr_data(struct scst_device *dev);
4261+struct scst_thr_data_hdr *__scst_find_thr_data(struct scst_tgt_dev *tgt_dev,
4262+ struct task_struct *tsk);
4263+
4264+/* Finds local to the current thread data. Returns NULL, if they not found. */
4265+static inline struct scst_thr_data_hdr *scst_find_thr_data(
4266+ struct scst_tgt_dev *tgt_dev)
4267+{
4268+ return __scst_find_thr_data(tgt_dev, current);
4269+}
4270+
4271+/* Increase ref counter for the thread data */
4272+static inline void scst_thr_data_get(struct scst_thr_data_hdr *data)
4273+{
4274+ atomic_inc(&data->ref);
4275+}
4276+
4277+/* Decrease ref counter for the thread data */
4278+static inline void scst_thr_data_put(struct scst_thr_data_hdr *data)
4279+{
4280+ if (atomic_dec_and_test(&data->ref))
4281+ data->free_fn(data);
4282+}
4283+
4284+int scst_calc_block_shift(int sector_size);
4285+int scst_sbc_generic_parse(struct scst_cmd *cmd,
4286+ int (*get_block_shift)(struct scst_cmd *cmd));
4287+int scst_cdrom_generic_parse(struct scst_cmd *cmd,
4288+ int (*get_block_shift)(struct scst_cmd *cmd));
4289+int scst_modisk_generic_parse(struct scst_cmd *cmd,
4290+ int (*get_block_shift)(struct scst_cmd *cmd));
4291+int scst_tape_generic_parse(struct scst_cmd *cmd,
4292+ int (*get_block_size)(struct scst_cmd *cmd));
4293+int scst_changer_generic_parse(struct scst_cmd *cmd,
4294+ int (*nothing)(struct scst_cmd *cmd));
4295+int scst_processor_generic_parse(struct scst_cmd *cmd,
4296+ int (*nothing)(struct scst_cmd *cmd));
4297+int scst_raid_generic_parse(struct scst_cmd *cmd,
4298+ int (*nothing)(struct scst_cmd *cmd));
4299+
4300+int scst_block_generic_dev_done(struct scst_cmd *cmd,
4301+ void (*set_block_shift)(struct scst_cmd *cmd, int block_shift));
4302+int scst_tape_generic_dev_done(struct scst_cmd *cmd,
4303+ void (*set_block_size)(struct scst_cmd *cmd, int block_size));
4304+
4305+int scst_obtain_device_parameters(struct scst_device *dev);
4306+
4307+void scst_reassign_persistent_sess_states(struct scst_session *new_sess,
4308+ struct scst_session *old_sess);
4309+
4310+int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun);
4311+
4312+/*
4313+ * Has to be put here open coded, because Linux doesn't have equivalent, which
4314+ * allows exclusive wake ups of threads in LIFO order. We need it to let (yet)
4315+ * unneeded threads sleep and not pollute CPU cache by their stacks.
4316+ */
4317+static inline void add_wait_queue_exclusive_head(wait_queue_head_t *q,
4318+ wait_queue_t *wait)
4319+{
4320+ unsigned long flags;
4321+
4322+ wait->flags |= WQ_FLAG_EXCLUSIVE;
4323+ spin_lock_irqsave(&q->lock, flags);
4324+ __add_wait_queue(q, wait);
4325+ spin_unlock_irqrestore(&q->lock, flags);
4326+}
4327+
4328+/*
4329+ * Structure to match events to user space and replies on them
4330+ */
4331+struct scst_sysfs_user_info {
4332+ /* Unique cookie to identify request */
4333+ uint32_t info_cookie;
4334+
4335+ /* Entry in the global list */
4336+ struct list_head info_list_entry;
4337+
4338+ /* Set if reply from the user space is being executed */
4339+ unsigned int info_being_executed:1;
4340+
4341+ /* Set if this info is in the info_list */
4342+ unsigned int info_in_list:1;
4343+
4344+ /* Completion to wait on for the request completion */
4345+ struct completion info_completion;
4346+
4347+ /* Request completion status and optional data */
4348+ int info_status;
4349+ void *data;
4350+};
4351+
4352+int scst_sysfs_user_add_info(struct scst_sysfs_user_info **out_info);
4353+void scst_sysfs_user_del_info(struct scst_sysfs_user_info *info);
4354+struct scst_sysfs_user_info *scst_sysfs_user_get_info(uint32_t cookie);
4355+int scst_wait_info_completion(struct scst_sysfs_user_info *info,
4356+ unsigned long timeout);
4357+
4358+unsigned int scst_get_setup_id(void);
4359+
4360+/*
4361+ * Needed to avoid potential circular locking dependency between scst_mutex
4362+ * and internal sysfs locking (s_active). It could be since most sysfs entries
4363+ * are created and deleted under scst_mutex AND scst_mutex is taken inside
4364+ * sysfs functions. So, we push from the sysfs functions all the processing
4365+ * taking scst_mutex. To avoid deadlock, we return from them with EAGAIN
4366+ * if processing is taking too long. User space then should poll
4367+ * last_sysfs_mgmt_res until it returns the result of the processing
4368+ * (something other than EAGAIN).
4369+ */
4370+struct scst_sysfs_work_item {
4371+ /*
4372+ * If true, then last_sysfs_mgmt_res will not be updated. This is
4373+ * needed to allow read only sysfs monitoring during management actions.
4374+ * All management actions are supposed to be externally serialized,
4375+ * so then last_sysfs_mgmt_res automatically serialized too.
4376+ * Othewrwise a monitoring action can overwrite value of simultaneous
4377+ * management action's last_sysfs_mgmt_res.
4378+ */
4379+ bool read_only_action;
4380+
4381+ struct list_head sysfs_work_list_entry;
4382+ struct kref sysfs_work_kref;
4383+ int (*sysfs_work_fn)(struct scst_sysfs_work_item *work);
4384+ struct completion sysfs_work_done;
4385+ char *buf;
4386+
4387+ union {
4388+ struct scst_dev_type *devt;
4389+ struct scst_tgt_template *tgtt;
4390+ struct {
4391+ struct scst_tgt *tgt;
4392+ struct scst_acg *acg;
4393+ union {
4394+ bool is_tgt_kobj;
4395+ int io_grouping_type;
4396+ bool enable;
4397+ };
4398+ };
4399+ struct {
4400+ struct scst_device *dev;
4401+ int new_threads_num;
4402+ enum scst_dev_type_threads_pool_type new_threads_pool_type;
4403+ };
4404+ struct scst_session *sess;
4405+ struct {
4406+ struct scst_tgt *tgt;
4407+ unsigned long l;
4408+ };
4409+ };
4410+ int work_res;
4411+ char *res_buf;
4412+};
4413+
4414+int scst_alloc_sysfs_work(int (*sysfs_work_fn)(struct scst_sysfs_work_item *),
4415+ bool read_only_action, struct scst_sysfs_work_item **res_work);
4416+int scst_sysfs_queue_wait_work(struct scst_sysfs_work_item *work);
4417+void scst_sysfs_work_get(struct scst_sysfs_work_item *work);
4418+void scst_sysfs_work_put(struct scst_sysfs_work_item *work);
4419+
4420+char *scst_get_next_lexem(char **token_str);
4421+void scst_restore_token_str(char *prev_lexem, char *token_str);
4422+char *scst_get_next_token_str(char **input_str);
4423+
4424+void scst_init_threads(struct scst_cmd_threads *cmd_threads);
4425+void scst_deinit_threads(struct scst_cmd_threads *cmd_threads);
4426+
4427+#endif /* __SCST_H */
4428diff -uprN orig/linux-2.6.35/include/scst/scst_const.h linux-2.6.35/include/scst/scst_const.h
4429--- orig/linux-2.6.35/include/scst/scst_const.h
4430+++ linux-2.6.35/include/scst/scst_const.h
4431@@ -0,0 +1,412 @@
4432+/*
4433+ * include/scst_const.h
4434+ *
4435+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
4436+ * Copyright (C) 2007 - 2010 ID7 Ltd.
4437+ *
4438+ * Contains common SCST constants.
4439+ *
4440+ * This program is free software; you can redistribute it and/or
4441+ * modify it under the terms of the GNU General Public License
4442+ * as published by the Free Software Foundation, version 2
4443+ * of the License.
4444+ *
4445+ * This program is distributed in the hope that it will be useful,
4446+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4447+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4448+ * GNU General Public License for more details.
4449+ */
4450+
4451+#ifndef __SCST_CONST_H
4452+#define __SCST_CONST_H
4453+
4454+#ifndef GENERATING_UPSTREAM_PATCH
4455+/*
4456+ * Include <linux/version.h> only when not converting this header file into
4457+ * a patch for upstream review because only then the symbol LINUX_VERSION_CODE
4458+ * is needed.
4459+ */
4460+#include <linux/version.h>
4461+#endif
4462+#include <scsi/scsi.h>
4463+
4464+#define SCST_CONST_VERSION "$Revision: 2605 $"
4465+
4466+/*** Shared constants between user and kernel spaces ***/
4467+
4468+/* Max size of CDB */
4469+#define SCST_MAX_CDB_SIZE 16
4470+
4471+/* Max size of various names */
4472+#define SCST_MAX_NAME 50
4473+
4474+/* Max size of external names, like initiator name */
4475+#define SCST_MAX_EXTERNAL_NAME 256
4476+
4477+/*
4478+ * Size of sense sufficient to carry standard sense data.
4479+ * Warning! It's allocated on stack!
4480+ */
4481+#define SCST_STANDARD_SENSE_LEN 18
4482+
4483+/* Max size of sense */
4484+#define SCST_SENSE_BUFFERSIZE 96
4485+
4486+/*************************************************************
4487+ ** Allowed delivery statuses for cmd's delivery_status
4488+ *************************************************************/
4489+
4490+#define SCST_CMD_DELIVERY_SUCCESS 0
4491+#define SCST_CMD_DELIVERY_FAILED -1
4492+#define SCST_CMD_DELIVERY_ABORTED -2
4493+
4494+/*************************************************************
4495+ ** Values for task management functions
4496+ *************************************************************/
4497+#define SCST_ABORT_TASK 0
4498+#define SCST_ABORT_TASK_SET 1
4499+#define SCST_CLEAR_ACA 2
4500+#define SCST_CLEAR_TASK_SET 3
4501+#define SCST_LUN_RESET 4
4502+#define SCST_TARGET_RESET 5
4503+
4504+/** SCST extensions **/
4505+
4506+/*
4507+ * Notifies about I_T nexus loss event in the corresponding session.
4508+ * Aborts all tasks there, resets the reservation, if any, and sets
4509+ * up the I_T Nexus loss UA.
4510+ */
4511+#define SCST_NEXUS_LOSS_SESS 6
4512+
4513+/* Aborts all tasks in the corresponding session */
4514+#define SCST_ABORT_ALL_TASKS_SESS 7
4515+
4516+/*
4517+ * Notifies about I_T nexus loss event. Aborts all tasks in all sessions
4518+ * of the tgt, resets the reservations, if any, and sets up the I_T Nexus
4519+ * loss UA.
4520+ */
4521+#define SCST_NEXUS_LOSS 8
4522+
4523+/* Aborts all tasks in all sessions of the tgt */
4524+#define SCST_ABORT_ALL_TASKS 9
4525+
4526+/*
4527+ * Internal TM command issued by SCST in scst_unregister_session(). It is the
4528+ * same as SCST_NEXUS_LOSS_SESS, except:
4529+ * - it doesn't call task_mgmt_affected_cmds_done()
4530+ * - it doesn't call task_mgmt_fn_done()
4531+ * - it doesn't queue NEXUS LOSS UA.
4532+ *
4533+ * Target drivers must NEVER use it!!
4534+ */
4535+#define SCST_UNREG_SESS_TM 10
4536+
4537+/*
4538+ * Internal TM command issued by SCST in scst_pr_abort_reg(). It aborts all
4539+ * tasks from mcmd->origin_pr_cmd->tgt_dev, except mcmd->origin_pr_cmd.
4540+ * Additionally:
4541+ * - it signals pr_aborting_cmpl completion when all affected
4542+ * commands marked as aborted.
4543+ * - it doesn't call task_mgmt_affected_cmds_done()
4544+ * - it doesn't call task_mgmt_fn_done()
4545+ * - it calls mcmd->origin_pr_cmd->scst_cmd_done() when all affected
4546+ * commands aborted.
4547+ *
4548+ * Target drivers must NEVER use it!!
4549+ */
4550+#define SCST_PR_ABORT_ALL 11
4551+
4552+/*************************************************************
4553+ ** Values for mgmt cmd's status field. Codes taken from iSCSI
4554+ *************************************************************/
4555+#define SCST_MGMT_STATUS_SUCCESS 0
4556+#define SCST_MGMT_STATUS_TASK_NOT_EXIST -1
4557+#define SCST_MGMT_STATUS_LUN_NOT_EXIST -2
4558+#define SCST_MGMT_STATUS_FN_NOT_SUPPORTED -5
4559+#define SCST_MGMT_STATUS_REJECTED -255
4560+#define SCST_MGMT_STATUS_FAILED -129
4561+
4562+/*************************************************************
4563+ ** SCSI task attribute queue types
4564+ *************************************************************/
4565+enum scst_cmd_queue_type {
4566+ SCST_CMD_QUEUE_UNTAGGED = 0,
4567+ SCST_CMD_QUEUE_SIMPLE,
4568+ SCST_CMD_QUEUE_ORDERED,
4569+ SCST_CMD_QUEUE_HEAD_OF_QUEUE,
4570+ SCST_CMD_QUEUE_ACA
4571+};
4572+
4573+/*************************************************************
4574+ ** CDB flags
4575+ **
4576+ ** Implicit ordered used for commands which need calm environment
4577+ ** without any simultaneous activities. For instance, for MODE
4578+ ** SELECT it is needed to correctly generate its UA.
4579+ *************************************************************/
4580+enum scst_cdb_flags {
4581+ SCST_TRANSFER_LEN_TYPE_FIXED = 0x0001,
4582+ SCST_SMALL_TIMEOUT = 0x0002,
4583+ SCST_LONG_TIMEOUT = 0x0004,
4584+ SCST_UNKNOWN_LENGTH = 0x0008,
4585+ SCST_INFO_VALID = 0x0010, /* must be single bit */
4586+ SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x0020,
4587+ SCST_IMPLICIT_HQ = 0x0040,
4588+ SCST_IMPLICIT_ORDERED = 0x0080, /* ToDo: remove it's nonsense */
4589+ SCST_SKIP_UA = 0x0100,
4590+ SCST_WRITE_MEDIUM = 0x0200,
4591+ SCST_LOCAL_CMD = 0x0400,
4592+ SCST_FULLY_LOCAL_CMD = 0x0800,
4593+ SCST_REG_RESERVE_ALLOWED = 0x1000,
4594+ SCST_WRITE_EXCL_ALLOWED = 0x2000,
4595+ SCST_EXCL_ACCESS_ALLOWED = 0x4000,
4596+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
4597+ SCST_TEST_IO_IN_SIRQ_ALLOWED = 0x8000,
4598+#endif
4599+};
4600+
4601+/*************************************************************
4602+ ** Data direction aliases. Changing it don't forget to change
4603+ ** scst_to_tgt_dma_dir as well!!
4604+ *************************************************************/
4605+#define SCST_DATA_UNKNOWN 0
4606+#define SCST_DATA_WRITE 1
4607+#define SCST_DATA_READ 2
4608+#define SCST_DATA_BIDI (SCST_DATA_WRITE | SCST_DATA_READ)
4609+#define SCST_DATA_NONE 4
4610+
4611+/*************************************************************
4612+ ** Default suffix for targets with NULL names
4613+ *************************************************************/
4614+#define SCST_DEFAULT_TGT_NAME_SUFFIX "_target_"
4615+
4616+/*************************************************************
4617+ ** Sense manipulation and examination
4618+ *************************************************************/
4619+#define SCST_LOAD_SENSE(key_asc_ascq) key_asc_ascq
4620+
4621+#define SCST_SENSE_VALID(sense) ((sense != NULL) && \
4622+ ((((const uint8_t *)(sense))[0] & 0x70) == 0x70))
4623+
4624+#define SCST_NO_SENSE(sense) ((sense != NULL) && \
4625+ (((const uint8_t *)(sense))[2] == 0))
4626+
4627+/*************************************************************
4628+ ** Sense data for the appropriate errors. Can be used with
4629+ ** scst_set_cmd_error()
4630+ *************************************************************/
4631+#define scst_sense_no_sense NO_SENSE, 0x00, 0
4632+#define scst_sense_hardw_error HARDWARE_ERROR, 0x44, 0
4633+#define scst_sense_aborted_command ABORTED_COMMAND, 0x00, 0
4634+#define scst_sense_invalid_opcode ILLEGAL_REQUEST, 0x20, 0
4635+#define scst_sense_invalid_field_in_cdb ILLEGAL_REQUEST, 0x24, 0
4636+#define scst_sense_invalid_field_in_parm_list ILLEGAL_REQUEST, 0x26, 0
4637+#define scst_sense_parameter_value_invalid ILLEGAL_REQUEST, 0x26, 2
4638+#define scst_sense_invalid_release ILLEGAL_REQUEST, 0x26, 4
4639+#define scst_sense_parameter_list_length_invalid \
4640+ ILLEGAL_REQUEST, 0x1A, 0
4641+#define scst_sense_reset_UA UNIT_ATTENTION, 0x29, 0
4642+#define scst_sense_nexus_loss_UA UNIT_ATTENTION, 0x29, 0x7
4643+#define scst_sense_saving_params_unsup ILLEGAL_REQUEST, 0x39, 0
4644+#define scst_sense_lun_not_supported ILLEGAL_REQUEST, 0x25, 0
4645+#define scst_sense_data_protect DATA_PROTECT, 0x00, 0
4646+#define scst_sense_miscompare_error MISCOMPARE, 0x1D, 0
4647+#define scst_sense_block_out_range_error ILLEGAL_REQUEST, 0x21, 0
4648+#define scst_sense_medium_changed_UA UNIT_ATTENTION, 0x28, 0
4649+#define scst_sense_read_error MEDIUM_ERROR, 0x11, 0
4650+#define scst_sense_write_error MEDIUM_ERROR, 0x03, 0
4651+#define scst_sense_not_ready NOT_READY, 0x04, 0x10
4652+#define scst_sense_invalid_message ILLEGAL_REQUEST, 0x49, 0
4653+#define scst_sense_cleared_by_another_ini_UA UNIT_ATTENTION, 0x2F, 0
4654+#define scst_sense_capacity_data_changed UNIT_ATTENTION, 0x2A, 0x9
4655+#define scst_sense_reservation_preempted UNIT_ATTENTION, 0x2A, 0x03
4656+#define scst_sense_reservation_released UNIT_ATTENTION, 0x2A, 0x04
4657+#define scst_sense_registrations_preempted UNIT_ATTENTION, 0x2A, 0x05
4658+#define scst_sense_reported_luns_data_changed UNIT_ATTENTION, 0x3F, 0xE
4659+#define scst_sense_inquery_data_changed UNIT_ATTENTION, 0x3F, 0x3
4660+
4661+/*************************************************************
4662+ * SCSI opcodes not listed anywhere else
4663+ *************************************************************/
4664+#define REPORT_DEVICE_IDENTIFIER 0xA3
4665+#define INIT_ELEMENT_STATUS 0x07
4666+#define INIT_ELEMENT_STATUS_RANGE 0x37
4667+#define PREVENT_ALLOW_MEDIUM 0x1E
4668+#define READ_ATTRIBUTE 0x8C
4669+#define REQUEST_VOLUME_ADDRESS 0xB5
4670+#define WRITE_ATTRIBUTE 0x8D
4671+#define WRITE_VERIFY_16 0x8E
4672+#define VERIFY_6 0x13
4673+#ifndef VERIFY_12
4674+#define VERIFY_12 0xAF
4675+#endif
4676+#ifndef GENERATING_UPSTREAM_PATCH
4677+/*
4678+ * The constants below have been defined in the kernel header <scsi/scsi.h>
4679+ * and hence are not needed when this header file is included in kernel code.
4680+ * The definitions below are only used when this header file is included during
4681+ * compilation of SCST's user space components.
4682+ */
4683+#ifndef READ_16
4684+#define READ_16 0x88
4685+#endif
4686+#ifndef WRITE_16
4687+#define WRITE_16 0x8a
4688+#endif
4689+#ifndef VERIFY_16
4690+#define VERIFY_16 0x8f
4691+#endif
4692+#ifndef SERVICE_ACTION_IN
4693+#define SERVICE_ACTION_IN 0x9e
4694+#endif
4695+#ifndef SAI_READ_CAPACITY_16
4696+/* values for service action in */
4697+#define SAI_READ_CAPACITY_16 0x10
4698+#endif
4699+#endif
4700+#ifndef GENERATING_UPSTREAM_PATCH
4701+#ifndef REPORT_LUNS
4702+#define REPORT_LUNS 0xa0
4703+#endif
4704+#endif
4705+
4706+/*************************************************************
4707+ ** SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
4708+ ** T10/1561-D Revision 4 Draft dated 7th November 2002.
4709+ *************************************************************/
4710+#define SAM_STAT_GOOD 0x00
4711+#define SAM_STAT_CHECK_CONDITION 0x02
4712+#define SAM_STAT_CONDITION_MET 0x04
4713+#define SAM_STAT_BUSY 0x08
4714+#define SAM_STAT_INTERMEDIATE 0x10
4715+#define SAM_STAT_INTERMEDIATE_CONDITION_MET 0x14
4716+#define SAM_STAT_RESERVATION_CONFLICT 0x18
4717+#define SAM_STAT_COMMAND_TERMINATED 0x22 /* obsolete in SAM-3 */
4718+#define SAM_STAT_TASK_SET_FULL 0x28
4719+#define SAM_STAT_ACA_ACTIVE 0x30
4720+#define SAM_STAT_TASK_ABORTED 0x40
4721+
4722+/*************************************************************
4723+ ** Control byte field in CDB
4724+ *************************************************************/
4725+#define CONTROL_BYTE_LINK_BIT 0x01
4726+#define CONTROL_BYTE_NACA_BIT 0x04
4727+
4728+/*************************************************************
4729+ ** Byte 1 in INQUIRY CDB
4730+ *************************************************************/
4731+#define SCST_INQ_EVPD 0x01
4732+
4733+/*************************************************************
4734+ ** Byte 3 in Standard INQUIRY data
4735+ *************************************************************/
4736+#define SCST_INQ_BYTE3 3
4737+
4738+#define SCST_INQ_NORMACA_BIT 0x20
4739+
4740+/*************************************************************
4741+ ** Byte 2 in RESERVE_10 CDB
4742+ *************************************************************/
4743+#define SCST_RES_3RDPTY 0x10
4744+#define SCST_RES_LONGID 0x02
4745+
4746+/*************************************************************
4747+ ** Values for the control mode page TST field
4748+ *************************************************************/
4749+#define SCST_CONTR_MODE_ONE_TASK_SET 0
4750+#define SCST_CONTR_MODE_SEP_TASK_SETS 1
4751+
4752+/*******************************************************************
4753+ ** Values for the control mode page QUEUE ALGORITHM MODIFIER field
4754+ *******************************************************************/
4755+#define SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER 0
4756+#define SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER 1
4757+
4758+/*************************************************************
4759+ ** Values for the control mode page D_SENSE field
4760+ *************************************************************/
4761+#define SCST_CONTR_MODE_FIXED_SENSE 0
4762+#define SCST_CONTR_MODE_DESCR_SENSE 1
4763+
4764+/*************************************************************
4765+ ** TransportID protocol identifiers
4766+ *************************************************************/
4767+
4768+#define SCSI_TRANSPORTID_PROTOCOLID_FCP2 0
4769+#define SCSI_TRANSPORTID_PROTOCOLID_SPI5 1
4770+#define SCSI_TRANSPORTID_PROTOCOLID_SRP 4
4771+#define SCSI_TRANSPORTID_PROTOCOLID_ISCSI 5
4772+#define SCSI_TRANSPORTID_PROTOCOLID_SAS 6
4773+
4774+/*************************************************************
4775+ ** Misc SCSI constants
4776+ *************************************************************/
4777+#define SCST_SENSE_ASC_UA_RESET 0x29
4778+#define BYTCHK 0x02
4779+#define POSITION_LEN_SHORT 20
4780+#define POSITION_LEN_LONG 32
4781+
4782+/*************************************************************
4783+ ** Various timeouts
4784+ *************************************************************/
4785+#define SCST_DEFAULT_TIMEOUT (60 * HZ)
4786+
4787+#define SCST_GENERIC_CHANGER_TIMEOUT (3 * HZ)
4788+#define SCST_GENERIC_CHANGER_LONG_TIMEOUT (14000 * HZ)
4789+
4790+#define SCST_GENERIC_PROCESSOR_TIMEOUT (3 * HZ)
4791+#define SCST_GENERIC_PROCESSOR_LONG_TIMEOUT (14000 * HZ)
4792+
4793+#define SCST_GENERIC_TAPE_SMALL_TIMEOUT (3 * HZ)
4794+#define SCST_GENERIC_TAPE_REG_TIMEOUT (900 * HZ)
4795+#define SCST_GENERIC_TAPE_LONG_TIMEOUT (14000 * HZ)
4796+
4797+#define SCST_GENERIC_MODISK_SMALL_TIMEOUT (3 * HZ)
4798+#define SCST_GENERIC_MODISK_REG_TIMEOUT (900 * HZ)
4799+#define SCST_GENERIC_MODISK_LONG_TIMEOUT (14000 * HZ)
4800+
4801+#define SCST_GENERIC_DISK_SMALL_TIMEOUT (3 * HZ)
4802+#define SCST_GENERIC_DISK_REG_TIMEOUT (60 * HZ)
4803+#define SCST_GENERIC_DISK_LONG_TIMEOUT (3600 * HZ)
4804+
4805+#define SCST_GENERIC_RAID_TIMEOUT (3 * HZ)
4806+#define SCST_GENERIC_RAID_LONG_TIMEOUT (14000 * HZ)
4807+
4808+#define SCST_GENERIC_CDROM_SMALL_TIMEOUT (3 * HZ)
4809+#define SCST_GENERIC_CDROM_REG_TIMEOUT (900 * HZ)
4810+#define SCST_GENERIC_CDROM_LONG_TIMEOUT (14000 * HZ)
4811+
4812+#define SCST_MAX_OTHER_TIMEOUT (14000 * HZ)
4813+
4814+/*************************************************************
4815+ ** I/O grouping attribute string values. Must match constants
4816+ ** w/o '_STR' suffix!
4817+ *************************************************************/
4818+#define SCST_IO_GROUPING_AUTO_STR "auto"
4819+#define SCST_IO_GROUPING_THIS_GROUP_ONLY_STR "this_group_only"
4820+#define SCST_IO_GROUPING_NEVER_STR "never"
4821+
4822+/*************************************************************
4823+ ** Threads pool type attribute string values.
4824+ ** Must match scst_dev_type_threads_pool_type!
4825+ *************************************************************/
4826+#define SCST_THREADS_POOL_PER_INITIATOR_STR "per_initiator"
4827+#define SCST_THREADS_POOL_SHARED_STR "shared"
4828+
4829+/*************************************************************
4830+ ** Misc constants
4831+ *************************************************************/
4832+#define SCST_SYSFS_BLOCK_SIZE PAGE_SIZE
4833+
4834+#define SCST_PR_DIR "/var/lib/scst/pr"
4835+
4836+#define TID_COMMON_SIZE 24
4837+
4838+#define SCST_SYSFS_KEY_MARK "[key]"
4839+
4840+#define SCST_MIN_REL_TGT_ID 1
4841+#define SCST_MAX_REL_TGT_ID 65535
4842+
4843+#endif /* __SCST_CONST_H */
4844diff -upkr -X linux-2.6.35/Documentation/dontdiff linux-2.6.35/drivers/Kconfig linux-2.6.35/drivers/Kconfig
4845--- orig/linux-2.6.35/drivers/Kconfig 01:51:29.000000000 +0400
4846+++ linux-2.6.35/drivers/Kconfig 14:14:46.000000000 +0400
4847@@ -22,6 +22,8 @@ source "drivers/ide/Kconfig"
4848
4849 source "drivers/scsi/Kconfig"
4850
4851+source "drivers/scst/Kconfig"
4852+
4853 source "drivers/ata/Kconfig"
4854
4855 source "drivers/md/Kconfig"
4856diff -upkr -X linux-2.6.35/Documentation/dontdiff linux-2.6.35/drivers/Makefile linux-2.6.35/drivers/Makefile
4857--- orig/linux-2.6.35/drivers/Makefile 01:51:29.000000000 +0400
4858+++ linux-2.6.35/drivers/Makefile 14:15:29.000000000 +0400
4859@@ -43,6 +43,7 @@ obj-$(CONFIG_ATM) += atm/
4860 obj-y += macintosh/
4861 obj-$(CONFIG_IDE) += ide/
4862 obj-$(CONFIG_SCSI) += scsi/
4863+obj-$(CONFIG_SCST) += scst/
4864 obj-$(CONFIG_ATA) += ata/
4865 obj-y += net/
4866 obj-$(CONFIG_ATM) += atm/
4867diff -uprN orig/linux-2.6.35/drivers/scst/Kconfig linux-2.6.35/drivers/scst/Kconfig
4868--- orig/linux-2.6.35/drivers/scst/Kconfig
4869+++ linux-2.6.35/drivers/scst/Kconfig
4870@@ -0,0 +1,255 @@
4871+menu "SCSI target (SCST) support"
4872+
4873+config SCST
4874+ tristate "SCSI target (SCST) support"
4875+ depends on SCSI
4876+ help
4877+ SCSI target (SCST) is designed to provide unified, consistent
4878+ interface between SCSI target drivers and Linux kernel and
4879+ simplify target drivers development as much as possible. Visit
4880+ http://scst.sourceforge.net for more info about it.
4881+
4882+config SCST_DISK
4883+ tristate "SCSI target disk support"
4884+ default SCST
4885+ depends on SCSI && SCST
4886+ help
4887+ SCST pass-through device handler for disk device.
4888+
4889+config SCST_TAPE
4890+ tristate "SCSI target tape support"
4891+ default SCST
4892+ depends on SCSI && SCST
4893+ help
4894+ SCST pass-through device handler for tape device.
4895+
4896+config SCST_CDROM
4897+ tristate "SCSI target CDROM support"
4898+ default SCST
4899+ depends on SCSI && SCST
4900+ help
4901+ SCST pass-through device handler for CDROM device.
4902+
4903+config SCST_MODISK
4904+ tristate "SCSI target MO disk support"
4905+ default SCST
4906+ depends on SCSI && SCST
4907+ help
4908+ SCST pass-through device handler for MO disk device.
4909+
4910+config SCST_CHANGER
4911+ tristate "SCSI target changer support"
4912+ default SCST
4913+ depends on SCSI && SCST
4914+ help
4915+ SCST pass-through device handler for changer device.
4916+
4917+config SCST_PROCESSOR
4918+ tristate "SCSI target processor support"
4919+ default SCST
4920+ depends on SCSI && SCST
4921+ help
4922+ SCST pass-through device handler for processor device.
4923+
4924+config SCST_RAID
4925+ tristate "SCSI target storage array controller (RAID) support"
4926+ default SCST
4927+ depends on SCSI && SCST
4928+ help
4929+ SCST pass-through device handler for raid storage array controller (RAID) device.
4930+
4931+config SCST_VDISK
4932+ tristate "SCSI target virtual disk and/or CDROM support"
4933+ default SCST
4934+ depends on SCSI && SCST
4935+ help
4936+ SCST device handler for virtual disk and/or CDROM device.
4937+
4938+config SCST_USER
4939+ tristate "User-space SCSI target driver support"
4940+ default SCST
4941+ depends on SCSI && SCST && !HIGHMEM4G && !HIGHMEM64G
4942+ help
4943+ The SCST device handler scst_user allows to implement full-feature
4944+ SCSI target devices in user space.
4945+
4946+ If unsure, say "N".
4947+
4948+config SCST_STRICT_SERIALIZING
4949+ bool "Strict serialization"
4950+ depends on SCST
4951+ help
4952+ Enable strict SCSI command serialization. When enabled, SCST sends
4953+ all SCSI commands to the underlying SCSI device synchronously, one
4954+ after one. This makes task management more reliable, at the cost of
4955+ a performance penalty. This is most useful for stateful SCSI devices
4956+ like tapes, where the result of the execution of a command
4957+ depends on the device settings configured by previous commands. Disk
4958+ and RAID devices are stateless in most cases. The current SCSI core
4959+ in Linux doesn't allow to abort all commands reliably if they have
4960+ been sent asynchronously to a stateful device.
4961+ Enable this option if you use stateful device(s) and need as much
4962+ error recovery reliability as possible.
4963+
4964+ If unsure, say "N".
4965+
4966+config SCST_STRICT_SECURITY
4967+ bool "Strict security"
4968+ depends on SCST
4969+ help
4970+ Makes SCST clear (zero-fill) allocated data buffers. Note: this has a
4971+ significant performance penalty.
4972+
4973+ If unsure, say "N".
4974+
4975+config SCST_TEST_IO_IN_SIRQ
4976+ bool "Allow test I/O from soft-IRQ context"
4977+ depends on SCST
4978+ help
4979+ Allows SCST to submit selected SCSI commands (TUR and
4980+ READ/WRITE) from soft-IRQ context (tasklets). Enabling it will
4981+ decrease amount of context switches and slightly improve
4982+ performance. The goal of this option is to be able to measure
4983+ overhead of the context switches. See more info about it in
4984+ README.scst.
4985+
4986+ WARNING! Improperly used, this option can lead you to a kernel crash!
4987+
4988+ If unsure, say "N".
4989+
4990+config SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING
4991+ bool "Send back UNKNOWN TASK when an already finished task is aborted"
4992+ depends on SCST
4993+ help
4994+ Controls which response is sent by SCST to the initiator in case
4995+ the initiator attempts to abort (ABORT TASK) an already finished
4996+ request. If this option is enabled, the response UNKNOWN TASK is
4997+ sent back to the initiator. However, some initiators, particularly
4998+ the VMware iSCSI initiator, interpret the UNKNOWN TASK response as
4999+ if the target got crazy and try to RESET it. Then sometimes the
5000+ initiator gets crazy itself.
5001+
5002+ If unsure, say "N".
5003+
5004+config SCST_USE_EXPECTED_VALUES
5005+ bool "Prefer initiator-supplied SCSI command attributes"
5006+ depends on SCST
5007+ help
5008+ When SCST receives a SCSI command from an initiator, such a SCSI
5009+ command has both data transfer length and direction attributes.
5010+ There are two possible sources for these attributes: either the
5011+ values computed by SCST from its internal command translation table
5012+ or the values supplied by the initiator. The former are used by
5013+ default because of security reasons. Invalid initiator-supplied
5014+ attributes can crash the target, especially in pass-through mode.
5015+ Only consider enabling this option when SCST logs the following
5016+ message: "Unknown opcode XX for YY. Should you update
5017+ scst_scsi_op_table?" and when the initiator complains. Please
5018+ report any unrecognized commands to scst-devel@lists.sourceforge.net.
5019+
5020+ If unsure, say "N".
5021+
5022+config SCST_EXTRACHECKS
5023+ bool "Extra consistency checks"
5024+ depends on SCST
5025+ help
5026+ Enable additional consistency checks in the SCSI middle level target
5027+ code. This may be helpful for SCST developers. Enable it if you have
5028+ any problems.
5029+
5030+ If unsure, say "N".
5031+
5032+config SCST_TRACING
5033+ bool "Tracing support"
5034+ depends on SCST
5035+ default y
5036+ help
5037+ Enable SCSI middle level tracing support. Tracing can be controlled
5038+ dynamically via sysfs interface. The traced information
5039+ is sent to the kernel log and may be very helpful when analyzing
5040+ the cause of a communication problem between initiator and target.
5041+
5042+ If unsure, say "Y".
5043+
5044+config SCST_DEBUG
5045+ bool "Debugging support"
5046+ depends on SCST
5047+ select DEBUG_BUGVERBOSE
5048+ help
5049+ Enables support for debugging SCST. This may be helpful for SCST
5050+ developers.
5051+
5052+ If unsure, say "N".
5053+
5054+config SCST_DEBUG_OOM
5055+ bool "Out-of-memory debugging support"
5056+ depends on SCST
5057+ help
5058+ Let SCST's internal memory allocation function
5059+ (scst_alloc_sg_entries()) fail about once in every 10000 calls, at
5060+ least if the flag __GFP_NOFAIL has not been set. This allows SCST
5061+ developers to test the behavior of SCST in out-of-memory conditions.
5062+ This may be helpful for SCST developers.
5063+
5064+ If unsure, say "N".
5065+
5066+config SCST_DEBUG_RETRY
5067+ bool "SCSI command retry debugging support"
5068+ depends on SCST
5069+ help
5070+ Let SCST's internal SCSI command transfer function
5071+ (scst_rdy_to_xfer()) fail about once in every 100 calls. This allows
5072+ SCST developers to test the behavior of SCST when SCSI queues fill
5073+ up. This may be helpful for SCST developers.
5074+
5075+ If unsure, say "N".
5076+
5077+config SCST_DEBUG_SN
5078+ bool "SCSI sequence number debugging support"
5079+ depends on SCST
5080+ help
5081+ Allows to test SCSI command ordering via sequence numbers by
5082+ randomly changing the type of SCSI commands into
5083+ SCST_CMD_QUEUE_ORDERED, SCST_CMD_QUEUE_HEAD_OF_QUEUE or
5084+ SCST_CMD_QUEUE_SIMPLE for about one in 300 SCSI commands.
5085+ This may be helpful for SCST developers.
5086+
5087+ If unsure, say "N".
5088+
5089+config SCST_DEBUG_TM
5090+ bool "Task management debugging support"
5091+ depends on SCST_DEBUG
5092+ help
5093+ Enables support for debugging of SCST's task management functions.
5094+ When enabled, some of the commands on LUN 0 in the default access
5095+ control group will be delayed for about 60 seconds. This will
5096+ cause the remote initiator send SCSI task management functions,
5097+ e.g. ABORT TASK and TARGET RESET.
5098+
5099+ If unsure, say "N".
5100+
5101+config SCST_TM_DBG_GO_OFFLINE
5102+ bool "Let devices become completely unresponsive"
5103+ depends on SCST_DEBUG_TM
5104+ help
5105+ Enable this option if you want that the device eventually becomes
5106+ completely unresponsive. When disabled, the device will receive
5107+ ABORT and RESET commands.
5108+
5109+config SCST_MEASURE_LATENCY
5110+ bool "Commands processing latency measurement facility"
5111+ depends on SCST
5112+ help
5113+ This option enables commands processing latency measurement
5114+ facility in SCST. It will provide in the sysfs interface
5115+ average commands processing latency statistics. You can clear
5116+ already measured results by writing 0 in the corresponding sysfs file.
5117+ Note, you need a non-preemtible kernel to have correct results.
5118+
5119+ If unsure, say "N".
5120+
5121+source "drivers/scst/fcst/Kconfig"
5122+source "drivers/scst/iscsi-scst/Kconfig"
5123+source "drivers/scst/srpt/Kconfig"
5124+
5125+endmenu
5126diff -uprN orig/linux-2.6.35/drivers/scst/Makefile linux-2.6.35/drivers/scst/Makefile
5127--- orig/linux-2.6.35/drivers/scst/Makefile
5128+++ linux-2.6.35/drivers/scst/Makefile
5129@@ -0,0 +1,12 @@
5130+ccflags-y += -Wno-unused-parameter
5131+
5132+scst-y += scst_main.o
5133+scst-y += scst_pres.o
5134+scst-y += scst_targ.o
5135+scst-y += scst_lib.o
5136+scst-y += scst_sysfs.o
5137+scst-y += scst_mem.o
5138+scst-y += scst_debug.o
5139+
5140+obj-$(CONFIG_SCST) += scst.o dev_handlers/ fcst/ iscsi-scst/ qla2xxx-target/ \
5141+ srpt/ scst_local/
5142diff -uprN orig/linux-2.6.35/drivers/scst/scst_lib.c linux-2.6.35/drivers/scst/scst_lib.c
5143--- orig/linux-2.6.35/drivers/scst/scst_lib.c
5144+++ linux-2.6.35/drivers/scst/scst_lib.c
5145@@ -0,0 +1,7361 @@
5146+/*
5147+ * scst_lib.c
5148+ *
5149+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
5150+ * Copyright (C) 2004 - 2005 Leonid Stoljar
5151+ * Copyright (C) 2007 - 2010 ID7 Ltd.
5152+ *
5153+ * This program is free software; you can redistribute it and/or
5154+ * modify it under the terms of the GNU General Public License
5155+ * as published by the Free Software Foundation, version 2
5156+ * of the License.
5157+ *
5158+ * This program is distributed in the hope that it will be useful,
5159+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5160+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5161+ * GNU General Public License for more details.
5162+ */
5163+
5164+#include <linux/init.h>
5165+#include <linux/kernel.h>
5166+#include <linux/errno.h>
5167+#include <linux/list.h>
5168+#include <linux/spinlock.h>
5169+#include <linux/slab.h>
5170+#include <linux/sched.h>
5171+#include <linux/kthread.h>
5172+#include <linux/cdrom.h>
5173+#include <linux/unistd.h>
5174+#include <linux/string.h>
5175+#include <linux/ctype.h>
5176+#include <linux/delay.h>
5177+#include <linux/vmalloc.h>
5178+#include <asm/kmap_types.h>
5179+#include <asm/unaligned.h>
5180+
5181+#include <scst/scst.h>
5182+#include "scst_priv.h"
5183+#include "scst_mem.h"
5184+#include "scst_pres.h"
5185+
5186+struct scsi_io_context {
5187+ unsigned int full_cdb_used:1;
5188+ void *data;
5189+ void (*done)(void *data, char *sense, int result, int resid);
5190+ char sense[SCST_SENSE_BUFFERSIZE];
5191+ unsigned char full_cdb[0];
5192+};
5193+static struct kmem_cache *scsi_io_context_cache;
5194+
5195+/* get_trans_len_x extract x bytes from cdb as length starting from off */
5196+static int get_trans_len_1(struct scst_cmd *cmd, uint8_t off);
5197+static int get_trans_len_1_256(struct scst_cmd *cmd, uint8_t off);
5198+static int get_trans_len_2(struct scst_cmd *cmd, uint8_t off);
5199+static int get_trans_len_3(struct scst_cmd *cmd, uint8_t off);
5200+static int get_trans_len_4(struct scst_cmd *cmd, uint8_t off);
5201+
5202+static int get_bidi_trans_len_2(struct scst_cmd *cmd, uint8_t off);
5203+
5204+/* for special commands */
5205+static int get_trans_len_block_limit(struct scst_cmd *cmd, uint8_t off);
5206+static int get_trans_len_read_capacity(struct scst_cmd *cmd, uint8_t off);
5207+static int get_trans_len_serv_act_in(struct scst_cmd *cmd, uint8_t off);
5208+static int get_trans_len_single(struct scst_cmd *cmd, uint8_t off);
5209+static int get_trans_len_none(struct scst_cmd *cmd, uint8_t off);
5210+static int get_trans_len_read_pos(struct scst_cmd *cmd, uint8_t off);
5211+static int get_trans_cdb_len_10(struct scst_cmd *cmd, uint8_t off);
5212+static int get_trans_len_prevent_allow_medium_removal(struct scst_cmd *cmd,
5213+ uint8_t off);
5214+static int get_trans_len_3_read_elem_stat(struct scst_cmd *cmd, uint8_t off);
5215+static int get_trans_len_start_stop(struct scst_cmd *cmd, uint8_t off);
5216+
5217+/*
5218++=====================================-============-======-
5219+| Command name | Operation | Type |
5220+| | code | |
5221+|-------------------------------------+------------+------+
5222+
5223++=========================================================+
5224+|Key: M = command implementation is mandatory. |
5225+| O = command implementation is optional. |
5226+| V = Vendor-specific |
5227+| R = Reserved |
5228+| ' '= DON'T use for this device |
5229++=========================================================+
5230+*/
5231+
5232+#define SCST_CDB_MANDATORY 'M' /* mandatory */
5233+#define SCST_CDB_OPTIONAL 'O' /* optional */
5234+#define SCST_CDB_VENDOR 'V' /* vendor */
5235+#define SCST_CDB_RESERVED 'R' /* reserved */
5236+#define SCST_CDB_NOTSUPP ' ' /* don't use */
5237+
5238+struct scst_sdbops {
5239+ uint8_t ops; /* SCSI-2 op codes */
5240+ uint8_t devkey[16]; /* Key for every device type M,O,V,R
5241+ * type_disk devkey[0]
5242+ * type_tape devkey[1]
5243+ * type_printer devkey[2]
5244+ * type_proseccor devkey[3]
5245+ * type_worm devkey[4]
5246+ * type_cdrom devkey[5]
5247+ * type_scanner devkey[6]
5248+ * type_mod devkey[7]
5249+ * type_changer devkey[8]
5250+ * type_commdev devkey[9]
5251+ * type_reserv devkey[A]
5252+ * type_reserv devkey[B]
5253+ * type_raid devkey[C]
5254+ * type_enclosure devkey[D]
5255+ * type_reserv devkey[E]
5256+ * type_reserv devkey[F]
5257+ */
5258+ const char *op_name; /* SCSI-2 op codes full name */
5259+ uint8_t direction; /* init --> target: SCST_DATA_WRITE
5260+ * target --> init: SCST_DATA_READ
5261+ */
5262+ uint16_t flags; /* opcode -- various flags */
5263+ uint8_t off; /* length offset in cdb */
5264+ int (*get_trans_len)(struct scst_cmd *cmd, uint8_t off);
5265+};
5266+
5267+static int scst_scsi_op_list[256];
5268+
5269+#define FLAG_NONE 0
5270+
5271+static const struct scst_sdbops scst_scsi_op_table[] = {
5272+ /*
5273+ * +-------------------> TYPE_IS_DISK (0)
5274+ * |
5275+ * |+------------------> TYPE_IS_TAPE (1)
5276+ * ||
5277+ * || +----------------> TYPE_IS_PROCESSOR (3)
5278+ * || |
5279+ * || | +--------------> TYPE_IS_CDROM (5)
5280+ * || | |
5281+ * || | | +------------> TYPE_IS_MOD (7)
5282+ * || | | |
5283+ * || | | |+-----------> TYPE_IS_CHANGER (8)
5284+ * || | | ||
5285+ * || | | || +-------> TYPE_IS_RAID (C)
5286+ * || | | || |
5287+ * || | | || |
5288+ * 0123456789ABCDEF ---> TYPE_IS_???? */
5289+
5290+ /* 6-bytes length CDB */
5291+ {0x00, "MMMMMMMMMMMMMMMM", "TEST UNIT READY",
5292+ /* let's be HQ to don't look dead under high load */
5293+ SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|
5294+ SCST_REG_RESERVE_ALLOWED|
5295+ SCST_WRITE_EXCL_ALLOWED|
5296+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
5297+ SCST_TEST_IO_IN_SIRQ_ALLOWED|
5298+#endif
5299+ SCST_EXCL_ACCESS_ALLOWED,
5300+ 0, get_trans_len_none},
5301+ {0x01, " M ", "REWIND",
5302+ SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_EXCL_ALLOWED,
5303+ 0, get_trans_len_none},
5304+ {0x01, "O V OO OO ", "REZERO UNIT",
5305+ SCST_DATA_NONE, SCST_WRITE_EXCL_ALLOWED,
5306+ 0, get_trans_len_none},
5307+ {0x02, "VVVVVV V ", "REQUEST BLOCK ADDR",
5308+ SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none},
5309+ {0x03, "MMMMMMMMMMMMMMMM", "REQUEST SENSE",
5310+ SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_SKIP_UA|SCST_LOCAL_CMD|
5311+ SCST_REG_RESERVE_ALLOWED|
5312+ SCST_WRITE_EXCL_ALLOWED|
5313+ SCST_EXCL_ACCESS_ALLOWED,
5314+ 4, get_trans_len_1},
5315+ {0x04, "M O O ", "FORMAT UNIT",
5316+ SCST_DATA_WRITE, SCST_LONG_TIMEOUT|SCST_UNKNOWN_LENGTH|SCST_WRITE_MEDIUM,
5317+ 0, get_trans_len_none},
5318+ {0x04, " O ", "FORMAT",
5319+ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
5320+ {0x05, "VMVVVV V ", "READ BLOCK LIMITS",
5321+ SCST_DATA_READ, SCST_SMALL_TIMEOUT|
5322+ SCST_REG_RESERVE_ALLOWED|
5323+ SCST_WRITE_EXCL_ALLOWED|
5324+ SCST_EXCL_ACCESS_ALLOWED,
5325+ 0, get_trans_len_block_limit},
5326+ {0x07, " O ", "INITIALIZE ELEMENT STATUS",
5327+ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
5328+ {0x07, "OVV O OV ", "REASSIGN BLOCKS",
5329+ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
5330+ {0x08, "O ", "READ(6)",
5331+ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
5332+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
5333+ SCST_TEST_IO_IN_SIRQ_ALLOWED|
5334+#endif
5335+ SCST_WRITE_EXCL_ALLOWED,
5336+ 4, get_trans_len_1_256},
5337+ {0x08, " MV OO OV ", "READ(6)",
5338+ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
5339+ SCST_WRITE_EXCL_ALLOWED,
5340+ 2, get_trans_len_3},
5341+ {0x08, " M ", "GET MESSAGE(6)",
5342+ SCST_DATA_READ, FLAG_NONE, 2, get_trans_len_3},
5343+ {0x08, " O ", "RECEIVE",
5344+ SCST_DATA_READ, FLAG_NONE, 2, get_trans_len_3},
5345+ {0x0A, "O ", "WRITE(6)",
5346+ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
5347+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
5348+ SCST_TEST_IO_IN_SIRQ_ALLOWED|
5349+#endif
5350+ SCST_WRITE_MEDIUM,
5351+ 4, get_trans_len_1_256},
5352+ {0x0A, " M O OV ", "WRITE(6)",
5353+ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
5354+ 2, get_trans_len_3},
5355+ {0x0A, " M ", "PRINT",
5356+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5357+ {0x0A, " M ", "SEND MESSAGE(6)",
5358+ SCST_DATA_WRITE, FLAG_NONE, 2, get_trans_len_3},
5359+ {0x0A, " M ", "SEND(6)",
5360+ SCST_DATA_WRITE, FLAG_NONE, 2, get_trans_len_3},
5361+ {0x0B, "O OO OV ", "SEEK(6)",
5362+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5363+ {0x0B, " ", "TRACK SELECT",
5364+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5365+ {0x0B, " O ", "SLEW AND PRINT",
5366+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5367+ {0x0C, "VVVVVV V ", "SEEK BLOCK",
5368+ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
5369+ {0x0D, "VVVVVV V ", "PARTITION",
5370+ SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
5371+ 0, get_trans_len_none},
5372+ {0x0F, "VOVVVV V ", "READ REVERSE",
5373+ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
5374+ SCST_WRITE_EXCL_ALLOWED,
5375+ 2, get_trans_len_3},
5376+ {0x10, "VM V V ", "WRITE FILEMARKS",
5377+ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
5378+ {0x10, " O O ", "SYNCHRONIZE BUFFER",
5379+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5380+ {0x11, "VMVVVV ", "SPACE",
5381+ SCST_DATA_NONE, SCST_LONG_TIMEOUT|
5382+ SCST_WRITE_EXCL_ALLOWED,
5383+ 0, get_trans_len_none},
5384+ {0x12, "MMMMMMMMMMMMMMMM", "INQUIRY",
5385+ SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|SCST_SKIP_UA|
5386+ SCST_REG_RESERVE_ALLOWED|
5387+ SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
5388+ 4, get_trans_len_1},
5389+ {0x13, "VOVVVV ", "VERIFY(6)",
5390+ SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
5391+ SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED|
5392+ SCST_WRITE_EXCL_ALLOWED,
5393+ 2, get_trans_len_3},
5394+ {0x14, "VOOVVV ", "RECOVER BUFFERED DATA",
5395+ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
5396+ SCST_WRITE_EXCL_ALLOWED,
5397+ 2, get_trans_len_3},
5398+ {0x15, "OMOOOOOOOOOOOOOO", "MODE SELECT(6)",
5399+ SCST_DATA_WRITE, SCST_IMPLICIT_ORDERED, 4, get_trans_len_1},
5400+ {0x16, "MMMMMMMMMMMMMMMM", "RESERVE",
5401+ SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD|
5402+ SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
5403+ 0, get_trans_len_none},
5404+ {0x17, "MMMMMMMMMMMMMMMM", "RELEASE",
5405+ SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD|
5406+ SCST_REG_RESERVE_ALLOWED|
5407+ SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
5408+ 0, get_trans_len_none},
5409+ {0x18, "OOOOOOOO ", "COPY",
5410+ SCST_DATA_WRITE, SCST_LONG_TIMEOUT, 2, get_trans_len_3},
5411+ {0x19, "VMVVVV ", "ERASE",
5412+ SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
5413+ 0, get_trans_len_none},
5414+ {0x1A, "OMOOOOOOOOOOOOOO", "MODE SENSE(6)",
5415+ SCST_DATA_READ, SCST_SMALL_TIMEOUT, 4, get_trans_len_1},
5416+ {0x1B, " O ", "SCAN",
5417+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5418+ {0x1B, " O ", "LOAD UNLOAD",
5419+ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
5420+ {0x1B, " O ", "STOP PRINT",
5421+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5422+ {0x1B, "O OO O O ", "START STOP UNIT",
5423+ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_start_stop},
5424+ {0x1C, "OOOOOOOOOOOOOOOO", "RECEIVE DIAGNOSTIC RESULTS",
5425+ SCST_DATA_READ, FLAG_NONE, 3, get_trans_len_2},
5426+ {0x1D, "MMMMMMMMMMMMMMMM", "SEND DIAGNOSTIC",
5427+ SCST_DATA_WRITE, FLAG_NONE, 4, get_trans_len_1},
5428+ {0x1E, "OOOOOOOOOOOOOOOO", "PREVENT ALLOW MEDIUM REMOVAL",
5429+ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0,
5430+ get_trans_len_prevent_allow_medium_removal},
5431+ {0x1F, " O ", "PORT STATUS",
5432+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5433+
5434+ /* 10-bytes length CDB */
5435+ {0x23, "V VV V ", "READ FORMAT CAPACITY",
5436+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
5437+ {0x24, "V VVM ", "SET WINDOW",
5438+ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_3},
5439+ {0x25, "M MM M ", "READ CAPACITY",
5440+ SCST_DATA_READ, SCST_IMPLICIT_HQ|
5441+ SCST_REG_RESERVE_ALLOWED|
5442+ SCST_WRITE_EXCL_ALLOWED|
5443+ SCST_EXCL_ACCESS_ALLOWED,
5444+ 0, get_trans_len_read_capacity},
5445+ {0x25, " O ", "GET WINDOW",
5446+ SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_3},
5447+ {0x28, "M MMMM ", "READ(10)",
5448+ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
5449+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
5450+ SCST_TEST_IO_IN_SIRQ_ALLOWED|
5451+#endif
5452+ SCST_WRITE_EXCL_ALLOWED,
5453+ 7, get_trans_len_2},
5454+ {0x28, " O ", "GET MESSAGE(10)",
5455+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
5456+ {0x29, "V VV O ", "READ GENERATION",
5457+ SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_1},
5458+ {0x2A, "O MO M ", "WRITE(10)",
5459+ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
5460+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
5461+ SCST_TEST_IO_IN_SIRQ_ALLOWED|
5462+#endif
5463+ SCST_WRITE_MEDIUM,
5464+ 7, get_trans_len_2},
5465+ {0x2A, " O ", "SEND MESSAGE(10)",
5466+ SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
5467+ {0x2A, " O ", "SEND(10)",
5468+ SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
5469+ {0x2B, " O ", "LOCATE",
5470+ SCST_DATA_NONE, SCST_LONG_TIMEOUT|
5471+ SCST_WRITE_EXCL_ALLOWED,
5472+ 0, get_trans_len_none},
5473+ {0x2B, " O ", "POSITION TO ELEMENT",
5474+ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
5475+ {0x2B, "O OO O ", "SEEK(10)",
5476+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5477+ {0x2C, "V O O ", "ERASE(10)",
5478+ SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
5479+ 0, get_trans_len_none},
5480+ {0x2D, "V O O ", "READ UPDATED BLOCK",
5481+ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 0, get_trans_len_single},
5482+ {0x2E, "O OO O ", "WRITE AND VERIFY(10)",
5483+ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
5484+ 7, get_trans_len_2},
5485+ {0x2F, "O OO O ", "VERIFY(10)",
5486+ SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
5487+ SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED|
5488+ SCST_WRITE_EXCL_ALLOWED,
5489+ 7, get_trans_len_2},
5490+ {0x33, "O OO O ", "SET LIMITS(10)",
5491+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5492+ {0x34, " O ", "READ POSITION",
5493+ SCST_DATA_READ, SCST_SMALL_TIMEOUT|
5494+ SCST_WRITE_EXCL_ALLOWED,
5495+ 7, get_trans_len_read_pos},
5496+ {0x34, " O ", "GET DATA BUFFER STATUS",
5497+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
5498+ {0x34, "O OO O ", "PRE-FETCH",
5499+ SCST_DATA_NONE, SCST_WRITE_EXCL_ALLOWED,
5500+ 0, get_trans_len_none},
5501+ {0x35, "O OO O ", "SYNCHRONIZE CACHE",
5502+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5503+ {0x36, "O OO O ", "LOCK UNLOCK CACHE",
5504+ SCST_DATA_NONE, SCST_WRITE_EXCL_ALLOWED,
5505+ 0, get_trans_len_none},
5506+ {0x37, "O O ", "READ DEFECT DATA(10)",
5507+ SCST_DATA_READ, SCST_WRITE_EXCL_ALLOWED,
5508+ 8, get_trans_len_1},
5509+ {0x37, " O ", "INIT ELEMENT STATUS WRANGE",
5510+ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
5511+ {0x38, " O O ", "MEDIUM SCAN",
5512+ SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_1},
5513+ {0x39, "OOOOOOOO ", "COMPARE",
5514+ SCST_DATA_WRITE, FLAG_NONE, 3, get_trans_len_3},
5515+ {0x3A, "OOOOOOOO ", "COPY AND VERIFY",
5516+ SCST_DATA_WRITE, FLAG_NONE, 3, get_trans_len_3},
5517+ {0x3B, "OOOOOOOOOOOOOOOO", "WRITE BUFFER",
5518+ SCST_DATA_WRITE, SCST_SMALL_TIMEOUT, 6, get_trans_len_3},
5519+ {0x3C, "OOOOOOOOOOOOOOOO", "READ BUFFER",
5520+ SCST_DATA_READ, SCST_SMALL_TIMEOUT, 6, get_trans_len_3},
5521+ {0x3D, " O O ", "UPDATE BLOCK",
5522+ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED,
5523+ 0, get_trans_len_single},
5524+ {0x3E, "O OO O ", "READ LONG",
5525+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
5526+ {0x3F, "O O O ", "WRITE LONG",
5527+ SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 7, get_trans_len_2},
5528+ {0x40, "OOOOOOOOOO ", "CHANGE DEFINITION",
5529+ SCST_DATA_WRITE, SCST_SMALL_TIMEOUT, 8, get_trans_len_1},
5530+ {0x41, "O O ", "WRITE SAME",
5531+ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
5532+ 0, get_trans_len_single},
5533+ {0x42, " O ", "READ SUB-CHANNEL",
5534+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
5535+ {0x43, " O ", "READ TOC/PMA/ATIP",
5536+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
5537+ {0x44, " M ", "REPORT DENSITY SUPPORT",
5538+ SCST_DATA_READ, SCST_REG_RESERVE_ALLOWED|
5539+ SCST_WRITE_EXCL_ALLOWED|
5540+ SCST_EXCL_ACCESS_ALLOWED,
5541+ 7, get_trans_len_2},
5542+ {0x44, " O ", "READ HEADER",
5543+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
5544+ {0x45, " O ", "PLAY AUDIO(10)",
5545+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5546+ {0x46, " O ", "GET CONFIGURATION",
5547+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
5548+ {0x47, " O ", "PLAY AUDIO MSF",
5549+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5550+ {0x48, " O ", "PLAY AUDIO TRACK INDEX",
5551+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5552+ {0x49, " O ", "PLAY TRACK RELATIVE(10)",
5553+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5554+ {0x4A, " O ", "GET EVENT STATUS NOTIFICATION",
5555+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
5556+ {0x4B, " O ", "PAUSE/RESUME",
5557+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5558+ {0x4C, "OOOOOOOOOOOOOOOO", "LOG SELECT",
5559+ SCST_DATA_WRITE, SCST_IMPLICIT_ORDERED, 7, get_trans_len_2},
5560+ {0x4D, "OOOOOOOOOOOOOOOO", "LOG SENSE",
5561+ SCST_DATA_READ, SCST_SMALL_TIMEOUT|
5562+ SCST_REG_RESERVE_ALLOWED|
5563+ SCST_WRITE_EXCL_ALLOWED|
5564+ SCST_EXCL_ACCESS_ALLOWED,
5565+ 7, get_trans_len_2},
5566+ {0x4E, " O ", "STOP PLAY/SCAN",
5567+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5568+ {0x50, " ", "XDWRITE",
5569+ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
5570+ {0x51, " O ", "READ DISC INFORMATION",
5571+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
5572+ {0x51, " ", "XPWRITE",
5573+ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
5574+ {0x52, " O ", "READ TRACK INFORMATION",
5575+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
5576+ {0x53, "O ", "XDWRITEREAD(10)",
5577+ SCST_DATA_READ|SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
5578+ SCST_WRITE_MEDIUM,
5579+ 7, get_bidi_trans_len_2},
5580+ {0x53, " O ", "RESERVE TRACK",
5581+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5582+ {0x54, " O ", "SEND OPC INFORMATION",
5583+ SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
5584+ {0x55, "OOOOOOOOOOOOOOOO", "MODE SELECT(10)",
5585+ SCST_DATA_WRITE, SCST_IMPLICIT_ORDERED, 7, get_trans_len_2},
5586+ {0x56, "OOOOOOOOOOOOOOOO", "RESERVE(10)",
5587+ SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD,
5588+ 0, get_trans_len_none},
5589+ {0x57, "OOOOOOOOOOOOOOOO", "RELEASE(10)",
5590+ SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD|
5591+ SCST_REG_RESERVE_ALLOWED,
5592+ 0, get_trans_len_none},
5593+ {0x58, " O ", "REPAIR TRACK",
5594+ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
5595+ {0x5A, "OOOOOOOOOOOOOOOO", "MODE SENSE(10)",
5596+ SCST_DATA_READ, SCST_SMALL_TIMEOUT, 7, get_trans_len_2},
5597+ {0x5B, " O ", "CLOSE TRACK/SESSION",
5598+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5599+ {0x5C, " O ", "READ BUFFER CAPACITY",
5600+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
5601+ {0x5D, " O ", "SEND CUE SHEET",
5602+ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_3},
5603+ {0x5E, "OOOOO OOOO ", "PERSISTENT RESERV IN",
5604+ SCST_DATA_READ, SCST_SMALL_TIMEOUT|
5605+ SCST_LOCAL_CMD|
5606+ SCST_WRITE_EXCL_ALLOWED|
5607+ SCST_EXCL_ACCESS_ALLOWED,
5608+ 5, get_trans_len_4},
5609+ {0x5F, "OOOOO OOOO ", "PERSISTENT RESERV OUT",
5610+ SCST_DATA_WRITE, SCST_SMALL_TIMEOUT|
5611+ SCST_LOCAL_CMD|
5612+ SCST_WRITE_EXCL_ALLOWED|
5613+ SCST_EXCL_ACCESS_ALLOWED,
5614+ 5, get_trans_len_4},
5615+
5616+ /* 16-bytes length CDB */
5617+ {0x80, "O OO O ", "XDWRITE EXTENDED",
5618+ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
5619+ {0x80, " M ", "WRITE FILEMARKS",
5620+ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
5621+ {0x81, "O OO O ", "REBUILD",
5622+ SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4},
5623+ {0x82, "O OO O ", "REGENERATE",
5624+ SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4},
5625+ {0x83, "OOOOOOOOOOOOOOOO", "EXTENDED COPY",
5626+ SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4},
5627+ {0x84, "OOOOOOOOOOOOOOOO", "RECEIVE COPY RESULT",
5628+ SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4},
5629+ {0x86, "OOOOOOOOOO ", "ACCESS CONTROL IN",
5630+ SCST_DATA_NONE, SCST_REG_RESERVE_ALLOWED|
5631+ SCST_WRITE_EXCL_ALLOWED|
5632+ SCST_EXCL_ACCESS_ALLOWED,
5633+ 0, get_trans_len_none},
5634+ {0x87, "OOOOOOOOOO ", "ACCESS CONTROL OUT",
5635+ SCST_DATA_NONE, SCST_REG_RESERVE_ALLOWED|
5636+ SCST_WRITE_EXCL_ALLOWED|
5637+ SCST_EXCL_ACCESS_ALLOWED,
5638+ 0, get_trans_len_none},
5639+ {0x88, "M MMMM ", "READ(16)",
5640+ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
5641+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
5642+ SCST_TEST_IO_IN_SIRQ_ALLOWED|
5643+#endif
5644+ SCST_WRITE_EXCL_ALLOWED,
5645+ 10, get_trans_len_4},
5646+ {0x8A, "O OO O ", "WRITE(16)",
5647+ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
5648+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
5649+ SCST_TEST_IO_IN_SIRQ_ALLOWED|
5650+#endif
5651+ SCST_WRITE_MEDIUM,
5652+ 10, get_trans_len_4},
5653+ {0x8C, "OOOOOOOOOO ", "READ ATTRIBUTE",
5654+ SCST_DATA_READ, FLAG_NONE, 10, get_trans_len_4},
5655+ {0x8D, "OOOOOOOOOO ", "WRITE ATTRIBUTE",
5656+ SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4},
5657+ {0x8E, "O OO O ", "WRITE AND VERIFY(16)",
5658+ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
5659+ 10, get_trans_len_4},
5660+ {0x8F, "O OO O ", "VERIFY(16)",
5661+ SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
5662+ SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED|
5663+ SCST_WRITE_EXCL_ALLOWED,
5664+ 10, get_trans_len_4},
5665+ {0x90, "O OO O ", "PRE-FETCH(16)",
5666+ SCST_DATA_NONE, SCST_WRITE_EXCL_ALLOWED,
5667+ 0, get_trans_len_none},
5668+ {0x91, "O OO O ", "SYNCHRONIZE CACHE(16)",
5669+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5670+ {0x91, " M ", "SPACE(16)",
5671+ SCST_DATA_NONE, SCST_LONG_TIMEOUT|
5672+ SCST_WRITE_EXCL_ALLOWED,
5673+ 0, get_trans_len_none},
5674+ {0x92, "O OO O ", "LOCK UNLOCK CACHE(16)",
5675+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5676+ {0x92, " O ", "LOCATE(16)",
5677+ SCST_DATA_NONE, SCST_LONG_TIMEOUT|
5678+ SCST_WRITE_EXCL_ALLOWED,
5679+ 0, get_trans_len_none},
5680+ {0x93, "O O ", "WRITE SAME(16)",
5681+ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
5682+ 10, get_trans_len_4},
5683+ {0x93, " M ", "ERASE(16)",
5684+ SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
5685+ 0, get_trans_len_none},
5686+ {0x9E, "O ", "SERVICE ACTION IN",
5687+ SCST_DATA_READ, FLAG_NONE, 0, get_trans_len_serv_act_in},
5688+
5689+ /* 12-bytes length CDB */
5690+ {0xA0, "VVVVVVVVVV M ", "REPORT LUNS",
5691+ SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|SCST_SKIP_UA|
5692+ SCST_FULLY_LOCAL_CMD|SCST_LOCAL_CMD|
5693+ SCST_REG_RESERVE_ALLOWED|
5694+ SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
5695+ 6, get_trans_len_4},
5696+ {0xA1, " O ", "BLANK",
5697+ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
5698+ {0xA3, " O ", "SEND KEY",
5699+ SCST_DATA_WRITE, FLAG_NONE, 8, get_trans_len_2},
5700+ {0xA3, "OOOOO OOOO ", "REPORT DEVICE IDENTIDIER",
5701+ SCST_DATA_READ, SCST_REG_RESERVE_ALLOWED|
5702+ SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
5703+ 6, get_trans_len_4},
5704+ {0xA3, " M ", "MAINTENANCE(IN)",
5705+ SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_4},
5706+ {0xA4, " O ", "REPORT KEY",
5707+ SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_2},
5708+ {0xA4, " O ", "MAINTENANCE(OUT)",
5709+ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4},
5710+ {0xA5, " M ", "MOVE MEDIUM",
5711+ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
5712+ {0xA5, " O ", "PLAY AUDIO(12)",
5713+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5714+ {0xA6, " O O ", "EXCHANGE/LOAD/UNLOAD MEDIUM",
5715+ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
5716+ {0xA7, " O ", "SET READ AHEAD",
5717+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5718+ {0xA8, " O ", "GET MESSAGE(12)",
5719+ SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_4},
5720+ {0xA8, "O OO O ", "READ(12)",
5721+ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
5722+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
5723+ SCST_TEST_IO_IN_SIRQ_ALLOWED|
5724+#endif
5725+ SCST_WRITE_EXCL_ALLOWED,
5726+ 6, get_trans_len_4},
5727+ {0xA9, " O ", "PLAY TRACK RELATIVE(12)",
5728+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5729+ {0xAA, "O OO O ", "WRITE(12)",
5730+ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
5731+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
5732+ SCST_TEST_IO_IN_SIRQ_ALLOWED|
5733+#endif
5734+ SCST_WRITE_MEDIUM,
5735+ 6, get_trans_len_4},
5736+ {0xAA, " O ", "SEND MESSAGE(12)",
5737+ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4},
5738+ {0xAC, " O ", "ERASE(12)",
5739+ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
5740+ {0xAC, " M ", "GET PERFORMANCE",
5741+ SCST_DATA_READ, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none},
5742+ {0xAD, " O ", "READ DVD STRUCTURE",
5743+ SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_2},
5744+ {0xAE, "O OO O ", "WRITE AND VERIFY(12)",
5745+ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
5746+ 6, get_trans_len_4},
5747+ {0xAF, "O OO O ", "VERIFY(12)",
5748+ SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
5749+ SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED|
5750+ SCST_WRITE_EXCL_ALLOWED,
5751+ 6, get_trans_len_4},
5752+#if 0 /* No need to support at all */
5753+ {0xB0, " OO O ", "SEARCH DATA HIGH(12)",
5754+ SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_1},
5755+ {0xB1, " OO O ", "SEARCH DATA EQUAL(12)",
5756+ SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_1},
5757+ {0xB2, " OO O ", "SEARCH DATA LOW(12)",
5758+ SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_1},
5759+#endif
5760+ {0xB3, " OO O ", "SET LIMITS(12)",
5761+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5762+ {0xB5, " O ", "REQUEST VOLUME ELEMENT ADDRESS",
5763+ SCST_DATA_READ, FLAG_NONE, 9, get_trans_len_1},
5764+ {0xB6, " O ", "SEND VOLUME TAG",
5765+ SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_1},
5766+ {0xB6, " M ", "SET STREAMING",
5767+ SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_2},
5768+ {0xB7, " O ", "READ DEFECT DATA(12)",
5769+ SCST_DATA_READ, SCST_WRITE_EXCL_ALLOWED,
5770+ 9, get_trans_len_1},
5771+ {0xB8, " O ", "READ ELEMENT STATUS",
5772+ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_3_read_elem_stat},
5773+ {0xB9, " O ", "READ CD MSF",
5774+ SCST_DATA_READ, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none},
5775+ {0xBA, " O ", "SCAN",
5776+ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
5777+ {0xBA, " O ", "REDUNDANCY GROUP(IN)",
5778+ SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_4},
5779+ {0xBB, " O ", "SET SPEED",
5780+ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
5781+ {0xBB, " O ", "REDUNDANCY GROUP(OUT)",
5782+ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4},
5783+ {0xBC, " O ", "SPARE(IN)",
5784+ SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_4},
5785+ {0xBD, " O ", "MECHANISM STATUS",
5786+ SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_2},
5787+ {0xBD, " O ", "SPARE(OUT)",
5788+ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4},
5789+ {0xBE, " O ", "READ CD",
5790+ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 6, get_trans_len_3},
5791+ {0xBE, " O ", "VOLUME SET(IN)",
5792+ SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_4},
5793+ {0xBF, " O ", "SEND DVD STRUCTUE",
5794+ SCST_DATA_WRITE, FLAG_NONE, 8, get_trans_len_2},
5795+ {0xBF, " O ", "VOLUME SET(OUT)",
5796+ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4},
5797+ {0xE7, " V ", "INIT ELEMENT STATUS WRANGE",
5798+ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_cdb_len_10}
5799+};
5800+
5801+#define SCST_CDB_TBL_SIZE ((int)ARRAY_SIZE(scst_scsi_op_table))
5802+
5803+static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev);
5804+static void scst_check_internal_sense(struct scst_device *dev, int result,
5805+ uint8_t *sense, int sense_len);
5806+static void scst_queue_report_luns_changed_UA(struct scst_session *sess,
5807+ int flags);
5808+static void __scst_check_set_UA(struct scst_tgt_dev *tgt_dev,
5809+ const uint8_t *sense, int sense_len, int flags);
5810+static void scst_alloc_set_UA(struct scst_tgt_dev *tgt_dev,
5811+ const uint8_t *sense, int sense_len, int flags);
5812+static void scst_free_all_UA(struct scst_tgt_dev *tgt_dev);
5813+static void scst_release_space(struct scst_cmd *cmd);
5814+static void scst_unblock_cmds(struct scst_device *dev);
5815+static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev);
5816+static int scst_alloc_add_tgt_dev(struct scst_session *sess,
5817+ struct scst_acg_dev *acg_dev, struct scst_tgt_dev **out_tgt_dev);
5818+static void scst_tgt_retry_timer_fn(unsigned long arg);
5819+
5820+#ifdef CONFIG_SCST_DEBUG_TM
5821+static void tm_dbg_init_tgt_dev(struct scst_tgt_dev *tgt_dev);
5822+static void tm_dbg_deinit_tgt_dev(struct scst_tgt_dev *tgt_dev);
5823+#else
5824+static inline void tm_dbg_init_tgt_dev(struct scst_tgt_dev *tgt_dev) {}
5825+static inline void tm_dbg_deinit_tgt_dev(struct scst_tgt_dev *tgt_dev) {}
5826+#endif /* CONFIG_SCST_DEBUG_TM */
5827+
5828+/**
5829+ * scst_alloc_sense() - allocate sense buffer for command
5830+ *
5831+ * Allocates, if necessary, sense buffer for command. Returns 0 on success
5832+ * and error code othrwise. Parameter "atomic" should be non-0 if the
5833+ * function called in atomic context.
5834+ */
5835+int scst_alloc_sense(struct scst_cmd *cmd, int atomic)
5836+{
5837+ int res = 0;
5838+ gfp_t gfp_mask = atomic ? GFP_ATOMIC : (GFP_KERNEL|__GFP_NOFAIL);
5839+
5840+ TRACE_ENTRY();
5841+
5842+ if (cmd->sense != NULL)
5843+ goto memzero;
5844+
5845+ cmd->sense = mempool_alloc(scst_sense_mempool, gfp_mask);
5846+ if (cmd->sense == NULL) {
5847+ PRINT_CRIT_ERROR("Sense memory allocation failed (op %x). "
5848+ "The sense data will be lost!!", cmd->cdb[0]);
5849+ res = -ENOMEM;
5850+ goto out;
5851+ }
5852+
5853+ cmd->sense_buflen = SCST_SENSE_BUFFERSIZE;
5854+
5855+memzero:
5856+ cmd->sense_valid_len = 0;
5857+ memset(cmd->sense, 0, cmd->sense_buflen);
5858+
5859+out:
5860+ TRACE_EXIT_RES(res);
5861+ return res;
5862+}
5863+EXPORT_SYMBOL(scst_alloc_sense);
5864+
5865+/**
5866+ * scst_alloc_set_sense() - allocate and fill sense buffer for command
5867+ *
5868+ * Allocates, if necessary, sense buffer for command and copies in
5869+ * it data from the supplied sense buffer. Returns 0 on success
5870+ * and error code othrwise.
5871+ */
5872+int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic,
5873+ const uint8_t *sense, unsigned int len)
5874+{
5875+ int res;
5876+
5877+ TRACE_ENTRY();
5878+
5879+ /*
5880+ * We don't check here if the existing sense is valid or not, because
5881+ * we suppose the caller did it based on cmd->status.
5882+ */
5883+
5884+ res = scst_alloc_sense(cmd, atomic);
5885+ if (res != 0) {
5886+ PRINT_BUFFER("Lost sense", sense, len);
5887+ goto out;
5888+ }
5889+
5890+ cmd->sense_valid_len = len;
5891+ if (cmd->sense_buflen < len) {
5892+ PRINT_WARNING("Sense truncated (needed %d), shall you increase "
5893+ "SCST_SENSE_BUFFERSIZE? Op: %x", len, cmd->cdb[0]);
5894+ cmd->sense_valid_len = cmd->sense_buflen;
5895+ }
5896+
5897+ memcpy(cmd->sense, sense, cmd->sense_valid_len);
5898+ TRACE_BUFFER("Sense set", cmd->sense, cmd->sense_valid_len);
5899+
5900+out:
5901+ TRACE_EXIT_RES(res);
5902+ return res;
5903+}
5904+EXPORT_SYMBOL(scst_alloc_set_sense);
5905+
5906+/**
5907+ * scst_set_cmd_error_status() - set error SCSI status
5908+ * @cmd: SCST command
5909+ * @status: SCSI status to set
5910+ *
5911+ * Description:
5912+ * Sets error SCSI status in the command and prepares it for returning it.
5913+ * Returns 0 on success, error code otherwise.
5914+ */
5915+int scst_set_cmd_error_status(struct scst_cmd *cmd, int status)
5916+{
5917+ int res = 0;
5918+
5919+ TRACE_ENTRY();
5920+
5921+ if (cmd->status != 0) {
5922+ TRACE_MGMT_DBG("cmd %p already has status %x set", cmd,
5923+ cmd->status);
5924+ res = -EEXIST;
5925+ goto out;
5926+ }
5927+
5928+ cmd->status = status;
5929+ cmd->host_status = DID_OK;
5930+
5931+ cmd->dbl_ua_orig_resp_data_len = cmd->resp_data_len;
5932+ cmd->dbl_ua_orig_data_direction = cmd->data_direction;
5933+
5934+ cmd->data_direction = SCST_DATA_NONE;
5935+ cmd->resp_data_len = 0;
5936+ cmd->resid_possible = 1;
5937+ cmd->is_send_status = 1;
5938+
5939+ cmd->completed = 1;
5940+
5941+out:
5942+ TRACE_EXIT_RES(res);
5943+ return res;
5944+}
5945+EXPORT_SYMBOL(scst_set_cmd_error_status);
5946+
5947+static int scst_set_lun_not_supported_request_sense(struct scst_cmd *cmd,
5948+ int key, int asc, int ascq)
5949+{
5950+ int res;
5951+ int sense_len, len;
5952+ struct scatterlist *sg;
5953+
5954+ TRACE_ENTRY();
5955+
5956+ if (cmd->status != 0) {
5957+ TRACE_MGMT_DBG("cmd %p already has status %x set", cmd,
5958+ cmd->status);
5959+ res = -EEXIST;
5960+ goto out;
5961+ }
5962+
5963+ if ((cmd->sg != NULL) && SCST_SENSE_VALID(sg_virt(cmd->sg))) {
5964+ TRACE_MGMT_DBG("cmd %p already has sense set", cmd);
5965+ res = -EEXIST;
5966+ goto out;
5967+ }
5968+
5969+ if (cmd->sg == NULL) {
5970+ /*
5971+ * If target driver preparing data buffer using alloc_data_buf()
5972+ * callback, it is responsible to copy the sense to its buffer
5973+ * in xmit_response().
5974+ */
5975+ if (cmd->tgt_data_buf_alloced && (cmd->tgt_sg != NULL)) {
5976+ cmd->sg = cmd->tgt_sg;
5977+ cmd->sg_cnt = cmd->tgt_sg_cnt;
5978+ TRACE_MEM("Tgt sg used for sense for cmd %p", cmd);
5979+ goto go;
5980+ }
5981+
5982+ if (cmd->bufflen == 0)
5983+ cmd->bufflen = cmd->cdb[4];
5984+
5985+ cmd->sg = scst_alloc(cmd->bufflen, GFP_ATOMIC, &cmd->sg_cnt);
5986+ if (cmd->sg == NULL) {
5987+ PRINT_ERROR("Unable to alloc sg for REQUEST SENSE"
5988+ "(sense %x/%x/%x)", key, asc, ascq);
5989+ res = 1;
5990+ goto out;
5991+ }
5992+
5993+ TRACE_MEM("sg %p alloced for sense for cmd %p (cnt %d, "
5994+ "len %d)", cmd->sg, cmd, cmd->sg_cnt, cmd->bufflen);
5995+ }
5996+
5997+go:
5998+ sg = cmd->sg;
5999+ len = sg->length;
6000+
6001+ TRACE_MEM("sg %p (len %d) for sense for cmd %p", sg, len, cmd);
6002+
6003+ sense_len = scst_set_sense(sg_virt(sg), len, cmd->cdb[1] & 1,
6004+ key, asc, ascq);
6005+
6006+ TRACE_BUFFER("Sense set", sg_virt(sg), sense_len);
6007+
6008+ cmd->data_direction = SCST_DATA_READ;
6009+ scst_set_resp_data_len(cmd, sense_len);
6010+
6011+ res = 0;
6012+ cmd->completed = 1;
6013+ cmd->resid_possible = 1;
6014+
6015+out:
6016+ TRACE_EXIT_RES(res);
6017+ return res;
6018+}
6019+
6020+static int scst_set_lun_not_supported_inquiry(struct scst_cmd *cmd)
6021+{
6022+ int res;
6023+ uint8_t *buf;
6024+ struct scatterlist *sg;
6025+ int len;
6026+
6027+ TRACE_ENTRY();
6028+
6029+ if (cmd->status != 0) {
6030+ TRACE_MGMT_DBG("cmd %p already has status %x set", cmd,
6031+ cmd->status);
6032+ res = -EEXIST;
6033+ goto out;
6034+ }
6035+
6036+ if (cmd->sg == NULL) {
6037+ /*
6038+ * If target driver preparing data buffer using alloc_data_buf()
6039+ * callback, it is responsible to copy the sense to its buffer
6040+ * in xmit_response().
6041+ */
6042+ if (cmd->tgt_data_buf_alloced && (cmd->tgt_sg != NULL)) {
6043+ cmd->sg = cmd->tgt_sg;
6044+ cmd->sg_cnt = cmd->tgt_sg_cnt;
6045+ TRACE_MEM("Tgt used for INQUIRY for not supported "
6046+ "LUN for cmd %p", cmd);
6047+ goto go;
6048+ }
6049+
6050+ if (cmd->bufflen == 0)
6051+ cmd->bufflen = min_t(int, 36, (cmd->cdb[3] << 8) | cmd->cdb[4]);
6052+
6053+ cmd->sg = scst_alloc(cmd->bufflen, GFP_ATOMIC, &cmd->sg_cnt);
6054+ if (cmd->sg == NULL) {
6055+ PRINT_ERROR("%s", "Unable to alloc sg for INQUIRY "
6056+ "for not supported LUN");
6057+ res = 1;
6058+ goto out;
6059+ }
6060+
6061+ TRACE_MEM("sg %p alloced for INQUIRY for not supported LUN for "
6062+ "cmd %p (cnt %d, len %d)", cmd->sg, cmd, cmd->sg_cnt,
6063+ cmd->bufflen);
6064+ }
6065+
6066+go:
6067+ sg = cmd->sg;
6068+ len = sg->length;
6069+
6070+ TRACE_MEM("sg %p (len %d) for INQUIRY for cmd %p", sg, len, cmd);
6071+
6072+ buf = sg_virt(sg);
6073+ len = min_t(int, 36, len);
6074+
6075+ memset(buf, 0, len);
6076+ buf[0] = 0x7F; /* Peripheral qualifier 011b, Peripheral device type 1Fh */
6077+ buf[4] = len - 4;
6078+
6079+ TRACE_BUFFER("INQUIRY for not supported LUN set", buf, len);
6080+
6081+ cmd->data_direction = SCST_DATA_READ;
6082+ scst_set_resp_data_len(cmd, len);
6083+
6084+ res = 0;
6085+ cmd->completed = 1;
6086+ cmd->resid_possible = 1;
6087+
6088+out:
6089+ TRACE_EXIT_RES(res);
6090+ return res;
6091+}
6092+
6093+/**
6094+ * scst_set_cmd_error() - set error in the command and fill the sense buffer.
6095+ *
6096+ * Sets error in the command and fill the sense buffer. Returns 0 on success,
6097+ * error code otherwise.
6098+ */
6099+int scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq)
6100+{
6101+ int res;
6102+
6103+ TRACE_ENTRY();
6104+
6105+ /*
6106+ * We need for LOGICAL UNIT NOT SUPPORTED special handling for
6107+ * REQUEST SENSE and INQUIRY.
6108+ */
6109+ if ((key == ILLEGAL_REQUEST) && (asc == 0x25) && (ascq == 0)) {
6110+ if (cmd->cdb[0] == REQUEST_SENSE)
6111+ res = scst_set_lun_not_supported_request_sense(cmd,
6112+ key, asc, ascq);
6113+ else if (cmd->cdb[0] == INQUIRY)
6114+ res = scst_set_lun_not_supported_inquiry(cmd);
6115+ else
6116+ goto do_sense;
6117+
6118+ if (res > 0)
6119+ goto do_sense;
6120+ else
6121+ goto out;
6122+ }
6123+
6124+do_sense:
6125+ res = scst_set_cmd_error_status(cmd, SAM_STAT_CHECK_CONDITION);
6126+ if (res != 0)
6127+ goto out;
6128+
6129+ res = scst_alloc_sense(cmd, 1);
6130+ if (res != 0) {
6131+ PRINT_ERROR("Lost sense data (key %x, asc %x, ascq %x)",
6132+ key, asc, ascq);
6133+ goto out;
6134+ }
6135+
6136+ cmd->sense_valid_len = scst_set_sense(cmd->sense, cmd->sense_buflen,
6137+ scst_get_cmd_dev_d_sense(cmd), key, asc, ascq);
6138+ TRACE_BUFFER("Sense set", cmd->sense, cmd->sense_valid_len);
6139+
6140+out:
6141+ TRACE_EXIT_RES(res);
6142+ return res;
6143+}
6144+EXPORT_SYMBOL(scst_set_cmd_error);
6145+
6146+/**
6147+ * scst_set_sense() - set sense from KEY/ASC/ASCQ numbers
6148+ *
6149+ * Sets the corresponding fields in the sense buffer taking sense type
6150+ * into account. Returns resulting sense length.
6151+ */
6152+int scst_set_sense(uint8_t *buffer, int len, bool d_sense,
6153+ int key, int asc, int ascq)
6154+{
6155+ int res;
6156+
6157+ BUG_ON(len == 0);
6158+
6159+ memset(buffer, 0, len);
6160+
6161+ if (d_sense) {
6162+ /* Descriptor format */
6163+ if (len < 8) {
6164+ PRINT_ERROR("Length %d of sense buffer too small to "
6165+ "fit sense %x:%x:%x", len, key, asc, ascq);
6166+ }
6167+
6168+ buffer[0] = 0x72; /* Response Code */
6169+ if (len > 1)
6170+ buffer[1] = key; /* Sense Key */
6171+ if (len > 2)
6172+ buffer[2] = asc; /* ASC */
6173+ if (len > 3)
6174+ buffer[3] = ascq; /* ASCQ */
6175+ res = 8;
6176+ } else {
6177+ /* Fixed format */
6178+ if (len < 18) {
6179+ PRINT_ERROR("Length %d of sense buffer too small to "
6180+ "fit sense %x:%x:%x", len, key, asc, ascq);
6181+ }
6182+
6183+ buffer[0] = 0x70; /* Response Code */
6184+ if (len > 2)
6185+ buffer[2] = key; /* Sense Key */
6186+ if (len > 7)
6187+ buffer[7] = 0x0a; /* Additional Sense Length */
6188+ if (len > 12)
6189+ buffer[12] = asc; /* ASC */
6190+ if (len > 13)
6191+ buffer[13] = ascq; /* ASCQ */
6192+ res = 18;
6193+ }
6194+
6195+ TRACE_BUFFER("Sense set", buffer, res);
6196+ return res;
6197+}
6198+EXPORT_SYMBOL(scst_set_sense);
6199+
6200+/**
6201+ * scst_analyze_sense() - analyze sense
6202+ *
6203+ * Returns true if sense matches to (key, asc, ascq) and false otherwise.
6204+ * Valid_mask is one or several SCST_SENSE_*_VALID constants setting valid
6205+ * (key, asc, ascq) values.
6206+ */
6207+bool scst_analyze_sense(const uint8_t *sense, int len, unsigned int valid_mask,
6208+ int key, int asc, int ascq)
6209+{
6210+ bool res = false;
6211+
6212+ /* Response Code */
6213+ if ((sense[0] == 0x70) || (sense[0] == 0x71)) {
6214+ /* Fixed format */
6215+
6216+ /* Sense Key */
6217+ if (valid_mask & SCST_SENSE_KEY_VALID) {
6218+ if (len < 3)
6219+ goto out;
6220+ if (sense[2] != key)
6221+ goto out;
6222+ }
6223+
6224+ /* ASC */
6225+ if (valid_mask & SCST_SENSE_ASC_VALID) {
6226+ if (len < 13)
6227+ goto out;
6228+ if (sense[12] != asc)
6229+ goto out;
6230+ }
6231+
6232+ /* ASCQ */
6233+ if (valid_mask & SCST_SENSE_ASCQ_VALID) {
6234+ if (len < 14)
6235+ goto out;
6236+ if (sense[13] != ascq)
6237+ goto out;
6238+ }
6239+ } else if ((sense[0] == 0x72) || (sense[0] == 0x73)) {
6240+ /* Descriptor format */
6241+
6242+ /* Sense Key */
6243+ if (valid_mask & SCST_SENSE_KEY_VALID) {
6244+ if (len < 2)
6245+ goto out;
6246+ if (sense[1] != key)
6247+ goto out;
6248+ }
6249+
6250+ /* ASC */
6251+ if (valid_mask & SCST_SENSE_ASC_VALID) {
6252+ if (len < 3)
6253+ goto out;
6254+ if (sense[2] != asc)
6255+ goto out;
6256+ }
6257+
6258+ /* ASCQ */
6259+ if (valid_mask & SCST_SENSE_ASCQ_VALID) {
6260+ if (len < 4)
6261+ goto out;
6262+ if (sense[3] != ascq)
6263+ goto out;
6264+ }
6265+ } else
6266+ goto out;
6267+
6268+ res = true;
6269+
6270+out:
6271+ TRACE_EXIT_RES((int)res);
6272+ return res;
6273+}
6274+EXPORT_SYMBOL(scst_analyze_sense);
6275+
6276+/**
6277+ * scst_is_ua_sense() - determine if the sense is UA sense
6278+ *
6279+ * Returns true if the sense is valid and carrying a Unit
6280+ * Attention or false otherwise.
6281+ */
6282+bool scst_is_ua_sense(const uint8_t *sense, int len)
6283+{
6284+ if (SCST_SENSE_VALID(sense))
6285+ return scst_analyze_sense(sense, len,
6286+ SCST_SENSE_KEY_VALID, UNIT_ATTENTION, 0, 0);
6287+ else
6288+ return false;
6289+}
6290+EXPORT_SYMBOL(scst_is_ua_sense);
6291+
6292+bool scst_is_ua_global(const uint8_t *sense, int len)
6293+{
6294+ bool res;
6295+
6296+ /* Changing it don't forget to change scst_requeue_ua() as well!! */
6297+
6298+ if (scst_analyze_sense(sense, len, SCST_SENSE_ALL_VALID,
6299+ SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed)))
6300+ res = true;
6301+ else
6302+ res = false;
6303+
6304+ return res;
6305+}
6306+
6307+/**
6308+ * scst_check_convert_sense() - check sense type and convert it if needed
6309+ *
6310+ * Checks if sense in the sense buffer, if any, is in the correct format.
6311+ * If not, converts it in the correct format.
6312+ */
6313+void scst_check_convert_sense(struct scst_cmd *cmd)
6314+{
6315+ bool d_sense;
6316+
6317+ TRACE_ENTRY();
6318+
6319+ if ((cmd->sense == NULL) || (cmd->status != SAM_STAT_CHECK_CONDITION))
6320+ goto out;
6321+
6322+ d_sense = scst_get_cmd_dev_d_sense(cmd);
6323+ if (d_sense && ((cmd->sense[0] == 0x70) || (cmd->sense[0] == 0x71))) {
6324+ TRACE_MGMT_DBG("Converting fixed sense to descriptor (cmd %p)",
6325+ cmd);
6326+ if ((cmd->sense_valid_len < 18)) {
6327+ PRINT_ERROR("Sense too small to convert (%d, "
6328+ "type: fixed)", cmd->sense_buflen);
6329+ goto out;
6330+ }
6331+ cmd->sense_valid_len = scst_set_sense(cmd->sense, cmd->sense_buflen,
6332+ d_sense, cmd->sense[2], cmd->sense[12], cmd->sense[13]);
6333+ } else if (!d_sense && ((cmd->sense[0] == 0x72) ||
6334+ (cmd->sense[0] == 0x73))) {
6335+ TRACE_MGMT_DBG("Converting descriptor sense to fixed (cmd %p)",
6336+ cmd);
6337+ if ((cmd->sense_buflen < 18) || (cmd->sense_valid_len < 8)) {
6338+ PRINT_ERROR("Sense too small to convert (%d, "
6339+ "type: descryptor, valid %d)",
6340+ cmd->sense_buflen, cmd->sense_valid_len);
6341+ goto out;
6342+ }
6343+ cmd->sense_valid_len = scst_set_sense(cmd->sense,
6344+ cmd->sense_buflen, d_sense,
6345+ cmd->sense[1], cmd->sense[2], cmd->sense[3]);
6346+ }
6347+
6348+out:
6349+ TRACE_EXIT();
6350+ return;
6351+}
6352+EXPORT_SYMBOL(scst_check_convert_sense);
6353+
6354+static int scst_set_cmd_error_sense(struct scst_cmd *cmd, uint8_t *sense,
6355+ unsigned int len)
6356+{
6357+ int res;
6358+
6359+ TRACE_ENTRY();
6360+
6361+ res = scst_set_cmd_error_status(cmd, SAM_STAT_CHECK_CONDITION);
6362+ if (res != 0)
6363+ goto out;
6364+
6365+ res = scst_alloc_set_sense(cmd, 1, sense, len);
6366+
6367+out:
6368+ TRACE_EXIT_RES(res);
6369+ return res;
6370+}
6371+
6372+/**
6373+ * scst_set_busy() - set BUSY or TASK QUEUE FULL status
6374+ *
6375+ * Sets BUSY or TASK QUEUE FULL status depending on if this session has other
6376+ * outstanding commands or not.
6377+ */
6378+void scst_set_busy(struct scst_cmd *cmd)
6379+{
6380+ int c = atomic_read(&cmd->sess->sess_cmd_count);
6381+
6382+ TRACE_ENTRY();
6383+
6384+ if ((c <= 1) || (cmd->sess->init_phase != SCST_SESS_IPH_READY)) {
6385+ scst_set_cmd_error_status(cmd, SAM_STAT_BUSY);
6386+ TRACE(TRACE_FLOW_CONTROL, "Sending BUSY status to initiator %s "
6387+ "(cmds count %d, queue_type %x, sess->init_phase %d)",
6388+ cmd->sess->initiator_name, c,
6389+ cmd->queue_type, cmd->sess->init_phase);
6390+ } else {
6391+ scst_set_cmd_error_status(cmd, SAM_STAT_TASK_SET_FULL);
6392+ TRACE(TRACE_FLOW_CONTROL, "Sending QUEUE_FULL status to "
6393+ "initiator %s (cmds count %d, queue_type %x, "
6394+ "sess->init_phase %d)", cmd->sess->initiator_name, c,
6395+ cmd->queue_type, cmd->sess->init_phase);
6396+ }
6397+
6398+ TRACE_EXIT();
6399+ return;
6400+}
6401+EXPORT_SYMBOL(scst_set_busy);
6402+
6403+/**
6404+ * scst_set_initial_UA() - set initial Unit Attention
6405+ *
6406+ * Sets initial Unit Attention on all devices of the session,
6407+ * replacing default scst_sense_reset_UA
6408+ */
6409+void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq)
6410+{
6411+ int i;
6412+
6413+ TRACE_ENTRY();
6414+
6415+ TRACE_MGMT_DBG("Setting for sess %p initial UA %x/%x/%x", sess, key,
6416+ asc, ascq);
6417+
6418+ /* Protect sess_tgt_dev_list_hash */
6419+ mutex_lock(&scst_mutex);
6420+
6421+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
6422+ struct list_head *sess_tgt_dev_list_head =
6423+ &sess->sess_tgt_dev_list_hash[i];
6424+ struct scst_tgt_dev *tgt_dev;
6425+
6426+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
6427+ sess_tgt_dev_list_entry) {
6428+ spin_lock_bh(&tgt_dev->tgt_dev_lock);
6429+ if (!list_empty(&tgt_dev->UA_list)) {
6430+ struct scst_tgt_dev_UA *ua;
6431+
6432+ ua = list_entry(tgt_dev->UA_list.next,
6433+ typeof(*ua), UA_list_entry);
6434+ if (scst_analyze_sense(ua->UA_sense_buffer,
6435+ ua->UA_valid_sense_len,
6436+ SCST_SENSE_ALL_VALID,
6437+ SCST_LOAD_SENSE(scst_sense_reset_UA))) {
6438+ ua->UA_valid_sense_len = scst_set_sense(
6439+ ua->UA_sense_buffer,
6440+ sizeof(ua->UA_sense_buffer),
6441+ tgt_dev->dev->d_sense,
6442+ key, asc, ascq);
6443+ } else
6444+ PRINT_ERROR("%s",
6445+ "The first UA isn't RESET UA");
6446+ } else
6447+ PRINT_ERROR("%s", "There's no RESET UA to "
6448+ "replace");
6449+ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
6450+ }
6451+ }
6452+
6453+ mutex_unlock(&scst_mutex);
6454+
6455+ TRACE_EXIT();
6456+ return;
6457+}
6458+EXPORT_SYMBOL(scst_set_initial_UA);
6459+
6460+static struct scst_aen *scst_alloc_aen(struct scst_session *sess,
6461+ uint64_t unpacked_lun)
6462+{
6463+ struct scst_aen *aen;
6464+
6465+ TRACE_ENTRY();
6466+
6467+ aen = mempool_alloc(scst_aen_mempool, GFP_KERNEL);
6468+ if (aen == NULL) {
6469+ PRINT_ERROR("AEN memory allocation failed. Corresponding "
6470+ "event notification will not be performed (initiator "
6471+ "%s)", sess->initiator_name);
6472+ goto out;
6473+ }
6474+ memset(aen, 0, sizeof(*aen));
6475+
6476+ aen->sess = sess;
6477+ scst_sess_get(sess);
6478+
6479+ aen->lun = scst_pack_lun(unpacked_lun, sess->acg->addr_method);
6480+
6481+out:
6482+ TRACE_EXIT_HRES((unsigned long)aen);
6483+ return aen;
6484+};
6485+
6486+static void scst_free_aen(struct scst_aen *aen)
6487+{
6488+ TRACE_ENTRY();
6489+
6490+ scst_sess_put(aen->sess);
6491+ mempool_free(aen, scst_aen_mempool);
6492+
6493+ TRACE_EXIT();
6494+ return;
6495+};
6496+
6497+/* Must be called under scst_mutex */
6498+void scst_gen_aen_or_ua(struct scst_tgt_dev *tgt_dev,
6499+ int key, int asc, int ascq)
6500+{
6501+ struct scst_tgt_template *tgtt = tgt_dev->sess->tgt->tgtt;
6502+ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
6503+ int sl;
6504+
6505+ TRACE_ENTRY();
6506+
6507+ if ((tgt_dev->sess->init_phase != SCST_SESS_IPH_READY) ||
6508+ (tgt_dev->sess->shut_phase != SCST_SESS_SPH_READY))
6509+ goto out;
6510+
6511+ if (tgtt->report_aen != NULL) {
6512+ struct scst_aen *aen;
6513+ int rc;
6514+
6515+ aen = scst_alloc_aen(tgt_dev->sess, tgt_dev->lun);
6516+ if (aen == NULL)
6517+ goto queue_ua;
6518+
6519+ aen->event_fn = SCST_AEN_SCSI;
6520+ aen->aen_sense_len = scst_set_sense(aen->aen_sense,
6521+ sizeof(aen->aen_sense), tgt_dev->dev->d_sense,
6522+ key, asc, ascq);
6523+
6524+ TRACE_DBG("Calling target's %s report_aen(%p)",
6525+ tgtt->name, aen);
6526+ rc = tgtt->report_aen(aen);
6527+ TRACE_DBG("Target's %s report_aen(%p) returned %d",
6528+ tgtt->name, aen, rc);
6529+ if (rc == SCST_AEN_RES_SUCCESS)
6530+ goto out;
6531+
6532+ scst_free_aen(aen);
6533+ }
6534+
6535+queue_ua:
6536+ TRACE_MGMT_DBG("AEN not supported, queuing plain UA (tgt_dev %p)",
6537+ tgt_dev);
6538+ sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
6539+ tgt_dev->dev->d_sense, key, asc, ascq);
6540+ scst_check_set_UA(tgt_dev, sense_buffer, sl, 0);
6541+
6542+out:
6543+ TRACE_EXIT();
6544+ return;
6545+}
6546+
6547+/**
6548+ * scst_capacity_data_changed() - notify SCST about device capacity change
6549+ *
6550+ * Notifies SCST core that dev has changed its capacity. Called under no locks.
6551+ */
6552+void scst_capacity_data_changed(struct scst_device *dev)
6553+{
6554+ struct scst_tgt_dev *tgt_dev;
6555+
6556+ TRACE_ENTRY();
6557+
6558+ if (dev->type != TYPE_DISK) {
6559+ TRACE_MGMT_DBG("Device type %d isn't for CAPACITY DATA "
6560+ "CHANGED UA", dev->type);
6561+ goto out;
6562+ }
6563+
6564+ TRACE_MGMT_DBG("CAPACITY DATA CHANGED (dev %p)", dev);
6565+
6566+ mutex_lock(&scst_mutex);
6567+
6568+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
6569+ dev_tgt_dev_list_entry) {
6570+ scst_gen_aen_or_ua(tgt_dev,
6571+ SCST_LOAD_SENSE(scst_sense_capacity_data_changed));
6572+ }
6573+
6574+ mutex_unlock(&scst_mutex);
6575+
6576+out:
6577+ TRACE_EXIT();
6578+ return;
6579+}
6580+EXPORT_SYMBOL_GPL(scst_capacity_data_changed);
6581+
6582+static inline bool scst_is_report_luns_changed_type(int type)
6583+{
6584+ switch (type) {
6585+ case TYPE_DISK:
6586+ case TYPE_TAPE:
6587+ case TYPE_PRINTER:
6588+ case TYPE_PROCESSOR:
6589+ case TYPE_WORM:
6590+ case TYPE_ROM:
6591+ case TYPE_SCANNER:
6592+ case TYPE_MOD:
6593+ case TYPE_MEDIUM_CHANGER:
6594+ case TYPE_RAID:
6595+ case TYPE_ENCLOSURE:
6596+ return true;
6597+ default:
6598+ return false;
6599+ }
6600+}
6601+
6602+/* scst_mutex supposed to be held */
6603+static void scst_queue_report_luns_changed_UA(struct scst_session *sess,
6604+ int flags)
6605+{
6606+ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
6607+ struct list_head *shead;
6608+ struct scst_tgt_dev *tgt_dev;
6609+ int i;
6610+
6611+ TRACE_ENTRY();
6612+
6613+ TRACE_MGMT_DBG("Queuing REPORTED LUNS DATA CHANGED UA "
6614+ "(sess %p)", sess);
6615+
6616+ local_bh_disable();
6617+
6618+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
6619+ shead = &sess->sess_tgt_dev_list_hash[i];
6620+
6621+ list_for_each_entry(tgt_dev, shead,
6622+ sess_tgt_dev_list_entry) {
6623+ /* Lockdep triggers here a false positive.. */
6624+ spin_lock(&tgt_dev->tgt_dev_lock);
6625+ }
6626+ }
6627+
6628+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
6629+ shead = &sess->sess_tgt_dev_list_hash[i];
6630+
6631+ list_for_each_entry(tgt_dev, shead,
6632+ sess_tgt_dev_list_entry) {
6633+ int sl;
6634+
6635+ if (!scst_is_report_luns_changed_type(
6636+ tgt_dev->dev->type))
6637+ continue;
6638+
6639+ sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
6640+ tgt_dev->dev->d_sense,
6641+ SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed));
6642+
6643+ __scst_check_set_UA(tgt_dev, sense_buffer,
6644+ sl, flags | SCST_SET_UA_FLAG_GLOBAL);
6645+ }
6646+ }
6647+
6648+ for (i = TGT_DEV_HASH_SIZE-1; i >= 0; i--) {
6649+ shead = &sess->sess_tgt_dev_list_hash[i];
6650+
6651+ list_for_each_entry_reverse(tgt_dev,
6652+ shead, sess_tgt_dev_list_entry) {
6653+ spin_unlock(&tgt_dev->tgt_dev_lock);
6654+ }
6655+ }
6656+
6657+ local_bh_enable();
6658+
6659+ TRACE_EXIT();
6660+ return;
6661+}
6662+
6663+/* The activity supposed to be suspended and scst_mutex held */
6664+static void scst_report_luns_changed_sess(struct scst_session *sess)
6665+{
6666+ int i;
6667+ struct scst_tgt_template *tgtt = sess->tgt->tgtt;
6668+ int d_sense = 0;
6669+ uint64_t lun = 0;
6670+
6671+ TRACE_ENTRY();
6672+
6673+ if ((sess->init_phase != SCST_SESS_IPH_READY) ||
6674+ (sess->shut_phase != SCST_SESS_SPH_READY))
6675+ goto out;
6676+
6677+ TRACE_DBG("REPORTED LUNS DATA CHANGED (sess %p)", sess);
6678+
6679+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
6680+ struct list_head *shead;
6681+ struct scst_tgt_dev *tgt_dev;
6682+
6683+ shead = &sess->sess_tgt_dev_list_hash[i];
6684+
6685+ list_for_each_entry(tgt_dev, shead,
6686+ sess_tgt_dev_list_entry) {
6687+ if (scst_is_report_luns_changed_type(
6688+ tgt_dev->dev->type)) {
6689+ lun = tgt_dev->lun;
6690+ d_sense = tgt_dev->dev->d_sense;
6691+ goto found;
6692+ }
6693+ }
6694+ }
6695+
6696+found:
6697+ if (tgtt->report_aen != NULL) {
6698+ struct scst_aen *aen;
6699+ int rc;
6700+
6701+ aen = scst_alloc_aen(sess, lun);
6702+ if (aen == NULL)
6703+ goto queue_ua;
6704+
6705+ aen->event_fn = SCST_AEN_SCSI;
6706+ aen->aen_sense_len = scst_set_sense(aen->aen_sense,
6707+ sizeof(aen->aen_sense), d_sense,
6708+ SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed));
6709+
6710+ TRACE_DBG("Calling target's %s report_aen(%p)",
6711+ tgtt->name, aen);
6712+ rc = tgtt->report_aen(aen);
6713+ TRACE_DBG("Target's %s report_aen(%p) returned %d",
6714+ tgtt->name, aen, rc);
6715+ if (rc == SCST_AEN_RES_SUCCESS)
6716+ goto out;
6717+
6718+ scst_free_aen(aen);
6719+ }
6720+
6721+queue_ua:
6722+ scst_queue_report_luns_changed_UA(sess, 0);
6723+
6724+out:
6725+ TRACE_EXIT();
6726+ return;
6727+}
6728+
6729+/* The activity supposed to be suspended and scst_mutex held */
6730+void scst_report_luns_changed(struct scst_acg *acg)
6731+{
6732+ struct scst_session *sess;
6733+
6734+ TRACE_ENTRY();
6735+
6736+ TRACE_MGMT_DBG("REPORTED LUNS DATA CHANGED (acg %s)", acg->acg_name);
6737+
6738+ list_for_each_entry(sess, &acg->acg_sess_list, acg_sess_list_entry) {
6739+ scst_report_luns_changed_sess(sess);
6740+ }
6741+
6742+ TRACE_EXIT();
6743+ return;
6744+}
6745+
6746+/**
6747+ * scst_aen_done() - AEN processing done
6748+ *
6749+ * Notifies SCST that the driver has sent the AEN and it
6750+ * can be freed now. Don't forget to set the delivery status, if it
6751+ * isn't success, using scst_set_aen_delivery_status() before calling
6752+ * this function.
6753+ */
6754+void scst_aen_done(struct scst_aen *aen)
6755+{
6756+ TRACE_ENTRY();
6757+
6758+ TRACE_MGMT_DBG("AEN %p (fn %d) done (initiator %s)", aen,
6759+ aen->event_fn, aen->sess->initiator_name);
6760+
6761+ if (aen->delivery_status == SCST_AEN_RES_SUCCESS)
6762+ goto out_free;
6763+
6764+ if (aen->event_fn != SCST_AEN_SCSI)
6765+ goto out_free;
6766+
6767+ TRACE_MGMT_DBG("Delivery of SCSI AEN failed (initiator %s)",
6768+ aen->sess->initiator_name);
6769+
6770+ if (scst_analyze_sense(aen->aen_sense, aen->aen_sense_len,
6771+ SCST_SENSE_ALL_VALID, SCST_LOAD_SENSE(
6772+ scst_sense_reported_luns_data_changed))) {
6773+ mutex_lock(&scst_mutex);
6774+ scst_queue_report_luns_changed_UA(aen->sess,
6775+ SCST_SET_UA_FLAG_AT_HEAD);
6776+ mutex_unlock(&scst_mutex);
6777+ } else {
6778+ struct list_head *shead;
6779+ struct scst_tgt_dev *tgt_dev;
6780+ uint64_t lun;
6781+
6782+ lun = scst_unpack_lun((uint8_t *)&aen->lun, sizeof(aen->lun));
6783+
6784+ mutex_lock(&scst_mutex);
6785+
6786+ /* tgt_dev might get dead, so we need to reseek it */
6787+ shead = &aen->sess->sess_tgt_dev_list_hash[HASH_VAL(lun)];
6788+ list_for_each_entry(tgt_dev, shead,
6789+ sess_tgt_dev_list_entry) {
6790+ if (tgt_dev->lun == lun) {
6791+ TRACE_MGMT_DBG("Requeuing failed AEN UA for "
6792+ "tgt_dev %p", tgt_dev);
6793+ scst_check_set_UA(tgt_dev, aen->aen_sense,
6794+ aen->aen_sense_len,
6795+ SCST_SET_UA_FLAG_AT_HEAD);
6796+ break;
6797+ }
6798+ }
6799+
6800+ mutex_unlock(&scst_mutex);
6801+ }
6802+
6803+out_free:
6804+ scst_free_aen(aen);
6805+
6806+ TRACE_EXIT();
6807+ return;
6808+}
6809+EXPORT_SYMBOL(scst_aen_done);
6810+
6811+void scst_requeue_ua(struct scst_cmd *cmd)
6812+{
6813+ TRACE_ENTRY();
6814+
6815+ if (scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
6816+ SCST_SENSE_ALL_VALID,
6817+ SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed))) {
6818+ TRACE_MGMT_DBG("Requeuing REPORTED LUNS DATA CHANGED UA "
6819+ "for delivery failed cmd %p", cmd);
6820+ mutex_lock(&scst_mutex);
6821+ scst_queue_report_luns_changed_UA(cmd->sess,
6822+ SCST_SET_UA_FLAG_AT_HEAD);
6823+ mutex_unlock(&scst_mutex);
6824+ } else {
6825+ TRACE_MGMT_DBG("Requeuing UA for delivery failed cmd %p", cmd);
6826+ scst_check_set_UA(cmd->tgt_dev, cmd->sense,
6827+ cmd->sense_valid_len, SCST_SET_UA_FLAG_AT_HEAD);
6828+ }
6829+
6830+ TRACE_EXIT();
6831+ return;
6832+}
6833+
6834+/* The activity supposed to be suspended and scst_mutex held */
6835+static void scst_check_reassign_sess(struct scst_session *sess)
6836+{
6837+ struct scst_acg *acg, *old_acg;
6838+ struct scst_acg_dev *acg_dev;
6839+ int i, rc;
6840+ struct list_head *shead;
6841+ struct scst_tgt_dev *tgt_dev;
6842+ bool luns_changed = false;
6843+ bool add_failed, something_freed, not_needed_freed = false;
6844+
6845+ TRACE_ENTRY();
6846+
6847+ if (sess->shut_phase != SCST_SESS_SPH_READY)
6848+ goto out;
6849+
6850+ TRACE_MGMT_DBG("Checking reassignment for sess %p (initiator %s)",
6851+ sess, sess->initiator_name);
6852+
6853+ acg = scst_find_acg(sess);
6854+ if (acg == sess->acg) {
6855+ TRACE_MGMT_DBG("No reassignment for sess %p", sess);
6856+ goto out;
6857+ }
6858+
6859+ TRACE_MGMT_DBG("sess %p will be reassigned from acg %s to acg %s",
6860+ sess, sess->acg->acg_name, acg->acg_name);
6861+
6862+ old_acg = sess->acg;
6863+ sess->acg = NULL; /* to catch implicit dependencies earlier */
6864+
6865+retry_add:
6866+ add_failed = false;
6867+ list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
6868+ unsigned int inq_changed_ua_needed = 0;
6869+
6870+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
6871+ shead = &sess->sess_tgt_dev_list_hash[i];
6872+
6873+ list_for_each_entry(tgt_dev, shead,
6874+ sess_tgt_dev_list_entry) {
6875+ if ((tgt_dev->dev == acg_dev->dev) &&
6876+ (tgt_dev->lun == acg_dev->lun) &&
6877+ (tgt_dev->acg_dev->rd_only == acg_dev->rd_only)) {
6878+ TRACE_MGMT_DBG("sess %p: tgt_dev %p for "
6879+ "LUN %lld stays the same",
6880+ sess, tgt_dev,
6881+ (unsigned long long)tgt_dev->lun);
6882+ tgt_dev->acg_dev = acg_dev;
6883+ goto next;
6884+ } else if (tgt_dev->lun == acg_dev->lun)
6885+ inq_changed_ua_needed = 1;
6886+ }
6887+ }
6888+
6889+ luns_changed = true;
6890+
6891+ TRACE_MGMT_DBG("sess %p: Allocing new tgt_dev for LUN %lld",
6892+ sess, (unsigned long long)acg_dev->lun);
6893+
6894+ rc = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev);
6895+ if (rc == -EPERM)
6896+ continue;
6897+ else if (rc != 0) {
6898+ add_failed = true;
6899+ break;
6900+ }
6901+
6902+ tgt_dev->inq_changed_ua_needed = inq_changed_ua_needed ||
6903+ not_needed_freed;
6904+next:
6905+ continue;
6906+ }
6907+
6908+ something_freed = false;
6909+ not_needed_freed = true;
6910+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
6911+ struct scst_tgt_dev *t;
6912+ shead = &sess->sess_tgt_dev_list_hash[i];
6913+
6914+ list_for_each_entry_safe(tgt_dev, t, shead,
6915+ sess_tgt_dev_list_entry) {
6916+ if (tgt_dev->acg_dev->acg != acg) {
6917+ TRACE_MGMT_DBG("sess %p: Deleting not used "
6918+ "tgt_dev %p for LUN %lld",
6919+ sess, tgt_dev,
6920+ (unsigned long long)tgt_dev->lun);
6921+ luns_changed = true;
6922+ something_freed = true;
6923+ scst_free_tgt_dev(tgt_dev);
6924+ }
6925+ }
6926+ }
6927+
6928+ if (add_failed && something_freed) {
6929+ TRACE_MGMT_DBG("sess %p: Retrying adding new tgt_devs", sess);
6930+ goto retry_add;
6931+ }
6932+
6933+ sess->acg = acg;
6934+
6935+ TRACE_DBG("Moving sess %p from acg %s to acg %s", sess,
6936+ old_acg->acg_name, acg->acg_name);
6937+ list_move_tail(&sess->acg_sess_list_entry, &acg->acg_sess_list);
6938+
6939+ scst_recreate_sess_luns_link(sess);
6940+ /* Ignore possible error, since we can't do anything on it */
6941+
6942+ if (luns_changed) {
6943+ scst_report_luns_changed_sess(sess);
6944+
6945+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
6946+ shead = &sess->sess_tgt_dev_list_hash[i];
6947+
6948+ list_for_each_entry(tgt_dev, shead,
6949+ sess_tgt_dev_list_entry) {
6950+ if (tgt_dev->inq_changed_ua_needed) {
6951+ TRACE_MGMT_DBG("sess %p: Setting "
6952+ "INQUIRY DATA HAS CHANGED UA "
6953+ "(tgt_dev %p)", sess, tgt_dev);
6954+
6955+ tgt_dev->inq_changed_ua_needed = 0;
6956+
6957+ scst_gen_aen_or_ua(tgt_dev,
6958+ SCST_LOAD_SENSE(scst_sense_inquery_data_changed));
6959+ }
6960+ }
6961+ }
6962+ }
6963+
6964+out:
6965+ TRACE_EXIT();
6966+ return;
6967+}
6968+
6969+/* The activity supposed to be suspended and scst_mutex held */
6970+void scst_check_reassign_sessions(void)
6971+{
6972+ struct scst_tgt_template *tgtt;
6973+
6974+ TRACE_ENTRY();
6975+
6976+ list_for_each_entry(tgtt, &scst_template_list, scst_template_list_entry) {
6977+ struct scst_tgt *tgt;
6978+ list_for_each_entry(tgt, &tgtt->tgt_list, tgt_list_entry) {
6979+ struct scst_session *sess;
6980+ list_for_each_entry(sess, &tgt->sess_list,
6981+ sess_list_entry) {
6982+ scst_check_reassign_sess(sess);
6983+ }
6984+ }
6985+ }
6986+
6987+ TRACE_EXIT();
6988+ return;
6989+}
6990+
6991+static int scst_get_cmd_abnormal_done_state(const struct scst_cmd *cmd)
6992+{
6993+ int res;
6994+
6995+ TRACE_ENTRY();
6996+
6997+ switch (cmd->state) {
6998+ case SCST_CMD_STATE_INIT_WAIT:
6999+ case SCST_CMD_STATE_INIT:
7000+ case SCST_CMD_STATE_PARSE:
7001+ if (cmd->preprocessing_only) {
7002+ res = SCST_CMD_STATE_PREPROCESSING_DONE;
7003+ break;
7004+ } /* else go through */
7005+ case SCST_CMD_STATE_DEV_DONE:
7006+ if (cmd->internal)
7007+ res = SCST_CMD_STATE_FINISHED_INTERNAL;
7008+ else
7009+ res = SCST_CMD_STATE_PRE_XMIT_RESP;
7010+ break;
7011+
7012+ case SCST_CMD_STATE_PRE_DEV_DONE:
7013+ case SCST_CMD_STATE_MODE_SELECT_CHECKS:
7014+ res = SCST_CMD_STATE_DEV_DONE;
7015+ break;
7016+
7017+ case SCST_CMD_STATE_PRE_XMIT_RESP:
7018+ res = SCST_CMD_STATE_XMIT_RESP;
7019+ break;
7020+
7021+ case SCST_CMD_STATE_PREPROCESSING_DONE:
7022+ case SCST_CMD_STATE_PREPROCESSING_DONE_CALLED:
7023+ if (cmd->tgt_dev == NULL)
7024+ res = SCST_CMD_STATE_PRE_XMIT_RESP;
7025+ else
7026+ res = SCST_CMD_STATE_PRE_DEV_DONE;
7027+ break;
7028+
7029+ case SCST_CMD_STATE_PREPARE_SPACE:
7030+ if (cmd->preprocessing_only) {
7031+ res = SCST_CMD_STATE_PREPROCESSING_DONE;
7032+ break;
7033+ } /* else go through */
7034+ case SCST_CMD_STATE_RDY_TO_XFER:
7035+ case SCST_CMD_STATE_DATA_WAIT:
7036+ case SCST_CMD_STATE_TGT_PRE_EXEC:
7037+ case SCST_CMD_STATE_SEND_FOR_EXEC:
7038+ case SCST_CMD_STATE_LOCAL_EXEC:
7039+ case SCST_CMD_STATE_REAL_EXEC:
7040+ case SCST_CMD_STATE_REAL_EXECUTING:
7041+ res = SCST_CMD_STATE_PRE_DEV_DONE;
7042+ break;
7043+
7044+ default:
7045+ PRINT_CRIT_ERROR("Wrong cmd state %d (cmd %p, op %x)",
7046+ cmd->state, cmd, cmd->cdb[0]);
7047+ BUG();
7048+ /* Invalid state to supress compiler's warning */
7049+ res = SCST_CMD_STATE_LAST_ACTIVE;
7050+ }
7051+
7052+ TRACE_EXIT_RES(res);
7053+ return res;
7054+}
7055+
7056+/**
7057+ * scst_set_cmd_abnormal_done_state() - set command's next abnormal done state
7058+ *
7059+ * Sets state of the SCSI target state machine to abnormally complete command
7060+ * ASAP.
7061+ *
7062+ * Returns the new state.
7063+ */
7064+int scst_set_cmd_abnormal_done_state(struct scst_cmd *cmd)
7065+{
7066+ TRACE_ENTRY();
7067+
7068+#ifdef CONFIG_SCST_EXTRACHECKS
7069+ switch (cmd->state) {
7070+ case SCST_CMD_STATE_XMIT_RESP:
7071+ case SCST_CMD_STATE_FINISHED:
7072+ case SCST_CMD_STATE_FINISHED_INTERNAL:
7073+ case SCST_CMD_STATE_XMIT_WAIT:
7074+ PRINT_CRIT_ERROR("Wrong cmd state %d (cmd %p, op %x)",
7075+ cmd->state, cmd, cmd->cdb[0]);
7076+ BUG();
7077+ }
7078+#endif
7079+
7080+ cmd->state = scst_get_cmd_abnormal_done_state(cmd);
7081+
7082+ switch (cmd->state) {
7083+ case SCST_CMD_STATE_INIT_WAIT:
7084+ case SCST_CMD_STATE_INIT:
7085+ case SCST_CMD_STATE_PARSE:
7086+ case SCST_CMD_STATE_PREPROCESSING_DONE:
7087+ case SCST_CMD_STATE_PREPROCESSING_DONE_CALLED:
7088+ case SCST_CMD_STATE_PREPARE_SPACE:
7089+ case SCST_CMD_STATE_RDY_TO_XFER:
7090+ case SCST_CMD_STATE_DATA_WAIT:
7091+ cmd->write_len = 0;
7092+ cmd->resid_possible = 1;
7093+ break;
7094+ case SCST_CMD_STATE_TGT_PRE_EXEC:
7095+ case SCST_CMD_STATE_SEND_FOR_EXEC:
7096+ case SCST_CMD_STATE_LOCAL_EXEC:
7097+ case SCST_CMD_STATE_REAL_EXEC:
7098+ case SCST_CMD_STATE_REAL_EXECUTING:
7099+ case SCST_CMD_STATE_DEV_DONE:
7100+ case SCST_CMD_STATE_PRE_DEV_DONE:
7101+ case SCST_CMD_STATE_MODE_SELECT_CHECKS:
7102+ case SCST_CMD_STATE_PRE_XMIT_RESP:
7103+ break;
7104+ default:
7105+ PRINT_CRIT_ERROR("Wrong cmd state %d (cmd %p, op %x)",
7106+ cmd->state, cmd, cmd->cdb[0]);
7107+ BUG();
7108+ break;
7109+ }
7110+
7111+#ifdef CONFIG_SCST_EXTRACHECKS
7112+ if (((cmd->state != SCST_CMD_STATE_PRE_XMIT_RESP) &&
7113+ (cmd->state != SCST_CMD_STATE_PREPROCESSING_DONE)) &&
7114+ (cmd->tgt_dev == NULL) && !cmd->internal) {
7115+ PRINT_CRIT_ERROR("Wrong not inited cmd state %d (cmd %p, "
7116+ "op %x)", cmd->state, cmd, cmd->cdb[0]);
7117+ BUG();
7118+ }
7119+#endif
7120+
7121+ TRACE_EXIT_RES(cmd->state);
7122+ return cmd->state;
7123+}
7124+EXPORT_SYMBOL_GPL(scst_set_cmd_abnormal_done_state);
7125+
7126+void scst_zero_write_rest(struct scst_cmd *cmd)
7127+{
7128+ int len, offs = 0;
7129+ uint8_t *buf;
7130+
7131+ TRACE_ENTRY();
7132+
7133+ len = scst_get_sg_buf_first(cmd, &buf, *cmd->write_sg,
7134+ *cmd->write_sg_cnt);
7135+ while (len > 0) {
7136+ int cur_offs;
7137+
7138+ if (offs + len <= cmd->write_len)
7139+ goto next;
7140+ else if (offs >= cmd->write_len)
7141+ cur_offs = 0;
7142+ else
7143+ cur_offs = cmd->write_len - offs;
7144+
7145+ memset(&buf[cur_offs], 0, len - cur_offs);
7146+
7147+next:
7148+ offs += len;
7149+ scst_put_sg_buf(cmd, buf, *cmd->write_sg, *cmd->write_sg_cnt);
7150+ len = scst_get_sg_buf_next(cmd, &buf, *cmd->write_sg,
7151+ *cmd->write_sg_cnt);
7152+ }
7153+
7154+ TRACE_EXIT();
7155+ return;
7156+}
7157+
7158+static void scst_adjust_sg(struct scst_cmd *cmd, struct scatterlist *sg,
7159+ int *sg_cnt, int adjust_len)
7160+{
7161+ int i, l;
7162+
7163+ TRACE_ENTRY();
7164+
7165+ l = 0;
7166+ for (i = 0; i < *sg_cnt; i++) {
7167+ l += sg[i].length;
7168+ if (l >= adjust_len) {
7169+ int left = adjust_len - (l - sg[i].length);
7170+#ifdef CONFIG_SCST_DEBUG
7171+ TRACE(TRACE_SG_OP|TRACE_MEMORY, "cmd %p (tag %llu), "
7172+ "sg %p, sg_cnt %d, adjust_len %d, i %d, "
7173+ "sg[i].length %d, left %d",
7174+ cmd, (long long unsigned int)cmd->tag,
7175+ sg, *sg_cnt, adjust_len, i,
7176+ sg[i].length, left);
7177+#endif
7178+ cmd->orig_sg = sg;
7179+ cmd->p_orig_sg_cnt = sg_cnt;
7180+ cmd->orig_sg_cnt = *sg_cnt;
7181+ cmd->orig_sg_entry = i;
7182+ cmd->orig_entry_len = sg[i].length;
7183+ *sg_cnt = (left > 0) ? i+1 : i;
7184+ sg[i].length = left;
7185+ cmd->sg_buff_modified = 1;
7186+ break;
7187+ }
7188+ }
7189+
7190+ TRACE_EXIT();
7191+ return;
7192+}
7193+
7194+/**
7195+ * scst_restore_sg_buff() - restores modified sg buffer
7196+ *
7197+ * Restores modified sg buffer in the original state.
7198+ */
7199+void scst_restore_sg_buff(struct scst_cmd *cmd)
7200+{
7201+ TRACE_MEM("cmd %p, sg %p, orig_sg_entry %d, "
7202+ "orig_entry_len %d, orig_sg_cnt %d", cmd, cmd->orig_sg,
7203+ cmd->orig_sg_entry, cmd->orig_entry_len,
7204+ cmd->orig_sg_cnt);
7205+ cmd->orig_sg[cmd->orig_sg_entry].length = cmd->orig_entry_len;
7206+ *cmd->p_orig_sg_cnt = cmd->orig_sg_cnt;
7207+ cmd->sg_buff_modified = 0;
7208+}
7209+EXPORT_SYMBOL(scst_restore_sg_buff);
7210+
7211+/**
7212+ * scst_set_resp_data_len() - set response data length
7213+ *
7214+ * Sets response data length for cmd and truncates its SG vector accordingly.
7215+ *
7216+ * The cmd->resp_data_len must not be set directly, it must be set only
7217+ * using this function. Value of resp_data_len must be <= cmd->bufflen.
7218+ */
7219+void scst_set_resp_data_len(struct scst_cmd *cmd, int resp_data_len)
7220+{
7221+ TRACE_ENTRY();
7222+
7223+ scst_check_restore_sg_buff(cmd);
7224+ cmd->resp_data_len = resp_data_len;
7225+
7226+ if (resp_data_len == cmd->bufflen)
7227+ goto out;
7228+
7229+ scst_adjust_sg(cmd, cmd->sg, &cmd->sg_cnt, resp_data_len);
7230+
7231+ cmd->resid_possible = 1;
7232+
7233+out:
7234+ TRACE_EXIT();
7235+ return;
7236+}
7237+EXPORT_SYMBOL_GPL(scst_set_resp_data_len);
7238+
7239+void scst_limit_sg_write_len(struct scst_cmd *cmd)
7240+{
7241+ TRACE_ENTRY();
7242+
7243+ TRACE_MEM("Limiting sg write len to %d (cmd %p, sg %p, sg_cnt %d)",
7244+ cmd->write_len, cmd, *cmd->write_sg, *cmd->write_sg_cnt);
7245+
7246+ scst_check_restore_sg_buff(cmd);
7247+ scst_adjust_sg(cmd, *cmd->write_sg, cmd->write_sg_cnt, cmd->write_len);
7248+
7249+ TRACE_EXIT();
7250+ return;
7251+}
7252+
7253+void scst_adjust_resp_data_len(struct scst_cmd *cmd)
7254+{
7255+ TRACE_ENTRY();
7256+
7257+ if (!cmd->expected_values_set) {
7258+ cmd->adjusted_resp_data_len = cmd->resp_data_len;
7259+ goto out;
7260+ }
7261+
7262+ cmd->adjusted_resp_data_len = min(cmd->resp_data_len,
7263+ cmd->expected_transfer_len);
7264+
7265+ if (cmd->adjusted_resp_data_len != cmd->resp_data_len) {
7266+ TRACE_MEM("Abjusting resp_data_len to %d (cmd %p, sg %p, "
7267+ "sg_cnt %d)", cmd->adjusted_resp_data_len, cmd, cmd->sg,
7268+ cmd->sg_cnt);
7269+ scst_check_restore_sg_buff(cmd);
7270+ scst_adjust_sg(cmd, cmd->sg, &cmd->sg_cnt,
7271+ cmd->adjusted_resp_data_len);
7272+ }
7273+
7274+out:
7275+ TRACE_EXIT();
7276+ return;
7277+}
7278+
7279+/**
7280+ * scst_cmd_set_write_not_received_data_len() - sets cmd's not received len
7281+ *
7282+ * Sets cmd's not received data length. Also automatically sets resid_possible.
7283+ */
7284+void scst_cmd_set_write_not_received_data_len(struct scst_cmd *cmd,
7285+ int not_received)
7286+{
7287+ TRACE_ENTRY();
7288+
7289+ BUG_ON(!cmd->expected_values_set);
7290+
7291+ cmd->resid_possible = 1;
7292+
7293+ if ((cmd->expected_data_direction & SCST_DATA_READ) &&
7294+ (cmd->expected_data_direction & SCST_DATA_WRITE)) {
7295+ cmd->write_len = cmd->expected_out_transfer_len - not_received;
7296+ if (cmd->write_len == cmd->out_bufflen)
7297+ goto out;
7298+ } else if (cmd->expected_data_direction & SCST_DATA_WRITE) {
7299+ cmd->write_len = cmd->expected_transfer_len - not_received;
7300+ if (cmd->write_len == cmd->bufflen)
7301+ goto out;
7302+ }
7303+
7304+ /*
7305+ * Write len now can be bigger cmd->(out_)bufflen, but that's OK,
7306+ * because it will be used to only calculate write residuals.
7307+ */
7308+
7309+ TRACE_DBG("cmd %p, not_received %d, write_len %d", cmd, not_received,
7310+ cmd->write_len);
7311+
7312+ if (cmd->data_direction & SCST_DATA_WRITE)
7313+ scst_limit_sg_write_len(cmd);
7314+
7315+out:
7316+ TRACE_EXIT();
7317+ return;
7318+}
7319+EXPORT_SYMBOL(scst_cmd_set_write_not_received_data_len);
7320+
7321+/**
7322+ * __scst_get_resid() - returns residuals for cmd
7323+ *
7324+ * Returns residuals for command. Must not be called directly, use
7325+ * scst_get_resid() instead.
7326+ */
7327+bool __scst_get_resid(struct scst_cmd *cmd, int *resid, int *bidi_out_resid)
7328+{
7329+ TRACE_ENTRY();
7330+
7331+ *resid = 0;
7332+ if (bidi_out_resid != NULL)
7333+ *bidi_out_resid = 0;
7334+
7335+ BUG_ON(!cmd->expected_values_set);
7336+
7337+ if (cmd->expected_data_direction & SCST_DATA_READ) {
7338+ *resid = cmd->expected_transfer_len - cmd->resp_data_len;
7339+ if ((cmd->expected_data_direction & SCST_DATA_WRITE) && bidi_out_resid) {
7340+ if (cmd->write_len < cmd->expected_out_transfer_len)
7341+ *bidi_out_resid = cmd->expected_out_transfer_len -
7342+ cmd->write_len;
7343+ else
7344+ *bidi_out_resid = cmd->write_len - cmd->out_bufflen;
7345+ }
7346+ } else if (cmd->expected_data_direction & SCST_DATA_WRITE) {
7347+ if (cmd->write_len < cmd->expected_transfer_len)
7348+ *resid = cmd->expected_transfer_len - cmd->write_len;
7349+ else
7350+ *resid = cmd->write_len - cmd->bufflen;
7351+ }
7352+
7353+ TRACE_DBG("cmd %p, resid %d, bidi_out_resid %d (resp_data_len %d, "
7354+ "expected_data_direction %d, write_len %d, bufflen %d)", cmd,
7355+ *resid, bidi_out_resid ? *bidi_out_resid : 0, cmd->resp_data_len,
7356+ cmd->expected_data_direction, cmd->write_len, cmd->bufflen);
7357+
7358+ TRACE_EXIT_RES(1);
7359+ return true;
7360+}
7361+EXPORT_SYMBOL(__scst_get_resid);
7362+
7363+/* No locks */
7364+int scst_queue_retry_cmd(struct scst_cmd *cmd, int finished_cmds)
7365+{
7366+ struct scst_tgt *tgt = cmd->tgt;
7367+ int res = 0;
7368+ unsigned long flags;
7369+
7370+ TRACE_ENTRY();
7371+
7372+ spin_lock_irqsave(&tgt->tgt_lock, flags);
7373+ tgt->retry_cmds++;
7374+ /*
7375+ * Memory barrier is needed here, because we need the exact order
7376+ * between the read and write between retry_cmds and finished_cmds to
7377+ * not miss the case when a command finished while we queuing it for
7378+ * retry after the finished_cmds check.
7379+ */
7380+ smp_mb();
7381+ TRACE_RETRY("TGT QUEUE FULL: incrementing retry_cmds %d",
7382+ tgt->retry_cmds);
7383+ if (finished_cmds != atomic_read(&tgt->finished_cmds)) {
7384+ /* At least one cmd finished, so try again */
7385+ tgt->retry_cmds--;
7386+ TRACE_RETRY("Some command(s) finished, direct retry "
7387+ "(finished_cmds=%d, tgt->finished_cmds=%d, "
7388+ "retry_cmds=%d)", finished_cmds,
7389+ atomic_read(&tgt->finished_cmds), tgt->retry_cmds);
7390+ res = -1;
7391+ goto out_unlock_tgt;
7392+ }
7393+
7394+ TRACE_RETRY("Adding cmd %p to retry cmd list", cmd);
7395+ list_add_tail(&cmd->cmd_list_entry, &tgt->retry_cmd_list);
7396+
7397+ if (!tgt->retry_timer_active) {
7398+ tgt->retry_timer.expires = jiffies + SCST_TGT_RETRY_TIMEOUT;
7399+ add_timer(&tgt->retry_timer);
7400+ tgt->retry_timer_active = 1;
7401+ }
7402+
7403+out_unlock_tgt:
7404+ spin_unlock_irqrestore(&tgt->tgt_lock, flags);
7405+
7406+ TRACE_EXIT_RES(res);
7407+ return res;
7408+}
7409+
7410+/**
7411+ * scst_update_hw_pending_start() - update commands pending start
7412+ *
7413+ * Updates the command's hw_pending_start as if it's just started hw pending.
7414+ * Target drivers should call it if they received reply from this pending
7415+ * command, but SCST core won't see it.
7416+ */
7417+void scst_update_hw_pending_start(struct scst_cmd *cmd)
7418+{
7419+ unsigned long flags;
7420+
7421+ TRACE_ENTRY();
7422+
7423+ /* To sync with scst_check_hw_pending_cmd() */
7424+ spin_lock_irqsave(&cmd->sess->sess_list_lock, flags);
7425+ cmd->hw_pending_start = jiffies;
7426+ TRACE_MGMT_DBG("Updated hw_pending_start to %ld (cmd %p)",
7427+ cmd->hw_pending_start, cmd);
7428+ spin_unlock_irqrestore(&cmd->sess->sess_list_lock, flags);
7429+
7430+ TRACE_EXIT();
7431+ return;
7432+}
7433+EXPORT_SYMBOL_GPL(scst_update_hw_pending_start);
7434+
7435+/*
7436+ * Supposed to be called under sess_list_lock, but can release/reaquire it.
7437+ * Returns 0 to continue, >0 to restart, <0 to break.
7438+ */
7439+static int scst_check_hw_pending_cmd(struct scst_cmd *cmd,
7440+ unsigned long cur_time, unsigned long max_time,
7441+ struct scst_session *sess, unsigned long *flags,
7442+ struct scst_tgt_template *tgtt)
7443+{
7444+ int res = -1; /* break */
7445+
7446+ TRACE_DBG("cmd %p, hw_pending %d, proc time %ld, "
7447+ "pending time %ld", cmd, cmd->cmd_hw_pending,
7448+ (long)(cur_time - cmd->start_time) / HZ,
7449+ (long)(cur_time - cmd->hw_pending_start) / HZ);
7450+
7451+ if (time_before(cur_time, cmd->start_time + max_time)) {
7452+ /* Cmds are ordered, so no need to check more */
7453+ goto out;
7454+ }
7455+
7456+ if (!cmd->cmd_hw_pending) {
7457+ res = 0; /* continue */
7458+ goto out;
7459+ }
7460+
7461+ if (time_before(cur_time, cmd->hw_pending_start + max_time)) {
7462+ res = 0; /* continue */
7463+ goto out;
7464+ }
7465+
7466+ TRACE_MGMT_DBG("Cmd %p HW pending for too long %ld (state %x)",
7467+ cmd, (cur_time - cmd->hw_pending_start) / HZ,
7468+ cmd->state);
7469+
7470+ cmd->cmd_hw_pending = 0;
7471+
7472+ spin_unlock_irqrestore(&sess->sess_list_lock, *flags);
7473+ tgtt->on_hw_pending_cmd_timeout(cmd);
7474+ spin_lock_irqsave(&sess->sess_list_lock, *flags);
7475+
7476+ res = 1; /* restart */
7477+
7478+out:
7479+ TRACE_EXIT_RES(res);
7480+ return res;
7481+}
7482+
7483+static void scst_hw_pending_work_fn(struct delayed_work *work)
7484+{
7485+ struct scst_session *sess = container_of(work, struct scst_session,
7486+ hw_pending_work);
7487+ struct scst_tgt_template *tgtt = sess->tgt->tgtt;
7488+ struct scst_cmd *cmd;
7489+ unsigned long cur_time = jiffies;
7490+ unsigned long flags;
7491+ unsigned long max_time = tgtt->max_hw_pending_time * HZ;
7492+
7493+ TRACE_ENTRY();
7494+
7495+ TRACE_DBG("HW pending work (sess %p, max time %ld)", sess, max_time/HZ);
7496+
7497+ clear_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED, &sess->sess_aflags);
7498+
7499+ spin_lock_irqsave(&sess->sess_list_lock, flags);
7500+
7501+restart:
7502+ list_for_each_entry(cmd, &sess->sess_cmd_list, sess_cmd_list_entry) {
7503+ int rc;
7504+
7505+ rc = scst_check_hw_pending_cmd(cmd, cur_time, max_time, sess,
7506+ &flags, tgtt);
7507+ if (rc < 0)
7508+ break;
7509+ else if (rc == 0)
7510+ continue;
7511+ else
7512+ goto restart;
7513+ }
7514+
7515+ if (!list_empty(&sess->sess_cmd_list)) {
7516+ /*
7517+ * For stuck cmds if there is no activity we might need to have
7518+ * one more run to release them, so reschedule once again.
7519+ */
7520+ TRACE_DBG("Sched HW pending work for sess %p (max time %d)",
7521+ sess, tgtt->max_hw_pending_time);
7522+ set_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED, &sess->sess_aflags);
7523+ schedule_delayed_work(&sess->hw_pending_work,
7524+ tgtt->max_hw_pending_time * HZ);
7525+ }
7526+
7527+ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
7528+
7529+ TRACE_EXIT();
7530+ return;
7531+}
7532+
7533+static bool __scst_is_relative_target_port_id_unique(uint16_t id,
7534+ const struct scst_tgt *t)
7535+{
7536+ bool res = true;
7537+ struct scst_tgt_template *tgtt;
7538+
7539+ TRACE_ENTRY();
7540+
7541+ list_for_each_entry(tgtt, &scst_template_list,
7542+ scst_template_list_entry) {
7543+ struct scst_tgt *tgt;
7544+ list_for_each_entry(tgt, &tgtt->tgt_list, tgt_list_entry) {
7545+ if (tgt == t)
7546+ continue;
7547+ if ((tgt->tgtt->is_target_enabled != NULL) &&
7548+ !tgt->tgtt->is_target_enabled(tgt))
7549+ continue;
7550+ if (id == tgt->rel_tgt_id) {
7551+ res = false;
7552+ break;
7553+ }
7554+ }
7555+ }
7556+
7557+ TRACE_EXIT_RES(res);
7558+ return res;
7559+}
7560+
7561+/* scst_mutex supposed to be locked */
7562+bool scst_is_relative_target_port_id_unique(uint16_t id,
7563+ const struct scst_tgt *t)
7564+{
7565+ bool res;
7566+
7567+ TRACE_ENTRY();
7568+
7569+ mutex_lock(&scst_mutex);
7570+ res = __scst_is_relative_target_port_id_unique(id, t);
7571+ mutex_unlock(&scst_mutex);
7572+
7573+ TRACE_EXIT_RES(res);
7574+ return res;
7575+}
7576+
7577+int gen_relative_target_port_id(uint16_t *id)
7578+{
7579+ int res = -EOVERFLOW;
7580+ static unsigned long rti = SCST_MIN_REL_TGT_ID, rti_prev;
7581+
7582+ TRACE_ENTRY();
7583+
7584+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
7585+ res = -EINTR;
7586+ goto out;
7587+ }
7588+
7589+ rti_prev = rti;
7590+ do {
7591+ if (__scst_is_relative_target_port_id_unique(rti, NULL)) {
7592+ *id = (uint16_t)rti++;
7593+ res = 0;
7594+ goto out_unlock;
7595+ }
7596+ rti++;
7597+ if (rti > SCST_MAX_REL_TGT_ID)
7598+ rti = SCST_MIN_REL_TGT_ID;
7599+ } while (rti != rti_prev);
7600+
7601+ PRINT_ERROR("%s", "Unable to create unique relative target port id");
7602+
7603+out_unlock:
7604+ mutex_unlock(&scst_mutex);
7605+
7606+out:
7607+ TRACE_EXIT_RES(res);
7608+ return res;
7609+}
7610+
7611+/* No locks */
7612+int scst_alloc_tgt(struct scst_tgt_template *tgtt, struct scst_tgt **tgt)
7613+{
7614+ struct scst_tgt *t;
7615+ int res = 0;
7616+
7617+ TRACE_ENTRY();
7618+
7619+ t = kzalloc(sizeof(*t), GFP_KERNEL);
7620+ if (t == NULL) {
7621+ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of tgt failed");
7622+ res = -ENOMEM;
7623+ goto out;
7624+ }
7625+
7626+ INIT_LIST_HEAD(&t->sess_list);
7627+ init_waitqueue_head(&t->unreg_waitQ);
7628+ t->tgtt = tgtt;
7629+ t->sg_tablesize = tgtt->sg_tablesize;
7630+ spin_lock_init(&t->tgt_lock);
7631+ INIT_LIST_HEAD(&t->retry_cmd_list);
7632+ atomic_set(&t->finished_cmds, 0);
7633+ init_timer(&t->retry_timer);
7634+ t->retry_timer.data = (unsigned long)t;
7635+ t->retry_timer.function = scst_tgt_retry_timer_fn;
7636+
7637+ INIT_LIST_HEAD(&t->tgt_acg_list);
7638+
7639+ *tgt = t;
7640+
7641+out:
7642+ TRACE_EXIT_HRES(res);
7643+ return res;
7644+}
7645+
7646+/* No locks */
7647+void scst_free_tgt(struct scst_tgt *tgt)
7648+{
7649+ TRACE_ENTRY();
7650+
7651+ kfree(tgt->tgt_name);
7652+
7653+ kfree(tgt);
7654+
7655+ TRACE_EXIT();
7656+ return;
7657+}
7658+
7659+/* Called under scst_mutex and suspended activity */
7660+int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev)
7661+{
7662+ struct scst_device *dev;
7663+ int res = 0;
7664+
7665+ TRACE_ENTRY();
7666+
7667+ dev = kzalloc(sizeof(*dev), gfp_mask);
7668+ if (dev == NULL) {
7669+ TRACE(TRACE_OUT_OF_MEM, "%s",
7670+ "Allocation of scst_device failed");
7671+ res = -ENOMEM;
7672+ goto out;
7673+ }
7674+
7675+ dev->handler = &scst_null_devtype;
7676+ atomic_set(&dev->dev_cmd_count, 0);
7677+ atomic_set(&dev->write_cmd_count, 0);
7678+ scst_init_mem_lim(&dev->dev_mem_lim);
7679+ spin_lock_init(&dev->dev_lock);
7680+ INIT_LIST_HEAD(&dev->blocked_cmd_list);
7681+ INIT_LIST_HEAD(&dev->dev_tgt_dev_list);
7682+ INIT_LIST_HEAD(&dev->dev_acg_dev_list);
7683+ dev->dev_double_ua_possible = 1;
7684+ dev->queue_alg = SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER;
7685+
7686+ mutex_init(&dev->dev_pr_mutex);
7687+ atomic_set(&dev->pr_readers_count, 0);
7688+ dev->pr_generation = 0;
7689+ dev->pr_is_set = 0;
7690+ dev->pr_holder = NULL;
7691+ dev->pr_scope = SCOPE_LU;
7692+ dev->pr_type = TYPE_UNSPECIFIED;
7693+ INIT_LIST_HEAD(&dev->dev_registrants_list);
7694+
7695+ scst_init_threads(&dev->dev_cmd_threads);
7696+
7697+ *out_dev = dev;
7698+
7699+out:
7700+ TRACE_EXIT_RES(res);
7701+ return res;
7702+}
7703+
7704+void scst_free_device(struct scst_device *dev)
7705+{
7706+ TRACE_ENTRY();
7707+
7708+#ifdef CONFIG_SCST_EXTRACHECKS
7709+ if (!list_empty(&dev->dev_tgt_dev_list) ||
7710+ !list_empty(&dev->dev_acg_dev_list)) {
7711+ PRINT_CRIT_ERROR("%s: dev_tgt_dev_list or dev_acg_dev_list "
7712+ "is not empty!", __func__);
7713+ BUG();
7714+ }
7715+#endif
7716+
7717+ scst_deinit_threads(&dev->dev_cmd_threads);
7718+
7719+ kfree(dev->virt_name);
7720+ kfree(dev);
7721+
7722+ TRACE_EXIT();
7723+ return;
7724+}
7725+
7726+/**
7727+ * scst_init_mem_lim - initialize memory limits structure
7728+ *
7729+ * Initializes memory limits structure mem_lim according to
7730+ * the current system configuration. This structure should be latter used
7731+ * to track and limit allocated by one or more SGV pools memory.
7732+ */
7733+void scst_init_mem_lim(struct scst_mem_lim *mem_lim)
7734+{
7735+ atomic_set(&mem_lim->alloced_pages, 0);
7736+ mem_lim->max_allowed_pages =
7737+ ((uint64_t)scst_max_dev_cmd_mem << 10) >> (PAGE_SHIFT - 10);
7738+}
7739+EXPORT_SYMBOL_GPL(scst_init_mem_lim);
7740+
7741+static struct scst_acg_dev *scst_alloc_acg_dev(struct scst_acg *acg,
7742+ struct scst_device *dev, uint64_t lun)
7743+{
7744+ struct scst_acg_dev *res;
7745+
7746+ TRACE_ENTRY();
7747+
7748+ res = kmem_cache_zalloc(scst_acgd_cachep, GFP_KERNEL);
7749+ if (res == NULL) {
7750+ TRACE(TRACE_OUT_OF_MEM,
7751+ "%s", "Allocation of scst_acg_dev failed");
7752+ goto out;
7753+ }
7754+
7755+ res->dev = dev;
7756+ res->acg = acg;
7757+ res->lun = lun;
7758+
7759+out:
7760+ TRACE_EXIT_HRES(res);
7761+ return res;
7762+}
7763+
7764+/*
7765+ * The activity supposed to be suspended and scst_mutex held or the
7766+ * corresponding target supposed to be stopped.
7767+ */
7768+static void scst_del_free_acg_dev(struct scst_acg_dev *acg_dev, bool del_sysfs)
7769+{
7770+ TRACE_ENTRY();
7771+
7772+ TRACE_DBG("Removing acg_dev %p from acg_dev_list and dev_acg_dev_list",
7773+ acg_dev);
7774+ list_del(&acg_dev->acg_dev_list_entry);
7775+ list_del(&acg_dev->dev_acg_dev_list_entry);
7776+
7777+ if (del_sysfs)
7778+ scst_acg_dev_sysfs_del(acg_dev);
7779+
7780+ kmem_cache_free(scst_acgd_cachep, acg_dev);
7781+
7782+ TRACE_EXIT();
7783+ return;
7784+}
7785+
7786+/* The activity supposed to be suspended and scst_mutex held */
7787+int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
7788+ struct scst_device *dev, uint64_t lun, int read_only,
7789+ bool gen_scst_report_luns_changed, struct scst_acg_dev **out_acg_dev)
7790+{
7791+ int res = 0;
7792+ struct scst_acg_dev *acg_dev;
7793+ struct scst_tgt_dev *tgt_dev;
7794+ struct scst_session *sess;
7795+ LIST_HEAD(tmp_tgt_dev_list);
7796+ bool del_sysfs = true;
7797+
7798+ TRACE_ENTRY();
7799+
7800+ INIT_LIST_HEAD(&tmp_tgt_dev_list);
7801+
7802+ acg_dev = scst_alloc_acg_dev(acg, dev, lun);
7803+ if (acg_dev == NULL) {
7804+ res = -ENOMEM;
7805+ goto out;
7806+ }
7807+ acg_dev->rd_only = read_only;
7808+
7809+ TRACE_DBG("Adding acg_dev %p to acg_dev_list and dev_acg_dev_list",
7810+ acg_dev);
7811+ list_add_tail(&acg_dev->acg_dev_list_entry, &acg->acg_dev_list);
7812+ list_add_tail(&acg_dev->dev_acg_dev_list_entry, &dev->dev_acg_dev_list);
7813+
7814+ list_for_each_entry(sess, &acg->acg_sess_list, acg_sess_list_entry) {
7815+ res = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev);
7816+ if (res == -EPERM)
7817+ continue;
7818+ else if (res != 0)
7819+ goto out_free;
7820+
7821+ list_add_tail(&tgt_dev->extra_tgt_dev_list_entry,
7822+ &tmp_tgt_dev_list);
7823+ }
7824+
7825+ res = scst_acg_dev_sysfs_create(acg_dev, parent);
7826+ if (res != 0) {
7827+ del_sysfs = false;
7828+ goto out_free;
7829+ }
7830+
7831+ if (gen_scst_report_luns_changed)
7832+ scst_report_luns_changed(acg);
7833+
7834+ PRINT_INFO("Added device %s to group %s (LUN %lld, "
7835+ "rd_only %d)", dev->virt_name, acg->acg_name,
7836+ (long long unsigned int)lun, read_only);
7837+
7838+ if (out_acg_dev != NULL)
7839+ *out_acg_dev = acg_dev;
7840+
7841+out:
7842+ TRACE_EXIT_RES(res);
7843+ return res;
7844+
7845+out_free:
7846+ list_for_each_entry(tgt_dev, &tmp_tgt_dev_list,
7847+ extra_tgt_dev_list_entry) {
7848+ scst_free_tgt_dev(tgt_dev);
7849+ }
7850+ scst_del_free_acg_dev(acg_dev, del_sysfs);
7851+ goto out;
7852+}
7853+
7854+/* The activity supposed to be suspended and scst_mutex held */
7855+int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
7856+ bool gen_scst_report_luns_changed)
7857+{
7858+ int res = 0;
7859+ struct scst_acg_dev *acg_dev = NULL, *a;
7860+ struct scst_tgt_dev *tgt_dev, *tt;
7861+
7862+ TRACE_ENTRY();
7863+
7864+ list_for_each_entry(a, &acg->acg_dev_list, acg_dev_list_entry) {
7865+ if (a->lun == lun) {
7866+ acg_dev = a;
7867+ break;
7868+ }
7869+ }
7870+ if (acg_dev == NULL) {
7871+ PRINT_ERROR("Device is not found in group %s", acg->acg_name);
7872+ res = -EINVAL;
7873+ goto out;
7874+ }
7875+
7876+ list_for_each_entry_safe(tgt_dev, tt, &acg_dev->dev->dev_tgt_dev_list,
7877+ dev_tgt_dev_list_entry) {
7878+ if (tgt_dev->acg_dev == acg_dev)
7879+ scst_free_tgt_dev(tgt_dev);
7880+ }
7881+
7882+ scst_del_free_acg_dev(acg_dev, true);
7883+
7884+ if (gen_scst_report_luns_changed)
7885+ scst_report_luns_changed(acg);
7886+
7887+ PRINT_INFO("Removed LUN %lld from group %s", (unsigned long long)lun,
7888+ acg->acg_name);
7889+
7890+out:
7891+ TRACE_EXIT_RES(res);
7892+ return res;
7893+}
7894+
7895+/* The activity supposed to be suspended and scst_mutex held */
7896+struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
7897+ const char *acg_name, bool tgt_acg)
7898+{
7899+ struct scst_acg *acg;
7900+
7901+ TRACE_ENTRY();
7902+
7903+ acg = kzalloc(sizeof(*acg), GFP_KERNEL);
7904+ if (acg == NULL) {
7905+ PRINT_ERROR("%s", "Allocation of acg failed");
7906+ goto out;
7907+ }
7908+
7909+ acg->tgt = tgt;
7910+ INIT_LIST_HEAD(&acg->acg_dev_list);
7911+ INIT_LIST_HEAD(&acg->acg_sess_list);
7912+ INIT_LIST_HEAD(&acg->acn_list);
7913+ acg->acg_name = kstrdup(acg_name, GFP_KERNEL);
7914+ if (acg->acg_name == NULL) {
7915+ PRINT_ERROR("%s", "Allocation of acg_name failed");
7916+ goto out_free;
7917+ }
7918+
7919+ acg->addr_method = SCST_LUN_ADDR_METHOD_PERIPHERAL;
7920+
7921+ if (tgt_acg) {
7922+ int rc;
7923+
7924+ TRACE_DBG("Adding acg '%s' to device '%s' acg_list", acg_name,
7925+ tgt->tgt_name);
7926+ list_add_tail(&acg->acg_list_entry, &tgt->tgt_acg_list);
7927+ acg->tgt_acg = 1;
7928+
7929+ rc = scst_acg_sysfs_create(tgt, acg);
7930+ if (rc != 0)
7931+ goto out_del;
7932+ }
7933+
7934+out:
7935+ TRACE_EXIT_HRES(acg);
7936+ return acg;
7937+
7938+out_del:
7939+ list_del(&acg->acg_list_entry);
7940+
7941+out_free:
7942+ kfree(acg);
7943+ acg = NULL;
7944+ goto out;
7945+}
7946+
7947+/* The activity supposed to be suspended and scst_mutex held */
7948+void scst_del_free_acg(struct scst_acg *acg)
7949+{
7950+ struct scst_acn *acn, *acnt;
7951+ struct scst_acg_dev *acg_dev, *acg_dev_tmp;
7952+
7953+ TRACE_ENTRY();
7954+
7955+ TRACE_DBG("Clearing acg %s from list", acg->acg_name);
7956+
7957+ BUG_ON(!list_empty(&acg->acg_sess_list));
7958+
7959+ /* Freeing acg_devs */
7960+ list_for_each_entry_safe(acg_dev, acg_dev_tmp, &acg->acg_dev_list,
7961+ acg_dev_list_entry) {
7962+ struct scst_tgt_dev *tgt_dev, *tt;
7963+ list_for_each_entry_safe(tgt_dev, tt,
7964+ &acg_dev->dev->dev_tgt_dev_list,
7965+ dev_tgt_dev_list_entry) {
7966+ if (tgt_dev->acg_dev == acg_dev)
7967+ scst_free_tgt_dev(tgt_dev);
7968+ }
7969+ scst_del_free_acg_dev(acg_dev, true);
7970+ }
7971+
7972+ /* Freeing names */
7973+ list_for_each_entry_safe(acn, acnt, &acg->acn_list, acn_list_entry) {
7974+ scst_del_free_acn(acn,
7975+ list_is_last(&acn->acn_list_entry, &acg->acn_list));
7976+ }
7977+ INIT_LIST_HEAD(&acg->acn_list);
7978+
7979+ if (acg->tgt_acg) {
7980+ TRACE_DBG("Removing acg %s from list", acg->acg_name);
7981+ list_del(&acg->acg_list_entry);
7982+
7983+ scst_acg_sysfs_del(acg);
7984+ } else
7985+ acg->tgt->default_acg = NULL;
7986+
7987+ BUG_ON(!list_empty(&acg->acg_sess_list));
7988+ BUG_ON(!list_empty(&acg->acg_dev_list));
7989+ BUG_ON(!list_empty(&acg->acn_list));
7990+
7991+ kfree(acg->acg_name);
7992+ kfree(acg);
7993+
7994+ TRACE_EXIT();
7995+ return;
7996+}
7997+
7998+/* The activity supposed to be suspended and scst_mutex held */
7999+struct scst_acg *scst_tgt_find_acg(struct scst_tgt *tgt, const char *name)
8000+{
8001+ struct scst_acg *acg, *acg_ret = NULL;
8002+
8003+ TRACE_ENTRY();
8004+
8005+ list_for_each_entry(acg, &tgt->tgt_acg_list, acg_list_entry) {
8006+ if (strcmp(acg->acg_name, name) == 0) {
8007+ acg_ret = acg;
8008+ break;
8009+ }
8010+ }
8011+
8012+ TRACE_EXIT();
8013+ return acg_ret;
8014+}
8015+
8016+/* scst_mutex supposed to be held */
8017+static struct scst_tgt_dev *scst_find_shared_io_tgt_dev(
8018+ struct scst_tgt_dev *tgt_dev)
8019+{
8020+ struct scst_tgt_dev *res = NULL;
8021+ struct scst_acg *acg = tgt_dev->acg_dev->acg;
8022+ struct scst_tgt_dev *t;
8023+
8024+ TRACE_ENTRY();
8025+
8026+ TRACE_DBG("tgt_dev %s (acg %p, io_grouping_type %d)",
8027+ tgt_dev->sess->initiator_name, acg, acg->acg_io_grouping_type);
8028+
8029+ switch (acg->acg_io_grouping_type) {
8030+ case SCST_IO_GROUPING_AUTO:
8031+ if (tgt_dev->sess->initiator_name == NULL)
8032+ goto out;
8033+
8034+ list_for_each_entry(t, &tgt_dev->dev->dev_tgt_dev_list,
8035+ dev_tgt_dev_list_entry) {
8036+ if ((t == tgt_dev) ||
8037+ (t->sess->initiator_name == NULL) ||
8038+ (t->active_cmd_threads == NULL))
8039+ continue;
8040+
8041+ TRACE_DBG("t %s", t->sess->initiator_name);
8042+
8043+ /* We check other ACG's as well */
8044+
8045+ if (strcmp(t->sess->initiator_name,
8046+ tgt_dev->sess->initiator_name) == 0)
8047+ goto found;
8048+ }
8049+ break;
8050+
8051+ case SCST_IO_GROUPING_THIS_GROUP_ONLY:
8052+ list_for_each_entry(t, &tgt_dev->dev->dev_tgt_dev_list,
8053+ dev_tgt_dev_list_entry) {
8054+ if ((t == tgt_dev) || (t->active_cmd_threads == NULL))
8055+ continue;
8056+
8057+ TRACE_DBG("t %s (acg %p)", t->sess->initiator_name,
8058+ t->acg_dev->acg);
8059+
8060+ if (t->acg_dev->acg == acg)
8061+ goto found;
8062+ }
8063+ break;
8064+
8065+ case SCST_IO_GROUPING_NEVER:
8066+ goto out;
8067+
8068+ default:
8069+ list_for_each_entry(t, &tgt_dev->dev->dev_tgt_dev_list,
8070+ dev_tgt_dev_list_entry) {
8071+ if ((t == tgt_dev) || (t->active_cmd_threads == NULL))
8072+ continue;
8073+
8074+ TRACE_DBG("t %s (acg %p, io_grouping_type %d)",
8075+ t->sess->initiator_name, t->acg_dev->acg,
8076+ t->acg_dev->acg->acg_io_grouping_type);
8077+
8078+ if (t->acg_dev->acg->acg_io_grouping_type ==
8079+ acg->acg_io_grouping_type)
8080+ goto found;
8081+ }
8082+ break;
8083+ }
8084+
8085+out:
8086+ TRACE_EXIT_HRES((unsigned long)res);
8087+ return res;
8088+
8089+found:
8090+ if (t->active_cmd_threads == &scst_main_cmd_threads) {
8091+ res = t;
8092+ TRACE_MGMT_DBG("Going to share async IO context %p (res %p, "
8093+ "ini %s, dev %s, grouping type %d)",
8094+ t->aic_keeper->aic, res, t->sess->initiator_name,
8095+ t->dev->virt_name,
8096+ t->acg_dev->acg->acg_io_grouping_type);
8097+ } else {
8098+ res = t;
8099+ if (!*(volatile bool*)&res->active_cmd_threads->io_context_ready) {
8100+ TRACE_MGMT_DBG("IO context for t %p not yet "
8101+ "initialized, waiting...", t);
8102+ msleep(100);
8103+ barrier();
8104+ goto found;
8105+ }
8106+ TRACE_MGMT_DBG("Going to share IO context %p (res %p, ini %s, "
8107+ "dev %s, cmd_threads %p, grouping type %d)",
8108+ res->active_cmd_threads->io_context, res,
8109+ t->sess->initiator_name, t->dev->virt_name,
8110+ t->active_cmd_threads,
8111+ t->acg_dev->acg->acg_io_grouping_type);
8112+ }
8113+ goto out;
8114+}
8115+
8116+enum scst_dev_type_threads_pool_type scst_parse_threads_pool_type(const char *p,
8117+ int len)
8118+{
8119+ enum scst_dev_type_threads_pool_type res;
8120+
8121+ if (strncasecmp(p, SCST_THREADS_POOL_PER_INITIATOR_STR,
8122+ min_t(int, strlen(SCST_THREADS_POOL_PER_INITIATOR_STR),
8123+ len)) == 0)
8124+ res = SCST_THREADS_POOL_PER_INITIATOR;
8125+ else if (strncasecmp(p, SCST_THREADS_POOL_SHARED_STR,
8126+ min_t(int, strlen(SCST_THREADS_POOL_SHARED_STR),
8127+ len)) == 0)
8128+ res = SCST_THREADS_POOL_SHARED;
8129+ else {
8130+ PRINT_ERROR("Unknown threads pool type %s", p);
8131+ res = SCST_THREADS_POOL_TYPE_INVALID;
8132+ }
8133+
8134+ return res;
8135+}
8136+
8137+static int scst_ioc_keeper_thread(void *arg)
8138+{
8139+ struct scst_async_io_context_keeper *aic_keeper =
8140+ (struct scst_async_io_context_keeper *)arg;
8141+
8142+ TRACE_ENTRY();
8143+
8144+ TRACE_MGMT_DBG("AIC %p keeper thread %s (PID %d) started", aic_keeper,
8145+ current->comm, current->pid);
8146+
8147+ current->flags |= PF_NOFREEZE;
8148+
8149+ BUG_ON(aic_keeper->aic != NULL);
8150+
8151+ aic_keeper->aic = get_io_context(GFP_KERNEL, -1);
8152+ TRACE_MGMT_DBG("Alloced new async IO context %p (aic %p)",
8153+ aic_keeper->aic, aic_keeper);
8154+
8155+ /* We have our own ref counting */
8156+ put_io_context(aic_keeper->aic);
8157+
8158+ /* We are ready */
8159+ aic_keeper->aic_ready = true;
8160+ wake_up_all(&aic_keeper->aic_keeper_waitQ);
8161+
8162+ wait_event_interruptible(aic_keeper->aic_keeper_waitQ,
8163+ kthread_should_stop());
8164+
8165+ TRACE_MGMT_DBG("AIC %p keeper thread %s (PID %d) finished", aic_keeper,
8166+ current->comm, current->pid);
8167+
8168+ TRACE_EXIT();
8169+ return 0;
8170+}
8171+
8172+/* scst_mutex supposed to be held */
8173+int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev)
8174+{
8175+ int res = 0;
8176+ struct scst_device *dev = tgt_dev->dev;
8177+ struct scst_async_io_context_keeper *aic_keeper;
8178+
8179+ TRACE_ENTRY();
8180+
8181+ if (dev->threads_num < 0)
8182+ goto out;
8183+
8184+ if (dev->threads_num == 0) {
8185+ struct scst_tgt_dev *shared_io_tgt_dev;
8186+ tgt_dev->active_cmd_threads = &scst_main_cmd_threads;
8187+
8188+ shared_io_tgt_dev = scst_find_shared_io_tgt_dev(tgt_dev);
8189+ if (shared_io_tgt_dev != NULL) {
8190+ aic_keeper = shared_io_tgt_dev->aic_keeper;
8191+ kref_get(&aic_keeper->aic_keeper_kref);
8192+
8193+ TRACE_MGMT_DBG("Linking async io context %p "
8194+ "for shared tgt_dev %p (dev %s)",
8195+ aic_keeper->aic, tgt_dev,
8196+ tgt_dev->dev->virt_name);
8197+ } else {
8198+ /* Create new context */
8199+ aic_keeper = kzalloc(sizeof(*aic_keeper), GFP_KERNEL);
8200+ if (aic_keeper == NULL) {
8201+ PRINT_ERROR("Unable to alloc aic_keeper "
8202+ "(size %zd)", sizeof(*aic_keeper));
8203+ res = -ENOMEM;
8204+ goto out;
8205+ }
8206+
8207+ kref_init(&aic_keeper->aic_keeper_kref);
8208+ init_waitqueue_head(&aic_keeper->aic_keeper_waitQ);
8209+
8210+ aic_keeper->aic_keeper_thr =
8211+ kthread_run(scst_ioc_keeper_thread,
8212+ aic_keeper, "aic_keeper");
8213+ if (IS_ERR(aic_keeper->aic_keeper_thr)) {
8214+ PRINT_ERROR("Error running ioc_keeper "
8215+ "thread (tgt_dev %p)", tgt_dev);
8216+ res = PTR_ERR(aic_keeper->aic_keeper_thr);
8217+ goto out_free_keeper;
8218+ }
8219+
8220+ wait_event(aic_keeper->aic_keeper_waitQ,
8221+ aic_keeper->aic_ready);
8222+
8223+ TRACE_MGMT_DBG("Created async io context %p "
8224+ "for not shared tgt_dev %p (dev %s)",
8225+ aic_keeper->aic, tgt_dev,
8226+ tgt_dev->dev->virt_name);
8227+ }
8228+
8229+ tgt_dev->async_io_context = aic_keeper->aic;
8230+ tgt_dev->aic_keeper = aic_keeper;
8231+
8232+ res = scst_add_threads(tgt_dev->active_cmd_threads, NULL, NULL,
8233+ tgt_dev->sess->tgt->tgtt->threads_num);
8234+ goto out;
8235+ }
8236+
8237+ switch (dev->threads_pool_type) {
8238+ case SCST_THREADS_POOL_PER_INITIATOR:
8239+ {
8240+ struct scst_tgt_dev *shared_io_tgt_dev;
8241+
8242+ scst_init_threads(&tgt_dev->tgt_dev_cmd_threads);
8243+
8244+ tgt_dev->active_cmd_threads = &tgt_dev->tgt_dev_cmd_threads;
8245+
8246+ shared_io_tgt_dev = scst_find_shared_io_tgt_dev(tgt_dev);
8247+ if (shared_io_tgt_dev != NULL) {
8248+ TRACE_MGMT_DBG("Linking io context %p for "
8249+ "shared tgt_dev %p (cmd_threads %p)",
8250+ shared_io_tgt_dev->active_cmd_threads->io_context,
8251+ tgt_dev, tgt_dev->active_cmd_threads);
8252+ /* It's ref counted via threads */
8253+ tgt_dev->active_cmd_threads->io_context =
8254+ shared_io_tgt_dev->active_cmd_threads->io_context;
8255+ }
8256+
8257+ res = scst_add_threads(tgt_dev->active_cmd_threads, NULL,
8258+ tgt_dev,
8259+ dev->threads_num + tgt_dev->sess->tgt->tgtt->threads_num);
8260+ if (res != 0) {
8261+ /* Let's clear here, because no threads could be run */
8262+ tgt_dev->active_cmd_threads->io_context = NULL;
8263+ }
8264+ break;
8265+ }
8266+ case SCST_THREADS_POOL_SHARED:
8267+ {
8268+ tgt_dev->active_cmd_threads = &dev->dev_cmd_threads;
8269+
8270+ res = scst_add_threads(tgt_dev->active_cmd_threads, dev, NULL,
8271+ tgt_dev->sess->tgt->tgtt->threads_num);
8272+ break;
8273+ }
8274+ default:
8275+ PRINT_CRIT_ERROR("Unknown threads pool type %d (dev %s)",
8276+ dev->threads_pool_type, dev->virt_name);
8277+ BUG();
8278+ break;
8279+ }
8280+
8281+out:
8282+ if (res == 0)
8283+ tm_dbg_init_tgt_dev(tgt_dev);
8284+
8285+ TRACE_EXIT_RES(res);
8286+ return res;
8287+
8288+out_free_keeper:
8289+ kfree(aic_keeper);
8290+ goto out;
8291+}
8292+
8293+static void scst_aic_keeper_release(struct kref *kref)
8294+{
8295+ struct scst_async_io_context_keeper *aic_keeper;
8296+
8297+ TRACE_ENTRY();
8298+
8299+ aic_keeper = container_of(kref, struct scst_async_io_context_keeper,
8300+ aic_keeper_kref);
8301+
8302+ kthread_stop(aic_keeper->aic_keeper_thr);
8303+
8304+ kfree(aic_keeper);
8305+
8306+ TRACE_EXIT();
8307+ return;
8308+}
8309+
8310+/* scst_mutex supposed to be held */
8311+void scst_tgt_dev_stop_threads(struct scst_tgt_dev *tgt_dev)
8312+{
8313+ TRACE_ENTRY();
8314+
8315+ if (tgt_dev->dev->threads_num < 0)
8316+ goto out_deinit;
8317+
8318+ if (tgt_dev->active_cmd_threads == &scst_main_cmd_threads) {
8319+ /* Global async threads */
8320+ kref_put(&tgt_dev->aic_keeper->aic_keeper_kref,
8321+ scst_aic_keeper_release);
8322+ tgt_dev->async_io_context = NULL;
8323+ tgt_dev->aic_keeper = NULL;
8324+ } else if (tgt_dev->active_cmd_threads == &tgt_dev->dev->dev_cmd_threads) {
8325+ /* Per device shared threads */
8326+ scst_del_threads(tgt_dev->active_cmd_threads,
8327+ tgt_dev->sess->tgt->tgtt->threads_num);
8328+ } else if (tgt_dev->active_cmd_threads == &tgt_dev->tgt_dev_cmd_threads) {
8329+ /* Per tgt_dev threads */
8330+ scst_del_threads(tgt_dev->active_cmd_threads, -1);
8331+ scst_deinit_threads(&tgt_dev->tgt_dev_cmd_threads);
8332+ } /* else no threads (not yet initialized, e.g.) */
8333+
8334+out_deinit:
8335+ tm_dbg_deinit_tgt_dev(tgt_dev);
8336+ tgt_dev->active_cmd_threads = NULL;
8337+
8338+ TRACE_EXIT();
8339+ return;
8340+}
8341+
8342+/*
8343+ * scst_mutex supposed to be held, there must not be parallel activity in this
8344+ * session.
8345+ */
8346+static int scst_alloc_add_tgt_dev(struct scst_session *sess,
8347+ struct scst_acg_dev *acg_dev, struct scst_tgt_dev **out_tgt_dev)
8348+{
8349+ int res = 0;
8350+ int ini_sg, ini_unchecked_isa_dma, ini_use_clustering;
8351+ struct scst_tgt_dev *tgt_dev;
8352+ struct scst_device *dev = acg_dev->dev;
8353+ struct list_head *sess_tgt_dev_list_head;
8354+ int i, sl;
8355+ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
8356+
8357+ TRACE_ENTRY();
8358+
8359+ tgt_dev = kmem_cache_zalloc(scst_tgtd_cachep, GFP_KERNEL);
8360+ if (tgt_dev == NULL) {
8361+ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of scst_tgt_dev "
8362+ "failed");
8363+ res = -ENOMEM;
8364+ goto out;
8365+ }
8366+
8367+ tgt_dev->dev = dev;
8368+ tgt_dev->lun = acg_dev->lun;
8369+ tgt_dev->acg_dev = acg_dev;
8370+ tgt_dev->sess = sess;
8371+ atomic_set(&tgt_dev->tgt_dev_cmd_count, 0);
8372+
8373+ scst_sgv_pool_use_norm(tgt_dev);
8374+
8375+ if (dev->scsi_dev != NULL) {
8376+ ini_sg = dev->scsi_dev->host->sg_tablesize;
8377+ ini_unchecked_isa_dma = dev->scsi_dev->host->unchecked_isa_dma;
8378+ ini_use_clustering = (dev->scsi_dev->host->use_clustering ==
8379+ ENABLE_CLUSTERING);
8380+ } else {
8381+ ini_sg = (1 << 15) /* infinite */;
8382+ ini_unchecked_isa_dma = 0;
8383+ ini_use_clustering = 0;
8384+ }
8385+ tgt_dev->max_sg_cnt = min(ini_sg, sess->tgt->sg_tablesize);
8386+
8387+ if ((sess->tgt->tgtt->use_clustering || ini_use_clustering) &&
8388+ !sess->tgt->tgtt->no_clustering)
8389+ scst_sgv_pool_use_norm_clust(tgt_dev);
8390+
8391+ if (sess->tgt->tgtt->unchecked_isa_dma || ini_unchecked_isa_dma)
8392+ scst_sgv_pool_use_dma(tgt_dev);
8393+
8394+ TRACE_MGMT_DBG("Device %s on SCST lun=%lld",
8395+ dev->virt_name, (long long unsigned int)tgt_dev->lun);
8396+
8397+ spin_lock_init(&tgt_dev->tgt_dev_lock);
8398+ INIT_LIST_HEAD(&tgt_dev->UA_list);
8399+ spin_lock_init(&tgt_dev->thr_data_lock);
8400+ INIT_LIST_HEAD(&tgt_dev->thr_data_list);
8401+ spin_lock_init(&tgt_dev->sn_lock);
8402+ INIT_LIST_HEAD(&tgt_dev->deferred_cmd_list);
8403+ INIT_LIST_HEAD(&tgt_dev->skipped_sn_list);
8404+ tgt_dev->curr_sn = (typeof(tgt_dev->curr_sn))(-300);
8405+ tgt_dev->expected_sn = tgt_dev->curr_sn + 1;
8406+ tgt_dev->num_free_sn_slots = ARRAY_SIZE(tgt_dev->sn_slots)-1;
8407+ tgt_dev->cur_sn_slot = &tgt_dev->sn_slots[0];
8408+ for (i = 0; i < (int)ARRAY_SIZE(tgt_dev->sn_slots); i++)
8409+ atomic_set(&tgt_dev->sn_slots[i], 0);
8410+
8411+ if (dev->handler->parse_atomic &&
8412+ dev->handler->alloc_data_buf_atomic &&
8413+ (sess->tgt->tgtt->preprocessing_done == NULL)) {
8414+ if (sess->tgt->tgtt->rdy_to_xfer_atomic)
8415+ __set_bit(SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC,
8416+ &tgt_dev->tgt_dev_flags);
8417+ }
8418+ if (dev->handler->dev_done_atomic &&
8419+ sess->tgt->tgtt->xmit_response_atomic) {
8420+ __set_bit(SCST_TGT_DEV_AFTER_EXEC_ATOMIC,
8421+ &tgt_dev->tgt_dev_flags);
8422+ }
8423+
8424+ sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
8425+ dev->d_sense, SCST_LOAD_SENSE(scst_sense_reset_UA));
8426+ scst_alloc_set_UA(tgt_dev, sense_buffer, sl, 0);
8427+
8428+ if (sess->tgt->tgtt->get_initiator_port_transport_id == NULL) {
8429+ if (!list_empty(&dev->dev_registrants_list)) {
8430+ PRINT_WARNING("Initiators from target %s can't connect "
8431+ "to device %s, because the device has PR "
8432+ "registrants and the target doesn't support "
8433+ "Persistent Reservations", sess->tgt->tgtt->name,
8434+ dev->virt_name);
8435+ res = -EPERM;
8436+ goto out_free;
8437+ }
8438+ dev->not_pr_supporting_tgt_devs_num++;
8439+ }
8440+
8441+ res = scst_pr_init_tgt_dev(tgt_dev);
8442+ if (res != 0)
8443+ goto out_dec_free;
8444+
8445+ res = scst_tgt_dev_setup_threads(tgt_dev);
8446+ if (res != 0)
8447+ goto out_pr_clear;
8448+
8449+ if (dev->handler && dev->handler->attach_tgt) {
8450+ TRACE_DBG("Calling dev handler's attach_tgt(%p)", tgt_dev);
8451+ res = dev->handler->attach_tgt(tgt_dev);
8452+ TRACE_DBG("%s", "Dev handler's attach_tgt() returned");
8453+ if (res != 0) {
8454+ PRINT_ERROR("Device handler's %s attach_tgt() "
8455+ "failed: %d", dev->handler->name, res);
8456+ goto out_stop_threads;
8457+ }
8458+ }
8459+
8460+ res = scst_tgt_dev_sysfs_create(tgt_dev);
8461+ if (res != 0)
8462+ goto out_detach;
8463+
8464+ spin_lock_bh(&dev->dev_lock);
8465+ list_add_tail(&tgt_dev->dev_tgt_dev_list_entry, &dev->dev_tgt_dev_list);
8466+ if (dev->dev_reserved)
8467+ __set_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags);
8468+ spin_unlock_bh(&dev->dev_lock);
8469+
8470+ sess_tgt_dev_list_head =
8471+ &sess->sess_tgt_dev_list_hash[HASH_VAL(tgt_dev->lun)];
8472+ list_add_tail(&tgt_dev->sess_tgt_dev_list_entry,
8473+ sess_tgt_dev_list_head);
8474+
8475+ *out_tgt_dev = tgt_dev;
8476+
8477+out:
8478+ TRACE_EXIT_RES(res);
8479+ return res;
8480+
8481+out_detach:
8482+ if (dev->handler && dev->handler->detach_tgt) {
8483+ TRACE_DBG("Calling dev handler's detach_tgt(%p)",
8484+ tgt_dev);
8485+ dev->handler->detach_tgt(tgt_dev);
8486+ TRACE_DBG("%s", "Dev handler's detach_tgt() returned");
8487+ }
8488+
8489+out_stop_threads:
8490+ scst_tgt_dev_stop_threads(tgt_dev);
8491+
8492+out_pr_clear:
8493+ scst_pr_clear_tgt_dev(tgt_dev);
8494+
8495+out_dec_free:
8496+ if (tgt_dev->sess->tgt->tgtt->get_initiator_port_transport_id == NULL)
8497+ dev->not_pr_supporting_tgt_devs_num--;
8498+
8499+out_free:
8500+ scst_free_all_UA(tgt_dev);
8501+ kmem_cache_free(scst_tgtd_cachep, tgt_dev);
8502+ goto out;
8503+}
8504+
8505+/* No locks supposed to be held, scst_mutex - held */
8506+void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA)
8507+{
8508+ TRACE_ENTRY();
8509+
8510+ scst_clear_reservation(tgt_dev);
8511+
8512+ /* With activity suspended the lock isn't needed, but let's be safe */
8513+ spin_lock_bh(&tgt_dev->tgt_dev_lock);
8514+ scst_free_all_UA(tgt_dev);
8515+ memset(tgt_dev->tgt_dev_sense, 0, sizeof(tgt_dev->tgt_dev_sense));
8516+ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
8517+
8518+ if (queue_UA) {
8519+ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
8520+ int sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
8521+ tgt_dev->dev->d_sense,
8522+ SCST_LOAD_SENSE(scst_sense_nexus_loss_UA));
8523+ scst_check_set_UA(tgt_dev, sense_buffer, sl, 0);
8524+ }
8525+
8526+ TRACE_EXIT();
8527+ return;
8528+}
8529+
8530+/*
8531+ * scst_mutex supposed to be held, there must not be parallel activity in this
8532+ * session.
8533+ */
8534+static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev)
8535+{
8536+ struct scst_device *dev = tgt_dev->dev;
8537+
8538+ TRACE_ENTRY();
8539+
8540+ spin_lock_bh(&dev->dev_lock);
8541+ list_del(&tgt_dev->dev_tgt_dev_list_entry);
8542+ spin_unlock_bh(&dev->dev_lock);
8543+
8544+ list_del(&tgt_dev->sess_tgt_dev_list_entry);
8545+
8546+ scst_tgt_dev_sysfs_del(tgt_dev);
8547+
8548+ if (tgt_dev->sess->tgt->tgtt->get_initiator_port_transport_id == NULL)
8549+ dev->not_pr_supporting_tgt_devs_num--;
8550+
8551+ scst_clear_reservation(tgt_dev);
8552+ scst_pr_clear_tgt_dev(tgt_dev);
8553+ scst_free_all_UA(tgt_dev);
8554+
8555+ if (dev->handler && dev->handler->detach_tgt) {
8556+ TRACE_DBG("Calling dev handler's detach_tgt(%p)",
8557+ tgt_dev);
8558+ dev->handler->detach_tgt(tgt_dev);
8559+ TRACE_DBG("%s", "Dev handler's detach_tgt() returned");
8560+ }
8561+
8562+ scst_tgt_dev_stop_threads(tgt_dev);
8563+
8564+ BUG_ON(!list_empty(&tgt_dev->thr_data_list));
8565+
8566+ kmem_cache_free(scst_tgtd_cachep, tgt_dev);
8567+
8568+ TRACE_EXIT();
8569+ return;
8570+}
8571+
8572+/* scst_mutex supposed to be held */
8573+int scst_sess_alloc_tgt_devs(struct scst_session *sess)
8574+{
8575+ int res = 0;
8576+ struct scst_acg_dev *acg_dev;
8577+ struct scst_tgt_dev *tgt_dev;
8578+
8579+ TRACE_ENTRY();
8580+
8581+ list_for_each_entry(acg_dev, &sess->acg->acg_dev_list,
8582+ acg_dev_list_entry) {
8583+ res = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev);
8584+ if (res == -EPERM)
8585+ continue;
8586+ else if (res != 0)
8587+ goto out_free;
8588+ }
8589+
8590+out:
8591+ TRACE_EXIT();
8592+ return res;
8593+
8594+out_free:
8595+ scst_sess_free_tgt_devs(sess);
8596+ goto out;
8597+}
8598+
8599+/*
8600+ * scst_mutex supposed to be held, there must not be parallel activity in this
8601+ * session.
8602+ */
8603+void scst_sess_free_tgt_devs(struct scst_session *sess)
8604+{
8605+ int i;
8606+ struct scst_tgt_dev *tgt_dev, *t;
8607+
8608+ TRACE_ENTRY();
8609+
8610+ /* The session is going down, no users, so no locks */
8611+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
8612+ struct list_head *sess_tgt_dev_list_head =
8613+ &sess->sess_tgt_dev_list_hash[i];
8614+ list_for_each_entry_safe(tgt_dev, t, sess_tgt_dev_list_head,
8615+ sess_tgt_dev_list_entry) {
8616+ scst_free_tgt_dev(tgt_dev);
8617+ }
8618+ INIT_LIST_HEAD(sess_tgt_dev_list_head);
8619+ }
8620+
8621+ TRACE_EXIT();
8622+ return;
8623+}
8624+
8625+/* The activity supposed to be suspended and scst_mutex held */
8626+int scst_acg_add_acn(struct scst_acg *acg, const char *name)
8627+{
8628+ int res = 0;
8629+ struct scst_acn *acn;
8630+ int len;
8631+ char *nm;
8632+
8633+ TRACE_ENTRY();
8634+
8635+ list_for_each_entry(acn, &acg->acn_list, acn_list_entry) {
8636+ if (strcmp(acn->name, name) == 0) {
8637+ PRINT_ERROR("Name %s already exists in group %s",
8638+ name, acg->acg_name);
8639+ res = -EEXIST;
8640+ goto out;
8641+ }
8642+ }
8643+
8644+ acn = kzalloc(sizeof(*acn), GFP_KERNEL);
8645+ if (acn == NULL) {
8646+ PRINT_ERROR("%s", "Unable to allocate scst_acn");
8647+ res = -ENOMEM;
8648+ goto out;
8649+ }
8650+
8651+ acn->acg = acg;
8652+
8653+ len = strlen(name);
8654+ nm = kmalloc(len + 1, GFP_KERNEL);
8655+ if (nm == NULL) {
8656+ PRINT_ERROR("%s", "Unable to allocate scst_acn->name");
8657+ res = -ENOMEM;
8658+ goto out_free;
8659+ }
8660+
8661+ strcpy(nm, name);
8662+ acn->name = nm;
8663+
8664+ res = scst_acn_sysfs_create(acn);
8665+ if (res != 0)
8666+ goto out_free_nm;
8667+
8668+ list_add_tail(&acn->acn_list_entry, &acg->acn_list);
8669+
8670+out:
8671+ if (res == 0) {
8672+ PRINT_INFO("Added name %s to group %s", name, acg->acg_name);
8673+ scst_check_reassign_sessions();
8674+ }
8675+
8676+ TRACE_EXIT_RES(res);
8677+ return res;
8678+
8679+out_free_nm:
8680+ kfree(nm);
8681+
8682+out_free:
8683+ kfree(acn);
8684+ goto out;
8685+}
8686+
8687+/* The activity supposed to be suspended and scst_mutex held */
8688+void scst_del_free_acn(struct scst_acn *acn, bool reassign)
8689+{
8690+ TRACE_ENTRY();
8691+
8692+ list_del(&acn->acn_list_entry);
8693+
8694+ scst_acn_sysfs_del(acn);
8695+
8696+ kfree(acn->name);
8697+ kfree(acn);
8698+
8699+ if (reassign)
8700+ scst_check_reassign_sessions();
8701+
8702+ TRACE_EXIT();
8703+ return;
8704+}
8705+
8706+/* The activity supposed to be suspended and scst_mutex held */
8707+struct scst_acn *scst_find_acn(struct scst_acg *acg, const char *name)
8708+{
8709+ struct scst_acn *acn;
8710+
8711+ TRACE_ENTRY();
8712+
8713+ TRACE_DBG("Trying to find name '%s'", name);
8714+
8715+ list_for_each_entry(acn, &acg->acn_list, acn_list_entry) {
8716+ if (strcmp(acn->name, name) == 0) {
8717+ TRACE_DBG("%s", "Found");
8718+ goto out;
8719+ }
8720+ }
8721+ acn = NULL;
8722+out:
8723+ TRACE_EXIT();
8724+ return acn;
8725+}
8726+
8727+static struct scst_cmd *scst_create_prepare_internal_cmd(
8728+ struct scst_cmd *orig_cmd, int bufsize)
8729+{
8730+ struct scst_cmd *res;
8731+ gfp_t gfp_mask = scst_cmd_atomic(orig_cmd) ? GFP_ATOMIC : GFP_KERNEL;
8732+
8733+ TRACE_ENTRY();
8734+
8735+ res = scst_alloc_cmd(gfp_mask);
8736+ if (res == NULL)
8737+ goto out;
8738+
8739+ res->cmd_threads = orig_cmd->cmd_threads;
8740+ res->sess = orig_cmd->sess;
8741+ res->atomic = scst_cmd_atomic(orig_cmd);
8742+ res->internal = 1;
8743+ res->tgtt = orig_cmd->tgtt;
8744+ res->tgt = orig_cmd->tgt;
8745+ res->dev = orig_cmd->dev;
8746+ res->tgt_dev = orig_cmd->tgt_dev;
8747+ res->lun = orig_cmd->lun;
8748+ res->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
8749+ res->data_direction = SCST_DATA_UNKNOWN;
8750+ res->orig_cmd = orig_cmd;
8751+ res->bufflen = bufsize;
8752+
8753+ scst_sess_get(res->sess);
8754+ if (res->tgt_dev != NULL)
8755+ __scst_get();
8756+
8757+ res->state = SCST_CMD_STATE_PARSE;
8758+
8759+out:
8760+ TRACE_EXIT_HRES((unsigned long)res);
8761+ return res;
8762+}
8763+
8764+int scst_prepare_request_sense(struct scst_cmd *orig_cmd)
8765+{
8766+ int res = 0;
8767+ static const uint8_t request_sense[6] = {
8768+ REQUEST_SENSE, 0, 0, 0, SCST_SENSE_BUFFERSIZE, 0
8769+ };
8770+ struct scst_cmd *rs_cmd;
8771+
8772+ TRACE_ENTRY();
8773+
8774+ if (orig_cmd->sense != NULL) {
8775+ TRACE_MEM("Releasing sense %p (orig_cmd %p)",
8776+ orig_cmd->sense, orig_cmd);
8777+ mempool_free(orig_cmd->sense, scst_sense_mempool);
8778+ orig_cmd->sense = NULL;
8779+ }
8780+
8781+ rs_cmd = scst_create_prepare_internal_cmd(orig_cmd,
8782+ SCST_SENSE_BUFFERSIZE);
8783+ if (rs_cmd == NULL)
8784+ goto out_error;
8785+
8786+ memcpy(rs_cmd->cdb, request_sense, sizeof(request_sense));
8787+ rs_cmd->cdb[1] |= scst_get_cmd_dev_d_sense(orig_cmd);
8788+ rs_cmd->cdb_len = sizeof(request_sense);
8789+ rs_cmd->data_direction = SCST_DATA_READ;
8790+ rs_cmd->expected_data_direction = rs_cmd->data_direction;
8791+ rs_cmd->expected_transfer_len = SCST_SENSE_BUFFERSIZE;
8792+ rs_cmd->expected_values_set = 1;
8793+
8794+ TRACE_MGMT_DBG("Adding REQUEST SENSE cmd %p to head of active "
8795+ "cmd list", rs_cmd);
8796+ spin_lock_irq(&rs_cmd->cmd_threads->cmd_list_lock);
8797+ list_add(&rs_cmd->cmd_list_entry, &rs_cmd->cmd_threads->active_cmd_list);
8798+ wake_up(&rs_cmd->cmd_threads->cmd_list_waitQ);
8799+ spin_unlock_irq(&rs_cmd->cmd_threads->cmd_list_lock);
8800+
8801+out:
8802+ TRACE_EXIT_RES(res);
8803+ return res;
8804+
8805+out_error:
8806+ res = -1;
8807+ goto out;
8808+}
8809+
8810+static void scst_complete_request_sense(struct scst_cmd *req_cmd)
8811+{
8812+ struct scst_cmd *orig_cmd = req_cmd->orig_cmd;
8813+ uint8_t *buf;
8814+ int len;
8815+
8816+ TRACE_ENTRY();
8817+
8818+ BUG_ON(orig_cmd == NULL);
8819+
8820+ len = scst_get_buf_first(req_cmd, &buf);
8821+
8822+ if (scsi_status_is_good(req_cmd->status) && (len > 0) &&
8823+ SCST_SENSE_VALID(buf) && (!SCST_NO_SENSE(buf))) {
8824+ PRINT_BUFF_FLAG(TRACE_SCSI, "REQUEST SENSE returned",
8825+ buf, len);
8826+ scst_alloc_set_sense(orig_cmd, scst_cmd_atomic(req_cmd), buf,
8827+ len);
8828+ } else {
8829+ PRINT_ERROR("%s", "Unable to get the sense via "
8830+ "REQUEST SENSE, returning HARDWARE ERROR");
8831+ scst_set_cmd_error(orig_cmd,
8832+ SCST_LOAD_SENSE(scst_sense_hardw_error));
8833+ }
8834+
8835+ if (len > 0)
8836+ scst_put_buf(req_cmd, buf);
8837+
8838+ TRACE_MGMT_DBG("Adding orig cmd %p to head of active "
8839+ "cmd list", orig_cmd);
8840+ spin_lock_irq(&orig_cmd->cmd_threads->cmd_list_lock);
8841+ list_add(&orig_cmd->cmd_list_entry, &orig_cmd->cmd_threads->active_cmd_list);
8842+ wake_up(&orig_cmd->cmd_threads->cmd_list_waitQ);
8843+ spin_unlock_irq(&orig_cmd->cmd_threads->cmd_list_lock);
8844+
8845+ TRACE_EXIT();
8846+ return;
8847+}
8848+
8849+int scst_finish_internal_cmd(struct scst_cmd *cmd)
8850+{
8851+ int res;
8852+
8853+ TRACE_ENTRY();
8854+
8855+ BUG_ON(!cmd->internal);
8856+
8857+ if (cmd->cdb[0] == REQUEST_SENSE)
8858+ scst_complete_request_sense(cmd);
8859+
8860+ __scst_cmd_put(cmd);
8861+
8862+ res = SCST_CMD_STATE_RES_CONT_NEXT;
8863+
8864+ TRACE_EXIT_HRES(res);
8865+ return res;
8866+}
8867+
8868+static void scst_send_release(struct scst_device *dev)
8869+{
8870+ struct scsi_device *scsi_dev;
8871+ unsigned char cdb[6];
8872+ uint8_t sense[SCSI_SENSE_BUFFERSIZE];
8873+ int rc, i;
8874+
8875+ TRACE_ENTRY();
8876+
8877+ if (dev->scsi_dev == NULL)
8878+ goto out;
8879+
8880+ scsi_dev = dev->scsi_dev;
8881+
8882+ for (i = 0; i < 5; i++) {
8883+ memset(cdb, 0, sizeof(cdb));
8884+ cdb[0] = RELEASE;
8885+ cdb[1] = (scsi_dev->scsi_level <= SCSI_2) ?
8886+ ((scsi_dev->lun << 5) & 0xe0) : 0;
8887+
8888+ memset(sense, 0, sizeof(sense));
8889+
8890+ TRACE(TRACE_DEBUG | TRACE_SCSI, "%s", "Sending RELEASE req to "
8891+ "SCSI mid-level");
8892+ rc = scsi_execute(scsi_dev, cdb, SCST_DATA_NONE, NULL, 0,
8893+ sense, 15, 0, 0
8894+ , NULL
8895+ );
8896+ TRACE_DBG("MODE_SENSE done: %x", rc);
8897+
8898+ if (scsi_status_is_good(rc)) {
8899+ break;
8900+ } else {
8901+ PRINT_ERROR("RELEASE failed: %d", rc);
8902+ PRINT_BUFFER("RELEASE sense", sense, sizeof(sense));
8903+ scst_check_internal_sense(dev, rc, sense,
8904+ sizeof(sense));
8905+ }
8906+ }
8907+
8908+out:
8909+ TRACE_EXIT();
8910+ return;
8911+}
8912+
8913+/* scst_mutex supposed to be held */
8914+static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev)
8915+{
8916+ struct scst_device *dev = tgt_dev->dev;
8917+ int release = 0;
8918+
8919+ TRACE_ENTRY();
8920+
8921+ spin_lock_bh(&dev->dev_lock);
8922+ if (dev->dev_reserved &&
8923+ !test_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags)) {
8924+ /* This is one who holds the reservation */
8925+ struct scst_tgt_dev *tgt_dev_tmp;
8926+ list_for_each_entry(tgt_dev_tmp, &dev->dev_tgt_dev_list,
8927+ dev_tgt_dev_list_entry) {
8928+ clear_bit(SCST_TGT_DEV_RESERVED,
8929+ &tgt_dev_tmp->tgt_dev_flags);
8930+ }
8931+ dev->dev_reserved = 0;
8932+ release = 1;
8933+ }
8934+ spin_unlock_bh(&dev->dev_lock);
8935+
8936+ if (release)
8937+ scst_send_release(dev);
8938+
8939+ TRACE_EXIT();
8940+ return;
8941+}
8942+
8943+struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask,
8944+ const char *initiator_name)
8945+{
8946+ struct scst_session *sess;
8947+ int i;
8948+
8949+ TRACE_ENTRY();
8950+
8951+ sess = kmem_cache_zalloc(scst_sess_cachep, gfp_mask);
8952+ if (sess == NULL) {
8953+ TRACE(TRACE_OUT_OF_MEM, "%s",
8954+ "Allocation of scst_session failed");
8955+ goto out;
8956+ }
8957+
8958+ sess->init_phase = SCST_SESS_IPH_INITING;
8959+ sess->shut_phase = SCST_SESS_SPH_READY;
8960+ atomic_set(&sess->refcnt, 0);
8961+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
8962+ struct list_head *sess_tgt_dev_list_head =
8963+ &sess->sess_tgt_dev_list_hash[i];
8964+ INIT_LIST_HEAD(sess_tgt_dev_list_head);
8965+ }
8966+ spin_lock_init(&sess->sess_list_lock);
8967+ INIT_LIST_HEAD(&sess->sess_cmd_list);
8968+ sess->tgt = tgt;
8969+ INIT_LIST_HEAD(&sess->init_deferred_cmd_list);
8970+ INIT_LIST_HEAD(&sess->init_deferred_mcmd_list);
8971+ INIT_DELAYED_WORK(&sess->hw_pending_work,
8972+ (void (*)(struct work_struct *))scst_hw_pending_work_fn);
8973+
8974+#ifdef CONFIG_SCST_MEASURE_LATENCY
8975+ spin_lock_init(&sess->lat_lock);
8976+#endif
8977+
8978+ sess->initiator_name = kstrdup(initiator_name, gfp_mask);
8979+ if (sess->initiator_name == NULL) {
8980+ PRINT_ERROR("%s", "Unable to dup sess->initiator_name");
8981+ goto out_free;
8982+ }
8983+
8984+out:
8985+ TRACE_EXIT();
8986+ return sess;
8987+
8988+out_free:
8989+ kmem_cache_free(scst_sess_cachep, sess);
8990+ sess = NULL;
8991+ goto out;
8992+}
8993+
8994+void scst_free_session(struct scst_session *sess)
8995+{
8996+ TRACE_ENTRY();
8997+
8998+ mutex_lock(&scst_mutex);
8999+
9000+ scst_sess_free_tgt_devs(sess);
9001+
9002+ /* tgt will stay alive at least until its sysfs alive */
9003+ kobject_get(&sess->tgt->tgt_kobj);
9004+
9005+ mutex_unlock(&scst_mutex);
9006+ scst_sess_sysfs_del(sess);
9007+ mutex_lock(&scst_mutex);
9008+
9009+ /*
9010+ * The lists delete must be after sysfs del. Otherwise it would break
9011+ * logic in scst_sess_sysfs_create() to avoid duplicate sysfs names.
9012+ */
9013+
9014+ TRACE_DBG("Removing sess %p from the list", sess);
9015+ list_del(&sess->sess_list_entry);
9016+ TRACE_DBG("Removing session %p from acg %s", sess, sess->acg->acg_name);
9017+ list_del(&sess->acg_sess_list_entry);
9018+
9019+ mutex_unlock(&scst_mutex);
9020+
9021+ wake_up_all(&sess->tgt->unreg_waitQ);
9022+
9023+ kobject_put(&sess->tgt->tgt_kobj);
9024+
9025+ kfree(sess->transport_id);
9026+ kfree(sess->initiator_name);
9027+
9028+ kmem_cache_free(scst_sess_cachep, sess);
9029+
9030+ TRACE_EXIT();
9031+ return;
9032+}
9033+
9034+void scst_free_session_callback(struct scst_session *sess)
9035+{
9036+ struct completion *c;
9037+
9038+ TRACE_ENTRY();
9039+
9040+ TRACE_DBG("Freeing session %p", sess);
9041+
9042+ cancel_delayed_work_sync(&sess->hw_pending_work);
9043+
9044+ c = sess->shutdown_compl;
9045+
9046+ mutex_lock(&scst_mutex);
9047+ /*
9048+ * Necessary to sync with other threads trying to queue AEN, which
9049+ * the target driver will not be able to serve and crash, because after
9050+ * unreg_done_fn() called its internal session data will be destroyed.
9051+ */
9052+ sess->shut_phase = SCST_SESS_SPH_UNREG_DONE_CALLING;
9053+ mutex_unlock(&scst_mutex);
9054+
9055+ if (sess->unreg_done_fn) {
9056+ TRACE_DBG("Calling unreg_done_fn(%p)", sess);
9057+ sess->unreg_done_fn(sess);
9058+ TRACE_DBG("%s", "unreg_done_fn() returned");
9059+ }
9060+ scst_free_session(sess);
9061+
9062+ if (c)
9063+ complete_all(c);
9064+
9065+ TRACE_EXIT();
9066+ return;
9067+}
9068+
9069+void scst_sched_session_free(struct scst_session *sess)
9070+{
9071+ unsigned long flags;
9072+
9073+ TRACE_ENTRY();
9074+
9075+ if (sess->shut_phase != SCST_SESS_SPH_SHUTDOWN) {
9076+ PRINT_CRIT_ERROR("session %p is going to shutdown with unknown "
9077+ "shut phase %lx", sess, sess->shut_phase);
9078+ BUG();
9079+ }
9080+
9081+ spin_lock_irqsave(&scst_mgmt_lock, flags);
9082+ TRACE_DBG("Adding sess %p to scst_sess_shut_list", sess);
9083+ list_add_tail(&sess->sess_shut_list_entry, &scst_sess_shut_list);
9084+ spin_unlock_irqrestore(&scst_mgmt_lock, flags);
9085+
9086+ wake_up(&scst_mgmt_waitQ);
9087+
9088+ TRACE_EXIT();
9089+ return;
9090+}
9091+
9092+/**
9093+ * scst_cmd_get() - increase command's reference counter
9094+ */
9095+void scst_cmd_get(struct scst_cmd *cmd)
9096+{
9097+ __scst_cmd_get(cmd);
9098+}
9099+EXPORT_SYMBOL(scst_cmd_get);
9100+
9101+/**
9102+ * scst_cmd_put() - decrease command's reference counter
9103+ */
9104+void scst_cmd_put(struct scst_cmd *cmd)
9105+{
9106+ __scst_cmd_put(cmd);
9107+}
9108+EXPORT_SYMBOL(scst_cmd_put);
9109+
9110+struct scst_cmd *scst_alloc_cmd(gfp_t gfp_mask)
9111+{
9112+ struct scst_cmd *cmd;
9113+
9114+ TRACE_ENTRY();
9115+
9116+ cmd = kmem_cache_zalloc(scst_cmd_cachep, gfp_mask);
9117+ if (cmd == NULL) {
9118+ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of scst_cmd failed");
9119+ goto out;
9120+ }
9121+
9122+ cmd->state = SCST_CMD_STATE_INIT_WAIT;
9123+ cmd->start_time = jiffies;
9124+ atomic_set(&cmd->cmd_ref, 1);
9125+ cmd->cmd_threads = &scst_main_cmd_threads;
9126+ INIT_LIST_HEAD(&cmd->mgmt_cmd_list);
9127+ cmd->queue_type = SCST_CMD_QUEUE_SIMPLE;
9128+ cmd->timeout = SCST_DEFAULT_TIMEOUT;
9129+ cmd->retries = 0;
9130+ cmd->data_len = -1;
9131+ cmd->is_send_status = 1;
9132+ cmd->resp_data_len = -1;
9133+ cmd->write_sg = &cmd->sg;
9134+ cmd->write_sg_cnt = &cmd->sg_cnt;
9135+
9136+ cmd->dbl_ua_orig_data_direction = SCST_DATA_UNKNOWN;
9137+ cmd->dbl_ua_orig_resp_data_len = -1;
9138+
9139+out:
9140+ TRACE_EXIT();
9141+ return cmd;
9142+}
9143+
9144+static void scst_destroy_put_cmd(struct scst_cmd *cmd)
9145+{
9146+ scst_sess_put(cmd->sess);
9147+
9148+ /*
9149+ * At this point tgt_dev can be dead, but the pointer remains non-NULL
9150+ */
9151+ if (likely(cmd->tgt_dev != NULL))
9152+ __scst_put();
9153+
9154+ scst_destroy_cmd(cmd);
9155+ return;
9156+}
9157+
9158+/* No locks supposed to be held */
9159+void scst_free_cmd(struct scst_cmd *cmd)
9160+{
9161+ int destroy = 1;
9162+
9163+ TRACE_ENTRY();
9164+
9165+ TRACE_DBG("Freeing cmd %p (tag %llu)",
9166+ cmd, (long long unsigned int)cmd->tag);
9167+
9168+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
9169+ TRACE_MGMT_DBG("Freeing aborted cmd %p (scst_cmd_count %d)",
9170+ cmd, atomic_read(&scst_cmd_count));
9171+ }
9172+
9173+ BUG_ON(cmd->unblock_dev);
9174+
9175+ /*
9176+ * Target driver can already free sg buffer before calling
9177+ * scst_tgt_cmd_done(). E.g., scst_local has to do that.
9178+ */
9179+ if (!cmd->tgt_data_buf_alloced)
9180+ scst_check_restore_sg_buff(cmd);
9181+
9182+ if ((cmd->tgtt->on_free_cmd != NULL) && likely(!cmd->internal)) {
9183+ TRACE_DBG("Calling target's on_free_cmd(%p)", cmd);
9184+ scst_set_cur_start(cmd);
9185+ cmd->tgtt->on_free_cmd(cmd);
9186+ scst_set_tgt_on_free_time(cmd);
9187+ TRACE_DBG("%s", "Target's on_free_cmd() returned");
9188+ }
9189+
9190+ if (likely(cmd->dev != NULL)) {
9191+ struct scst_dev_type *handler = cmd->dev->handler;
9192+ if (handler->on_free_cmd != NULL) {
9193+ TRACE_DBG("Calling dev handler %s on_free_cmd(%p)",
9194+ handler->name, cmd);
9195+ scst_set_cur_start(cmd);
9196+ handler->on_free_cmd(cmd);
9197+ scst_set_dev_on_free_time(cmd);
9198+ TRACE_DBG("Dev handler %s on_free_cmd() returned",
9199+ handler->name);
9200+ }
9201+ }
9202+
9203+ scst_release_space(cmd);
9204+
9205+ if (unlikely(cmd->sense != NULL)) {
9206+ TRACE_MEM("Releasing sense %p (cmd %p)", cmd->sense, cmd);
9207+ mempool_free(cmd->sense, scst_sense_mempool);
9208+ cmd->sense = NULL;
9209+ }
9210+
9211+ if (likely(cmd->tgt_dev != NULL)) {
9212+#ifdef CONFIG_SCST_EXTRACHECKS
9213+ if (unlikely(!cmd->sent_for_exec) && !cmd->internal) {
9214+ PRINT_ERROR("Finishing not executed cmd %p (opcode "
9215+ "%d, target %s, LUN %lld, sn %d, expected_sn %d)",
9216+ cmd, cmd->cdb[0], cmd->tgtt->name,
9217+ (long long unsigned int)cmd->lun,
9218+ cmd->sn, cmd->tgt_dev->expected_sn);
9219+ scst_unblock_deferred(cmd->tgt_dev, cmd);
9220+ }
9221+#endif
9222+
9223+ if (unlikely(cmd->out_of_sn)) {
9224+ TRACE_SN("Out of SN cmd %p (tag %llu, sn %d), "
9225+ "destroy=%d", cmd,
9226+ (long long unsigned int)cmd->tag,
9227+ cmd->sn, destroy);
9228+ destroy = test_and_set_bit(SCST_CMD_CAN_BE_DESTROYED,
9229+ &cmd->cmd_flags);
9230+ }
9231+ }
9232+
9233+ if (likely(destroy))
9234+ scst_destroy_put_cmd(cmd);
9235+
9236+ TRACE_EXIT();
9237+ return;
9238+}
9239+
9240+/* No locks supposed to be held. */
9241+void scst_check_retries(struct scst_tgt *tgt)
9242+{
9243+ int need_wake_up = 0;
9244+
9245+ TRACE_ENTRY();
9246+
9247+ /*
9248+ * We don't worry about overflow of finished_cmds, because we check
9249+ * only for its change.
9250+ */
9251+ atomic_inc(&tgt->finished_cmds);
9252+ /* See comment in scst_queue_retry_cmd() */
9253+ smp_mb__after_atomic_inc();
9254+ if (unlikely(tgt->retry_cmds > 0)) {
9255+ struct scst_cmd *c, *tc;
9256+ unsigned long flags;
9257+
9258+ TRACE_RETRY("Checking retry cmd list (retry_cmds %d)",
9259+ tgt->retry_cmds);
9260+
9261+ spin_lock_irqsave(&tgt->tgt_lock, flags);
9262+ list_for_each_entry_safe(c, tc, &tgt->retry_cmd_list,
9263+ cmd_list_entry) {
9264+ tgt->retry_cmds--;
9265+
9266+ TRACE_RETRY("Moving retry cmd %p to head of active "
9267+ "cmd list (retry_cmds left %d)",
9268+ c, tgt->retry_cmds);
9269+ spin_lock(&c->cmd_threads->cmd_list_lock);
9270+ list_move(&c->cmd_list_entry,
9271+ &c->cmd_threads->active_cmd_list);
9272+ wake_up(&c->cmd_threads->cmd_list_waitQ);
9273+ spin_unlock(&c->cmd_threads->cmd_list_lock);
9274+
9275+ need_wake_up++;
9276+ if (need_wake_up >= 2) /* "slow start" */
9277+ break;
9278+ }
9279+ spin_unlock_irqrestore(&tgt->tgt_lock, flags);
9280+ }
9281+
9282+ TRACE_EXIT();
9283+ return;
9284+}
9285+
9286+static void scst_tgt_retry_timer_fn(unsigned long arg)
9287+{
9288+ struct scst_tgt *tgt = (struct scst_tgt *)arg;
9289+ unsigned long flags;
9290+
9291+ TRACE_RETRY("Retry timer expired (retry_cmds %d)", tgt->retry_cmds);
9292+
9293+ spin_lock_irqsave(&tgt->tgt_lock, flags);
9294+ tgt->retry_timer_active = 0;
9295+ spin_unlock_irqrestore(&tgt->tgt_lock, flags);
9296+
9297+ scst_check_retries(tgt);
9298+
9299+ TRACE_EXIT();
9300+ return;
9301+}
9302+
9303+struct scst_mgmt_cmd *scst_alloc_mgmt_cmd(gfp_t gfp_mask)
9304+{
9305+ struct scst_mgmt_cmd *mcmd;
9306+
9307+ TRACE_ENTRY();
9308+
9309+ mcmd = mempool_alloc(scst_mgmt_mempool, gfp_mask);
9310+ if (mcmd == NULL) {
9311+ PRINT_CRIT_ERROR("%s", "Allocation of management command "
9312+ "failed, some commands and their data could leak");
9313+ goto out;
9314+ }
9315+ memset(mcmd, 0, sizeof(*mcmd));
9316+
9317+out:
9318+ TRACE_EXIT();
9319+ return mcmd;
9320+}
9321+
9322+void scst_free_mgmt_cmd(struct scst_mgmt_cmd *mcmd)
9323+{
9324+ unsigned long flags;
9325+
9326+ TRACE_ENTRY();
9327+
9328+ spin_lock_irqsave(&mcmd->sess->sess_list_lock, flags);
9329+ atomic_dec(&mcmd->sess->sess_cmd_count);
9330+ spin_unlock_irqrestore(&mcmd->sess->sess_list_lock, flags);
9331+
9332+ scst_sess_put(mcmd->sess);
9333+
9334+ if (mcmd->mcmd_tgt_dev != NULL)
9335+ __scst_put();
9336+
9337+ mempool_free(mcmd, scst_mgmt_mempool);
9338+
9339+ TRACE_EXIT();
9340+ return;
9341+}
9342+
9343+int scst_alloc_space(struct scst_cmd *cmd)
9344+{
9345+ gfp_t gfp_mask;
9346+ int res = -ENOMEM;
9347+ int atomic = scst_cmd_atomic(cmd);
9348+ int flags;
9349+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
9350+ static int ll;
9351+
9352+ TRACE_ENTRY();
9353+
9354+ gfp_mask = tgt_dev->gfp_mask | (atomic ? GFP_ATOMIC : GFP_KERNEL);
9355+
9356+ flags = atomic ? SGV_POOL_NO_ALLOC_ON_CACHE_MISS : 0;
9357+ if (cmd->no_sgv)
9358+ flags |= SGV_POOL_ALLOC_NO_CACHED;
9359+
9360+ cmd->sg = sgv_pool_alloc(tgt_dev->pool, cmd->bufflen, gfp_mask, flags,
9361+ &cmd->sg_cnt, &cmd->sgv, &cmd->dev->dev_mem_lim, NULL);
9362+ if (cmd->sg == NULL)
9363+ goto out;
9364+
9365+ if (unlikely(cmd->sg_cnt > tgt_dev->max_sg_cnt)) {
9366+ if ((ll < 10) || TRACING_MINOR()) {
9367+ PRINT_INFO("Unable to complete command due to "
9368+ "SG IO count limitation (requested %d, "
9369+ "available %d, tgt lim %d)", cmd->sg_cnt,
9370+ tgt_dev->max_sg_cnt, cmd->tgt->sg_tablesize);
9371+ ll++;
9372+ }
9373+ goto out_sg_free;
9374+ }
9375+
9376+ if (cmd->data_direction != SCST_DATA_BIDI)
9377+ goto success;
9378+
9379+ cmd->out_sg = sgv_pool_alloc(tgt_dev->pool, cmd->out_bufflen, gfp_mask,
9380+ flags, &cmd->out_sg_cnt, &cmd->out_sgv,
9381+ &cmd->dev->dev_mem_lim, NULL);
9382+ if (cmd->out_sg == NULL)
9383+ goto out_sg_free;
9384+
9385+ if (unlikely(cmd->out_sg_cnt > tgt_dev->max_sg_cnt)) {
9386+ if ((ll < 10) || TRACING_MINOR()) {
9387+ PRINT_INFO("Unable to complete command due to "
9388+ "SG IO count limitation (OUT buffer, requested "
9389+ "%d, available %d, tgt lim %d)", cmd->out_sg_cnt,
9390+ tgt_dev->max_sg_cnt, cmd->tgt->sg_tablesize);
9391+ ll++;
9392+ }
9393+ goto out_out_sg_free;
9394+ }
9395+
9396+success:
9397+ res = 0;
9398+
9399+out:
9400+ TRACE_EXIT();
9401+ return res;
9402+
9403+out_out_sg_free:
9404+ sgv_pool_free(cmd->out_sgv, &cmd->dev->dev_mem_lim);
9405+ cmd->out_sgv = NULL;
9406+ cmd->out_sg = NULL;
9407+ cmd->out_sg_cnt = 0;
9408+
9409+out_sg_free:
9410+ sgv_pool_free(cmd->sgv, &cmd->dev->dev_mem_lim);
9411+ cmd->sgv = NULL;
9412+ cmd->sg = NULL;
9413+ cmd->sg_cnt = 0;
9414+ goto out;
9415+}
9416+
9417+static void scst_release_space(struct scst_cmd *cmd)
9418+{
9419+ TRACE_ENTRY();
9420+
9421+ if (cmd->sgv == NULL) {
9422+ if ((cmd->sg != NULL) &&
9423+ !(cmd->tgt_data_buf_alloced || cmd->dh_data_buf_alloced)) {
9424+ TRACE_MEM("Freeing sg %p for cmd %p (cnt %d)", cmd->sg,
9425+ cmd, cmd->sg_cnt);
9426+ scst_free(cmd->sg, cmd->sg_cnt);
9427+ goto out_zero;
9428+ } else
9429+ goto out;
9430+ }
9431+
9432+ if (cmd->tgt_data_buf_alloced || cmd->dh_data_buf_alloced) {
9433+ TRACE_MEM("%s", "*data_buf_alloced set, returning");
9434+ goto out;
9435+ }
9436+
9437+ if (cmd->out_sgv != NULL) {
9438+ sgv_pool_free(cmd->out_sgv, &cmd->dev->dev_mem_lim);
9439+ cmd->out_sgv = NULL;
9440+ cmd->out_sg_cnt = 0;
9441+ cmd->out_sg = NULL;
9442+ cmd->out_bufflen = 0;
9443+ }
9444+
9445+ sgv_pool_free(cmd->sgv, &cmd->dev->dev_mem_lim);
9446+
9447+out_zero:
9448+ cmd->sgv = NULL;
9449+ cmd->sg_cnt = 0;
9450+ cmd->sg = NULL;
9451+ cmd->bufflen = 0;
9452+ cmd->data_len = 0;
9453+
9454+out:
9455+ TRACE_EXIT();
9456+ return;
9457+}
9458+
9459+static void scsi_end_async(struct request *req, int error)
9460+{
9461+ struct scsi_io_context *sioc = req->end_io_data;
9462+
9463+ TRACE_DBG("sioc %p, cmd %p", sioc, sioc->data);
9464+
9465+ if (sioc->done)
9466+ sioc->done(sioc->data, sioc->sense, req->errors, req->resid_len);
9467+
9468+ if (!sioc->full_cdb_used)
9469+ kmem_cache_free(scsi_io_context_cache, sioc);
9470+ else
9471+ kfree(sioc);
9472+
9473+ __blk_put_request(req->q, req);
9474+ return;
9475+}
9476+
9477+/**
9478+ * scst_scsi_exec_async - executes a SCSI command in pass-through mode
9479+ * @cmd: scst command
9480+ * @done: callback function when done
9481+ */
9482+int scst_scsi_exec_async(struct scst_cmd *cmd,
9483+ void (*done)(void *, char *, int, int))
9484+{
9485+ int res = 0;
9486+ struct request_queue *q = cmd->dev->scsi_dev->request_queue;
9487+ struct request *rq;
9488+ struct scsi_io_context *sioc;
9489+ int write = (cmd->data_direction & SCST_DATA_WRITE) ? WRITE : READ;
9490+ gfp_t gfp = GFP_KERNEL;
9491+ int cmd_len = cmd->cdb_len;
9492+
9493+ if (cmd->ext_cdb_len == 0) {
9494+ TRACE_DBG("Simple CDB (cmd_len %d)", cmd_len);
9495+ sioc = kmem_cache_zalloc(scsi_io_context_cache, gfp);
9496+ if (sioc == NULL) {
9497+ res = -ENOMEM;
9498+ goto out;
9499+ }
9500+ } else {
9501+ cmd_len += cmd->ext_cdb_len;
9502+
9503+ TRACE_DBG("Extended CDB (cmd_len %d)", cmd_len);
9504+
9505+ sioc = kzalloc(sizeof(*sioc) + cmd_len, gfp);
9506+ if (sioc == NULL) {
9507+ res = -ENOMEM;
9508+ goto out;
9509+ }
9510+
9511+ sioc->full_cdb_used = 1;
9512+
9513+ memcpy(sioc->full_cdb, cmd->cdb, cmd->cdb_len);
9514+ memcpy(&sioc->full_cdb[cmd->cdb_len], cmd->ext_cdb,
9515+ cmd->ext_cdb_len);
9516+ }
9517+
9518+ rq = blk_get_request(q, write, gfp);
9519+ if (rq == NULL) {
9520+ res = -ENOMEM;
9521+ goto out_free_sioc;
9522+ }
9523+
9524+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
9525+ rq->cmd_flags |= REQ_QUIET;
9526+
9527+ if (cmd->sg == NULL)
9528+ goto done;
9529+
9530+ if (cmd->data_direction == SCST_DATA_BIDI) {
9531+ struct request *next_rq;
9532+
9533+ if (!test_bit(QUEUE_FLAG_BIDI, &q->queue_flags)) {
9534+ res = -EOPNOTSUPP;
9535+ goto out_free_rq;
9536+ }
9537+
9538+ res = blk_rq_map_kern_sg(rq, cmd->out_sg, cmd->out_sg_cnt, gfp);
9539+ if (res != 0) {
9540+ TRACE_DBG("blk_rq_map_kern_sg() failed: %d", res);
9541+ goto out_free_rq;
9542+ }
9543+
9544+ next_rq = blk_get_request(q, READ, gfp);
9545+ if (next_rq == NULL) {
9546+ res = -ENOMEM;
9547+ goto out_free_unmap;
9548+ }
9549+ rq->next_rq = next_rq;
9550+ next_rq->cmd_type = rq->cmd_type;
9551+
9552+ res = blk_rq_map_kern_sg(next_rq, cmd->sg, cmd->sg_cnt, gfp);
9553+ if (res != 0) {
9554+ TRACE_DBG("blk_rq_map_kern_sg() failed: %d", res);
9555+ goto out_free_unmap;
9556+ }
9557+ } else {
9558+ res = blk_rq_map_kern_sg(rq, cmd->sg, cmd->sg_cnt, gfp);
9559+ if (res != 0) {
9560+ TRACE_DBG("blk_rq_map_kern_sg() failed: %d", res);
9561+ goto out_free_rq;
9562+ }
9563+ }
9564+
9565+done:
9566+ TRACE_DBG("sioc %p, cmd %p", sioc, cmd);
9567+
9568+ sioc->data = cmd;
9569+ sioc->done = done;
9570+
9571+ rq->cmd_len = cmd_len;
9572+ if (cmd->ext_cdb_len == 0) {
9573+ memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
9574+ memcpy(rq->cmd, cmd->cdb, cmd->cdb_len);
9575+ } else
9576+ rq->cmd = sioc->full_cdb;
9577+
9578+ rq->sense = sioc->sense;
9579+ rq->sense_len = sizeof(sioc->sense);
9580+ rq->timeout = cmd->timeout;
9581+ rq->retries = cmd->retries;
9582+ rq->end_io_data = sioc;
9583+
9584+ blk_execute_rq_nowait(rq->q, NULL, rq,
9585+ (cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE), scsi_end_async);
9586+out:
9587+ return res;
9588+
9589+out_free_unmap:
9590+ if (rq->next_rq != NULL) {
9591+ blk_put_request(rq->next_rq);
9592+ rq->next_rq = NULL;
9593+ }
9594+ blk_rq_unmap_kern_sg(rq, res);
9595+
9596+out_free_rq:
9597+ blk_put_request(rq);
9598+
9599+out_free_sioc:
9600+ if (!sioc->full_cdb_used)
9601+ kmem_cache_free(scsi_io_context_cache, sioc);
9602+ else
9603+ kfree(sioc);
9604+ goto out;
9605+}
9606+
9607+/**
9608+ * scst_copy_sg() - copy data between the command's SGs
9609+ *
9610+ * Copies data between cmd->tgt_sg and cmd->sg in direction defined by
9611+ * copy_dir parameter.
9612+ */
9613+void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir copy_dir)
9614+{
9615+ struct scatterlist *src_sg, *dst_sg;
9616+ unsigned int to_copy;
9617+ int atomic = scst_cmd_atomic(cmd);
9618+
9619+ TRACE_ENTRY();
9620+
9621+ if (copy_dir == SCST_SG_COPY_FROM_TARGET) {
9622+ if (cmd->data_direction != SCST_DATA_BIDI) {
9623+ src_sg = cmd->tgt_sg;
9624+ dst_sg = cmd->sg;
9625+ to_copy = cmd->bufflen;
9626+ } else {
9627+ TRACE_MEM("BIDI cmd %p", cmd);
9628+ src_sg = cmd->tgt_out_sg;
9629+ dst_sg = cmd->out_sg;
9630+ to_copy = cmd->out_bufflen;
9631+ }
9632+ } else {
9633+ src_sg = cmd->sg;
9634+ dst_sg = cmd->tgt_sg;
9635+ to_copy = cmd->resp_data_len;
9636+ }
9637+
9638+ TRACE_MEM("cmd %p, copy_dir %d, src_sg %p, dst_sg %p, to_copy %lld",
9639+ cmd, copy_dir, src_sg, dst_sg, (long long)to_copy);
9640+
9641+ if (unlikely(src_sg == NULL) || unlikely(dst_sg == NULL)) {
9642+ /*
9643+ * It can happened, e.g., with scst_user for cmd with delay
9644+ * alloc, which failed with Check Condition.
9645+ */
9646+ goto out;
9647+ }
9648+
9649+ sg_copy(dst_sg, src_sg, 0, to_copy,
9650+ atomic ? KM_SOFTIRQ0 : KM_USER0,
9651+ atomic ? KM_SOFTIRQ1 : KM_USER1);
9652+
9653+out:
9654+ TRACE_EXIT();
9655+ return;
9656+}
9657+EXPORT_SYMBOL_GPL(scst_copy_sg);
9658+
9659+int scst_get_full_buf(struct scst_cmd *cmd, uint8_t **buf)
9660+{
9661+ int res = 0;
9662+
9663+ TRACE_ENTRY();
9664+
9665+ EXTRACHECKS_BUG_ON(cmd->sg_buff_vmallocated);
9666+
9667+ if (scst_get_buf_count(cmd) > 1) {
9668+ int len;
9669+ uint8_t *tmp_buf;
9670+ int full_size;
9671+
9672+ full_size = 0;
9673+ len = scst_get_buf_first(cmd, &tmp_buf);
9674+ while (len > 0) {
9675+ full_size += len;
9676+ scst_put_buf(cmd, tmp_buf);
9677+ len = scst_get_buf_next(cmd, &tmp_buf);
9678+ }
9679+
9680+ *buf = vmalloc(full_size);
9681+ if (*buf == NULL) {
9682+ TRACE(TRACE_OUT_OF_MEM, "vmalloc() failed for opcode "
9683+ "%x", cmd->cdb[0]);
9684+ res = -ENOMEM;
9685+ goto out;
9686+ }
9687+ cmd->sg_buff_vmallocated = 1;
9688+
9689+ if (scst_cmd_get_data_direction(cmd) == SCST_DATA_WRITE) {
9690+ uint8_t *buf_ptr;
9691+
9692+ buf_ptr = *buf;
9693+
9694+ len = scst_get_buf_first(cmd, &tmp_buf);
9695+ while (len > 0) {
9696+ memcpy(buf_ptr, tmp_buf, len);
9697+ buf_ptr += len;
9698+
9699+ scst_put_buf(cmd, tmp_buf);
9700+ len = scst_get_buf_next(cmd, &tmp_buf);
9701+ }
9702+ }
9703+ res = full_size;
9704+ } else
9705+ res = scst_get_buf_first(cmd, buf);
9706+
9707+out:
9708+ TRACE_EXIT_RES(res);
9709+ return res;
9710+}
9711+
9712+void scst_put_full_buf(struct scst_cmd *cmd, uint8_t *buf)
9713+{
9714+ TRACE_ENTRY();
9715+
9716+ if (buf == NULL)
9717+ goto out;
9718+
9719+ if (cmd->sg_buff_vmallocated) {
9720+ if (scst_cmd_get_data_direction(cmd) == SCST_DATA_READ) {
9721+ int len;
9722+ uint8_t *tmp_buf, *buf_p;
9723+
9724+ buf_p = buf;
9725+
9726+ len = scst_get_buf_first(cmd, &tmp_buf);
9727+ while (len > 0) {
9728+ memcpy(tmp_buf, buf_p, len);
9729+ buf_p += len;
9730+
9731+ scst_put_buf(cmd, tmp_buf);
9732+ len = scst_get_buf_next(cmd, &tmp_buf);
9733+ }
9734+
9735+ }
9736+
9737+ cmd->sg_buff_vmallocated = 0;
9738+
9739+ vfree(buf);
9740+ } else
9741+ scst_put_buf(cmd, buf);
9742+
9743+out:
9744+ TRACE_EXIT();
9745+ return;
9746+}
9747+
9748+static const int SCST_CDB_LENGTH[8] = { 6, 10, 10, 0, 16, 12, 0, 0 };
9749+
9750+#define SCST_CDB_GROUP(opcode) ((opcode >> 5) & 0x7)
9751+#define SCST_GET_CDB_LEN(opcode) SCST_CDB_LENGTH[SCST_CDB_GROUP(opcode)]
9752+
9753+/* get_trans_len_x extract x bytes from cdb as length starting from off */
9754+
9755+static int get_trans_cdb_len_10(struct scst_cmd *cmd, uint8_t off)
9756+{
9757+ cmd->cdb_len = 10;
9758+ cmd->bufflen = 0;
9759+ return 0;
9760+}
9761+
9762+static int get_trans_len_block_limit(struct scst_cmd *cmd, uint8_t off)
9763+{
9764+ cmd->bufflen = 6;
9765+ return 0;
9766+}
9767+
9768+static int get_trans_len_read_capacity(struct scst_cmd *cmd, uint8_t off)
9769+{
9770+ cmd->bufflen = 8;
9771+ return 0;
9772+}
9773+
9774+static int get_trans_len_serv_act_in(struct scst_cmd *cmd, uint8_t off)
9775+{
9776+ int res = 0;
9777+
9778+ TRACE_ENTRY();
9779+
9780+ if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) {
9781+ cmd->op_name = "READ CAPACITY(16)";
9782+ cmd->bufflen = be32_to_cpu(get_unaligned((__be32 *)&cmd->cdb[10]));
9783+ cmd->op_flags |= SCST_IMPLICIT_HQ | SCST_REG_RESERVE_ALLOWED |
9784+ SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED;
9785+ } else
9786+ cmd->op_flags |= SCST_UNKNOWN_LENGTH;
9787+
9788+ TRACE_EXIT_RES(res);
9789+ return res;
9790+}
9791+
9792+static int get_trans_len_single(struct scst_cmd *cmd, uint8_t off)
9793+{
9794+ cmd->bufflen = 1;
9795+ return 0;
9796+}
9797+
9798+static int get_trans_len_read_pos(struct scst_cmd *cmd, uint8_t off)
9799+{
9800+ uint8_t *p = (uint8_t *)cmd->cdb + off;
9801+ int res = 0;
9802+
9803+ cmd->bufflen = 0;
9804+ cmd->bufflen |= ((u32)p[0]) << 8;
9805+ cmd->bufflen |= ((u32)p[1]);
9806+
9807+ switch (cmd->cdb[1] & 0x1f) {
9808+ case 0:
9809+ case 1:
9810+ case 6:
9811+ if (cmd->bufflen != 0) {
9812+ PRINT_ERROR("READ POSITION: Invalid non-zero (%d) "
9813+ "allocation length for service action %x",
9814+ cmd->bufflen, cmd->cdb[1] & 0x1f);
9815+ goto out_inval;
9816+ }
9817+ break;
9818+ }
9819+
9820+ switch (cmd->cdb[1] & 0x1f) {
9821+ case 0:
9822+ case 1:
9823+ cmd->bufflen = 20;
9824+ break;
9825+ case 6:
9826+ cmd->bufflen = 32;
9827+ break;
9828+ case 8:
9829+ cmd->bufflen = max(28, cmd->bufflen);
9830+ break;
9831+ default:
9832+ PRINT_ERROR("READ POSITION: Invalid service action %x",
9833+ cmd->cdb[1] & 0x1f);
9834+ goto out_inval;
9835+ }
9836+
9837+out:
9838+ return res;
9839+
9840+out_inval:
9841+ scst_set_cmd_error(cmd,
9842+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
9843+ res = 1;
9844+ goto out;
9845+}
9846+
9847+static int get_trans_len_prevent_allow_medium_removal(struct scst_cmd *cmd,
9848+ uint8_t off)
9849+{
9850+ if ((cmd->cdb[4] & 3) == 0)
9851+ cmd->op_flags |= SCST_REG_RESERVE_ALLOWED |
9852+ SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED;
9853+ return 0;
9854+}
9855+
9856+static int get_trans_len_start_stop(struct scst_cmd *cmd, uint8_t off)
9857+{
9858+ if ((cmd->cdb[4] & 0xF1) == 0x1)
9859+ cmd->op_flags |= SCST_REG_RESERVE_ALLOWED |
9860+ SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED;
9861+ return 0;
9862+}
9863+
9864+static int get_trans_len_3_read_elem_stat(struct scst_cmd *cmd, uint8_t off)
9865+{
9866+ const uint8_t *p = cmd->cdb + off;
9867+
9868+ cmd->bufflen = 0;
9869+ cmd->bufflen |= ((u32)p[0]) << 16;
9870+ cmd->bufflen |= ((u32)p[1]) << 8;
9871+ cmd->bufflen |= ((u32)p[2]);
9872+
9873+ if ((cmd->cdb[6] & 0x2) == 0x2)
9874+ cmd->op_flags |= SCST_REG_RESERVE_ALLOWED |
9875+ SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED;
9876+ return 0;
9877+}
9878+
9879+static int get_trans_len_1(struct scst_cmd *cmd, uint8_t off)
9880+{
9881+ cmd->bufflen = (u32)cmd->cdb[off];
9882+ return 0;
9883+}
9884+
9885+static int get_trans_len_1_256(struct scst_cmd *cmd, uint8_t off)
9886+{
9887+ cmd->bufflen = (u32)cmd->cdb[off];
9888+ if (cmd->bufflen == 0)
9889+ cmd->bufflen = 256;
9890+ return 0;
9891+}
9892+
9893+static int get_trans_len_2(struct scst_cmd *cmd, uint8_t off)
9894+{
9895+ const uint8_t *p = cmd->cdb + off;
9896+
9897+ cmd->bufflen = 0;
9898+ cmd->bufflen |= ((u32)p[0]) << 8;
9899+ cmd->bufflen |= ((u32)p[1]);
9900+
9901+ return 0;
9902+}
9903+
9904+static int get_trans_len_3(struct scst_cmd *cmd, uint8_t off)
9905+{
9906+ const uint8_t *p = cmd->cdb + off;
9907+
9908+ cmd->bufflen = 0;
9909+ cmd->bufflen |= ((u32)p[0]) << 16;
9910+ cmd->bufflen |= ((u32)p[1]) << 8;
9911+ cmd->bufflen |= ((u32)p[2]);
9912+
9913+ return 0;
9914+}
9915+
9916+static int get_trans_len_4(struct scst_cmd *cmd, uint8_t off)
9917+{
9918+ const uint8_t *p = cmd->cdb + off;
9919+
9920+ cmd->bufflen = 0;
9921+ cmd->bufflen |= ((u32)p[0]) << 24;
9922+ cmd->bufflen |= ((u32)p[1]) << 16;
9923+ cmd->bufflen |= ((u32)p[2]) << 8;
9924+ cmd->bufflen |= ((u32)p[3]);
9925+
9926+ return 0;
9927+}
9928+
9929+static int get_trans_len_none(struct scst_cmd *cmd, uint8_t off)
9930+{
9931+ cmd->bufflen = 0;
9932+ return 0;
9933+}
9934+
9935+static int get_bidi_trans_len_2(struct scst_cmd *cmd, uint8_t off)
9936+{
9937+ const uint8_t *p = cmd->cdb + off;
9938+
9939+ cmd->bufflen = 0;
9940+ cmd->bufflen |= ((u32)p[0]) << 8;
9941+ cmd->bufflen |= ((u32)p[1]);
9942+
9943+ cmd->out_bufflen = cmd->bufflen;
9944+
9945+ return 0;
9946+}
9947+
9948+/**
9949+ * scst_get_cdb_info() - fill various info about the command's CDB
9950+ *
9951+ * Description:
9952+ * Fills various info about the command's CDB in the corresponding fields
9953+ * in the command.
9954+ *
9955+ * Returns: 0 on success, <0 if command is unknown, >0 if command
9956+ * is invalid.
9957+ */
9958+int scst_get_cdb_info(struct scst_cmd *cmd)
9959+{
9960+ int dev_type = cmd->dev->type;
9961+ int i, res = 0;
9962+ uint8_t op;
9963+ const struct scst_sdbops *ptr = NULL;
9964+
9965+ TRACE_ENTRY();
9966+
9967+ op = cmd->cdb[0]; /* get clear opcode */
9968+
9969+ TRACE_DBG("opcode=%02x, cdblen=%d bytes, tblsize=%d, "
9970+ "dev_type=%d", op, SCST_GET_CDB_LEN(op), SCST_CDB_TBL_SIZE,
9971+ dev_type);
9972+
9973+ i = scst_scsi_op_list[op];
9974+ while (i < SCST_CDB_TBL_SIZE && scst_scsi_op_table[i].ops == op) {
9975+ if (scst_scsi_op_table[i].devkey[dev_type] != SCST_CDB_NOTSUPP) {
9976+ ptr = &scst_scsi_op_table[i];
9977+ TRACE_DBG("op = 0x%02x+'%c%c%c%c%c%c%c%c%c%c'+<%s>",
9978+ ptr->ops, ptr->devkey[0], /* disk */
9979+ ptr->devkey[1], /* tape */
9980+ ptr->devkey[2], /* printer */
9981+ ptr->devkey[3], /* cpu */
9982+ ptr->devkey[4], /* cdr */
9983+ ptr->devkey[5], /* cdrom */
9984+ ptr->devkey[6], /* scanner */
9985+ ptr->devkey[7], /* worm */
9986+ ptr->devkey[8], /* changer */
9987+ ptr->devkey[9], /* commdev */
9988+ ptr->op_name);
9989+ TRACE_DBG("direction=%d flags=%d off=%d",
9990+ ptr->direction,
9991+ ptr->flags,
9992+ ptr->off);
9993+ break;
9994+ }
9995+ i++;
9996+ }
9997+
9998+ if (unlikely(ptr == NULL)) {
9999+ /* opcode not found or now not used */
10000+ TRACE(TRACE_MINOR, "Unknown opcode 0x%x for type %d", op,
10001+ dev_type);
10002+ res = -1;
10003+ goto out;
10004+ }
10005+
10006+ cmd->cdb_len = SCST_GET_CDB_LEN(op);
10007+ cmd->op_name = ptr->op_name;
10008+ cmd->data_direction = ptr->direction;
10009+ cmd->op_flags = ptr->flags | SCST_INFO_VALID;
10010+ res = (*ptr->get_trans_len)(cmd, ptr->off);
10011+
10012+out:
10013+ TRACE_EXIT_RES(res);
10014+ return res;
10015+}
10016+EXPORT_SYMBOL_GPL(scst_get_cdb_info);
10017+
10018+/* Packs SCST LUN back to SCSI form */
10019+__be64 scst_pack_lun(const uint64_t lun, unsigned int addr_method)
10020+{
10021+ uint64_t res;
10022+ uint16_t *p = (uint16_t *)&res;
10023+
10024+ res = lun;
10025+
10026+ if ((addr_method == SCST_LUN_ADDR_METHOD_FLAT) && (lun != 0)) {
10027+ /*
10028+ * Flat space: luns other than 0 should use flat space
10029+ * addressing method.
10030+ */
10031+ *p = 0x7fff & *p;
10032+ *p = 0x4000 | *p;
10033+ }
10034+ /* Default is to use peripheral device addressing mode */
10035+
10036+ *p = (__force u16)cpu_to_be16(*p);
10037+
10038+ TRACE_EXIT_HRES((unsigned long)res);
10039+ return (__force __be64)res;
10040+}
10041+
10042+/*
10043+ * Routine to extract a lun number from an 8-byte LUN structure
10044+ * in network byte order (BE).
10045+ * (see SAM-2, Section 4.12.3 page 40)
10046+ * Supports 2 types of lun unpacking: peripheral and logical unit.
10047+ */
10048+uint64_t scst_unpack_lun(const uint8_t *lun, int len)
10049+{
10050+ uint64_t res = NO_SUCH_LUN;
10051+ int address_method;
10052+
10053+ TRACE_ENTRY();
10054+
10055+ TRACE_BUFF_FLAG(TRACE_DEBUG, "Raw LUN", lun, len);
10056+
10057+ if (unlikely(len < 2)) {
10058+ PRINT_ERROR("Illegal lun length %d, expected 2 bytes or "
10059+ "more", len);
10060+ goto out;
10061+ }
10062+
10063+ if (len > 2) {
10064+ switch (len) {
10065+ case 8:
10066+ if ((*((__be64 *)lun) &
10067+ __constant_cpu_to_be64(0x0000FFFFFFFFFFFFLL)) != 0)
10068+ goto out_err;
10069+ break;
10070+ case 4:
10071+ if (*((__be16 *)&lun[2]) != 0)
10072+ goto out_err;
10073+ break;
10074+ case 6:
10075+ if (*((__be32 *)&lun[2]) != 0)
10076+ goto out_err;
10077+ break;
10078+ default:
10079+ goto out_err;
10080+ }
10081+ }
10082+
10083+ address_method = (*lun) >> 6; /* high 2 bits of byte 0 */
10084+ switch (address_method) {
10085+ case 0: /* peripheral device addressing method */
10086+#if 0
10087+ if (*lun) {
10088+ PRINT_ERROR("Illegal BUS INDENTIFIER in LUN "
10089+ "peripheral device addressing method 0x%02x, "
10090+ "expected 0", *lun);
10091+ break;
10092+ }
10093+ res = *(lun + 1);
10094+ break;
10095+#else
10096+ /*
10097+ * Looks like it's legal to use it as flat space addressing
10098+ * method as well
10099+ */
10100+
10101+ /* go through */
10102+#endif
10103+
10104+ case 1: /* flat space addressing method */
10105+ res = *(lun + 1) | (((*lun) & 0x3f) << 8);
10106+ break;
10107+
10108+ case 2: /* logical unit addressing method */
10109+ if (*lun & 0x3f) {
10110+ PRINT_ERROR("Illegal BUS NUMBER in LUN logical unit "
10111+ "addressing method 0x%02x, expected 0",
10112+ *lun & 0x3f);
10113+ break;
10114+ }
10115+ if (*(lun + 1) & 0xe0) {
10116+ PRINT_ERROR("Illegal TARGET in LUN logical unit "
10117+ "addressing method 0x%02x, expected 0",
10118+ (*(lun + 1) & 0xf8) >> 5);
10119+ break;
10120+ }
10121+ res = *(lun + 1) & 0x1f;
10122+ break;
10123+
10124+ case 3: /* extended logical unit addressing method */
10125+ default:
10126+ PRINT_ERROR("Unimplemented LUN addressing method %u",
10127+ address_method);
10128+ break;
10129+ }
10130+
10131+out:
10132+ TRACE_EXIT_RES((int)res);
10133+ return res;
10134+
10135+out_err:
10136+ PRINT_ERROR("%s", "Multi-level LUN unimplemented");
10137+ goto out;
10138+}
10139+
10140+/**
10141+ ** Generic parse() support routines.
10142+ ** Done via pointer on functions to avoid unneeded dereferences on
10143+ ** the fast path.
10144+ **/
10145+
10146+/**
10147+ * scst_calc_block_shift() - calculate block shift
10148+ *
10149+ * Calculates and returns block shift for the given sector size
10150+ */
10151+int scst_calc_block_shift(int sector_size)
10152+{
10153+ int block_shift = 0;
10154+ int t;
10155+
10156+ if (sector_size == 0)
10157+ sector_size = 512;
10158+
10159+ t = sector_size;
10160+ while (1) {
10161+ if ((t & 1) != 0)
10162+ break;
10163+ t >>= 1;
10164+ block_shift++;
10165+ }
10166+ if (block_shift < 9) {
10167+ PRINT_ERROR("Wrong sector size %d", sector_size);
10168+ block_shift = -1;
10169+ }
10170+
10171+ TRACE_EXIT_RES(block_shift);
10172+ return block_shift;
10173+}
10174+EXPORT_SYMBOL_GPL(scst_calc_block_shift);
10175+
10176+/**
10177+ * scst_sbc_generic_parse() - generic SBC parsing
10178+ *
10179+ * Generic parse() for SBC (disk) devices
10180+ */
10181+int scst_sbc_generic_parse(struct scst_cmd *cmd,
10182+ int (*get_block_shift)(struct scst_cmd *cmd))
10183+{
10184+ int res = 0;
10185+
10186+ TRACE_ENTRY();
10187+
10188+ /*
10189+ * SCST sets good defaults for cmd->data_direction and cmd->bufflen,
10190+ * therefore change them only if necessary
10191+ */
10192+
10193+ TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
10194+ cmd->op_name, cmd->data_direction, cmd->op_flags, cmd->bufflen);
10195+
10196+ switch (cmd->cdb[0]) {
10197+ case VERIFY_6:
10198+ case VERIFY:
10199+ case VERIFY_12:
10200+ case VERIFY_16:
10201+ if ((cmd->cdb[1] & BYTCHK) == 0) {
10202+ cmd->data_len = cmd->bufflen << get_block_shift(cmd);
10203+ cmd->bufflen = 0;
10204+ goto set_timeout;
10205+ } else
10206+ cmd->data_len = 0;
10207+ break;
10208+ default:
10209+ /* It's all good */
10210+ break;
10211+ }
10212+
10213+ if (cmd->op_flags & SCST_TRANSFER_LEN_TYPE_FIXED) {
10214+ int block_shift = get_block_shift(cmd);
10215+ /*
10216+ * No need for locks here, since *_detach() can not be
10217+ * called, when there are existing commands.
10218+ */
10219+ cmd->bufflen = cmd->bufflen << block_shift;
10220+ cmd->out_bufflen = cmd->out_bufflen << block_shift;
10221+ }
10222+
10223+set_timeout:
10224+ if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
10225+ cmd->timeout = SCST_GENERIC_DISK_REG_TIMEOUT;
10226+ else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
10227+ cmd->timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT;
10228+ else if (cmd->op_flags & SCST_LONG_TIMEOUT)
10229+ cmd->timeout = SCST_GENERIC_DISK_LONG_TIMEOUT;
10230+
10231+ TRACE_DBG("res %d, bufflen %d, data_len %d, direct %d",
10232+ res, cmd->bufflen, cmd->data_len, cmd->data_direction);
10233+
10234+ TRACE_EXIT_RES(res);
10235+ return res;
10236+}
10237+EXPORT_SYMBOL_GPL(scst_sbc_generic_parse);
10238+
10239+/**
10240+ * scst_cdrom_generic_parse() - generic MMC parse
10241+ *
10242+ * Generic parse() for MMC (cdrom) devices
10243+ */
10244+int scst_cdrom_generic_parse(struct scst_cmd *cmd,
10245+ int (*get_block_shift)(struct scst_cmd *cmd))
10246+{
10247+ int res = 0;
10248+
10249+ TRACE_ENTRY();
10250+
10251+ /*
10252+ * SCST sets good defaults for cmd->data_direction and cmd->bufflen,
10253+ * therefore change them only if necessary
10254+ */
10255+
10256+ TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
10257+ cmd->op_name, cmd->data_direction, cmd->op_flags, cmd->bufflen);
10258+
10259+ cmd->cdb[1] &= 0x1f;
10260+
10261+ switch (cmd->cdb[0]) {
10262+ case VERIFY_6:
10263+ case VERIFY:
10264+ case VERIFY_12:
10265+ case VERIFY_16:
10266+ if ((cmd->cdb[1] & BYTCHK) == 0) {
10267+ cmd->data_len = cmd->bufflen << get_block_shift(cmd);
10268+ cmd->bufflen = 0;
10269+ goto set_timeout;
10270+ }
10271+ break;
10272+ default:
10273+ /* It's all good */
10274+ break;
10275+ }
10276+
10277+ if (cmd->op_flags & SCST_TRANSFER_LEN_TYPE_FIXED) {
10278+ int block_shift = get_block_shift(cmd);
10279+ cmd->bufflen = cmd->bufflen << block_shift;
10280+ cmd->out_bufflen = cmd->out_bufflen << block_shift;
10281+ }
10282+
10283+set_timeout:
10284+ if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
10285+ cmd->timeout = SCST_GENERIC_CDROM_REG_TIMEOUT;
10286+ else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
10287+ cmd->timeout = SCST_GENERIC_CDROM_SMALL_TIMEOUT;
10288+ else if (cmd->op_flags & SCST_LONG_TIMEOUT)
10289+ cmd->timeout = SCST_GENERIC_CDROM_LONG_TIMEOUT;
10290+
10291+ TRACE_DBG("res=%d, bufflen=%d, direct=%d", res, cmd->bufflen,
10292+ cmd->data_direction);
10293+
10294+ TRACE_EXIT();
10295+ return res;
10296+}
10297+EXPORT_SYMBOL_GPL(scst_cdrom_generic_parse);
10298+
10299+/**
10300+ * scst_modisk_generic_parse() - generic MO parse
10301+ *
10302+ * Generic parse() for MO disk devices
10303+ */
10304+int scst_modisk_generic_parse(struct scst_cmd *cmd,
10305+ int (*get_block_shift)(struct scst_cmd *cmd))
10306+{
10307+ int res = 0;
10308+
10309+ TRACE_ENTRY();
10310+
10311+ /*
10312+ * SCST sets good defaults for cmd->data_direction and cmd->bufflen,
10313+ * therefore change them only if necessary
10314+ */
10315+
10316+ TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
10317+ cmd->op_name, cmd->data_direction, cmd->op_flags, cmd->bufflen);
10318+
10319+ cmd->cdb[1] &= 0x1f;
10320+
10321+ switch (cmd->cdb[0]) {
10322+ case VERIFY_6:
10323+ case VERIFY:
10324+ case VERIFY_12:
10325+ case VERIFY_16:
10326+ if ((cmd->cdb[1] & BYTCHK) == 0) {
10327+ cmd->data_len = cmd->bufflen << get_block_shift(cmd);
10328+ cmd->bufflen = 0;
10329+ goto set_timeout;
10330+ }
10331+ break;
10332+ default:
10333+ /* It's all good */
10334+ break;
10335+ }
10336+
10337+ if (cmd->op_flags & SCST_TRANSFER_LEN_TYPE_FIXED) {
10338+ int block_shift = get_block_shift(cmd);
10339+ cmd->bufflen = cmd->bufflen << block_shift;
10340+ cmd->out_bufflen = cmd->out_bufflen << block_shift;
10341+ }
10342+
10343+set_timeout:
10344+ if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
10345+ cmd->timeout = SCST_GENERIC_MODISK_REG_TIMEOUT;
10346+ else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
10347+ cmd->timeout = SCST_GENERIC_MODISK_SMALL_TIMEOUT;
10348+ else if (cmd->op_flags & SCST_LONG_TIMEOUT)
10349+ cmd->timeout = SCST_GENERIC_MODISK_LONG_TIMEOUT;
10350+
10351+ TRACE_DBG("res=%d, bufflen=%d, direct=%d", res, cmd->bufflen,
10352+ cmd->data_direction);
10353+
10354+ TRACE_EXIT_RES(res);
10355+ return res;
10356+}
10357+EXPORT_SYMBOL_GPL(scst_modisk_generic_parse);
10358+
10359+/**
10360+ * scst_tape_generic_parse() - generic tape parse
10361+ *
10362+ * Generic parse() for tape devices
10363+ */
10364+int scst_tape_generic_parse(struct scst_cmd *cmd,
10365+ int (*get_block_size)(struct scst_cmd *cmd))
10366+{
10367+ int res = 0;
10368+
10369+ TRACE_ENTRY();
10370+
10371+ /*
10372+ * SCST sets good defaults for cmd->data_direction and cmd->bufflen,
10373+ * therefore change them only if necessary
10374+ */
10375+
10376+ TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
10377+ cmd->op_name, cmd->data_direction, cmd->op_flags, cmd->bufflen);
10378+
10379+ if (cmd->cdb[0] == READ_POSITION) {
10380+ int tclp = cmd->cdb[1] & 4;
10381+ int long_bit = cmd->cdb[1] & 2;
10382+ int bt = cmd->cdb[1] & 1;
10383+
10384+ if ((tclp == long_bit) && (!bt || !long_bit)) {
10385+ cmd->bufflen =
10386+ tclp ? POSITION_LEN_LONG : POSITION_LEN_SHORT;
10387+ cmd->data_direction = SCST_DATA_READ;
10388+ } else {
10389+ cmd->bufflen = 0;
10390+ cmd->data_direction = SCST_DATA_NONE;
10391+ }
10392+ }
10393+
10394+ if (cmd->op_flags & SCST_TRANSFER_LEN_TYPE_FIXED & cmd->cdb[1]) {
10395+ int block_size = get_block_size(cmd);
10396+ cmd->bufflen = cmd->bufflen * block_size;
10397+ cmd->out_bufflen = cmd->out_bufflen * block_size;
10398+ }
10399+
10400+ if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
10401+ cmd->timeout = SCST_GENERIC_TAPE_REG_TIMEOUT;
10402+ else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
10403+ cmd->timeout = SCST_GENERIC_TAPE_SMALL_TIMEOUT;
10404+ else if (cmd->op_flags & SCST_LONG_TIMEOUT)
10405+ cmd->timeout = SCST_GENERIC_TAPE_LONG_TIMEOUT;
10406+
10407+ TRACE_EXIT_RES(res);
10408+ return res;
10409+}
10410+EXPORT_SYMBOL_GPL(scst_tape_generic_parse);
10411+
10412+static int scst_null_parse(struct scst_cmd *cmd)
10413+{
10414+ int res = 0;
10415+
10416+ TRACE_ENTRY();
10417+
10418+ /*
10419+ * SCST sets good defaults for cmd->data_direction and cmd->bufflen,
10420+ * therefore change them only if necessary
10421+ */
10422+
10423+ TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
10424+ cmd->op_name, cmd->data_direction, cmd->op_flags, cmd->bufflen);
10425+#if 0
10426+ switch (cmd->cdb[0]) {
10427+ default:
10428+ /* It's all good */
10429+ break;
10430+ }
10431+#endif
10432+ TRACE_DBG("res %d bufflen %d direct %d",
10433+ res, cmd->bufflen, cmd->data_direction);
10434+
10435+ TRACE_EXIT();
10436+ return res;
10437+}
10438+
10439+/**
10440+ * scst_changer_generic_parse() - generic changer parse
10441+ *
10442+ * Generic parse() for changer devices
10443+ */
10444+int scst_changer_generic_parse(struct scst_cmd *cmd,
10445+ int (*nothing)(struct scst_cmd *cmd))
10446+{
10447+ int res = scst_null_parse(cmd);
10448+
10449+ if (cmd->op_flags & SCST_LONG_TIMEOUT)
10450+ cmd->timeout = SCST_GENERIC_CHANGER_LONG_TIMEOUT;
10451+ else
10452+ cmd->timeout = SCST_GENERIC_CHANGER_TIMEOUT;
10453+
10454+ return res;
10455+}
10456+EXPORT_SYMBOL_GPL(scst_changer_generic_parse);
10457+
10458+/**
10459+ * scst_processor_generic_parse - generic SCSI processor parse
10460+ *
10461+ * Generic parse() for SCSI processor devices
10462+ */
10463+int scst_processor_generic_parse(struct scst_cmd *cmd,
10464+ int (*nothing)(struct scst_cmd *cmd))
10465+{
10466+ int res = scst_null_parse(cmd);
10467+
10468+ if (cmd->op_flags & SCST_LONG_TIMEOUT)
10469+ cmd->timeout = SCST_GENERIC_PROCESSOR_LONG_TIMEOUT;
10470+ else
10471+ cmd->timeout = SCST_GENERIC_PROCESSOR_TIMEOUT;
10472+
10473+ return res;
10474+}
10475+EXPORT_SYMBOL_GPL(scst_processor_generic_parse);
10476+
10477+/**
10478+ * scst_raid_generic_parse() - generic RAID parse
10479+ *
10480+ * Generic parse() for RAID devices
10481+ */
10482+int scst_raid_generic_parse(struct scst_cmd *cmd,
10483+ int (*nothing)(struct scst_cmd *cmd))
10484+{
10485+ int res = scst_null_parse(cmd);
10486+
10487+ if (cmd->op_flags & SCST_LONG_TIMEOUT)
10488+ cmd->timeout = SCST_GENERIC_RAID_LONG_TIMEOUT;
10489+ else
10490+ cmd->timeout = SCST_GENERIC_RAID_TIMEOUT;
10491+
10492+ return res;
10493+}
10494+EXPORT_SYMBOL_GPL(scst_raid_generic_parse);
10495+
10496+/**
10497+ ** Generic dev_done() support routines.
10498+ ** Done via pointer on functions to avoid unneeded dereferences on
10499+ ** the fast path.
10500+ **/
10501+
10502+/**
10503+ * scst_block_generic_dev_done() - generic SBC dev_done
10504+ *
10505+ * Generic dev_done() for block (SBC) devices
10506+ */
10507+int scst_block_generic_dev_done(struct scst_cmd *cmd,
10508+ void (*set_block_shift)(struct scst_cmd *cmd, int block_shift))
10509+{
10510+ int opcode = cmd->cdb[0];
10511+ int status = cmd->status;
10512+ int res = SCST_CMD_STATE_DEFAULT;
10513+
10514+ TRACE_ENTRY();
10515+
10516+ /*
10517+ * SCST sets good defaults for cmd->is_send_status and
10518+ * cmd->resp_data_len based on cmd->status and cmd->data_direction,
10519+ * therefore change them only if necessary
10520+ */
10521+
10522+ if ((status == SAM_STAT_GOOD) || (status == SAM_STAT_CONDITION_MET)) {
10523+ switch (opcode) {
10524+ case READ_CAPACITY:
10525+ {
10526+ /* Always keep track of disk capacity */
10527+ int buffer_size, sector_size, sh;
10528+ uint8_t *buffer;
10529+
10530+ buffer_size = scst_get_buf_first(cmd, &buffer);
10531+ if (unlikely(buffer_size <= 0)) {
10532+ if (buffer_size < 0) {
10533+ PRINT_ERROR("%s: Unable to get the"
10534+ " buffer (%d)", __func__, buffer_size);
10535+ }
10536+ goto out;
10537+ }
10538+
10539+ sector_size =
10540+ ((buffer[4] << 24) | (buffer[5] << 16) |
10541+ (buffer[6] << 8) | (buffer[7] << 0));
10542+ scst_put_buf(cmd, buffer);
10543+ if (sector_size != 0)
10544+ sh = scst_calc_block_shift(sector_size);
10545+ else
10546+ sh = 0;
10547+ set_block_shift(cmd, sh);
10548+ TRACE_DBG("block_shift %d", sh);
10549+ break;
10550+ }
10551+ default:
10552+ /* It's all good */
10553+ break;
10554+ }
10555+ }
10556+
10557+ TRACE_DBG("cmd->is_send_status=%x, cmd->resp_data_len=%d, "
10558+ "res=%d", cmd->is_send_status, cmd->resp_data_len, res);
10559+
10560+out:
10561+ TRACE_EXIT_RES(res);
10562+ return res;
10563+}
10564+EXPORT_SYMBOL_GPL(scst_block_generic_dev_done);
10565+
10566+/**
10567+ * scst_tape_generic_dev_done() - generic tape dev done
10568+ *
10569+ * Generic dev_done() for tape devices
10570+ */
10571+int scst_tape_generic_dev_done(struct scst_cmd *cmd,
10572+ void (*set_block_size)(struct scst_cmd *cmd, int block_shift))
10573+{
10574+ int opcode = cmd->cdb[0];
10575+ int res = SCST_CMD_STATE_DEFAULT;
10576+ int buffer_size, bs;
10577+ uint8_t *buffer = NULL;
10578+
10579+ TRACE_ENTRY();
10580+
10581+ /*
10582+ * SCST sets good defaults for cmd->is_send_status and
10583+ * cmd->resp_data_len based on cmd->status and cmd->data_direction,
10584+ * therefore change them only if necessary
10585+ */
10586+
10587+ if (cmd->status != SAM_STAT_GOOD)
10588+ goto out;
10589+
10590+ switch (opcode) {
10591+ case MODE_SENSE:
10592+ case MODE_SELECT:
10593+ buffer_size = scst_get_buf_first(cmd, &buffer);
10594+ if (unlikely(buffer_size <= 0)) {
10595+ if (buffer_size < 0) {
10596+ PRINT_ERROR("%s: Unable to get the buffer (%d)",
10597+ __func__, buffer_size);
10598+ }
10599+ goto out;
10600+ }
10601+ break;
10602+ }
10603+
10604+ switch (opcode) {
10605+ case MODE_SENSE:
10606+ TRACE_DBG("%s", "MODE_SENSE");
10607+ if ((cmd->cdb[2] & 0xC0) == 0) {
10608+ if (buffer[3] == 8) {
10609+ bs = (buffer[9] << 16) |
10610+ (buffer[10] << 8) | buffer[11];
10611+ set_block_size(cmd, bs);
10612+ }
10613+ }
10614+ break;
10615+ case MODE_SELECT:
10616+ TRACE_DBG("%s", "MODE_SELECT");
10617+ if (buffer[3] == 8) {
10618+ bs = (buffer[9] << 16) | (buffer[10] << 8) |
10619+ (buffer[11]);
10620+ set_block_size(cmd, bs);
10621+ }
10622+ break;
10623+ default:
10624+ /* It's all good */
10625+ break;
10626+ }
10627+
10628+ switch (opcode) {
10629+ case MODE_SENSE:
10630+ case MODE_SELECT:
10631+ scst_put_buf(cmd, buffer);
10632+ break;
10633+ }
10634+
10635+out:
10636+ TRACE_EXIT_RES(res);
10637+ return res;
10638+}
10639+EXPORT_SYMBOL_GPL(scst_tape_generic_dev_done);
10640+
10641+static void scst_check_internal_sense(struct scst_device *dev, int result,
10642+ uint8_t *sense, int sense_len)
10643+{
10644+ TRACE_ENTRY();
10645+
10646+ if (host_byte(result) == DID_RESET) {
10647+ int sl;
10648+ TRACE(TRACE_MGMT, "DID_RESET received for device %s, "
10649+ "triggering reset UA", dev->virt_name);
10650+ sl = scst_set_sense(sense, sense_len, dev->d_sense,
10651+ SCST_LOAD_SENSE(scst_sense_reset_UA));
10652+ scst_dev_check_set_UA(dev, NULL, sense, sl);
10653+ } else if ((status_byte(result) == CHECK_CONDITION) &&
10654+ scst_is_ua_sense(sense, sense_len))
10655+ scst_dev_check_set_UA(dev, NULL, sense, sense_len);
10656+
10657+ TRACE_EXIT();
10658+ return;
10659+}
10660+
10661+/**
10662+ * scst_to_dma_dir() - translate SCST's data direction to DMA direction
10663+ *
10664+ * Translates SCST's data direction to DMA one from backend storage
10665+ * perspective.
10666+ */
10667+enum dma_data_direction scst_to_dma_dir(int scst_dir)
10668+{
10669+ static const enum dma_data_direction tr_tbl[] = { DMA_NONE,
10670+ DMA_TO_DEVICE, DMA_FROM_DEVICE, DMA_BIDIRECTIONAL, DMA_NONE };
10671+
10672+ return tr_tbl[scst_dir];
10673+}
10674+EXPORT_SYMBOL(scst_to_dma_dir);
10675+
10676+/*
10677+ * scst_to_tgt_dma_dir() - translate SCST data direction to DMA direction
10678+ *
10679+ * Translates SCST data direction to DMA data direction from the perspective
10680+ * of a target.
10681+ */
10682+enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir)
10683+{
10684+ static const enum dma_data_direction tr_tbl[] = { DMA_NONE,
10685+ DMA_FROM_DEVICE, DMA_TO_DEVICE, DMA_BIDIRECTIONAL, DMA_NONE };
10686+
10687+ return tr_tbl[scst_dir];
10688+}
10689+EXPORT_SYMBOL(scst_to_tgt_dma_dir);
10690+
10691+/**
10692+ * scst_obtain_device_parameters() - obtain device control parameters
10693+ *
10694+ * Issues a MODE SENSE for control mode page data and sets the corresponding
10695+ * dev's parameter from it. Returns 0 on success and not 0 otherwise.
10696+ */
10697+int scst_obtain_device_parameters(struct scst_device *dev)
10698+{
10699+ int rc, i;
10700+ uint8_t cmd[16];
10701+ uint8_t buffer[4+0x0A];
10702+ uint8_t sense_buffer[SCSI_SENSE_BUFFERSIZE];
10703+
10704+ TRACE_ENTRY();
10705+
10706+ EXTRACHECKS_BUG_ON(dev->scsi_dev == NULL);
10707+
10708+ for (i = 0; i < 5; i++) {
10709+ /* Get control mode page */
10710+ memset(cmd, 0, sizeof(cmd));
10711+#if 0
10712+ cmd[0] = MODE_SENSE_10;
10713+ cmd[1] = 0;
10714+ cmd[2] = 0x0A;
10715+ cmd[8] = sizeof(buffer); /* it's < 256 */
10716+#else
10717+ cmd[0] = MODE_SENSE;
10718+ cmd[1] = 8; /* DBD */
10719+ cmd[2] = 0x0A;
10720+ cmd[4] = sizeof(buffer);
10721+#endif
10722+
10723+ memset(buffer, 0, sizeof(buffer));
10724+ memset(sense_buffer, 0, sizeof(sense_buffer));
10725+
10726+ TRACE(TRACE_SCSI, "%s", "Doing internal MODE_SENSE");
10727+ rc = scsi_execute(dev->scsi_dev, cmd, SCST_DATA_READ, buffer,
10728+ sizeof(buffer), sense_buffer, 15, 0, 0
10729+ , NULL
10730+ );
10731+
10732+ TRACE_DBG("MODE_SENSE done: %x", rc);
10733+
10734+ if (scsi_status_is_good(rc)) {
10735+ int q;
10736+
10737+ PRINT_BUFF_FLAG(TRACE_SCSI, "Returned control mode "
10738+ "page data", buffer, sizeof(buffer));
10739+
10740+ dev->tst = buffer[4+2] >> 5;
10741+ q = buffer[4+3] >> 4;
10742+ if (q > SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER) {
10743+ PRINT_ERROR("Too big QUEUE ALG %x, dev %s",
10744+ dev->queue_alg, dev->virt_name);
10745+ }
10746+ dev->queue_alg = q;
10747+ dev->swp = (buffer[4+4] & 0x8) >> 3;
10748+ dev->tas = (buffer[4+5] & 0x40) >> 6;
10749+ dev->d_sense = (buffer[4+2] & 0x4) >> 2;
10750+
10751+ /*
10752+ * Unfortunately, SCSI ML doesn't provide a way to
10753+ * specify commands task attribute, so we can rely on
10754+ * device's restricted reordering only. Linux I/O
10755+ * subsystem doesn't reorder pass-through (PC) requests.
10756+ */
10757+ dev->has_own_order_mgmt = !dev->queue_alg;
10758+
10759+ PRINT_INFO("Device %s: TST %x, QUEUE ALG %x, SWP %x, "
10760+ "TAS %x, D_SENSE %d, has_own_order_mgmt %d",
10761+ dev->virt_name, dev->tst, dev->queue_alg,
10762+ dev->swp, dev->tas, dev->d_sense,
10763+ dev->has_own_order_mgmt);
10764+
10765+ goto out;
10766+ } else {
10767+ scst_check_internal_sense(dev, rc, sense_buffer,
10768+ sizeof(sense_buffer));
10769+#if 0
10770+ if ((status_byte(rc) == CHECK_CONDITION) &&
10771+ SCST_SENSE_VALID(sense_buffer)) {
10772+#else
10773+ /*
10774+ * 3ware controller is buggy and returns CONDITION_GOOD
10775+ * instead of CHECK_CONDITION
10776+ */
10777+ if (SCST_SENSE_VALID(sense_buffer)) {
10778+#endif
10779+ PRINT_BUFF_FLAG(TRACE_SCSI, "Returned sense "
10780+ "data", sense_buffer,
10781+ sizeof(sense_buffer));
10782+ if (scst_analyze_sense(sense_buffer,
10783+ sizeof(sense_buffer),
10784+ SCST_SENSE_KEY_VALID,
10785+ ILLEGAL_REQUEST, 0, 0)) {
10786+ PRINT_INFO("Device %s doesn't support "
10787+ "MODE SENSE", dev->virt_name);
10788+ break;
10789+ } else if (scst_analyze_sense(sense_buffer,
10790+ sizeof(sense_buffer),
10791+ SCST_SENSE_KEY_VALID,
10792+ NOT_READY, 0, 0)) {
10793+ PRINT_ERROR("Device %s not ready",
10794+ dev->virt_name);
10795+ break;
10796+ }
10797+ } else {
10798+ PRINT_INFO("Internal MODE SENSE to "
10799+ "device %s failed: %x",
10800+ dev->virt_name, rc);
10801+ PRINT_BUFF_FLAG(TRACE_SCSI, "MODE SENSE sense",
10802+ sense_buffer, sizeof(sense_buffer));
10803+ switch (host_byte(rc)) {
10804+ case DID_RESET:
10805+ case DID_ABORT:
10806+ case DID_SOFT_ERROR:
10807+ break;
10808+ default:
10809+ goto brk;
10810+ }
10811+ switch (driver_byte(rc)) {
10812+ case DRIVER_BUSY:
10813+ case DRIVER_SOFT:
10814+ break;
10815+ default:
10816+ goto brk;
10817+ }
10818+ }
10819+ }
10820+ }
10821+brk:
10822+ PRINT_WARNING("Unable to get device's %s control mode page, using "
10823+ "existing values/defaults: TST %x, QUEUE ALG %x, SWP %x, "
10824+ "TAS %x, D_SENSE %d, has_own_order_mgmt %d", dev->virt_name,
10825+ dev->tst, dev->queue_alg, dev->swp, dev->tas, dev->d_sense,
10826+ dev->has_own_order_mgmt);
10827+
10828+out:
10829+ TRACE_EXIT();
10830+ return 0;
10831+}
10832+EXPORT_SYMBOL_GPL(scst_obtain_device_parameters);
10833+
10834+/* Called under dev_lock and BH off */
10835+void scst_process_reset(struct scst_device *dev,
10836+ struct scst_session *originator, struct scst_cmd *exclude_cmd,
10837+ struct scst_mgmt_cmd *mcmd, bool setUA)
10838+{
10839+ struct scst_tgt_dev *tgt_dev;
10840+ struct scst_cmd *cmd, *tcmd;
10841+
10842+ TRACE_ENTRY();
10843+
10844+ /* Clear RESERVE'ation, if necessary */
10845+ if (dev->dev_reserved) {
10846+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
10847+ dev_tgt_dev_list_entry) {
10848+ TRACE_MGMT_DBG("Clearing RESERVE'ation for "
10849+ "tgt_dev LUN %lld",
10850+ (long long unsigned int)tgt_dev->lun);
10851+ clear_bit(SCST_TGT_DEV_RESERVED,
10852+ &tgt_dev->tgt_dev_flags);
10853+ }
10854+ dev->dev_reserved = 0;
10855+ /*
10856+ * There is no need to send RELEASE, since the device is going
10857+ * to be resetted. Actually, since we can be in RESET TM
10858+ * function, it might be dangerous.
10859+ */
10860+ }
10861+
10862+ dev->dev_double_ua_possible = 1;
10863+
10864+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
10865+ dev_tgt_dev_list_entry) {
10866+ struct scst_session *sess = tgt_dev->sess;
10867+
10868+ spin_lock_bh(&tgt_dev->tgt_dev_lock);
10869+
10870+ scst_free_all_UA(tgt_dev);
10871+
10872+ memset(tgt_dev->tgt_dev_sense, 0,
10873+ sizeof(tgt_dev->tgt_dev_sense));
10874+
10875+ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
10876+
10877+ spin_lock_irq(&sess->sess_list_lock);
10878+
10879+ TRACE_DBG("Searching in sess cmd list (sess=%p)", sess);
10880+ list_for_each_entry(cmd, &sess->sess_cmd_list,
10881+ sess_cmd_list_entry) {
10882+ if (cmd == exclude_cmd)
10883+ continue;
10884+ if ((cmd->tgt_dev == tgt_dev) ||
10885+ ((cmd->tgt_dev == NULL) &&
10886+ (cmd->lun == tgt_dev->lun))) {
10887+ scst_abort_cmd(cmd, mcmd,
10888+ (tgt_dev->sess != originator), 0);
10889+ }
10890+ }
10891+ spin_unlock_irq(&sess->sess_list_lock);
10892+ }
10893+
10894+ list_for_each_entry_safe(cmd, tcmd, &dev->blocked_cmd_list,
10895+ blocked_cmd_list_entry) {
10896+ if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
10897+ list_del(&cmd->blocked_cmd_list_entry);
10898+ TRACE_MGMT_DBG("Adding aborted blocked cmd %p "
10899+ "to active cmd list", cmd);
10900+ spin_lock_irq(&cmd->cmd_threads->cmd_list_lock);
10901+ list_add_tail(&cmd->cmd_list_entry,
10902+ &cmd->cmd_threads->active_cmd_list);
10903+ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
10904+ spin_unlock_irq(&cmd->cmd_threads->cmd_list_lock);
10905+ }
10906+ }
10907+
10908+ if (setUA) {
10909+ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
10910+ int sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
10911+ dev->d_sense, SCST_LOAD_SENSE(scst_sense_reset_UA));
10912+ scst_dev_check_set_local_UA(dev, exclude_cmd, sense_buffer, sl);
10913+ }
10914+
10915+ TRACE_EXIT();
10916+ return;
10917+}
10918+
10919+/* No locks, no IRQ or IRQ-disabled context allowed */
10920+int scst_set_pending_UA(struct scst_cmd *cmd)
10921+{
10922+ int res = 0, i;
10923+ struct scst_tgt_dev_UA *UA_entry;
10924+ bool first = true, global_unlock = false;
10925+ struct scst_session *sess = cmd->sess;
10926+
10927+ TRACE_ENTRY();
10928+
10929+ /*
10930+ * RMB and recheck to sync with setting SCST_CMD_ABORTED in
10931+ * scst_abort_cmd() to not set UA for the being aborted cmd, hence
10932+ * possibly miss its delivery by a legitimate command while the UA is
10933+ * being requeued.
10934+ */
10935+ smp_rmb();
10936+ if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
10937+ TRACE_MGMT_DBG("Not set pending UA for aborted cmd %p", cmd);
10938+ res = -1;
10939+ goto out;
10940+ }
10941+
10942+ TRACE_MGMT_DBG("Setting pending UA cmd %p", cmd);
10943+
10944+ spin_lock_bh(&cmd->tgt_dev->tgt_dev_lock);
10945+
10946+again:
10947+ /* UA list could be cleared behind us, so retest */
10948+ if (list_empty(&cmd->tgt_dev->UA_list)) {
10949+ TRACE_DBG("%s",
10950+ "SCST_TGT_DEV_UA_PENDING set, but UA_list empty");
10951+ res = -1;
10952+ goto out_unlock;
10953+ }
10954+
10955+ UA_entry = list_entry(cmd->tgt_dev->UA_list.next, typeof(*UA_entry),
10956+ UA_list_entry);
10957+
10958+ TRACE_DBG("next %p UA_entry %p",
10959+ cmd->tgt_dev->UA_list.next, UA_entry);
10960+
10961+ if (UA_entry->global_UA && first) {
10962+ TRACE_MGMT_DBG("Global UA %p detected", UA_entry);
10963+
10964+ spin_unlock_bh(&cmd->tgt_dev->tgt_dev_lock);
10965+
10966+ /*
10967+ * cmd won't allow to suspend activities, so we can access
10968+ * sess->sess_tgt_dev_list_hash without any additional
10969+ * protection.
10970+ */
10971+
10972+ local_bh_disable();
10973+
10974+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
10975+ struct list_head *sess_tgt_dev_list_head =
10976+ &sess->sess_tgt_dev_list_hash[i];
10977+ struct scst_tgt_dev *tgt_dev;
10978+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
10979+ sess_tgt_dev_list_entry) {
10980+ /* Lockdep triggers here a false positive.. */
10981+ spin_lock(&tgt_dev->tgt_dev_lock);
10982+ }
10983+ }
10984+
10985+ first = false;
10986+ global_unlock = true;
10987+ goto again;
10988+ }
10989+
10990+ if (scst_set_cmd_error_sense(cmd, UA_entry->UA_sense_buffer,
10991+ UA_entry->UA_valid_sense_len) != 0)
10992+ goto out_unlock;
10993+
10994+ cmd->ua_ignore = 1;
10995+
10996+ list_del(&UA_entry->UA_list_entry);
10997+
10998+ if (UA_entry->global_UA) {
10999+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
11000+ struct list_head *sess_tgt_dev_list_head =
11001+ &sess->sess_tgt_dev_list_hash[i];
11002+ struct scst_tgt_dev *tgt_dev;
11003+
11004+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
11005+ sess_tgt_dev_list_entry) {
11006+ struct scst_tgt_dev_UA *ua;
11007+ list_for_each_entry(ua, &tgt_dev->UA_list,
11008+ UA_list_entry) {
11009+ if (ua->global_UA &&
11010+ memcmp(ua->UA_sense_buffer,
11011+ UA_entry->UA_sense_buffer,
11012+ sizeof(ua->UA_sense_buffer)) == 0) {
11013+ TRACE_MGMT_DBG("Freeing not "
11014+ "needed global UA %p",
11015+ ua);
11016+ list_del(&ua->UA_list_entry);
11017+ mempool_free(ua, scst_ua_mempool);
11018+ break;
11019+ }
11020+ }
11021+ }
11022+ }
11023+ }
11024+
11025+ mempool_free(UA_entry, scst_ua_mempool);
11026+
11027+ if (list_empty(&cmd->tgt_dev->UA_list)) {
11028+ clear_bit(SCST_TGT_DEV_UA_PENDING,
11029+ &cmd->tgt_dev->tgt_dev_flags);
11030+ }
11031+
11032+out_unlock:
11033+ if (global_unlock) {
11034+ for (i = TGT_DEV_HASH_SIZE-1; i >= 0; i--) {
11035+ struct list_head *sess_tgt_dev_list_head =
11036+ &sess->sess_tgt_dev_list_hash[i];
11037+ struct scst_tgt_dev *tgt_dev;
11038+ list_for_each_entry_reverse(tgt_dev, sess_tgt_dev_list_head,
11039+ sess_tgt_dev_list_entry) {
11040+ spin_unlock(&tgt_dev->tgt_dev_lock);
11041+ }
11042+ }
11043+
11044+ local_bh_enable();
11045+ spin_lock_bh(&cmd->tgt_dev->tgt_dev_lock);
11046+ }
11047+
11048+ spin_unlock_bh(&cmd->tgt_dev->tgt_dev_lock);
11049+
11050+out:
11051+ TRACE_EXIT_RES(res);
11052+ return res;
11053+}
11054+
11055+/* Called under tgt_dev_lock and BH off */
11056+static void scst_alloc_set_UA(struct scst_tgt_dev *tgt_dev,
11057+ const uint8_t *sense, int sense_len, int flags)
11058+{
11059+ struct scst_tgt_dev_UA *UA_entry = NULL;
11060+
11061+ TRACE_ENTRY();
11062+
11063+ UA_entry = mempool_alloc(scst_ua_mempool, GFP_ATOMIC);
11064+ if (UA_entry == NULL) {
11065+ PRINT_CRIT_ERROR("%s", "UNIT ATTENTION memory "
11066+ "allocation failed. The UNIT ATTENTION "
11067+ "on some sessions will be missed");
11068+ PRINT_BUFFER("Lost UA", sense, sense_len);
11069+ goto out;
11070+ }
11071+ memset(UA_entry, 0, sizeof(*UA_entry));
11072+
11073+ UA_entry->global_UA = (flags & SCST_SET_UA_FLAG_GLOBAL) != 0;
11074+ if (UA_entry->global_UA)
11075+ TRACE_MGMT_DBG("Queuing global UA %p", UA_entry);
11076+
11077+ if (sense_len > (int)sizeof(UA_entry->UA_sense_buffer)) {
11078+ PRINT_WARNING("Sense truncated (needed %d), shall you increase "
11079+ "SCST_SENSE_BUFFERSIZE?", sense_len);
11080+ sense_len = sizeof(UA_entry->UA_sense_buffer);
11081+ }
11082+ memcpy(UA_entry->UA_sense_buffer, sense, sense_len);
11083+ UA_entry->UA_valid_sense_len = sense_len;
11084+
11085+ set_bit(SCST_TGT_DEV_UA_PENDING, &tgt_dev->tgt_dev_flags);
11086+
11087+ TRACE_MGMT_DBG("Adding new UA to tgt_dev %p", tgt_dev);
11088+
11089+ if (flags & SCST_SET_UA_FLAG_AT_HEAD)
11090+ list_add(&UA_entry->UA_list_entry, &tgt_dev->UA_list);
11091+ else
11092+ list_add_tail(&UA_entry->UA_list_entry, &tgt_dev->UA_list);
11093+
11094+out:
11095+ TRACE_EXIT();
11096+ return;
11097+}
11098+
11099+/* tgt_dev_lock supposed to be held and BH off */
11100+static void __scst_check_set_UA(struct scst_tgt_dev *tgt_dev,
11101+ const uint8_t *sense, int sense_len, int flags)
11102+{
11103+ int skip_UA = 0;
11104+ struct scst_tgt_dev_UA *UA_entry_tmp;
11105+ int len = min((int)sizeof(UA_entry_tmp->UA_sense_buffer), sense_len);
11106+
11107+ TRACE_ENTRY();
11108+
11109+ list_for_each_entry(UA_entry_tmp, &tgt_dev->UA_list,
11110+ UA_list_entry) {
11111+ if (memcmp(sense, UA_entry_tmp->UA_sense_buffer, len) == 0) {
11112+ TRACE_MGMT_DBG("%s", "UA already exists");
11113+ skip_UA = 1;
11114+ break;
11115+ }
11116+ }
11117+
11118+ if (skip_UA == 0)
11119+ scst_alloc_set_UA(tgt_dev, sense, len, flags);
11120+
11121+ TRACE_EXIT();
11122+ return;
11123+}
11124+
11125+void scst_check_set_UA(struct scst_tgt_dev *tgt_dev,
11126+ const uint8_t *sense, int sense_len, int flags)
11127+{
11128+ TRACE_ENTRY();
11129+
11130+ spin_lock_bh(&tgt_dev->tgt_dev_lock);
11131+ __scst_check_set_UA(tgt_dev, sense, sense_len, flags);
11132+ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
11133+
11134+ TRACE_EXIT();
11135+ return;
11136+}
11137+
11138+/* Called under dev_lock and BH off */
11139+void scst_dev_check_set_local_UA(struct scst_device *dev,
11140+ struct scst_cmd *exclude, const uint8_t *sense, int sense_len)
11141+{
11142+ struct scst_tgt_dev *tgt_dev, *exclude_tgt_dev = NULL;
11143+
11144+ TRACE_ENTRY();
11145+
11146+ if (exclude != NULL)
11147+ exclude_tgt_dev = exclude->tgt_dev;
11148+
11149+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
11150+ dev_tgt_dev_list_entry) {
11151+ if (tgt_dev != exclude_tgt_dev)
11152+ scst_check_set_UA(tgt_dev, sense, sense_len, 0);
11153+ }
11154+
11155+ TRACE_EXIT();
11156+ return;
11157+}
11158+
11159+/* Called under dev_lock and BH off */
11160+void __scst_dev_check_set_UA(struct scst_device *dev,
11161+ struct scst_cmd *exclude, const uint8_t *sense, int sense_len)
11162+{
11163+ TRACE_ENTRY();
11164+
11165+ TRACE_MGMT_DBG("Processing UA dev %p", dev);
11166+
11167+ /* Check for reset UA */
11168+ if (scst_analyze_sense(sense, sense_len, SCST_SENSE_ASC_VALID,
11169+ 0, SCST_SENSE_ASC_UA_RESET, 0))
11170+ scst_process_reset(dev,
11171+ (exclude != NULL) ? exclude->sess : NULL,
11172+ exclude, NULL, false);
11173+
11174+ scst_dev_check_set_local_UA(dev, exclude, sense, sense_len);
11175+
11176+ TRACE_EXIT();
11177+ return;
11178+}
11179+
11180+/* Called under tgt_dev_lock or when tgt_dev is unused */
11181+static void scst_free_all_UA(struct scst_tgt_dev *tgt_dev)
11182+{
11183+ struct scst_tgt_dev_UA *UA_entry, *t;
11184+
11185+ TRACE_ENTRY();
11186+
11187+ list_for_each_entry_safe(UA_entry, t,
11188+ &tgt_dev->UA_list, UA_list_entry) {
11189+ TRACE_MGMT_DBG("Clearing UA for tgt_dev LUN %lld",
11190+ (long long unsigned int)tgt_dev->lun);
11191+ list_del(&UA_entry->UA_list_entry);
11192+ mempool_free(UA_entry, scst_ua_mempool);
11193+ }
11194+ INIT_LIST_HEAD(&tgt_dev->UA_list);
11195+ clear_bit(SCST_TGT_DEV_UA_PENDING, &tgt_dev->tgt_dev_flags);
11196+
11197+ TRACE_EXIT();
11198+ return;
11199+}
11200+
11201+/* No locks */
11202+struct scst_cmd *__scst_check_deferred_commands(struct scst_tgt_dev *tgt_dev)
11203+{
11204+ struct scst_cmd *res = NULL, *cmd, *t;
11205+ typeof(tgt_dev->expected_sn) expected_sn = tgt_dev->expected_sn;
11206+
11207+ spin_lock_irq(&tgt_dev->sn_lock);
11208+
11209+ if (unlikely(tgt_dev->hq_cmd_count != 0))
11210+ goto out_unlock;
11211+
11212+restart:
11213+ list_for_each_entry_safe(cmd, t, &tgt_dev->deferred_cmd_list,
11214+ sn_cmd_list_entry) {
11215+ EXTRACHECKS_BUG_ON(cmd->queue_type ==
11216+ SCST_CMD_QUEUE_HEAD_OF_QUEUE);
11217+ if (cmd->sn == expected_sn) {
11218+ TRACE_SN("Deferred command %p (sn %d, set %d) found",
11219+ cmd, cmd->sn, cmd->sn_set);
11220+ tgt_dev->def_cmd_count--;
11221+ list_del(&cmd->sn_cmd_list_entry);
11222+ if (res == NULL)
11223+ res = cmd;
11224+ else {
11225+ spin_lock(&cmd->cmd_threads->cmd_list_lock);
11226+ TRACE_SN("Adding cmd %p to active cmd list",
11227+ cmd);
11228+ list_add_tail(&cmd->cmd_list_entry,
11229+ &cmd->cmd_threads->active_cmd_list);
11230+ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
11231+ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
11232+ }
11233+ }
11234+ }
11235+ if (res != NULL)
11236+ goto out_unlock;
11237+
11238+ list_for_each_entry(cmd, &tgt_dev->skipped_sn_list,
11239+ sn_cmd_list_entry) {
11240+ EXTRACHECKS_BUG_ON(cmd->queue_type ==
11241+ SCST_CMD_QUEUE_HEAD_OF_QUEUE);
11242+ if (cmd->sn == expected_sn) {
11243+ atomic_t *slot = cmd->sn_slot;
11244+ /*
11245+ * !! At this point any pointer in cmd, except !!
11246+ * !! sn_slot and sn_cmd_list_entry, could be !!
11247+ * !! already destroyed !!
11248+ */
11249+ TRACE_SN("cmd %p (tag %llu) with skipped sn %d found",
11250+ cmd,
11251+ (long long unsigned int)cmd->tag,
11252+ cmd->sn);
11253+ tgt_dev->def_cmd_count--;
11254+ list_del(&cmd->sn_cmd_list_entry);
11255+ spin_unlock_irq(&tgt_dev->sn_lock);
11256+ if (test_and_set_bit(SCST_CMD_CAN_BE_DESTROYED,
11257+ &cmd->cmd_flags))
11258+ scst_destroy_put_cmd(cmd);
11259+ scst_inc_expected_sn(tgt_dev, slot);
11260+ expected_sn = tgt_dev->expected_sn;
11261+ spin_lock_irq(&tgt_dev->sn_lock);
11262+ goto restart;
11263+ }
11264+ }
11265+
11266+out_unlock:
11267+ spin_unlock_irq(&tgt_dev->sn_lock);
11268+ return res;
11269+}
11270+
11271+/*****************************************************************
11272+ ** The following thr_data functions are necessary, because the
11273+ ** kernel doesn't provide a better way to have threads local
11274+ ** storage
11275+ *****************************************************************/
11276+
11277+/**
11278+ * scst_add_thr_data() - add the current thread's local data
11279+ *
11280+ * Adds local to the current thread data to tgt_dev
11281+ * (they will be local for the tgt_dev and current thread).
11282+ */
11283+void scst_add_thr_data(struct scst_tgt_dev *tgt_dev,
11284+ struct scst_thr_data_hdr *data,
11285+ void (*free_fn) (struct scst_thr_data_hdr *data))
11286+{
11287+ data->owner_thr = current;
11288+ atomic_set(&data->ref, 1);
11289+ EXTRACHECKS_BUG_ON(free_fn == NULL);
11290+ data->free_fn = free_fn;
11291+ spin_lock(&tgt_dev->thr_data_lock);
11292+ list_add_tail(&data->thr_data_list_entry, &tgt_dev->thr_data_list);
11293+ spin_unlock(&tgt_dev->thr_data_lock);
11294+}
11295+EXPORT_SYMBOL_GPL(scst_add_thr_data);
11296+
11297+/**
11298+ * scst_del_all_thr_data() - delete all thread's local data
11299+ *
11300+ * Deletes all local to threads data from tgt_dev
11301+ */
11302+void scst_del_all_thr_data(struct scst_tgt_dev *tgt_dev)
11303+{
11304+ spin_lock(&tgt_dev->thr_data_lock);
11305+ while (!list_empty(&tgt_dev->thr_data_list)) {
11306+ struct scst_thr_data_hdr *d = list_entry(
11307+ tgt_dev->thr_data_list.next, typeof(*d),
11308+ thr_data_list_entry);
11309+ list_del(&d->thr_data_list_entry);
11310+ spin_unlock(&tgt_dev->thr_data_lock);
11311+ scst_thr_data_put(d);
11312+ spin_lock(&tgt_dev->thr_data_lock);
11313+ }
11314+ spin_unlock(&tgt_dev->thr_data_lock);
11315+ return;
11316+}
11317+EXPORT_SYMBOL_GPL(scst_del_all_thr_data);
11318+
11319+/**
11320+ * scst_dev_del_all_thr_data() - delete all thread's local data from device
11321+ *
11322+ * Deletes all local to threads data from all tgt_dev's of the device
11323+ */
11324+void scst_dev_del_all_thr_data(struct scst_device *dev)
11325+{
11326+ struct scst_tgt_dev *tgt_dev;
11327+
11328+ TRACE_ENTRY();
11329+
11330+ mutex_lock(&scst_mutex);
11331+
11332+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
11333+ dev_tgt_dev_list_entry) {
11334+ scst_del_all_thr_data(tgt_dev);
11335+ }
11336+
11337+ mutex_unlock(&scst_mutex);
11338+
11339+ TRACE_EXIT();
11340+ return;
11341+}
11342+EXPORT_SYMBOL_GPL(scst_dev_del_all_thr_data);
11343+
11344+/* thr_data_lock supposed to be held */
11345+static struct scst_thr_data_hdr *__scst_find_thr_data_locked(
11346+ struct scst_tgt_dev *tgt_dev, struct task_struct *tsk)
11347+{
11348+ struct scst_thr_data_hdr *res = NULL, *d;
11349+
11350+ list_for_each_entry(d, &tgt_dev->thr_data_list, thr_data_list_entry) {
11351+ if (d->owner_thr == tsk) {
11352+ res = d;
11353+ scst_thr_data_get(res);
11354+ break;
11355+ }
11356+ }
11357+ return res;
11358+}
11359+
11360+/**
11361+ * __scst_find_thr_data() - find local to the thread data
11362+ *
11363+ * Finds local to the thread data. Returns NULL, if they not found.
11364+ */
11365+struct scst_thr_data_hdr *__scst_find_thr_data(struct scst_tgt_dev *tgt_dev,
11366+ struct task_struct *tsk)
11367+{
11368+ struct scst_thr_data_hdr *res;
11369+
11370+ spin_lock(&tgt_dev->thr_data_lock);
11371+ res = __scst_find_thr_data_locked(tgt_dev, tsk);
11372+ spin_unlock(&tgt_dev->thr_data_lock);
11373+
11374+ return res;
11375+}
11376+EXPORT_SYMBOL_GPL(__scst_find_thr_data);
11377+
11378+bool scst_del_thr_data(struct scst_tgt_dev *tgt_dev, struct task_struct *tsk)
11379+{
11380+ bool res;
11381+ struct scst_thr_data_hdr *td;
11382+
11383+ spin_lock(&tgt_dev->thr_data_lock);
11384+
11385+ td = __scst_find_thr_data_locked(tgt_dev, tsk);
11386+ if (td != NULL) {
11387+ list_del(&td->thr_data_list_entry);
11388+ res = true;
11389+ } else
11390+ res = false;
11391+
11392+ spin_unlock(&tgt_dev->thr_data_lock);
11393+
11394+ if (td != NULL) {
11395+ /* the find() fn also gets it */
11396+ scst_thr_data_put(td);
11397+ scst_thr_data_put(td);
11398+ }
11399+
11400+ return res;
11401+}
11402+
11403+/* dev_lock supposed to be held and BH disabled */
11404+void scst_block_dev(struct scst_device *dev)
11405+{
11406+ dev->block_count++;
11407+ TRACE_MGMT_DBG("Device BLOCK(new %d), dev %p", dev->block_count, dev);
11408+}
11409+
11410+/* No locks */
11411+void scst_unblock_dev(struct scst_device *dev)
11412+{
11413+ spin_lock_bh(&dev->dev_lock);
11414+ TRACE_MGMT_DBG("Device UNBLOCK(new %d), dev %p",
11415+ dev->block_count-1, dev);
11416+ if (--dev->block_count == 0)
11417+ scst_unblock_cmds(dev);
11418+ spin_unlock_bh(&dev->dev_lock);
11419+ BUG_ON(dev->block_count < 0);
11420+}
11421+
11422+/* No locks */
11423+bool __scst_check_blocked_dev(struct scst_cmd *cmd)
11424+{
11425+ int res = false;
11426+ struct scst_device *dev = cmd->dev;
11427+
11428+ TRACE_ENTRY();
11429+
11430+ EXTRACHECKS_BUG_ON(cmd->unblock_dev);
11431+
11432+ if (unlikely(cmd->internal) && (cmd->cdb[0] == REQUEST_SENSE)) {
11433+ /*
11434+ * The original command can already block the device, so
11435+ * REQUEST SENSE command should always pass.
11436+ */
11437+ goto out;
11438+ }
11439+
11440+repeat:
11441+ if (dev->block_count > 0) {
11442+ spin_lock_bh(&dev->dev_lock);
11443+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)))
11444+ goto out_unlock;
11445+ if (dev->block_count > 0) {
11446+ TRACE_MGMT_DBG("Delaying cmd %p due to blocking "
11447+ "(tag %llu, dev %p)", cmd,
11448+ (long long unsigned int)cmd->tag, dev);
11449+ list_add_tail(&cmd->blocked_cmd_list_entry,
11450+ &dev->blocked_cmd_list);
11451+ res = true;
11452+ spin_unlock_bh(&dev->dev_lock);
11453+ goto out;
11454+ } else {
11455+ TRACE_MGMT_DBG("%s", "Somebody unblocked the device, "
11456+ "continuing");
11457+ }
11458+ spin_unlock_bh(&dev->dev_lock);
11459+ }
11460+
11461+ if (dev->dev_double_ua_possible) {
11462+ spin_lock_bh(&dev->dev_lock);
11463+ if (dev->block_count == 0) {
11464+ TRACE_MGMT_DBG("cmd %p (tag %llu), blocking further "
11465+ "cmds due to possible double reset UA (dev %p)",
11466+ cmd, (long long unsigned int)cmd->tag, dev);
11467+ scst_block_dev(dev);
11468+ cmd->unblock_dev = 1;
11469+ } else {
11470+ spin_unlock_bh(&dev->dev_lock);
11471+ TRACE_MGMT_DBG("Somebody blocked the device, "
11472+ "repeating (count %d)", dev->block_count);
11473+ goto repeat;
11474+ }
11475+ spin_unlock_bh(&dev->dev_lock);
11476+ }
11477+
11478+out:
11479+ TRACE_EXIT_RES(res);
11480+ return res;
11481+
11482+out_unlock:
11483+ spin_unlock_bh(&dev->dev_lock);
11484+ goto out;
11485+}
11486+
11487+/* Called under dev_lock */
11488+static void scst_unblock_cmds(struct scst_device *dev)
11489+{
11490+ struct scst_cmd *cmd, *tcmd;
11491+ unsigned long flags;
11492+
11493+ TRACE_ENTRY();
11494+
11495+ local_irq_save(flags);
11496+ list_for_each_entry_safe(cmd, tcmd, &dev->blocked_cmd_list,
11497+ blocked_cmd_list_entry) {
11498+ list_del(&cmd->blocked_cmd_list_entry);
11499+ TRACE_MGMT_DBG("Adding blocked cmd %p to active cmd list", cmd);
11500+ spin_lock(&cmd->cmd_threads->cmd_list_lock);
11501+ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
11502+ list_add(&cmd->cmd_list_entry,
11503+ &cmd->cmd_threads->active_cmd_list);
11504+ else
11505+ list_add_tail(&cmd->cmd_list_entry,
11506+ &cmd->cmd_threads->active_cmd_list);
11507+ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
11508+ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
11509+ }
11510+ local_irq_restore(flags);
11511+
11512+ TRACE_EXIT();
11513+ return;
11514+}
11515+
11516+static void __scst_unblock_deferred(struct scst_tgt_dev *tgt_dev,
11517+ struct scst_cmd *out_of_sn_cmd)
11518+{
11519+ EXTRACHECKS_BUG_ON(!out_of_sn_cmd->sn_set);
11520+
11521+ if (out_of_sn_cmd->sn == tgt_dev->expected_sn) {
11522+ scst_inc_expected_sn(tgt_dev, out_of_sn_cmd->sn_slot);
11523+ scst_make_deferred_commands_active(tgt_dev);
11524+ } else {
11525+ out_of_sn_cmd->out_of_sn = 1;
11526+ spin_lock_irq(&tgt_dev->sn_lock);
11527+ tgt_dev->def_cmd_count++;
11528+ list_add_tail(&out_of_sn_cmd->sn_cmd_list_entry,
11529+ &tgt_dev->skipped_sn_list);
11530+ TRACE_SN("out_of_sn_cmd %p with sn %d added to skipped_sn_list"
11531+ " (expected_sn %d)", out_of_sn_cmd, out_of_sn_cmd->sn,
11532+ tgt_dev->expected_sn);
11533+ spin_unlock_irq(&tgt_dev->sn_lock);
11534+ }
11535+
11536+ return;
11537+}
11538+
11539+void scst_unblock_deferred(struct scst_tgt_dev *tgt_dev,
11540+ struct scst_cmd *out_of_sn_cmd)
11541+{
11542+ TRACE_ENTRY();
11543+
11544+ if (!out_of_sn_cmd->sn_set) {
11545+ TRACE_SN("cmd %p without sn", out_of_sn_cmd);
11546+ goto out;
11547+ }
11548+
11549+ __scst_unblock_deferred(tgt_dev, out_of_sn_cmd);
11550+
11551+out:
11552+ TRACE_EXIT();
11553+ return;
11554+}
11555+
11556+void scst_on_hq_cmd_response(struct scst_cmd *cmd)
11557+{
11558+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
11559+
11560+ TRACE_ENTRY();
11561+
11562+ if (!cmd->hq_cmd_inced)
11563+ goto out;
11564+
11565+ spin_lock_irq(&tgt_dev->sn_lock);
11566+ tgt_dev->hq_cmd_count--;
11567+ spin_unlock_irq(&tgt_dev->sn_lock);
11568+
11569+ EXTRACHECKS_BUG_ON(tgt_dev->hq_cmd_count < 0);
11570+
11571+ /*
11572+ * There is no problem in checking hq_cmd_count in the
11573+ * non-locked state. In the worst case we will only have
11574+ * unneeded run of the deferred commands.
11575+ */
11576+ if (tgt_dev->hq_cmd_count == 0)
11577+ scst_make_deferred_commands_active(tgt_dev);
11578+
11579+out:
11580+ TRACE_EXIT();
11581+ return;
11582+}
11583+
11584+void scst_store_sense(struct scst_cmd *cmd)
11585+{
11586+ TRACE_ENTRY();
11587+
11588+ if (SCST_SENSE_VALID(cmd->sense) &&
11589+ !test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags) &&
11590+ (cmd->tgt_dev != NULL)) {
11591+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
11592+
11593+ TRACE_DBG("Storing sense (cmd %p)", cmd);
11594+
11595+ spin_lock_bh(&tgt_dev->tgt_dev_lock);
11596+
11597+ if (cmd->sense_valid_len <= sizeof(tgt_dev->tgt_dev_sense))
11598+ tgt_dev->tgt_dev_valid_sense_len = cmd->sense_valid_len;
11599+ else {
11600+ tgt_dev->tgt_dev_valid_sense_len = sizeof(tgt_dev->tgt_dev_sense);
11601+ PRINT_ERROR("Stored sense truncated to size %d "
11602+ "(needed %d)", tgt_dev->tgt_dev_valid_sense_len,
11603+ cmd->sense_valid_len);
11604+ }
11605+ memcpy(tgt_dev->tgt_dev_sense, cmd->sense,
11606+ tgt_dev->tgt_dev_valid_sense_len);
11607+
11608+ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
11609+ }
11610+
11611+ TRACE_EXIT();
11612+ return;
11613+}
11614+
11615+void scst_xmit_process_aborted_cmd(struct scst_cmd *cmd)
11616+{
11617+ TRACE_ENTRY();
11618+
11619+ TRACE_MGMT_DBG("Aborted cmd %p done (cmd_ref %d, "
11620+ "scst_cmd_count %d)", cmd, atomic_read(&cmd->cmd_ref),
11621+ atomic_read(&scst_cmd_count));
11622+
11623+ scst_done_cmd_mgmt(cmd);
11624+
11625+ if (test_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags)) {
11626+ if (cmd->completed) {
11627+ /* It's completed and it's OK to return its result */
11628+ goto out;
11629+ }
11630+
11631+ /* For not yet inited commands cmd->dev can be NULL here */
11632+ if (test_bit(SCST_CMD_DEVICE_TAS, &cmd->cmd_flags)) {
11633+ TRACE_MGMT_DBG("Flag ABORTED OTHER set for cmd %p "
11634+ "(tag %llu), returning TASK ABORTED ", cmd,
11635+ (long long unsigned int)cmd->tag);
11636+ scst_set_cmd_error_status(cmd, SAM_STAT_TASK_ABORTED);
11637+ } else {
11638+ TRACE_MGMT_DBG("Flag ABORTED OTHER set for cmd %p "
11639+ "(tag %llu), aborting without delivery or "
11640+ "notification",
11641+ cmd, (long long unsigned int)cmd->tag);
11642+ /*
11643+ * There is no need to check/requeue possible UA,
11644+ * because, if it exists, it will be delivered
11645+ * by the "completed" branch above.
11646+ */
11647+ clear_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags);
11648+ }
11649+ }
11650+
11651+out:
11652+ TRACE_EXIT();
11653+ return;
11654+}
11655+
11656+/**
11657+ * scst_get_max_lun_commands() - return maximum supported commands count
11658+ *
11659+ * Returns maximum commands count which can be queued to this LUN in this
11660+ * session.
11661+ *
11662+ * If lun is NO_SUCH_LUN, returns minimum of maximum commands count which
11663+ * can be queued to any LUN in this session.
11664+ *
11665+ * If sess is NULL, returns minimum of maximum commands count which can be
11666+ * queued to any SCST device.
11667+ */
11668+int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun)
11669+{
11670+ return SCST_MAX_TGT_DEV_COMMANDS;
11671+}
11672+EXPORT_SYMBOL(scst_get_max_lun_commands);
11673+
11674+/**
11675+ * scst_reassign_persistent_sess_states() - reassigns persistent states
11676+ *
11677+ * Reassigns persistent states from old_sess to new_sess.
11678+ */
11679+void scst_reassign_persistent_sess_states(struct scst_session *new_sess,
11680+ struct scst_session *old_sess)
11681+{
11682+ struct scst_device *dev;
11683+
11684+ TRACE_ENTRY();
11685+
11686+ TRACE_PR("Reassigning persistent states from old_sess %p to "
11687+ "new_sess %p", old_sess, new_sess);
11688+
11689+ if ((new_sess == NULL) || (old_sess == NULL)) {
11690+ TRACE_DBG("%s", "new_sess or old_sess is NULL");
11691+ goto out;
11692+ }
11693+
11694+ if (new_sess == old_sess) {
11695+ TRACE_DBG("%s", "new_sess or old_sess are the same");
11696+ goto out;
11697+ }
11698+
11699+ if ((new_sess->transport_id == NULL) ||
11700+ (old_sess->transport_id == NULL)) {
11701+ TRACE_DBG("%s", "new_sess or old_sess doesn't support PRs");
11702+ goto out;
11703+ }
11704+
11705+ mutex_lock(&scst_mutex);
11706+
11707+ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
11708+ struct scst_tgt_dev *tgt_dev;
11709+ struct scst_tgt_dev *new_tgt_dev = NULL, *old_tgt_dev = NULL;
11710+
11711+ TRACE_DBG("Processing dev %s", dev->virt_name);
11712+
11713+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
11714+ dev_tgt_dev_list_entry) {
11715+ if (tgt_dev->sess == new_sess) {
11716+ new_tgt_dev = tgt_dev;
11717+ if (old_tgt_dev != NULL)
11718+ break;
11719+ }
11720+ if (tgt_dev->sess == old_sess) {
11721+ old_tgt_dev = tgt_dev;
11722+ if (new_tgt_dev != NULL)
11723+ break;
11724+ }
11725+ }
11726+
11727+ if ((new_tgt_dev == NULL) || (old_tgt_dev == NULL)) {
11728+ TRACE_DBG("new_tgt_dev %p or old_sess %p is NULL, "
11729+ "skipping (dev %s)", new_tgt_dev, old_tgt_dev,
11730+ dev->virt_name);
11731+ continue;
11732+ }
11733+
11734+ scst_pr_write_lock(dev);
11735+
11736+ if (old_tgt_dev->registrant != NULL) {
11737+ TRACE_PR("Reassigning reg %p from tgt_dev %p to %p",
11738+ old_tgt_dev->registrant, old_tgt_dev,
11739+ new_tgt_dev);
11740+
11741+ if (new_tgt_dev->registrant != NULL)
11742+ new_tgt_dev->registrant->tgt_dev = NULL;
11743+
11744+ new_tgt_dev->registrant = old_tgt_dev->registrant;
11745+ new_tgt_dev->registrant->tgt_dev = new_tgt_dev;
11746+
11747+ old_tgt_dev->registrant = NULL;
11748+ }
11749+
11750+ scst_pr_write_unlock(dev);
11751+ }
11752+
11753+ mutex_unlock(&scst_mutex);
11754+
11755+out:
11756+ TRACE_EXIT();
11757+ return;
11758+}
11759+EXPORT_SYMBOL(scst_reassign_persistent_sess_states);
11760+
11761+/**
11762+ * scst_get_next_lexem() - parse and return next lexem in the string
11763+ *
11764+ * Returns pointer to the next lexem from token_str skipping
11765+ * spaces and '=' character and using them then as a delimeter. Content
11766+ * of token_str is modified by setting '\0' at the delimeter's position.
11767+ */
11768+char *scst_get_next_lexem(char **token_str)
11769+{
11770+ char *p = *token_str;
11771+ char *q;
11772+ static const char blank = '\0';
11773+
11774+ if ((token_str == NULL) || (*token_str == NULL))
11775+ return (char *)&blank;
11776+
11777+ for (p = *token_str; (*p != '\0') && (isspace(*p) || (*p == '=')); p++)
11778+ ;
11779+
11780+ for (q = p; (*q != '\0') && !isspace(*q) && (*q != '='); q++)
11781+ ;
11782+
11783+ if (*q != '\0')
11784+ *q++ = '\0';
11785+
11786+ *token_str = q;
11787+ return p;
11788+}
11789+EXPORT_SYMBOL_GPL(scst_get_next_lexem);
11790+
11791+/**
11792+ * scst_restore_token_str() - restore string modified by scst_get_next_lexem()
11793+ *
11794+ * Restores token_str modified by scst_get_next_lexem() to the
11795+ * previous value before scst_get_next_lexem() was called. Prev_lexem is
11796+ * a pointer to lexem returned by scst_get_next_lexem().
11797+ */
11798+void scst_restore_token_str(char *prev_lexem, char *token_str)
11799+{
11800+ if (&prev_lexem[strlen(prev_lexem)] != token_str)
11801+ prev_lexem[strlen(prev_lexem)] = ' ';
11802+ return;
11803+}
11804+EXPORT_SYMBOL_GPL(scst_restore_token_str);
11805+
11806+/**
11807+ * scst_get_next_token_str() - parse and return next token
11808+ *
11809+ * This function returns pointer to the next token strings from input_str
11810+ * using '\n', ';' and '\0' as a delimeter. Content of input_str is
11811+ * modified by setting '\0' at the delimeter's position.
11812+ */
11813+char *scst_get_next_token_str(char **input_str)
11814+{
11815+ char *p = *input_str;
11816+ int i = 0;
11817+
11818+ while ((p[i] != '\n') && (p[i] != ';') && (p[i] != '\0'))
11819+ i++;
11820+
11821+ if (i == 0)
11822+ return NULL;
11823+
11824+ if (p[i] == '\0')
11825+ *input_str = &p[i];
11826+ else
11827+ *input_str = &p[i+1];
11828+
11829+ p[i] = '\0';
11830+
11831+ return p;
11832+}
11833+EXPORT_SYMBOL_GPL(scst_get_next_token_str);
11834+
11835+static void __init scst_scsi_op_list_init(void)
11836+{
11837+ int i;
11838+ uint8_t op = 0xff;
11839+
11840+ TRACE_ENTRY();
11841+
11842+ for (i = 0; i < 256; i++)
11843+ scst_scsi_op_list[i] = SCST_CDB_TBL_SIZE;
11844+
11845+ for (i = 0; i < SCST_CDB_TBL_SIZE; i++) {
11846+ if (scst_scsi_op_table[i].ops != op) {
11847+ op = scst_scsi_op_table[i].ops;
11848+ scst_scsi_op_list[op] = i;
11849+ }
11850+ }
11851+
11852+ TRACE_EXIT();
11853+ return;
11854+}
11855+
11856+int __init scst_lib_init(void)
11857+{
11858+ int res = 0;
11859+
11860+ scst_scsi_op_list_init();
11861+
11862+ scsi_io_context_cache = kmem_cache_create("scst_scsi_io_context",
11863+ sizeof(struct scsi_io_context),
11864+ 0, 0, NULL);
11865+ if (!scsi_io_context_cache) {
11866+ PRINT_ERROR("%s", "Can't init scsi io context cache");
11867+ res = -ENOMEM;
11868+ goto out;
11869+ }
11870+
11871+out:
11872+ TRACE_EXIT_RES(res);
11873+ return res;
11874+}
11875+
11876+void scst_lib_exit(void)
11877+{
11878+ BUILD_BUG_ON(SCST_MAX_CDB_SIZE != BLK_MAX_CDB);
11879+ BUILD_BUG_ON(SCST_SENSE_BUFFERSIZE < SCSI_SENSE_BUFFERSIZE);
11880+
11881+ kmem_cache_destroy(scsi_io_context_cache);
11882+}
11883+
11884+#ifdef CONFIG_SCST_DEBUG
11885+
11886+/**
11887+ * scst_random() - return a pseudo-random number for debugging purposes.
11888+ *
11889+ * Returns a pseudo-random number for debugging purposes. Available only in
11890+ * the DEBUG build.
11891+ *
11892+ * Original taken from the XFS code
11893+ */
11894+unsigned long scst_random(void)
11895+{
11896+ static int Inited;
11897+ static unsigned long RandomValue;
11898+ static DEFINE_SPINLOCK(lock);
11899+ /* cycles pseudo-randomly through all values between 1 and 2^31 - 2 */
11900+ register long rv;
11901+ register long lo;
11902+ register long hi;
11903+ unsigned long flags;
11904+
11905+ spin_lock_irqsave(&lock, flags);
11906+ if (!Inited) {
11907+ RandomValue = jiffies;
11908+ Inited = 1;
11909+ }
11910+ rv = RandomValue;
11911+ hi = rv / 127773;
11912+ lo = rv % 127773;
11913+ rv = 16807 * lo - 2836 * hi;
11914+ if (rv <= 0)
11915+ rv += 2147483647;
11916+ RandomValue = rv;
11917+ spin_unlock_irqrestore(&lock, flags);
11918+ return rv;
11919+}
11920+EXPORT_SYMBOL_GPL(scst_random);
11921+#endif /* CONFIG_SCST_DEBUG */
11922+
11923+#ifdef CONFIG_SCST_DEBUG_TM
11924+
11925+#define TM_DBG_STATE_ABORT 0
11926+#define TM_DBG_STATE_RESET 1
11927+#define TM_DBG_STATE_OFFLINE 2
11928+
11929+#define INIT_TM_DBG_STATE TM_DBG_STATE_ABORT
11930+
11931+static void tm_dbg_timer_fn(unsigned long arg);
11932+
11933+static DEFINE_SPINLOCK(scst_tm_dbg_lock);
11934+/* All serialized by scst_tm_dbg_lock */
11935+static struct {
11936+ unsigned int tm_dbg_release:1;
11937+ unsigned int tm_dbg_blocked:1;
11938+} tm_dbg_flags;
11939+static LIST_HEAD(tm_dbg_delayed_cmd_list);
11940+static int tm_dbg_delayed_cmds_count;
11941+static int tm_dbg_passed_cmds_count;
11942+static int tm_dbg_state;
11943+static int tm_dbg_on_state_passes;
11944+static DEFINE_TIMER(tm_dbg_timer, tm_dbg_timer_fn, 0, 0);
11945+static struct scst_tgt_dev *tm_dbg_tgt_dev;
11946+
11947+static const int tm_dbg_on_state_num_passes[] = { 5, 1, 0x7ffffff };
11948+
11949+static void tm_dbg_init_tgt_dev(struct scst_tgt_dev *tgt_dev)
11950+{
11951+ if (tgt_dev->lun == 6) {
11952+ unsigned long flags;
11953+
11954+ if (tm_dbg_tgt_dev != NULL)
11955+ tm_dbg_deinit_tgt_dev(tm_dbg_tgt_dev);
11956+
11957+ spin_lock_irqsave(&scst_tm_dbg_lock, flags);
11958+ tm_dbg_state = INIT_TM_DBG_STATE;
11959+ tm_dbg_on_state_passes =
11960+ tm_dbg_on_state_num_passes[tm_dbg_state];
11961+ tm_dbg_tgt_dev = tgt_dev;
11962+ PRINT_INFO("LUN %lld connected from initiator %s is under "
11963+ "TM debugging (tgt_dev %p)",
11964+ (unsigned long long)tgt_dev->lun,
11965+ tgt_dev->sess->initiator_name, tgt_dev);
11966+ spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
11967+ }
11968+ return;
11969+}
11970+
11971+static void tm_dbg_deinit_tgt_dev(struct scst_tgt_dev *tgt_dev)
11972+{
11973+ if (tm_dbg_tgt_dev == tgt_dev) {
11974+ unsigned long flags;
11975+ TRACE_MGMT_DBG("Deinit TM debugging tgt_dev %p", tgt_dev);
11976+ del_timer_sync(&tm_dbg_timer);
11977+ spin_lock_irqsave(&scst_tm_dbg_lock, flags);
11978+ tm_dbg_tgt_dev = NULL;
11979+ spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
11980+ }
11981+ return;
11982+}
11983+
11984+static void tm_dbg_timer_fn(unsigned long arg)
11985+{
11986+ TRACE_MGMT_DBG("%s", "delayed cmd timer expired");
11987+ tm_dbg_flags.tm_dbg_release = 1;
11988+ /* Used to make sure that all woken up threads see the new value */
11989+ smp_wmb();
11990+ wake_up_all(&tm_dbg_tgt_dev->active_cmd_threads->cmd_list_waitQ);
11991+ return;
11992+}
11993+
11994+/* Called under scst_tm_dbg_lock and IRQs off */
11995+static void tm_dbg_delay_cmd(struct scst_cmd *cmd)
11996+{
11997+ switch (tm_dbg_state) {
11998+ case TM_DBG_STATE_ABORT:
11999+ if (tm_dbg_delayed_cmds_count == 0) {
12000+ unsigned long d = 58*HZ + (scst_random() % (4*HZ));
12001+ TRACE_MGMT_DBG("STATE ABORT: delaying cmd %p (tag %llu)"
12002+ " for %ld.%ld seconds (%ld HZ), "
12003+ "tm_dbg_on_state_passes=%d", cmd, cmd->tag,
12004+ d/HZ, (d%HZ)*100/HZ, d, tm_dbg_on_state_passes);
12005+ mod_timer(&tm_dbg_timer, jiffies + d);
12006+#if 0
12007+ tm_dbg_flags.tm_dbg_blocked = 1;
12008+#endif
12009+ } else {
12010+ TRACE_MGMT_DBG("Delaying another timed cmd %p "
12011+ "(tag %llu), delayed_cmds_count=%d, "
12012+ "tm_dbg_on_state_passes=%d", cmd, cmd->tag,
12013+ tm_dbg_delayed_cmds_count,
12014+ tm_dbg_on_state_passes);
12015+ if (tm_dbg_delayed_cmds_count == 2)
12016+ tm_dbg_flags.tm_dbg_blocked = 0;
12017+ }
12018+ break;
12019+
12020+ case TM_DBG_STATE_RESET:
12021+ case TM_DBG_STATE_OFFLINE:
12022+ TRACE_MGMT_DBG("STATE RESET/OFFLINE: delaying cmd %p "
12023+ "(tag %llu), delayed_cmds_count=%d, "
12024+ "tm_dbg_on_state_passes=%d", cmd, cmd->tag,
12025+ tm_dbg_delayed_cmds_count, tm_dbg_on_state_passes);
12026+ tm_dbg_flags.tm_dbg_blocked = 1;
12027+ break;
12028+
12029+ default:
12030+ BUG();
12031+ }
12032+ /* IRQs already off */
12033+ spin_lock(&cmd->cmd_threads->cmd_list_lock);
12034+ list_add_tail(&cmd->cmd_list_entry, &tm_dbg_delayed_cmd_list);
12035+ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
12036+ cmd->tm_dbg_delayed = 1;
12037+ tm_dbg_delayed_cmds_count++;
12038+ return;
12039+}
12040+
12041+/* No locks */
12042+void tm_dbg_check_released_cmds(void)
12043+{
12044+ if (tm_dbg_flags.tm_dbg_release) {
12045+ struct scst_cmd *cmd, *tc;
12046+ spin_lock_irq(&scst_tm_dbg_lock);
12047+ list_for_each_entry_safe_reverse(cmd, tc,
12048+ &tm_dbg_delayed_cmd_list, cmd_list_entry) {
12049+ TRACE_MGMT_DBG("Releasing timed cmd %p (tag %llu), "
12050+ "delayed_cmds_count=%d", cmd, cmd->tag,
12051+ tm_dbg_delayed_cmds_count);
12052+ spin_lock(&cmd->cmd_threads->cmd_list_lock);
12053+ list_move(&cmd->cmd_list_entry,
12054+ &cmd->cmd_threads->active_cmd_list);
12055+ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
12056+ }
12057+ tm_dbg_flags.tm_dbg_release = 0;
12058+ spin_unlock_irq(&scst_tm_dbg_lock);
12059+ }
12060+}
12061+
12062+/* Called under scst_tm_dbg_lock */
12063+static void tm_dbg_change_state(void)
12064+{
12065+ tm_dbg_flags.tm_dbg_blocked = 0;
12066+ if (--tm_dbg_on_state_passes == 0) {
12067+ switch (tm_dbg_state) {
12068+ case TM_DBG_STATE_ABORT:
12069+ TRACE_MGMT_DBG("%s", "Changing "
12070+ "tm_dbg_state to RESET");
12071+ tm_dbg_state = TM_DBG_STATE_RESET;
12072+ tm_dbg_flags.tm_dbg_blocked = 0;
12073+ break;
12074+ case TM_DBG_STATE_RESET:
12075+ case TM_DBG_STATE_OFFLINE:
12076+#ifdef CONFIG_SCST_TM_DBG_GO_OFFLINE
12077+ TRACE_MGMT_DBG("%s", "Changing "
12078+ "tm_dbg_state to OFFLINE");
12079+ tm_dbg_state = TM_DBG_STATE_OFFLINE;
12080+#else
12081+ TRACE_MGMT_DBG("%s", "Changing "
12082+ "tm_dbg_state to ABORT");
12083+ tm_dbg_state = TM_DBG_STATE_ABORT;
12084+#endif
12085+ break;
12086+ default:
12087+ BUG();
12088+ }
12089+ tm_dbg_on_state_passes =
12090+ tm_dbg_on_state_num_passes[tm_dbg_state];
12091+ }
12092+
12093+ TRACE_MGMT_DBG("%s", "Deleting timer");
12094+ del_timer_sync(&tm_dbg_timer);
12095+ return;
12096+}
12097+
12098+/* No locks */
12099+int tm_dbg_check_cmd(struct scst_cmd *cmd)
12100+{
12101+ int res = 0;
12102+ unsigned long flags;
12103+
12104+ if (cmd->tm_dbg_immut)
12105+ goto out;
12106+
12107+ if (cmd->tm_dbg_delayed) {
12108+ spin_lock_irqsave(&scst_tm_dbg_lock, flags);
12109+ TRACE_MGMT_DBG("Processing delayed cmd %p (tag %llu), "
12110+ "delayed_cmds_count=%d", cmd, cmd->tag,
12111+ tm_dbg_delayed_cmds_count);
12112+
12113+ cmd->tm_dbg_immut = 1;
12114+ tm_dbg_delayed_cmds_count--;
12115+ if ((tm_dbg_delayed_cmds_count == 0) &&
12116+ (tm_dbg_state == TM_DBG_STATE_ABORT))
12117+ tm_dbg_change_state();
12118+ spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
12119+ } else if (cmd->tgt_dev && (tm_dbg_tgt_dev == cmd->tgt_dev)) {
12120+ /* Delay 50th command */
12121+ spin_lock_irqsave(&scst_tm_dbg_lock, flags);
12122+ if (tm_dbg_flags.tm_dbg_blocked ||
12123+ (++tm_dbg_passed_cmds_count % 50) == 0) {
12124+ tm_dbg_delay_cmd(cmd);
12125+ res = 1;
12126+ } else
12127+ cmd->tm_dbg_immut = 1;
12128+ spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
12129+ }
12130+
12131+out:
12132+ return res;
12133+}
12134+
12135+/* No locks */
12136+void tm_dbg_release_cmd(struct scst_cmd *cmd)
12137+{
12138+ struct scst_cmd *c;
12139+ unsigned long flags;
12140+
12141+ spin_lock_irqsave(&scst_tm_dbg_lock, flags);
12142+ list_for_each_entry(c, &tm_dbg_delayed_cmd_list,
12143+ cmd_list_entry) {
12144+ if (c == cmd) {
12145+ TRACE_MGMT_DBG("Abort request for "
12146+ "delayed cmd %p (tag=%llu), moving it to "
12147+ "active cmd list (delayed_cmds_count=%d)",
12148+ c, c->tag, tm_dbg_delayed_cmds_count);
12149+
12150+ if (!test_bit(SCST_CMD_ABORTED_OTHER,
12151+ &cmd->cmd_flags)) {
12152+ /* Test how completed commands handled */
12153+ if (((scst_random() % 10) == 5)) {
12154+ scst_set_cmd_error(cmd,
12155+ SCST_LOAD_SENSE(
12156+ scst_sense_hardw_error));
12157+ /* It's completed now */
12158+ }
12159+ }
12160+
12161+ spin_lock(&cmd->cmd_threads->cmd_list_lock);
12162+ list_move(&c->cmd_list_entry,
12163+ &c->cmd_threads->active_cmd_list);
12164+ wake_up(&c->cmd_threads->cmd_list_waitQ);
12165+ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
12166+ break;
12167+ }
12168+ }
12169+ spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
12170+ return;
12171+}
12172+
12173+/* Might be called under scst_mutex */
12174+void tm_dbg_task_mgmt(struct scst_device *dev, const char *fn, int force)
12175+{
12176+ unsigned long flags;
12177+
12178+ if (dev != NULL) {
12179+ if (tm_dbg_tgt_dev == NULL)
12180+ goto out;
12181+
12182+ if (tm_dbg_tgt_dev->dev != dev)
12183+ goto out;
12184+ }
12185+
12186+ spin_lock_irqsave(&scst_tm_dbg_lock, flags);
12187+ if ((tm_dbg_state != TM_DBG_STATE_OFFLINE) || force) {
12188+ TRACE_MGMT_DBG("%s: freeing %d delayed cmds", fn,
12189+ tm_dbg_delayed_cmds_count);
12190+ tm_dbg_change_state();
12191+ tm_dbg_flags.tm_dbg_release = 1;
12192+ /*
12193+ * Used to make sure that all woken up threads see the new
12194+ * value.
12195+ */
12196+ smp_wmb();
12197+ if (tm_dbg_tgt_dev != NULL)
12198+ wake_up_all(&tm_dbg_tgt_dev->active_cmd_threads->cmd_list_waitQ);
12199+ } else {
12200+ TRACE_MGMT_DBG("%s: while OFFLINE state, doing nothing", fn);
12201+ }
12202+ spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
12203+
12204+out:
12205+ return;
12206+}
12207+
12208+int tm_dbg_is_release(void)
12209+{
12210+ return tm_dbg_flags.tm_dbg_release;
12211+}
12212+#endif /* CONFIG_SCST_DEBUG_TM */
12213+
12214+#ifdef CONFIG_SCST_DEBUG_SN
12215+void scst_check_debug_sn(struct scst_cmd *cmd)
12216+{
12217+ static DEFINE_SPINLOCK(lock);
12218+ static int type;
12219+ static int cnt;
12220+ unsigned long flags;
12221+ int old = cmd->queue_type;
12222+
12223+ spin_lock_irqsave(&lock, flags);
12224+
12225+ if (cnt == 0) {
12226+ if ((scst_random() % 1000) == 500) {
12227+ if ((scst_random() % 3) == 1)
12228+ type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
12229+ else
12230+ type = SCST_CMD_QUEUE_ORDERED;
12231+ do {
12232+ cnt = scst_random() % 10;
12233+ } while (cnt == 0);
12234+ } else
12235+ goto out_unlock;
12236+ }
12237+
12238+ cmd->queue_type = type;
12239+ cnt--;
12240+
12241+ if (((scst_random() % 1000) == 750))
12242+ cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
12243+ else if (((scst_random() % 1000) == 751))
12244+ cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
12245+ else if (((scst_random() % 1000) == 752))
12246+ cmd->queue_type = SCST_CMD_QUEUE_SIMPLE;
12247+
12248+ TRACE_SN("DbgSN changed cmd %p: %d/%d (cnt %d)", cmd, old,
12249+ cmd->queue_type, cnt);
12250+
12251+out_unlock:
12252+ spin_unlock_irqrestore(&lock, flags);
12253+ return;
12254+}
12255+#endif /* CONFIG_SCST_DEBUG_SN */
12256+
12257+#ifdef CONFIG_SCST_MEASURE_LATENCY
12258+
12259+static uint64_t scst_get_nsec(void)
12260+{
12261+ struct timespec ts;
12262+ ktime_get_ts(&ts);
12263+ return (uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec;
12264+}
12265+
12266+void scst_set_start_time(struct scst_cmd *cmd)
12267+{
12268+ cmd->start = scst_get_nsec();
12269+ TRACE_DBG("cmd %p: start %lld", cmd, cmd->start);
12270+}
12271+
12272+void scst_set_cur_start(struct scst_cmd *cmd)
12273+{
12274+ cmd->curr_start = scst_get_nsec();
12275+ TRACE_DBG("cmd %p: cur_start %lld", cmd, cmd->curr_start);
12276+}
12277+
12278+void scst_set_parse_time(struct scst_cmd *cmd)
12279+{
12280+ cmd->parse_time += scst_get_nsec() - cmd->curr_start;
12281+ TRACE_DBG("cmd %p: parse_time %lld", cmd, cmd->parse_time);
12282+}
12283+
12284+void scst_set_alloc_buf_time(struct scst_cmd *cmd)
12285+{
12286+ cmd->alloc_buf_time += scst_get_nsec() - cmd->curr_start;
12287+ TRACE_DBG("cmd %p: alloc_buf_time %lld", cmd, cmd->alloc_buf_time);
12288+}
12289+
12290+void scst_set_restart_waiting_time(struct scst_cmd *cmd)
12291+{
12292+ cmd->restart_waiting_time += scst_get_nsec() - cmd->curr_start;
12293+ TRACE_DBG("cmd %p: restart_waiting_time %lld", cmd,
12294+ cmd->restart_waiting_time);
12295+}
12296+
12297+void scst_set_rdy_to_xfer_time(struct scst_cmd *cmd)
12298+{
12299+ cmd->rdy_to_xfer_time += scst_get_nsec() - cmd->curr_start;
12300+ TRACE_DBG("cmd %p: rdy_to_xfer_time %lld", cmd, cmd->rdy_to_xfer_time);
12301+}
12302+
12303+void scst_set_pre_exec_time(struct scst_cmd *cmd)
12304+{
12305+ cmd->pre_exec_time += scst_get_nsec() - cmd->curr_start;
12306+ TRACE_DBG("cmd %p: pre_exec_time %lld", cmd, cmd->pre_exec_time);
12307+}
12308+
12309+void scst_set_exec_time(struct scst_cmd *cmd)
12310+{
12311+ cmd->exec_time += scst_get_nsec() - cmd->curr_start;
12312+ TRACE_DBG("cmd %p: exec_time %lld", cmd, cmd->exec_time);
12313+}
12314+
12315+void scst_set_dev_done_time(struct scst_cmd *cmd)
12316+{
12317+ cmd->dev_done_time += scst_get_nsec() - cmd->curr_start;
12318+ TRACE_DBG("cmd %p: dev_done_time %lld", cmd, cmd->dev_done_time);
12319+}
12320+
12321+void scst_set_xmit_time(struct scst_cmd *cmd)
12322+{
12323+ cmd->xmit_time += scst_get_nsec() - cmd->curr_start;
12324+ TRACE_DBG("cmd %p: xmit_time %lld", cmd, cmd->xmit_time);
12325+}
12326+
12327+void scst_set_tgt_on_free_time(struct scst_cmd *cmd)
12328+{
12329+ cmd->tgt_on_free_time += scst_get_nsec() - cmd->curr_start;
12330+ TRACE_DBG("cmd %p: tgt_on_free_time %lld", cmd, cmd->tgt_on_free_time);
12331+}
12332+
12333+void scst_set_dev_on_free_time(struct scst_cmd *cmd)
12334+{
12335+ cmd->dev_on_free_time += scst_get_nsec() - cmd->curr_start;
12336+ TRACE_DBG("cmd %p: dev_on_free_time %lld", cmd, cmd->dev_on_free_time);
12337+}
12338+
12339+void scst_update_lat_stats(struct scst_cmd *cmd)
12340+{
12341+ uint64_t finish, scst_time, tgt_time, dev_time;
12342+ struct scst_session *sess = cmd->sess;
12343+ int data_len;
12344+ int i;
12345+ struct scst_ext_latency_stat *latency_stat, *dev_latency_stat;
12346+
12347+ finish = scst_get_nsec();
12348+
12349+ /* Determine the IO size for extended latency statistics */
12350+ data_len = cmd->bufflen;
12351+ i = SCST_LATENCY_STAT_INDEX_OTHER;
12352+ if (data_len <= SCST_IO_SIZE_THRESHOLD_SMALL)
12353+ i = SCST_LATENCY_STAT_INDEX_SMALL;
12354+ else if (data_len <= SCST_IO_SIZE_THRESHOLD_MEDIUM)
12355+ i = SCST_LATENCY_STAT_INDEX_MEDIUM;
12356+ else if (data_len <= SCST_IO_SIZE_THRESHOLD_LARGE)
12357+ i = SCST_LATENCY_STAT_INDEX_LARGE;
12358+ else if (data_len <= SCST_IO_SIZE_THRESHOLD_VERY_LARGE)
12359+ i = SCST_LATENCY_STAT_INDEX_VERY_LARGE;
12360+ latency_stat = &sess->sess_latency_stat[i];
12361+ if (cmd->tgt_dev != NULL)
12362+ dev_latency_stat = &cmd->tgt_dev->dev_latency_stat[i];
12363+ else
12364+ dev_latency_stat = NULL;
12365+
12366+ /* Calculate the latencies */
12367+ scst_time = finish - cmd->start - (cmd->parse_time +
12368+ cmd->alloc_buf_time + cmd->restart_waiting_time +
12369+ cmd->rdy_to_xfer_time + cmd->pre_exec_time +
12370+ cmd->exec_time + cmd->dev_done_time + cmd->xmit_time +
12371+ cmd->tgt_on_free_time + cmd->dev_on_free_time);
12372+ tgt_time = cmd->alloc_buf_time + cmd->restart_waiting_time +
12373+ cmd->rdy_to_xfer_time + cmd->pre_exec_time +
12374+ cmd->xmit_time + cmd->tgt_on_free_time;
12375+ dev_time = cmd->parse_time + cmd->exec_time + cmd->dev_done_time +
12376+ cmd->dev_on_free_time;
12377+
12378+ spin_lock_bh(&sess->lat_lock);
12379+
12380+ /* Save the basic latency information */
12381+ sess->scst_time += scst_time;
12382+ sess->tgt_time += tgt_time;
12383+ sess->dev_time += dev_time;
12384+ sess->processed_cmds++;
12385+
12386+ if ((sess->min_scst_time == 0) ||
12387+ (sess->min_scst_time > scst_time))
12388+ sess->min_scst_time = scst_time;
12389+ if ((sess->min_tgt_time == 0) ||
12390+ (sess->min_tgt_time > tgt_time))
12391+ sess->min_tgt_time = tgt_time;
12392+ if ((sess->min_dev_time == 0) ||
12393+ (sess->min_dev_time > dev_time))
12394+ sess->min_dev_time = dev_time;
12395+
12396+ if (sess->max_scst_time < scst_time)
12397+ sess->max_scst_time = scst_time;
12398+ if (sess->max_tgt_time < tgt_time)
12399+ sess->max_tgt_time = tgt_time;
12400+ if (sess->max_dev_time < dev_time)
12401+ sess->max_dev_time = dev_time;
12402+
12403+ /* Save the extended latency information */
12404+ if (cmd->data_direction & SCST_DATA_READ) {
12405+ latency_stat->scst_time_rd += scst_time;
12406+ latency_stat->tgt_time_rd += tgt_time;
12407+ latency_stat->dev_time_rd += dev_time;
12408+ latency_stat->processed_cmds_rd++;
12409+
12410+ if ((latency_stat->min_scst_time_rd == 0) ||
12411+ (latency_stat->min_scst_time_rd > scst_time))
12412+ latency_stat->min_scst_time_rd = scst_time;
12413+ if ((latency_stat->min_tgt_time_rd == 0) ||
12414+ (latency_stat->min_tgt_time_rd > tgt_time))
12415+ latency_stat->min_tgt_time_rd = tgt_time;
12416+ if ((latency_stat->min_dev_time_rd == 0) ||
12417+ (latency_stat->min_dev_time_rd > dev_time))
12418+ latency_stat->min_dev_time_rd = dev_time;
12419+
12420+ if (latency_stat->max_scst_time_rd < scst_time)
12421+ latency_stat->max_scst_time_rd = scst_time;
12422+ if (latency_stat->max_tgt_time_rd < tgt_time)
12423+ latency_stat->max_tgt_time_rd = tgt_time;
12424+ if (latency_stat->max_dev_time_rd < dev_time)
12425+ latency_stat->max_dev_time_rd = dev_time;
12426+
12427+ if (dev_latency_stat != NULL) {
12428+ dev_latency_stat->scst_time_rd += scst_time;
12429+ dev_latency_stat->tgt_time_rd += tgt_time;
12430+ dev_latency_stat->dev_time_rd += dev_time;
12431+ dev_latency_stat->processed_cmds_rd++;
12432+
12433+ if ((dev_latency_stat->min_scst_time_rd == 0) ||
12434+ (dev_latency_stat->min_scst_time_rd > scst_time))
12435+ dev_latency_stat->min_scst_time_rd = scst_time;
12436+ if ((dev_latency_stat->min_tgt_time_rd == 0) ||
12437+ (dev_latency_stat->min_tgt_time_rd > tgt_time))
12438+ dev_latency_stat->min_tgt_time_rd = tgt_time;
12439+ if ((dev_latency_stat->min_dev_time_rd == 0) ||
12440+ (dev_latency_stat->min_dev_time_rd > dev_time))
12441+ dev_latency_stat->min_dev_time_rd = dev_time;
12442+
12443+ if (dev_latency_stat->max_scst_time_rd < scst_time)
12444+ dev_latency_stat->max_scst_time_rd = scst_time;
12445+ if (dev_latency_stat->max_tgt_time_rd < tgt_time)
12446+ dev_latency_stat->max_tgt_time_rd = tgt_time;
12447+ if (dev_latency_stat->max_dev_time_rd < dev_time)
12448+ dev_latency_stat->max_dev_time_rd = dev_time;
12449+ }
12450+ } else if (cmd->data_direction & SCST_DATA_WRITE) {
12451+ latency_stat->scst_time_wr += scst_time;
12452+ latency_stat->tgt_time_wr += tgt_time;
12453+ latency_stat->dev_time_wr += dev_time;
12454+ latency_stat->processed_cmds_wr++;
12455+
12456+ if ((latency_stat->min_scst_time_wr == 0) ||
12457+ (latency_stat->min_scst_time_wr > scst_time))
12458+ latency_stat->min_scst_time_wr = scst_time;
12459+ if ((latency_stat->min_tgt_time_wr == 0) ||
12460+ (latency_stat->min_tgt_time_wr > tgt_time))
12461+ latency_stat->min_tgt_time_wr = tgt_time;
12462+ if ((latency_stat->min_dev_time_wr == 0) ||
12463+ (latency_stat->min_dev_time_wr > dev_time))
12464+ latency_stat->min_dev_time_wr = dev_time;
12465+
12466+ if (latency_stat->max_scst_time_wr < scst_time)
12467+ latency_stat->max_scst_time_wr = scst_time;
12468+ if (latency_stat->max_tgt_time_wr < tgt_time)
12469+ latency_stat->max_tgt_time_wr = tgt_time;
12470+ if (latency_stat->max_dev_time_wr < dev_time)
12471+ latency_stat->max_dev_time_wr = dev_time;
12472+
12473+ if (dev_latency_stat != NULL) {
12474+ dev_latency_stat->scst_time_wr += scst_time;
12475+ dev_latency_stat->tgt_time_wr += tgt_time;
12476+ dev_latency_stat->dev_time_wr += dev_time;
12477+ dev_latency_stat->processed_cmds_wr++;
12478+
12479+ if ((dev_latency_stat->min_scst_time_wr == 0) ||
12480+ (dev_latency_stat->min_scst_time_wr > scst_time))
12481+ dev_latency_stat->min_scst_time_wr = scst_time;
12482+ if ((dev_latency_stat->min_tgt_time_wr == 0) ||
12483+ (dev_latency_stat->min_tgt_time_wr > tgt_time))
12484+ dev_latency_stat->min_tgt_time_wr = tgt_time;
12485+ if ((dev_latency_stat->min_dev_time_wr == 0) ||
12486+ (dev_latency_stat->min_dev_time_wr > dev_time))
12487+ dev_latency_stat->min_dev_time_wr = dev_time;
12488+
12489+ if (dev_latency_stat->max_scst_time_wr < scst_time)
12490+ dev_latency_stat->max_scst_time_wr = scst_time;
12491+ if (dev_latency_stat->max_tgt_time_wr < tgt_time)
12492+ dev_latency_stat->max_tgt_time_wr = tgt_time;
12493+ if (dev_latency_stat->max_dev_time_wr < dev_time)
12494+ dev_latency_stat->max_dev_time_wr = dev_time;
12495+ }
12496+ }
12497+
12498+ spin_unlock_bh(&sess->lat_lock);
12499+
12500+ TRACE_DBG("cmd %p: finish %lld, scst_time %lld, "
12501+ "tgt_time %lld, dev_time %lld", cmd, finish, scst_time,
12502+ tgt_time, dev_time);
12503+ return;
12504+}
12505+
12506+#endif /* CONFIG_SCST_MEASURE_LATENCY */
12507diff -uprN orig/linux-2.6.35/drivers/scst/scst_main.c linux-2.6.35/drivers/scst/scst_main.c
12508--- orig/linux-2.6.35/drivers/scst/scst_main.c
12509+++ linux-2.6.35/drivers/scst/scst_main.c
12510@@ -0,0 +1,2195 @@
12511+/*
12512+ * scst_main.c
12513+ *
12514+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
12515+ * Copyright (C) 2004 - 2005 Leonid Stoljar
12516+ * Copyright (C) 2007 - 2010 ID7 Ltd.
12517+ *
12518+ * This program is free software; you can redistribute it and/or
12519+ * modify it under the terms of the GNU General Public License
12520+ * as published by the Free Software Foundation, version 2
12521+ * of the License.
12522+ *
12523+ * This program is distributed in the hope that it will be useful,
12524+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12525+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12526+ * GNU General Public License for more details.
12527+ */
12528+
12529+#include <linux/module.h>
12530+
12531+#include <linux/init.h>
12532+#include <linux/kernel.h>
12533+#include <linux/errno.h>
12534+#include <linux/list.h>
12535+#include <linux/spinlock.h>
12536+#include <linux/slab.h>
12537+#include <linux/sched.h>
12538+#include <linux/unistd.h>
12539+#include <linux/string.h>
12540+#include <linux/kthread.h>
12541+#include <linux/delay.h>
12542+
12543+#include <scst/scst.h>
12544+#include "scst_priv.h"
12545+#include "scst_mem.h"
12546+#include "scst_pres.h"
12547+
12548+#if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G)
12549+#warning "HIGHMEM kernel configurations are fully supported, but not\
12550+ recommended for performance reasons. Consider changing VMSPLIT\
12551+ option or use a 64-bit configuration instead. See README file for\
12552+ details."
12553+#endif
12554+
12555+/**
12556+ ** SCST global variables. They are all uninitialized to have their layout in
12557+ ** memory be exactly as specified. Otherwise compiler puts zero-initialized
12558+ ** variable separately from nonzero-initialized ones.
12559+ **/
12560+
12561+/*
12562+ * Main SCST mutex. All targets, devices and dev_types management is done
12563+ * under this mutex.
12564+ *
12565+ * It must NOT be used in any works (schedule_work(), etc.), because
12566+ * otherwise a deadlock (double lock, actually) is possible, e.g., with
12567+ * scst_user detach_tgt(), which is called under scst_mutex and calls
12568+ * flush_scheduled_work().
12569+ */
12570+struct mutex scst_mutex;
12571+EXPORT_SYMBOL_GPL(scst_mutex);
12572+
12573+/*
12574+ * Secondary level main mutex, inner for scst_mutex. Needed for
12575+ * __scst_pr_register_all_tg_pt(), since we can't use scst_mutex there,
12576+ * because of the circular locking dependency with dev_pr_mutex.
12577+ */
12578+struct mutex scst_mutex2;
12579+
12580+/* Both protected by scst_mutex or scst_mutex2 on read and both on write */
12581+struct list_head scst_template_list;
12582+struct list_head scst_dev_list;
12583+
12584+/* Protected by scst_mutex */
12585+struct list_head scst_dev_type_list;
12586+struct list_head scst_virtual_dev_type_list;
12587+
12588+spinlock_t scst_main_lock;
12589+
12590+static struct kmem_cache *scst_mgmt_cachep;
12591+mempool_t *scst_mgmt_mempool;
12592+static struct kmem_cache *scst_mgmt_stub_cachep;
12593+mempool_t *scst_mgmt_stub_mempool;
12594+static struct kmem_cache *scst_ua_cachep;
12595+mempool_t *scst_ua_mempool;
12596+static struct kmem_cache *scst_sense_cachep;
12597+mempool_t *scst_sense_mempool;
12598+static struct kmem_cache *scst_aen_cachep;
12599+mempool_t *scst_aen_mempool;
12600+struct kmem_cache *scst_tgtd_cachep;
12601+struct kmem_cache *scst_sess_cachep;
12602+struct kmem_cache *scst_acgd_cachep;
12603+
12604+unsigned int scst_setup_id;
12605+
12606+spinlock_t scst_init_lock;
12607+wait_queue_head_t scst_init_cmd_list_waitQ;
12608+struct list_head scst_init_cmd_list;
12609+unsigned int scst_init_poll_cnt;
12610+
12611+struct kmem_cache *scst_cmd_cachep;
12612+
12613+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
12614+unsigned long scst_trace_flag;
12615+#endif
12616+
12617+unsigned long scst_flags;
12618+atomic_t scst_cmd_count;
12619+
12620+struct scst_cmd_threads scst_main_cmd_threads;
12621+
12622+struct scst_tasklet scst_tasklets[NR_CPUS];
12623+
12624+spinlock_t scst_mcmd_lock;
12625+struct list_head scst_active_mgmt_cmd_list;
12626+struct list_head scst_delayed_mgmt_cmd_list;
12627+wait_queue_head_t scst_mgmt_cmd_list_waitQ;
12628+
12629+wait_queue_head_t scst_mgmt_waitQ;
12630+spinlock_t scst_mgmt_lock;
12631+struct list_head scst_sess_init_list;
12632+struct list_head scst_sess_shut_list;
12633+
12634+wait_queue_head_t scst_dev_cmd_waitQ;
12635+
12636+static struct mutex scst_suspend_mutex;
12637+/* protected by scst_suspend_mutex */
12638+static struct list_head scst_cmd_threads_list;
12639+
12640+int scst_threads;
12641+static struct task_struct *scst_init_cmd_thread;
12642+static struct task_struct *scst_mgmt_thread;
12643+static struct task_struct *scst_mgmt_cmd_thread;
12644+
12645+static int suspend_count;
12646+
12647+static int scst_virt_dev_last_id; /* protected by scst_mutex */
12648+
12649+static unsigned int scst_max_cmd_mem;
12650+unsigned int scst_max_dev_cmd_mem;
12651+
12652+module_param_named(scst_threads, scst_threads, int, 0);
12653+MODULE_PARM_DESC(scst_threads, "SCSI target threads count");
12654+
12655+module_param_named(scst_max_cmd_mem, scst_max_cmd_mem, int, S_IRUGO);
12656+MODULE_PARM_DESC(scst_max_cmd_mem, "Maximum memory allowed to be consumed by "
12657+ "all SCSI commands of all devices at any given time in MB");
12658+
12659+module_param_named(scst_max_dev_cmd_mem, scst_max_dev_cmd_mem, int, S_IRUGO);
12660+MODULE_PARM_DESC(scst_max_dev_cmd_mem, "Maximum memory allowed to be consumed "
12661+ "by all SCSI commands of a device at any given time in MB");
12662+
12663+struct scst_dev_type scst_null_devtype = {
12664+ .name = "none",
12665+ .threads_num = -1,
12666+};
12667+
12668+static void __scst_resume_activity(void);
12669+
12670+/**
12671+ * __scst_register_target_template() - register target template.
12672+ * @vtt: target template
12673+ * @version: SCST_INTERFACE_VERSION version string to ensure that
12674+ * SCST core and the target driver use the same version of
12675+ * the SCST interface
12676+ *
12677+ * Description:
12678+ * Registers a target template and returns 0 on success or appropriate
12679+ * error code otherwise.
12680+ *
12681+ * Target drivers supposed to behave sanely and not call register()
12682+ * and unregister() randomly sinultaneously.
12683+ */
12684+int __scst_register_target_template(struct scst_tgt_template *vtt,
12685+ const char *version)
12686+{
12687+ int res = 0;
12688+ struct scst_tgt_template *t;
12689+
12690+ TRACE_ENTRY();
12691+
12692+ INIT_LIST_HEAD(&vtt->tgt_list);
12693+
12694+ if (strcmp(version, SCST_INTERFACE_VERSION) != 0) {
12695+ PRINT_ERROR("Incorrect version of target %s", vtt->name);
12696+ res = -EINVAL;
12697+ goto out;
12698+ }
12699+
12700+ if (!vtt->detect) {
12701+ PRINT_ERROR("Target driver %s must have "
12702+ "detect() method.", vtt->name);
12703+ res = -EINVAL;
12704+ goto out;
12705+ }
12706+
12707+ if (!vtt->release) {
12708+ PRINT_ERROR("Target driver %s must have "
12709+ "release() method.", vtt->name);
12710+ res = -EINVAL;
12711+ goto out;
12712+ }
12713+
12714+ if (!vtt->xmit_response) {
12715+ PRINT_ERROR("Target driver %s must have "
12716+ "xmit_response() method.", vtt->name);
12717+ res = -EINVAL;
12718+ goto out;
12719+ }
12720+
12721+ if (vtt->get_initiator_port_transport_id == NULL)
12722+ PRINT_WARNING("Target driver %s doesn't support Persistent "
12723+ "Reservations", vtt->name);
12724+
12725+ if (vtt->threads_num < 0) {
12726+ PRINT_ERROR("Wrong threads_num value %d for "
12727+ "target \"%s\"", vtt->threads_num,
12728+ vtt->name);
12729+ res = -EINVAL;
12730+ goto out;
12731+ }
12732+
12733+ if ((!vtt->enable_target || !vtt->is_target_enabled) &&
12734+ !vtt->enabled_attr_not_needed)
12735+ PRINT_WARNING("Target driver %s doesn't have enable_target() "
12736+ "and/or is_target_enabled() method(s). This is unsafe "
12737+ "and can lead that initiators connected on the "
12738+ "initialization time can see an unexpected set of "
12739+ "devices or no devices at all!", vtt->name);
12740+
12741+ if (((vtt->add_target != NULL) && (vtt->del_target == NULL)) ||
12742+ ((vtt->add_target == NULL) && (vtt->del_target != NULL))) {
12743+ PRINT_ERROR("Target driver %s must either define both "
12744+ "add_target() and del_target(), or none.", vtt->name);
12745+ res = -EINVAL;
12746+ goto out;
12747+ }
12748+
12749+ if (vtt->rdy_to_xfer == NULL)
12750+ vtt->rdy_to_xfer_atomic = 1;
12751+
12752+ if (mutex_lock_interruptible(&scst_mutex) != 0)
12753+ goto out;
12754+ list_for_each_entry(t, &scst_template_list, scst_template_list_entry) {
12755+ if (strcmp(t->name, vtt->name) == 0) {
12756+ PRINT_ERROR("Target driver %s already registered",
12757+ vtt->name);
12758+ mutex_unlock(&scst_mutex);
12759+ goto out_unlock;
12760+ }
12761+ }
12762+ mutex_unlock(&scst_mutex);
12763+
12764+ res = scst_tgtt_sysfs_create(vtt);
12765+ if (res)
12766+ goto out;
12767+
12768+ mutex_lock(&scst_mutex);
12769+ mutex_lock(&scst_mutex2);
12770+ list_add_tail(&vtt->scst_template_list_entry, &scst_template_list);
12771+ mutex_unlock(&scst_mutex2);
12772+ mutex_unlock(&scst_mutex);
12773+
12774+ TRACE_DBG("%s", "Calling target driver's detect()");
12775+ res = vtt->detect(vtt);
12776+ TRACE_DBG("Target driver's detect() returned %d", res);
12777+ if (res < 0) {
12778+ PRINT_ERROR("%s", "The detect() routine failed");
12779+ res = -EINVAL;
12780+ goto out_del;
12781+ }
12782+
12783+ PRINT_INFO("Target template %s registered successfully", vtt->name);
12784+
12785+out:
12786+ TRACE_EXIT_RES(res);
12787+ return res;
12788+
12789+out_del:
12790+ scst_tgtt_sysfs_del(vtt);
12791+
12792+ mutex_lock(&scst_mutex);
12793+
12794+ mutex_lock(&scst_mutex2);
12795+ list_del(&vtt->scst_template_list_entry);
12796+ mutex_unlock(&scst_mutex2);
12797+
12798+out_unlock:
12799+ mutex_unlock(&scst_mutex);
12800+ goto out;
12801+}
12802+EXPORT_SYMBOL_GPL(__scst_register_target_template);
12803+
12804+static int scst_check_non_gpl_target_template(struct scst_tgt_template *vtt)
12805+{
12806+ int res;
12807+
12808+ TRACE_ENTRY();
12809+
12810+ if (vtt->task_mgmt_affected_cmds_done || vtt->threads_num ||
12811+ vtt->on_hw_pending_cmd_timeout) {
12812+ PRINT_ERROR("Not allowed functionality in non-GPL version for "
12813+ "target template %s", vtt->name);
12814+ res = -EPERM;
12815+ goto out;
12816+ }
12817+
12818+ res = 0;
12819+
12820+out:
12821+ TRACE_EXIT_RES(res);
12822+ return res;
12823+}
12824+
12825+/**
12826+ * __scst_register_target_template_non_gpl() - register target template,
12827+ * non-GPL version
12828+ * @vtt: target template
12829+ * @version: SCST_INTERFACE_VERSION version string to ensure that
12830+ * SCST core and the target driver use the same version of
12831+ * the SCST interface
12832+ *
12833+ * Description:
12834+ * Registers a target template and returns 0 on success or appropriate
12835+ * error code otherwise.
12836+ *
12837+ * Note: *vtt must be static!
12838+ */
12839+int __scst_register_target_template_non_gpl(struct scst_tgt_template *vtt,
12840+ const char *version)
12841+{
12842+ int res;
12843+
12844+ TRACE_ENTRY();
12845+
12846+ res = scst_check_non_gpl_target_template(vtt);
12847+ if (res != 0)
12848+ goto out;
12849+
12850+ res = __scst_register_target_template(vtt, version);
12851+
12852+out:
12853+ TRACE_EXIT_RES(res);
12854+ return res;
12855+}
12856+EXPORT_SYMBOL(__scst_register_target_template_non_gpl);
12857+
12858+/**
12859+ * scst_unregister_target_template() - unregister target template
12860+ *
12861+ * Target drivers supposed to behave sanely and not call register()
12862+ * and unregister() randomly sinultaneously. Also it is supposed that
12863+ * no attepts to create new targets for this vtt will be done in a race
12864+ * with this function.
12865+ */
12866+void scst_unregister_target_template(struct scst_tgt_template *vtt)
12867+{
12868+ struct scst_tgt *tgt;
12869+ struct scst_tgt_template *t;
12870+ int found = 0;
12871+
12872+ TRACE_ENTRY();
12873+
12874+ mutex_lock(&scst_mutex);
12875+
12876+ list_for_each_entry(t, &scst_template_list, scst_template_list_entry) {
12877+ if (strcmp(t->name, vtt->name) == 0) {
12878+ found = 1;
12879+ break;
12880+ }
12881+ }
12882+ if (!found) {
12883+ PRINT_ERROR("Target driver %s isn't registered", vtt->name);
12884+ goto out_err_up;
12885+ }
12886+
12887+ mutex_lock(&scst_mutex2);
12888+ list_del(&vtt->scst_template_list_entry);
12889+ mutex_unlock(&scst_mutex2);
12890+
12891+ /* Wait for outstanding sysfs mgmt calls completed */
12892+ while (vtt->tgtt_active_sysfs_works_count > 0) {
12893+ mutex_unlock(&scst_mutex);
12894+ msleep(100);
12895+ mutex_lock(&scst_mutex);
12896+ }
12897+
12898+restart:
12899+ list_for_each_entry(tgt, &vtt->tgt_list, tgt_list_entry) {
12900+ mutex_unlock(&scst_mutex);
12901+ scst_unregister_target(tgt);
12902+ mutex_lock(&scst_mutex);
12903+ goto restart;
12904+ }
12905+
12906+ mutex_unlock(&scst_mutex);
12907+
12908+ scst_tgtt_sysfs_del(vtt);
12909+
12910+ PRINT_INFO("Target template %s unregistered successfully", vtt->name);
12911+
12912+out:
12913+ TRACE_EXIT();
12914+ return;
12915+
12916+out_err_up:
12917+ mutex_unlock(&scst_mutex);
12918+ goto out;
12919+}
12920+EXPORT_SYMBOL(scst_unregister_target_template);
12921+
12922+/**
12923+ * scst_register_target() - register target
12924+ *
12925+ * Registers a target for template vtt and returns new target structure on
12926+ * success or NULL otherwise.
12927+ */
12928+struct scst_tgt *scst_register_target(struct scst_tgt_template *vtt,
12929+ const char *target_name)
12930+{
12931+ struct scst_tgt *tgt;
12932+ int rc = 0;
12933+
12934+ TRACE_ENTRY();
12935+
12936+ rc = scst_alloc_tgt(vtt, &tgt);
12937+ if (rc != 0)
12938+ goto out;
12939+
12940+ if (target_name != NULL) {
12941+
12942+ tgt->tgt_name = kmalloc(strlen(target_name) + 1, GFP_KERNEL);
12943+ if (tgt->tgt_name == NULL) {
12944+ TRACE(TRACE_OUT_OF_MEM, "Allocation of tgt name %s failed",
12945+ target_name);
12946+ rc = -ENOMEM;
12947+ goto out_free_tgt;
12948+ }
12949+ strcpy(tgt->tgt_name, target_name);
12950+ } else {
12951+ static int tgt_num; /* protected by scst_mutex */
12952+ int len = strlen(vtt->name) +
12953+ strlen(SCST_DEFAULT_TGT_NAME_SUFFIX) + 11 + 1;
12954+
12955+ tgt->tgt_name = kmalloc(len, GFP_KERNEL);
12956+ if (tgt->tgt_name == NULL) {
12957+ TRACE(TRACE_OUT_OF_MEM, "Allocation of tgt name failed "
12958+ "(template name %s)", vtt->name);
12959+ rc = -ENOMEM;
12960+ goto out_free_tgt;
12961+ }
12962+ sprintf(tgt->tgt_name, "%s%s%d", vtt->name,
12963+ SCST_DEFAULT_TGT_NAME_SUFFIX, tgt_num++);
12964+ }
12965+
12966+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
12967+ rc = -EINTR;
12968+ goto out_free_tgt;
12969+ }
12970+
12971+ rc = scst_tgt_sysfs_create(tgt);
12972+ if (rc < 0)
12973+ goto out_unlock;
12974+
12975+ tgt->default_acg = scst_alloc_add_acg(tgt, tgt->tgt_name, false);
12976+ if (tgt->default_acg == NULL)
12977+ goto out_sysfs_del;
12978+
12979+ mutex_lock(&scst_mutex2);
12980+ list_add_tail(&tgt->tgt_list_entry, &vtt->tgt_list);
12981+ mutex_unlock(&scst_mutex2);
12982+
12983+ mutex_unlock(&scst_mutex);
12984+
12985+ PRINT_INFO("Target %s for template %s registered successfully",
12986+ tgt->tgt_name, vtt->name);
12987+
12988+ TRACE_DBG("tgt %p", tgt);
12989+
12990+out:
12991+ TRACE_EXIT();
12992+ return tgt;
12993+
12994+out_sysfs_del:
12995+ mutex_unlock(&scst_mutex);
12996+ scst_tgt_sysfs_del(tgt);
12997+ goto out_free_tgt;
12998+
12999+out_unlock:
13000+ mutex_unlock(&scst_mutex);
13001+
13002+out_free_tgt:
13003+ /* In case of error tgt_name will be freed in scst_free_tgt() */
13004+ scst_free_tgt(tgt);
13005+ tgt = NULL;
13006+ goto out;
13007+}
13008+EXPORT_SYMBOL(scst_register_target);
13009+
13010+static inline int test_sess_list(struct scst_tgt *tgt)
13011+{
13012+ int res;
13013+ mutex_lock(&scst_mutex);
13014+ res = list_empty(&tgt->sess_list);
13015+ mutex_unlock(&scst_mutex);
13016+ return res;
13017+}
13018+
13019+/**
13020+ * scst_unregister_target() - unregister target.
13021+ *
13022+ * It is supposed that no attepts to create new sessions for this
13023+ * target will be done in a race with this function.
13024+ */
13025+void scst_unregister_target(struct scst_tgt *tgt)
13026+{
13027+ struct scst_session *sess;
13028+ struct scst_tgt_template *vtt = tgt->tgtt;
13029+ struct scst_acg *acg, *acg_tmp;
13030+
13031+ TRACE_ENTRY();
13032+
13033+ TRACE_DBG("%s", "Calling target driver's release()");
13034+ tgt->tgtt->release(tgt);
13035+ TRACE_DBG("%s", "Target driver's release() returned");
13036+
13037+ mutex_lock(&scst_mutex);
13038+again:
13039+ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
13040+ if (sess->shut_phase == SCST_SESS_SPH_READY) {
13041+ /*
13042+ * Sometimes it's hard for target driver to track all
13043+ * its sessions (see scst_local, eg), so let's help it.
13044+ */
13045+ mutex_unlock(&scst_mutex);
13046+ scst_unregister_session(sess, 0, NULL);
13047+ mutex_lock(&scst_mutex);
13048+ goto again;
13049+ }
13050+ }
13051+ mutex_unlock(&scst_mutex);
13052+
13053+ TRACE_DBG("%s", "Waiting for sessions shutdown");
13054+ wait_event(tgt->unreg_waitQ, test_sess_list(tgt));
13055+ TRACE_DBG("%s", "wait_event() returned");
13056+
13057+ scst_suspend_activity(false);
13058+ mutex_lock(&scst_mutex);
13059+
13060+ mutex_lock(&scst_mutex2);
13061+ list_del(&tgt->tgt_list_entry);
13062+ mutex_unlock(&scst_mutex2);
13063+
13064+ del_timer_sync(&tgt->retry_timer);
13065+
13066+ scst_del_free_acg(tgt->default_acg);
13067+
13068+ list_for_each_entry_safe(acg, acg_tmp, &tgt->tgt_acg_list,
13069+ acg_list_entry) {
13070+ scst_del_free_acg(acg);
13071+ }
13072+
13073+ mutex_unlock(&scst_mutex);
13074+ scst_resume_activity();
13075+
13076+ scst_tgt_sysfs_del(tgt);
13077+
13078+ PRINT_INFO("Target %s for template %s unregistered successfully",
13079+ tgt->tgt_name, vtt->name);
13080+
13081+ scst_free_tgt(tgt);
13082+
13083+ TRACE_DBG("Unregistering tgt %p finished", tgt);
13084+
13085+ TRACE_EXIT();
13086+ return;
13087+}
13088+EXPORT_SYMBOL(scst_unregister_target);
13089+
13090+static int scst_susp_wait(bool interruptible)
13091+{
13092+ int res = 0;
13093+
13094+ TRACE_ENTRY();
13095+
13096+ if (interruptible) {
13097+ res = wait_event_interruptible_timeout(scst_dev_cmd_waitQ,
13098+ (atomic_read(&scst_cmd_count) == 0),
13099+ SCST_SUSPENDING_TIMEOUT);
13100+ if (res <= 0) {
13101+ __scst_resume_activity();
13102+ if (res == 0)
13103+ res = -EBUSY;
13104+ } else
13105+ res = 0;
13106+ } else
13107+ wait_event(scst_dev_cmd_waitQ,
13108+ atomic_read(&scst_cmd_count) == 0);
13109+
13110+ TRACE_MGMT_DBG("wait_event() returned %d", res);
13111+
13112+ TRACE_EXIT_RES(res);
13113+ return res;
13114+}
13115+
13116+/**
13117+ * scst_suspend_activity() - globally suspend any activity
13118+ *
13119+ * Description:
13120+ * Globally suspends any activity and doesn't return, until there are any
13121+ * active commands (state after SCST_CMD_STATE_INIT). If "interruptible"
13122+ * is true, it returns after SCST_SUSPENDING_TIMEOUT or if it was interrupted
13123+ * by a signal with the corresponding error status < 0. If "interruptible"
13124+ * is false, it will wait virtually forever. On success returns 0.
13125+ *
13126+ * New arriving commands stay in the suspended state until
13127+ * scst_resume_activity() is called.
13128+ */
13129+int scst_suspend_activity(bool interruptible)
13130+{
13131+ int res = 0;
13132+ bool rep = false;
13133+
13134+ TRACE_ENTRY();
13135+
13136+ if (interruptible) {
13137+ if (mutex_lock_interruptible(&scst_suspend_mutex) != 0) {
13138+ res = -EINTR;
13139+ goto out;
13140+ }
13141+ } else
13142+ mutex_lock(&scst_suspend_mutex);
13143+
13144+ TRACE_MGMT_DBG("suspend_count %d", suspend_count);
13145+ suspend_count++;
13146+ if (suspend_count > 1)
13147+ goto out_up;
13148+
13149+ set_bit(SCST_FLAG_SUSPENDING, &scst_flags);
13150+ set_bit(SCST_FLAG_SUSPENDED, &scst_flags);
13151+ /*
13152+ * Assignment of SCST_FLAG_SUSPENDING and SCST_FLAG_SUSPENDED must be
13153+ * ordered with scst_cmd_count. Otherwise lockless logic in
13154+ * scst_translate_lun() and scst_mgmt_translate_lun() won't work.
13155+ */
13156+ smp_mb__after_set_bit();
13157+
13158+ /*
13159+ * See comment in scst_user.c::dev_user_task_mgmt_fn() for more
13160+ * information about scst_user behavior.
13161+ *
13162+ * ToDo: make the global suspending unneeded (switch to per-device
13163+ * reference counting? That would mean to switch off from lockless
13164+ * implementation of scst_translate_lun().. )
13165+ */
13166+
13167+ if (atomic_read(&scst_cmd_count) != 0) {
13168+ PRINT_INFO("Waiting for %d active commands to complete... This "
13169+ "might take few minutes for disks or few hours for "
13170+ "tapes, if you use long executed commands, like "
13171+ "REWIND or FORMAT. In case, if you have a hung user "
13172+ "space device (i.e. made using scst_user module) not "
13173+ "responding to any commands, if might take virtually "
13174+ "forever until the corresponding user space "
13175+ "program recovers and starts responding or gets "
13176+ "killed.", atomic_read(&scst_cmd_count));
13177+ rep = true;
13178+ }
13179+
13180+ res = scst_susp_wait(interruptible);
13181+ if (res != 0)
13182+ goto out_clear;
13183+
13184+ clear_bit(SCST_FLAG_SUSPENDING, &scst_flags);
13185+ /* See comment about smp_mb() above */
13186+ smp_mb__after_clear_bit();
13187+
13188+ TRACE_MGMT_DBG("Waiting for %d active commands finally to complete",
13189+ atomic_read(&scst_cmd_count));
13190+
13191+ res = scst_susp_wait(interruptible);
13192+ if (res != 0)
13193+ goto out_clear;
13194+
13195+ if (rep)
13196+ PRINT_INFO("%s", "All active commands completed");
13197+
13198+out_up:
13199+ mutex_unlock(&scst_suspend_mutex);
13200+
13201+out:
13202+ TRACE_EXIT_RES(res);
13203+ return res;
13204+
13205+out_clear:
13206+ clear_bit(SCST_FLAG_SUSPENDING, &scst_flags);
13207+ /* See comment about smp_mb() above */
13208+ smp_mb__after_clear_bit();
13209+ goto out_up;
13210+}
13211+EXPORT_SYMBOL_GPL(scst_suspend_activity);
13212+
13213+static void __scst_resume_activity(void)
13214+{
13215+ struct scst_cmd_threads *l;
13216+
13217+ TRACE_ENTRY();
13218+
13219+ suspend_count--;
13220+ TRACE_MGMT_DBG("suspend_count %d left", suspend_count);
13221+ if (suspend_count > 0)
13222+ goto out;
13223+
13224+ clear_bit(SCST_FLAG_SUSPENDED, &scst_flags);
13225+ /*
13226+ * The barrier is needed to make sure all woken up threads see the
13227+ * cleared flag. Not sure if it's really needed, but let's be safe.
13228+ */
13229+ smp_mb__after_clear_bit();
13230+
13231+ list_for_each_entry(l, &scst_cmd_threads_list, lists_list_entry) {
13232+ wake_up_all(&l->cmd_list_waitQ);
13233+ }
13234+ wake_up_all(&scst_init_cmd_list_waitQ);
13235+
13236+ spin_lock_irq(&scst_mcmd_lock);
13237+ if (!list_empty(&scst_delayed_mgmt_cmd_list)) {
13238+ struct scst_mgmt_cmd *m;
13239+ m = list_entry(scst_delayed_mgmt_cmd_list.next, typeof(*m),
13240+ mgmt_cmd_list_entry);
13241+ TRACE_MGMT_DBG("Moving delayed mgmt cmd %p to head of active "
13242+ "mgmt cmd list", m);
13243+ list_move(&m->mgmt_cmd_list_entry, &scst_active_mgmt_cmd_list);
13244+ }
13245+ spin_unlock_irq(&scst_mcmd_lock);
13246+ wake_up_all(&scst_mgmt_cmd_list_waitQ);
13247+
13248+out:
13249+ TRACE_EXIT();
13250+ return;
13251+}
13252+
13253+/**
13254+ * scst_resume_activity() - globally resume all activities
13255+ *
13256+ * Resumes suspended by scst_suspend_activity() activities.
13257+ */
13258+void scst_resume_activity(void)
13259+{
13260+ TRACE_ENTRY();
13261+
13262+ mutex_lock(&scst_suspend_mutex);
13263+ __scst_resume_activity();
13264+ mutex_unlock(&scst_suspend_mutex);
13265+
13266+ TRACE_EXIT();
13267+ return;
13268+}
13269+EXPORT_SYMBOL_GPL(scst_resume_activity);
13270+
13271+static int scst_register_device(struct scsi_device *scsidp)
13272+{
13273+ int res = 0;
13274+ struct scst_device *dev, *d;
13275+
13276+ TRACE_ENTRY();
13277+
13278+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
13279+ res = -EINTR;
13280+ goto out;
13281+ }
13282+
13283+ res = scst_alloc_device(GFP_KERNEL, &dev);
13284+ if (res != 0)
13285+ goto out_unlock;
13286+
13287+ dev->type = scsidp->type;
13288+
13289+ dev->virt_name = kmalloc(50, GFP_KERNEL);
13290+ if (dev->virt_name == NULL) {
13291+ PRINT_ERROR("%s", "Unable to alloc device name");
13292+ res = -ENOMEM;
13293+ goto out_free_dev;
13294+ }
13295+ snprintf(dev->virt_name, 50, "%d:%d:%d:%d", scsidp->host->host_no,
13296+ scsidp->channel, scsidp->id, scsidp->lun);
13297+
13298+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
13299+ if (strcmp(d->virt_name, dev->virt_name) == 0) {
13300+ PRINT_ERROR("Device %s already exists", dev->virt_name);
13301+ res = -EEXIST;
13302+ goto out_free_dev;
13303+ }
13304+ }
13305+
13306+ dev->scsi_dev = scsidp;
13307+
13308+ list_add_tail(&dev->dev_list_entry, &scst_dev_list);
13309+
13310+ mutex_unlock(&scst_mutex);
13311+
13312+ res = scst_dev_sysfs_create(dev);
13313+ if (res != 0)
13314+ goto out_del;
13315+
13316+ PRINT_INFO("Attached to scsi%d, channel %d, id %d, lun %d, "
13317+ "type %d", scsidp->host->host_no, scsidp->channel,
13318+ scsidp->id, scsidp->lun, scsidp->type);
13319+
13320+out:
13321+ TRACE_EXIT_RES(res);
13322+ return res;
13323+
13324+out_del:
13325+ list_del(&dev->dev_list_entry);
13326+
13327+out_free_dev:
13328+ scst_free_device(dev);
13329+
13330+out_unlock:
13331+ mutex_unlock(&scst_mutex);
13332+ goto out;
13333+}
13334+
13335+static void scst_unregister_device(struct scsi_device *scsidp)
13336+{
13337+ struct scst_device *d, *dev = NULL;
13338+ struct scst_acg_dev *acg_dev, *aa;
13339+
13340+ TRACE_ENTRY();
13341+
13342+ scst_suspend_activity(false);
13343+ mutex_lock(&scst_mutex);
13344+
13345+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
13346+ if (d->scsi_dev == scsidp) {
13347+ dev = d;
13348+ TRACE_DBG("Device %p found", dev);
13349+ break;
13350+ }
13351+ }
13352+ if (dev == NULL) {
13353+ PRINT_ERROR("SCST device for SCSI device %d:%d:%d:%d not found",
13354+ scsidp->host->host_no, scsidp->channel, scsidp->id,
13355+ scsidp->lun);
13356+ goto out_unlock;
13357+ }
13358+
13359+ list_del(&dev->dev_list_entry);
13360+
13361+ scst_assign_dev_handler(dev, &scst_null_devtype);
13362+
13363+ list_for_each_entry_safe(acg_dev, aa, &dev->dev_acg_dev_list,
13364+ dev_acg_dev_list_entry) {
13365+ scst_acg_del_lun(acg_dev->acg, acg_dev->lun, true);
13366+ }
13367+
13368+ mutex_unlock(&scst_mutex);
13369+
13370+ scst_resume_activity();
13371+
13372+ scst_dev_sysfs_del(dev);
13373+
13374+ PRINT_INFO("Detached from scsi%d, channel %d, id %d, lun %d, type %d",
13375+ scsidp->host->host_no, scsidp->channel, scsidp->id,
13376+ scsidp->lun, scsidp->type);
13377+
13378+ scst_free_device(dev);
13379+
13380+out:
13381+ TRACE_EXIT();
13382+ return;
13383+
13384+out_unlock:
13385+ mutex_unlock(&scst_mutex);
13386+ scst_resume_activity();
13387+ goto out;
13388+}
13389+
13390+static int scst_dev_handler_check(struct scst_dev_type *dev_handler)
13391+{
13392+ int res = 0;
13393+
13394+ if (dev_handler->parse == NULL) {
13395+ PRINT_ERROR("scst dev handler %s must have "
13396+ "parse() method.", dev_handler->name);
13397+ res = -EINVAL;
13398+ goto out;
13399+ }
13400+
13401+ if (((dev_handler->add_device != NULL) &&
13402+ (dev_handler->del_device == NULL)) ||
13403+ ((dev_handler->add_device == NULL) &&
13404+ (dev_handler->del_device != NULL))) {
13405+ PRINT_ERROR("Dev handler %s must either define both "
13406+ "add_device() and del_device(), or none.",
13407+ dev_handler->name);
13408+ res = -EINVAL;
13409+ goto out;
13410+ }
13411+
13412+ if (dev_handler->alloc_data_buf == NULL)
13413+ dev_handler->alloc_data_buf_atomic = 1;
13414+
13415+ if (dev_handler->dev_done == NULL)
13416+ dev_handler->dev_done_atomic = 1;
13417+
13418+out:
13419+ TRACE_EXIT_RES(res);
13420+ return res;
13421+}
13422+
13423+static int scst_check_device_name(const char *dev_name)
13424+{
13425+ int res = 0;
13426+
13427+ if (strchr(dev_name, '/') != NULL) {
13428+ PRINT_ERROR("Dev name %s contains illegal character '/'",
13429+ dev_name);
13430+ res = -EINVAL;
13431+ }
13432+
13433+ TRACE_EXIT_RES(res);
13434+ return res;
13435+}
13436+
13437+/**
13438+ * scst_register_virtual_device() - register a virtual device.
13439+ * @dev_handler: the device's device handler
13440+ * @dev_name: the new device name, NULL-terminated string. Must be uniq
13441+ * among all virtual devices in the system.
13442+ *
13443+ * Registers a virtual device and returns assinged to the device ID on
13444+ * success, or negative value otherwise
13445+ */
13446+int scst_register_virtual_device(struct scst_dev_type *dev_handler,
13447+ const char *dev_name)
13448+{
13449+ int res, rc;
13450+ struct scst_device *dev, *d;
13451+ bool sysfs_del = false;
13452+
13453+ TRACE_ENTRY();
13454+
13455+ if (dev_handler == NULL) {
13456+ PRINT_ERROR("%s: valid device handler must be supplied",
13457+ __func__);
13458+ res = -EINVAL;
13459+ goto out;
13460+ }
13461+
13462+ if (dev_name == NULL) {
13463+ PRINT_ERROR("%s: device name must be non-NULL", __func__);
13464+ res = -EINVAL;
13465+ goto out;
13466+ }
13467+
13468+ res = scst_check_device_name(dev_name);
13469+ if (res != 0)
13470+ goto out;
13471+
13472+ res = scst_dev_handler_check(dev_handler);
13473+ if (res != 0)
13474+ goto out;
13475+
13476+ res = scst_suspend_activity(true);
13477+ if (res != 0)
13478+ goto out;
13479+
13480+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
13481+ res = -EINTR;
13482+ goto out_resume;
13483+ }
13484+
13485+ res = scst_alloc_device(GFP_KERNEL, &dev);
13486+ if (res != 0)
13487+ goto out_unlock;
13488+
13489+ dev->type = dev_handler->type;
13490+ dev->scsi_dev = NULL;
13491+ dev->virt_name = kstrdup(dev_name, GFP_KERNEL);
13492+ if (dev->virt_name == NULL) {
13493+ PRINT_ERROR("Unable to allocate virt_name for dev %s",
13494+ dev_name);
13495+ res = -ENOMEM;
13496+ goto out_free_dev;
13497+ }
13498+
13499+ while (1) {
13500+ dev->virt_id = scst_virt_dev_last_id++;
13501+ if (dev->virt_id > 0)
13502+ break;
13503+ scst_virt_dev_last_id = 1;
13504+ }
13505+
13506+ res = dev->virt_id;
13507+
13508+ rc = scst_pr_init_dev(dev);
13509+ if (rc != 0) {
13510+ res = rc;
13511+ goto out_free_dev;
13512+ }
13513+
13514+ /*
13515+ * We can drop scst_mutex, because we have not yet added the dev in
13516+ * scst_dev_list, so it "doesn't exist" yet.
13517+ */
13518+ mutex_unlock(&scst_mutex);
13519+
13520+ res = scst_dev_sysfs_create(dev);
13521+ if (res != 0)
13522+ goto out_lock_pr_clear_dev;
13523+
13524+ mutex_lock(&scst_mutex);
13525+
13526+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
13527+ if (strcmp(d->virt_name, dev_name) == 0) {
13528+ PRINT_ERROR("Device %s already exists", dev_name);
13529+ res = -EEXIST;
13530+ sysfs_del = true;
13531+ goto out_pr_clear_dev;
13532+ }
13533+ }
13534+
13535+ rc = scst_assign_dev_handler(dev, dev_handler);
13536+ if (rc != 0) {
13537+ res = rc;
13538+ sysfs_del = true;
13539+ goto out_pr_clear_dev;
13540+ }
13541+
13542+ list_add_tail(&dev->dev_list_entry, &scst_dev_list);
13543+
13544+ mutex_unlock(&scst_mutex);
13545+ scst_resume_activity();
13546+
13547+ res = dev->virt_id;
13548+
13549+ PRINT_INFO("Attached to virtual device %s (id %d)",
13550+ dev_name, res);
13551+
13552+out:
13553+ TRACE_EXIT_RES(res);
13554+ return res;
13555+
13556+out_lock_pr_clear_dev:
13557+ mutex_lock(&scst_mutex);
13558+
13559+out_pr_clear_dev:
13560+ scst_pr_clear_dev(dev);
13561+
13562+out_free_dev:
13563+ mutex_unlock(&scst_mutex);
13564+ if (sysfs_del)
13565+ scst_dev_sysfs_del(dev);
13566+ scst_free_device(dev);
13567+ goto out_resume;
13568+
13569+out_unlock:
13570+ mutex_unlock(&scst_mutex);
13571+
13572+out_resume:
13573+ scst_resume_activity();
13574+ goto out;
13575+}
13576+EXPORT_SYMBOL_GPL(scst_register_virtual_device);
13577+
13578+/**
13579+ * scst_unregister_virtual_device() - unegister a virtual device.
13580+ * @id: the device's ID, returned by the registration function
13581+ */
13582+void scst_unregister_virtual_device(int id)
13583+{
13584+ struct scst_device *d, *dev = NULL;
13585+ struct scst_acg_dev *acg_dev, *aa;
13586+
13587+ TRACE_ENTRY();
13588+
13589+ scst_suspend_activity(false);
13590+ mutex_lock(&scst_mutex);
13591+
13592+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
13593+ if (d->virt_id == id) {
13594+ dev = d;
13595+ TRACE_DBG("Virtual device %p (id %d) found", dev, id);
13596+ break;
13597+ }
13598+ }
13599+ if (dev == NULL) {
13600+ PRINT_ERROR("Virtual device (id %d) not found", id);
13601+ goto out_unlock;
13602+ }
13603+
13604+ list_del(&dev->dev_list_entry);
13605+
13606+ scst_pr_clear_dev(dev);
13607+
13608+ scst_assign_dev_handler(dev, &scst_null_devtype);
13609+
13610+ list_for_each_entry_safe(acg_dev, aa, &dev->dev_acg_dev_list,
13611+ dev_acg_dev_list_entry) {
13612+ scst_acg_del_lun(acg_dev->acg, acg_dev->lun, true);
13613+ }
13614+
13615+ mutex_unlock(&scst_mutex);
13616+ scst_resume_activity();
13617+
13618+ scst_dev_sysfs_del(dev);
13619+
13620+ PRINT_INFO("Detached from virtual device %s (id %d)",
13621+ dev->virt_name, dev->virt_id);
13622+
13623+ scst_free_device(dev);
13624+
13625+out:
13626+ TRACE_EXIT();
13627+ return;
13628+
13629+out_unlock:
13630+ mutex_unlock(&scst_mutex);
13631+ scst_resume_activity();
13632+ goto out;
13633+}
13634+EXPORT_SYMBOL_GPL(scst_unregister_virtual_device);
13635+
13636+/**
13637+ * __scst_register_dev_driver() - register pass-through dev handler driver
13638+ * @dev_type: dev handler template
13639+ * @version: SCST_INTERFACE_VERSION version string to ensure that
13640+ * SCST core and the dev handler use the same version of
13641+ * the SCST interface
13642+ *
13643+ * Description:
13644+ * Registers a pass-through dev handler driver. Returns 0 on success
13645+ * or appropriate error code otherwise.
13646+ */
13647+int __scst_register_dev_driver(struct scst_dev_type *dev_type,
13648+ const char *version)
13649+{
13650+ int res, exist;
13651+ struct scst_dev_type *dt;
13652+
13653+ TRACE_ENTRY();
13654+
13655+ if (strcmp(version, SCST_INTERFACE_VERSION) != 0) {
13656+ PRINT_ERROR("Incorrect version of dev handler %s",
13657+ dev_type->name);
13658+ res = -EINVAL;
13659+ goto out;
13660+ }
13661+
13662+ res = scst_dev_handler_check(dev_type);
13663+ if (res != 0)
13664+ goto out;
13665+
13666+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
13667+ res = -EINTR;
13668+ goto out;
13669+ }
13670+
13671+ exist = 0;
13672+ list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) {
13673+ if (strcmp(dt->name, dev_type->name) == 0) {
13674+ PRINT_ERROR("Device type handler \"%s\" already "
13675+ "exist", dt->name);
13676+ exist = 1;
13677+ break;
13678+ }
13679+ }
13680+ if (exist)
13681+ goto out_unlock;
13682+
13683+ list_add_tail(&dev_type->dev_type_list_entry, &scst_dev_type_list);
13684+
13685+ mutex_unlock(&scst_mutex);
13686+
13687+ res = scst_devt_sysfs_create(dev_type);
13688+ if (res < 0)
13689+ goto out;
13690+
13691+ PRINT_INFO("Device handler \"%s\" for type %d registered "
13692+ "successfully", dev_type->name, dev_type->type);
13693+
13694+out:
13695+ TRACE_EXIT_RES(res);
13696+ return res;
13697+
13698+out_unlock:
13699+ mutex_unlock(&scst_mutex);
13700+ goto out;
13701+}
13702+EXPORT_SYMBOL_GPL(__scst_register_dev_driver);
13703+
13704+/**
13705+ * scst_unregister_dev_driver() - unregister pass-through dev handler driver
13706+ */
13707+void scst_unregister_dev_driver(struct scst_dev_type *dev_type)
13708+{
13709+ struct scst_device *dev;
13710+ struct scst_dev_type *dt;
13711+ int found = 0;
13712+
13713+ TRACE_ENTRY();
13714+
13715+ scst_suspend_activity(false);
13716+ mutex_lock(&scst_mutex);
13717+
13718+ list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) {
13719+ if (strcmp(dt->name, dev_type->name) == 0) {
13720+ found = 1;
13721+ break;
13722+ }
13723+ }
13724+ if (!found) {
13725+ PRINT_ERROR("Dev handler \"%s\" isn't registered",
13726+ dev_type->name);
13727+ goto out_up;
13728+ }
13729+
13730+ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
13731+ if (dev->handler == dev_type) {
13732+ scst_assign_dev_handler(dev, &scst_null_devtype);
13733+ TRACE_DBG("Dev handler removed from device %p", dev);
13734+ }
13735+ }
13736+
13737+ list_del(&dev_type->dev_type_list_entry);
13738+
13739+ mutex_unlock(&scst_mutex);
13740+ scst_resume_activity();
13741+
13742+ scst_devt_sysfs_del(dev_type);
13743+
13744+ PRINT_INFO("Device handler \"%s\" for type %d unloaded",
13745+ dev_type->name, dev_type->type);
13746+
13747+out:
13748+ TRACE_EXIT();
13749+ return;
13750+
13751+out_up:
13752+ mutex_unlock(&scst_mutex);
13753+ scst_resume_activity();
13754+ goto out;
13755+}
13756+EXPORT_SYMBOL_GPL(scst_unregister_dev_driver);
13757+
13758+/**
13759+ * __scst_register_virtual_dev_driver() - register virtual dev handler driver
13760+ * @dev_type: dev handler template
13761+ * @version: SCST_INTERFACE_VERSION version string to ensure that
13762+ * SCST core and the dev handler use the same version of
13763+ * the SCST interface
13764+ *
13765+ * Description:
13766+ * Registers a virtual dev handler driver. Returns 0 on success or
13767+ * appropriate error code otherwise.
13768+ */
13769+int __scst_register_virtual_dev_driver(struct scst_dev_type *dev_type,
13770+ const char *version)
13771+{
13772+ int res;
13773+
13774+ TRACE_ENTRY();
13775+
13776+ if (strcmp(version, SCST_INTERFACE_VERSION) != 0) {
13777+ PRINT_ERROR("Incorrect version of virtual dev handler %s",
13778+ dev_type->name);
13779+ res = -EINVAL;
13780+ goto out;
13781+ }
13782+
13783+ res = scst_dev_handler_check(dev_type);
13784+ if (res != 0)
13785+ goto out;
13786+
13787+ mutex_lock(&scst_mutex);
13788+ list_add_tail(&dev_type->dev_type_list_entry, &scst_virtual_dev_type_list);
13789+ mutex_unlock(&scst_mutex);
13790+
13791+ res = scst_devt_sysfs_create(dev_type);
13792+ if (res < 0)
13793+ goto out;
13794+
13795+ if (dev_type->type != -1) {
13796+ PRINT_INFO("Virtual device handler %s for type %d "
13797+ "registered successfully", dev_type->name,
13798+ dev_type->type);
13799+ } else {
13800+ PRINT_INFO("Virtual device handler \"%s\" registered "
13801+ "successfully", dev_type->name);
13802+ }
13803+
13804+out:
13805+ TRACE_EXIT_RES(res);
13806+ return res;
13807+}
13808+EXPORT_SYMBOL_GPL(__scst_register_virtual_dev_driver);
13809+
13810+/**
13811+ * scst_unregister_virtual_dev_driver() - unregister virtual dev driver
13812+ */
13813+void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type)
13814+{
13815+ TRACE_ENTRY();
13816+
13817+ mutex_lock(&scst_mutex);
13818+
13819+ /* Disable sysfs mgmt calls (e.g. addition of new devices) */
13820+ list_del(&dev_type->dev_type_list_entry);
13821+
13822+ /* Wait for outstanding sysfs mgmt calls completed */
13823+ while (dev_type->devt_active_sysfs_works_count > 0) {
13824+ mutex_unlock(&scst_mutex);
13825+ msleep(100);
13826+ mutex_lock(&scst_mutex);
13827+ }
13828+
13829+ mutex_unlock(&scst_mutex);
13830+
13831+ scst_devt_sysfs_del(dev_type);
13832+
13833+ PRINT_INFO("Device handler \"%s\" unloaded", dev_type->name);
13834+
13835+ TRACE_EXIT();
13836+ return;
13837+}
13838+EXPORT_SYMBOL_GPL(scst_unregister_virtual_dev_driver);
13839+
13840+/* scst_mutex supposed to be held */
13841+int scst_add_threads(struct scst_cmd_threads *cmd_threads,
13842+ struct scst_device *dev, struct scst_tgt_dev *tgt_dev, int num)
13843+{
13844+ int res = 0, i;
13845+ struct scst_cmd_thread_t *thr;
13846+ int n = 0, tgt_dev_num = 0;
13847+
13848+ TRACE_ENTRY();
13849+
13850+ if (num == 0) {
13851+ res = 0;
13852+ goto out;
13853+ }
13854+
13855+ list_for_each_entry(thr, &cmd_threads->threads_list, thread_list_entry) {
13856+ n++;
13857+ }
13858+
13859+ TRACE_DBG("cmd_threads %p, dev %p, tgt_dev %p, num %d, n %d",
13860+ cmd_threads, dev, tgt_dev, num, n);
13861+
13862+ if (tgt_dev != NULL) {
13863+ struct scst_tgt_dev *t;
13864+ list_for_each_entry(t, &tgt_dev->dev->dev_tgt_dev_list,
13865+ dev_tgt_dev_list_entry) {
13866+ if (t == tgt_dev)
13867+ break;
13868+ tgt_dev_num++;
13869+ }
13870+ }
13871+
13872+ for (i = 0; i < num; i++) {
13873+ thr = kmalloc(sizeof(*thr), GFP_KERNEL);
13874+ if (!thr) {
13875+ res = -ENOMEM;
13876+ PRINT_ERROR("Fail to allocate thr %d", res);
13877+ goto out_wait;
13878+ }
13879+
13880+ if (dev != NULL) {
13881+ char nm[14]; /* to limit the name's len */
13882+ strlcpy(nm, dev->virt_name, ARRAY_SIZE(nm));
13883+ thr->cmd_thread = kthread_create(scst_cmd_thread,
13884+ cmd_threads, "%s%d", nm, n++);
13885+ } else if (tgt_dev != NULL) {
13886+ char nm[11]; /* to limit the name's len */
13887+ strlcpy(nm, tgt_dev->dev->virt_name, ARRAY_SIZE(nm));
13888+ thr->cmd_thread = kthread_create(scst_cmd_thread,
13889+ cmd_threads, "%s%d_%d", nm, tgt_dev_num, n++);
13890+ } else
13891+ thr->cmd_thread = kthread_create(scst_cmd_thread,
13892+ cmd_threads, "scstd%d", n++);
13893+
13894+ if (IS_ERR(thr->cmd_thread)) {
13895+ res = PTR_ERR(thr->cmd_thread);
13896+ PRINT_ERROR("kthread_create() failed: %d", res);
13897+ kfree(thr);
13898+ goto out_wait;
13899+ }
13900+
13901+ list_add(&thr->thread_list_entry, &cmd_threads->threads_list);
13902+ cmd_threads->nr_threads++;
13903+
13904+ TRACE_DBG("Added thr %p to threads list (nr_threads %d, n %d)",
13905+ thr, cmd_threads->nr_threads, n);
13906+
13907+ wake_up_process(thr->cmd_thread);
13908+ }
13909+
13910+out_wait:
13911+ if (i > 0 && cmd_threads != &scst_main_cmd_threads) {
13912+ /*
13913+ * Wait for io_context gets initialized to avoid possible races
13914+ * for it from the sharing it tgt_devs.
13915+ */
13916+ while (!*(volatile bool*)&cmd_threads->io_context_ready) {
13917+ TRACE_DBG("Waiting for io_context for cmd_threads %p "
13918+ "initialized", cmd_threads);
13919+ msleep(50);
13920+ }
13921+ }
13922+
13923+ if (res != 0)
13924+ scst_del_threads(cmd_threads, i);
13925+
13926+out:
13927+ TRACE_EXIT_RES(res);
13928+ return res;
13929+}
13930+
13931+/* scst_mutex supposed to be held */
13932+void scst_del_threads(struct scst_cmd_threads *cmd_threads, int num)
13933+{
13934+ struct scst_cmd_thread_t *ct, *tmp;
13935+
13936+ TRACE_ENTRY();
13937+
13938+ if (num == 0)
13939+ goto out;
13940+
13941+ list_for_each_entry_safe_reverse(ct, tmp, &cmd_threads->threads_list,
13942+ thread_list_entry) {
13943+ int rc;
13944+ struct scst_device *dev;
13945+
13946+ rc = kthread_stop(ct->cmd_thread);
13947+ if (rc != 0 && rc != -EINTR)
13948+ TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
13949+
13950+ list_del(&ct->thread_list_entry);
13951+
13952+ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
13953+ struct scst_tgt_dev *tgt_dev;
13954+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
13955+ dev_tgt_dev_list_entry) {
13956+ scst_del_thr_data(tgt_dev, ct->cmd_thread);
13957+ }
13958+ }
13959+
13960+ kfree(ct);
13961+
13962+ cmd_threads->nr_threads--;
13963+
13964+ --num;
13965+ if (num == 0)
13966+ break;
13967+ }
13968+
13969+ EXTRACHECKS_BUG_ON((cmd_threads->nr_threads == 0) &&
13970+ (cmd_threads->io_context != NULL));
13971+
13972+out:
13973+ TRACE_EXIT();
13974+ return;
13975+}
13976+
13977+/* The activity supposed to be suspended and scst_mutex held */
13978+void scst_stop_dev_threads(struct scst_device *dev)
13979+{
13980+ struct scst_tgt_dev *tgt_dev;
13981+
13982+ TRACE_ENTRY();
13983+
13984+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
13985+ dev_tgt_dev_list_entry) {
13986+ scst_tgt_dev_stop_threads(tgt_dev);
13987+ }
13988+
13989+ if ((dev->threads_num > 0) &&
13990+ (dev->threads_pool_type == SCST_THREADS_POOL_SHARED))
13991+ scst_del_threads(&dev->dev_cmd_threads, -1);
13992+
13993+ TRACE_EXIT();
13994+ return;
13995+}
13996+
13997+/* The activity supposed to be suspended and scst_mutex held */
13998+int scst_create_dev_threads(struct scst_device *dev)
13999+{
14000+ int res = 0;
14001+ struct scst_tgt_dev *tgt_dev;
14002+
14003+ TRACE_ENTRY();
14004+
14005+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
14006+ dev_tgt_dev_list_entry) {
14007+ res = scst_tgt_dev_setup_threads(tgt_dev);
14008+ if (res != 0)
14009+ goto out_err;
14010+ }
14011+
14012+ if ((dev->threads_num > 0) &&
14013+ (dev->threads_pool_type == SCST_THREADS_POOL_SHARED)) {
14014+ res = scst_add_threads(&dev->dev_cmd_threads, dev, NULL,
14015+ dev->threads_num);
14016+ if (res != 0)
14017+ goto out_err;
14018+ }
14019+
14020+out:
14021+ TRACE_EXIT_RES(res);
14022+ return res;
14023+
14024+out_err:
14025+ scst_stop_dev_threads(dev);
14026+ goto out;
14027+}
14028+
14029+/* The activity supposed to be suspended and scst_mutex held */
14030+int scst_assign_dev_handler(struct scst_device *dev,
14031+ struct scst_dev_type *handler)
14032+{
14033+ int res = 0;
14034+ struct scst_tgt_dev *tgt_dev;
14035+ LIST_HEAD(attached_tgt_devs);
14036+
14037+ TRACE_ENTRY();
14038+
14039+ BUG_ON(handler == NULL);
14040+
14041+ if (dev->handler == handler)
14042+ goto out;
14043+
14044+ if (dev->handler == NULL)
14045+ goto assign;
14046+
14047+ if (dev->handler->detach_tgt) {
14048+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
14049+ dev_tgt_dev_list_entry) {
14050+ TRACE_DBG("Calling dev handler's detach_tgt(%p)",
14051+ tgt_dev);
14052+ dev->handler->detach_tgt(tgt_dev);
14053+ TRACE_DBG("%s", "Dev handler's detach_tgt() returned");
14054+ }
14055+ }
14056+
14057+ /*
14058+ * devt_dev sysfs must be created AFTER attach() and deleted BEFORE
14059+ * detach() to avoid calls from sysfs for not yet ready or already dead
14060+ * objects.
14061+ */
14062+ scst_devt_dev_sysfs_del(dev);
14063+
14064+ if (dev->handler->detach) {
14065+ TRACE_DBG("%s", "Calling dev handler's detach()");
14066+ dev->handler->detach(dev);
14067+ TRACE_DBG("%s", "Old handler's detach() returned");
14068+ }
14069+
14070+ scst_stop_dev_threads(dev);
14071+
14072+assign:
14073+ dev->handler = handler;
14074+
14075+ if (handler == NULL)
14076+ goto out;
14077+
14078+ dev->threads_num = handler->threads_num;
14079+ dev->threads_pool_type = handler->threads_pool_type;
14080+
14081+ if (handler->attach) {
14082+ TRACE_DBG("Calling new dev handler's attach(%p)", dev);
14083+ res = handler->attach(dev);
14084+ TRACE_DBG("New dev handler's attach() returned %d", res);
14085+ if (res != 0) {
14086+ PRINT_ERROR("New device handler's %s attach() "
14087+ "failed: %d", handler->name, res);
14088+ goto out;
14089+ }
14090+ }
14091+
14092+ res = scst_devt_dev_sysfs_create(dev);
14093+ if (res != 0)
14094+ goto out_detach;
14095+
14096+ if (handler->attach_tgt) {
14097+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
14098+ dev_tgt_dev_list_entry) {
14099+ TRACE_DBG("Calling dev handler's attach_tgt(%p)",
14100+ tgt_dev);
14101+ res = handler->attach_tgt(tgt_dev);
14102+ TRACE_DBG("%s", "Dev handler's attach_tgt() returned");
14103+ if (res != 0) {
14104+ PRINT_ERROR("Device handler's %s attach_tgt() "
14105+ "failed: %d", handler->name, res);
14106+ goto out_err_remove_sysfs;
14107+ }
14108+ list_add_tail(&tgt_dev->extra_tgt_dev_list_entry,
14109+ &attached_tgt_devs);
14110+ }
14111+ }
14112+
14113+ res = scst_create_dev_threads(dev);
14114+ if (res != 0)
14115+ goto out_err_detach_tgt;
14116+
14117+out:
14118+ TRACE_EXIT_RES(res);
14119+ return res;
14120+
14121+out_err_detach_tgt:
14122+ if (handler && handler->detach_tgt) {
14123+ list_for_each_entry(tgt_dev, &attached_tgt_devs,
14124+ extra_tgt_dev_list_entry) {
14125+ TRACE_DBG("Calling handler's detach_tgt(%p)",
14126+ tgt_dev);
14127+ handler->detach_tgt(tgt_dev);
14128+ TRACE_DBG("%s", "Handler's detach_tgt() returned");
14129+ }
14130+ }
14131+
14132+out_err_remove_sysfs:
14133+ scst_devt_dev_sysfs_del(dev);
14134+
14135+out_detach:
14136+ if (handler && handler->detach) {
14137+ TRACE_DBG("%s", "Calling handler's detach()");
14138+ handler->detach(dev);
14139+ TRACE_DBG("%s", "Handler's detach() returned");
14140+ }
14141+
14142+ dev->handler = &scst_null_devtype;
14143+ dev->threads_num = scst_null_devtype.threads_num;
14144+ dev->threads_pool_type = scst_null_devtype.threads_pool_type;
14145+ goto out;
14146+}
14147+
14148+/**
14149+ * scst_init_threads() - initialize SCST processing threads pool
14150+ *
14151+ * Initializes scst_cmd_threads structure
14152+ */
14153+void scst_init_threads(struct scst_cmd_threads *cmd_threads)
14154+{
14155+ TRACE_ENTRY();
14156+
14157+ spin_lock_init(&cmd_threads->cmd_list_lock);
14158+ INIT_LIST_HEAD(&cmd_threads->active_cmd_list);
14159+ init_waitqueue_head(&cmd_threads->cmd_list_waitQ);
14160+ INIT_LIST_HEAD(&cmd_threads->threads_list);
14161+ mutex_init(&cmd_threads->io_context_mutex);
14162+
14163+ mutex_lock(&scst_suspend_mutex);
14164+ list_add_tail(&cmd_threads->lists_list_entry,
14165+ &scst_cmd_threads_list);
14166+ mutex_unlock(&scst_suspend_mutex);
14167+
14168+ TRACE_EXIT();
14169+ return;
14170+}
14171+EXPORT_SYMBOL_GPL(scst_init_threads);
14172+
14173+/**
14174+ * scst_deinit_threads() - deinitialize SCST processing threads pool
14175+ *
14176+ * Deinitializes scst_cmd_threads structure
14177+ */
14178+void scst_deinit_threads(struct scst_cmd_threads *cmd_threads)
14179+{
14180+ TRACE_ENTRY();
14181+
14182+ mutex_lock(&scst_suspend_mutex);
14183+ list_del(&cmd_threads->lists_list_entry);
14184+ mutex_unlock(&scst_suspend_mutex);
14185+
14186+ BUG_ON(cmd_threads->io_context);
14187+
14188+ TRACE_EXIT();
14189+ return;
14190+}
14191+EXPORT_SYMBOL_GPL(scst_deinit_threads);
14192+
14193+static void scst_stop_global_threads(void)
14194+{
14195+ TRACE_ENTRY();
14196+
14197+ mutex_lock(&scst_mutex);
14198+
14199+ scst_del_threads(&scst_main_cmd_threads, -1);
14200+
14201+ if (scst_mgmt_cmd_thread)
14202+ kthread_stop(scst_mgmt_cmd_thread);
14203+ if (scst_mgmt_thread)
14204+ kthread_stop(scst_mgmt_thread);
14205+ if (scst_init_cmd_thread)
14206+ kthread_stop(scst_init_cmd_thread);
14207+
14208+ mutex_unlock(&scst_mutex);
14209+
14210+ TRACE_EXIT();
14211+ return;
14212+}
14213+
14214+/* It does NOT stop ran threads on error! */
14215+static int scst_start_global_threads(int num)
14216+{
14217+ int res;
14218+
14219+ TRACE_ENTRY();
14220+
14221+ mutex_lock(&scst_mutex);
14222+
14223+ res = scst_add_threads(&scst_main_cmd_threads, NULL, NULL, num);
14224+ if (res < 0)
14225+ goto out_unlock;
14226+
14227+ scst_init_cmd_thread = kthread_run(scst_init_thread,
14228+ NULL, "scst_initd");
14229+ if (IS_ERR(scst_init_cmd_thread)) {
14230+ res = PTR_ERR(scst_init_cmd_thread);
14231+ PRINT_ERROR("kthread_create() for init cmd failed: %d", res);
14232+ scst_init_cmd_thread = NULL;
14233+ goto out_unlock;
14234+ }
14235+
14236+ scst_mgmt_cmd_thread = kthread_run(scst_tm_thread,
14237+ NULL, "scsi_tm");
14238+ if (IS_ERR(scst_mgmt_cmd_thread)) {
14239+ res = PTR_ERR(scst_mgmt_cmd_thread);
14240+ PRINT_ERROR("kthread_create() for TM failed: %d", res);
14241+ scst_mgmt_cmd_thread = NULL;
14242+ goto out_unlock;
14243+ }
14244+
14245+ scst_mgmt_thread = kthread_run(scst_global_mgmt_thread,
14246+ NULL, "scst_mgmtd");
14247+ if (IS_ERR(scst_mgmt_thread)) {
14248+ res = PTR_ERR(scst_mgmt_thread);
14249+ PRINT_ERROR("kthread_create() for mgmt failed: %d", res);
14250+ scst_mgmt_thread = NULL;
14251+ goto out_unlock;
14252+ }
14253+
14254+out_unlock:
14255+ mutex_unlock(&scst_mutex);
14256+
14257+ TRACE_EXIT_RES(res);
14258+ return res;
14259+}
14260+
14261+/**
14262+ * scst_get() - increase global SCST ref counter
14263+ *
14264+ * Increases global SCST ref counter that prevents from entering into suspended
14265+ * activities stage, so protects from any global management operations.
14266+ */
14267+void scst_get(void)
14268+{
14269+ __scst_get();
14270+}
14271+EXPORT_SYMBOL(scst_get);
14272+
14273+/**
14274+ * scst_put() - decrease global SCST ref counter
14275+ *
14276+ * Decreses global SCST ref counter that prevents from entering into suspended
14277+ * activities stage, so protects from any global management operations. On
14278+ * zero, if suspending activities is waiting, they will be suspended.
14279+ */
14280+void scst_put(void)
14281+{
14282+ __scst_put();
14283+}
14284+EXPORT_SYMBOL(scst_put);
14285+
14286+/**
14287+ * scst_get_setup_id() - return SCST setup ID
14288+ *
14289+ * Returns SCST setup ID. This ID can be used for multiple
14290+ * setups with the same configuration.
14291+ */
14292+unsigned int scst_get_setup_id(void)
14293+{
14294+ return scst_setup_id;
14295+}
14296+EXPORT_SYMBOL_GPL(scst_get_setup_id);
14297+
14298+static int scst_add(struct device *cdev, struct class_interface *intf)
14299+{
14300+ struct scsi_device *scsidp;
14301+ int res = 0;
14302+
14303+ TRACE_ENTRY();
14304+
14305+ scsidp = to_scsi_device(cdev->parent);
14306+
14307+ if ((scsidp->host->hostt->name == NULL) ||
14308+ (strcmp(scsidp->host->hostt->name, SCST_LOCAL_NAME) != 0))
14309+ res = scst_register_device(scsidp);
14310+
14311+ TRACE_EXIT();
14312+ return res;
14313+}
14314+
14315+static void scst_remove(struct device *cdev, struct class_interface *intf)
14316+{
14317+ struct scsi_device *scsidp;
14318+
14319+ TRACE_ENTRY();
14320+
14321+ scsidp = to_scsi_device(cdev->parent);
14322+
14323+ if ((scsidp->host->hostt->name == NULL) ||
14324+ (strcmp(scsidp->host->hostt->name, SCST_LOCAL_NAME) != 0))
14325+ scst_unregister_device(scsidp);
14326+
14327+ TRACE_EXIT();
14328+ return;
14329+}
14330+
14331+static struct class_interface scst_interface = {
14332+ .add_dev = scst_add,
14333+ .remove_dev = scst_remove,
14334+};
14335+
14336+static void __init scst_print_config(void)
14337+{
14338+ char buf[128];
14339+ int i, j;
14340+
14341+ i = snprintf(buf, sizeof(buf), "Enabled features: ");
14342+ j = i;
14343+
14344+#ifdef CONFIG_SCST_STRICT_SERIALIZING
14345+ i += snprintf(&buf[i], sizeof(buf) - i, "STRICT_SERIALIZING");
14346+#endif
14347+
14348+#ifdef CONFIG_SCST_EXTRACHECKS
14349+ i += snprintf(&buf[i], sizeof(buf) - i, "%sEXTRACHECKS",
14350+ (j == i) ? "" : ", ");
14351+#endif
14352+
14353+#ifdef CONFIG_SCST_TRACING
14354+ i += snprintf(&buf[i], sizeof(buf) - i, "%sTRACING",
14355+ (j == i) ? "" : ", ");
14356+#endif
14357+
14358+#ifdef CONFIG_SCST_DEBUG
14359+ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG",
14360+ (j == i) ? "" : ", ");
14361+#endif
14362+
14363+#ifdef CONFIG_SCST_DEBUG_TM
14364+ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG_TM",
14365+ (j == i) ? "" : ", ");
14366+#endif
14367+
14368+#ifdef CONFIG_SCST_DEBUG_RETRY
14369+ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG_RETRY",
14370+ (j == i) ? "" : ", ");
14371+#endif
14372+
14373+#ifdef CONFIG_SCST_DEBUG_OOM
14374+ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG_OOM",
14375+ (j == i) ? "" : ", ");
14376+#endif
14377+
14378+#ifdef CONFIG_SCST_DEBUG_SN
14379+ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG_SN",
14380+ (j == i) ? "" : ", ");
14381+#endif
14382+
14383+#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
14384+ i += snprintf(&buf[i], sizeof(buf) - i, "%sUSE_EXPECTED_VALUES",
14385+ (j == i) ? "" : ", ");
14386+#endif
14387+
14388+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
14389+ i += snprintf(&buf[i], sizeof(buf) - i,
14390+ "%sTEST_IO_IN_SIRQ",
14391+ (j == i) ? "" : ", ");
14392+#endif
14393+
14394+#ifdef CONFIG_SCST_STRICT_SECURITY
14395+ i += snprintf(&buf[i], sizeof(buf) - i, "%sSTRICT_SECURITY",
14396+ (j == i) ? "" : ", ");
14397+#endif
14398+
14399+ if (j != i)
14400+ PRINT_INFO("%s", buf);
14401+}
14402+
14403+static int __init init_scst(void)
14404+{
14405+ int res, i;
14406+ int scst_num_cpus;
14407+
14408+ TRACE_ENTRY();
14409+
14410+ {
14411+ struct scsi_sense_hdr *shdr;
14412+ BUILD_BUG_ON(SCST_SENSE_BUFFERSIZE < sizeof(*shdr));
14413+ }
14414+ {
14415+ struct scst_tgt_dev *t;
14416+ struct scst_cmd *c;
14417+ BUILD_BUG_ON(sizeof(t->curr_sn) != sizeof(t->expected_sn));
14418+ BUILD_BUG_ON(sizeof(c->sn) != sizeof(t->expected_sn));
14419+ }
14420+
14421+ mutex_init(&scst_mutex);
14422+ mutex_init(&scst_mutex2);
14423+ INIT_LIST_HEAD(&scst_template_list);
14424+ INIT_LIST_HEAD(&scst_dev_list);
14425+ INIT_LIST_HEAD(&scst_dev_type_list);
14426+ INIT_LIST_HEAD(&scst_virtual_dev_type_list);
14427+ spin_lock_init(&scst_main_lock);
14428+ spin_lock_init(&scst_init_lock);
14429+ init_waitqueue_head(&scst_init_cmd_list_waitQ);
14430+ INIT_LIST_HEAD(&scst_init_cmd_list);
14431+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
14432+ scst_trace_flag = SCST_DEFAULT_LOG_FLAGS;
14433+#endif
14434+ atomic_set(&scst_cmd_count, 0);
14435+ spin_lock_init(&scst_mcmd_lock);
14436+ INIT_LIST_HEAD(&scst_active_mgmt_cmd_list);
14437+ INIT_LIST_HEAD(&scst_delayed_mgmt_cmd_list);
14438+ init_waitqueue_head(&scst_mgmt_cmd_list_waitQ);
14439+ init_waitqueue_head(&scst_mgmt_waitQ);
14440+ spin_lock_init(&scst_mgmt_lock);
14441+ INIT_LIST_HEAD(&scst_sess_init_list);
14442+ INIT_LIST_HEAD(&scst_sess_shut_list);
14443+ init_waitqueue_head(&scst_dev_cmd_waitQ);
14444+ mutex_init(&scst_suspend_mutex);
14445+ INIT_LIST_HEAD(&scst_cmd_threads_list);
14446+
14447+ scst_init_threads(&scst_main_cmd_threads);
14448+
14449+ res = scst_lib_init();
14450+ if (res != 0)
14451+ goto out_deinit_threads;
14452+
14453+ scst_num_cpus = num_online_cpus();
14454+
14455+ /* ToDo: register_cpu_notifier() */
14456+
14457+ if (scst_threads == 0)
14458+ scst_threads = scst_num_cpus;
14459+
14460+ if (scst_threads < 1) {
14461+ PRINT_ERROR("%s", "scst_threads can not be less than 1");
14462+ scst_threads = scst_num_cpus;
14463+ }
14464+
14465+#define INIT_CACHEP(p, s, o) do { \
14466+ p = KMEM_CACHE(s, SCST_SLAB_FLAGS); \
14467+ TRACE_MEM("Slab create: %s at %p size %zd", #s, p, \
14468+ sizeof(struct s)); \
14469+ if (p == NULL) { \
14470+ res = -ENOMEM; \
14471+ goto o; \
14472+ } \
14473+ } while (0)
14474+
14475+ INIT_CACHEP(scst_mgmt_cachep, scst_mgmt_cmd, out_lib_exit);
14476+ INIT_CACHEP(scst_mgmt_stub_cachep, scst_mgmt_cmd_stub,
14477+ out_destroy_mgmt_cache);
14478+ INIT_CACHEP(scst_ua_cachep, scst_tgt_dev_UA,
14479+ out_destroy_mgmt_stub_cache);
14480+ {
14481+ struct scst_sense { uint8_t s[SCST_SENSE_BUFFERSIZE]; };
14482+ INIT_CACHEP(scst_sense_cachep, scst_sense,
14483+ out_destroy_ua_cache);
14484+ }
14485+ INIT_CACHEP(scst_aen_cachep, scst_aen, out_destroy_sense_cache);
14486+ INIT_CACHEP(scst_cmd_cachep, scst_cmd, out_destroy_aen_cache);
14487+ INIT_CACHEP(scst_sess_cachep, scst_session, out_destroy_cmd_cache);
14488+ INIT_CACHEP(scst_tgtd_cachep, scst_tgt_dev, out_destroy_sess_cache);
14489+ INIT_CACHEP(scst_acgd_cachep, scst_acg_dev, out_destroy_tgt_cache);
14490+
14491+ scst_mgmt_mempool = mempool_create(64, mempool_alloc_slab,
14492+ mempool_free_slab, scst_mgmt_cachep);
14493+ if (scst_mgmt_mempool == NULL) {
14494+ res = -ENOMEM;
14495+ goto out_destroy_acg_cache;
14496+ }
14497+
14498+ /*
14499+ * All mgmt stubs, UAs and sense buffers are bursty and loosing them
14500+ * may have fatal consequences, so let's have big pools for them.
14501+ */
14502+
14503+ scst_mgmt_stub_mempool = mempool_create(1024, mempool_alloc_slab,
14504+ mempool_free_slab, scst_mgmt_stub_cachep);
14505+ if (scst_mgmt_stub_mempool == NULL) {
14506+ res = -ENOMEM;
14507+ goto out_destroy_mgmt_mempool;
14508+ }
14509+
14510+ scst_ua_mempool = mempool_create(512, mempool_alloc_slab,
14511+ mempool_free_slab, scst_ua_cachep);
14512+ if (scst_ua_mempool == NULL) {
14513+ res = -ENOMEM;
14514+ goto out_destroy_mgmt_stub_mempool;
14515+ }
14516+
14517+ scst_sense_mempool = mempool_create(1024, mempool_alloc_slab,
14518+ mempool_free_slab, scst_sense_cachep);
14519+ if (scst_sense_mempool == NULL) {
14520+ res = -ENOMEM;
14521+ goto out_destroy_ua_mempool;
14522+ }
14523+
14524+ scst_aen_mempool = mempool_create(100, mempool_alloc_slab,
14525+ mempool_free_slab, scst_aen_cachep);
14526+ if (scst_aen_mempool == NULL) {
14527+ res = -ENOMEM;
14528+ goto out_destroy_sense_mempool;
14529+ }
14530+
14531+ res = scst_sysfs_init();
14532+ if (res != 0)
14533+ goto out_destroy_aen_mempool;
14534+
14535+ if (scst_max_cmd_mem == 0) {
14536+ struct sysinfo si;
14537+ si_meminfo(&si);
14538+#if BITS_PER_LONG == 32
14539+ scst_max_cmd_mem = min(
14540+ (((uint64_t)(si.totalram - si.totalhigh) << PAGE_SHIFT)
14541+ >> 20) >> 2, (uint64_t)1 << 30);
14542+#else
14543+ scst_max_cmd_mem = (((si.totalram - si.totalhigh) << PAGE_SHIFT)
14544+ >> 20) >> 2;
14545+#endif
14546+ }
14547+
14548+ if (scst_max_dev_cmd_mem != 0) {
14549+ if (scst_max_dev_cmd_mem > scst_max_cmd_mem) {
14550+ PRINT_ERROR("scst_max_dev_cmd_mem (%d) > "
14551+ "scst_max_cmd_mem (%d)",
14552+ scst_max_dev_cmd_mem,
14553+ scst_max_cmd_mem);
14554+ scst_max_dev_cmd_mem = scst_max_cmd_mem;
14555+ }
14556+ } else
14557+ scst_max_dev_cmd_mem = scst_max_cmd_mem * 2 / 5;
14558+
14559+ res = scst_sgv_pools_init(
14560+ ((uint64_t)scst_max_cmd_mem << 10) >> (PAGE_SHIFT - 10), 0);
14561+ if (res != 0)
14562+ goto out_sysfs_cleanup;
14563+
14564+ res = scsi_register_interface(&scst_interface);
14565+ if (res != 0)
14566+ goto out_destroy_sgv_pool;
14567+
14568+ for (i = 0; i < (int)ARRAY_SIZE(scst_tasklets); i++) {
14569+ spin_lock_init(&scst_tasklets[i].tasklet_lock);
14570+ INIT_LIST_HEAD(&scst_tasklets[i].tasklet_cmd_list);
14571+ tasklet_init(&scst_tasklets[i].tasklet,
14572+ (void *)scst_cmd_tasklet,
14573+ (unsigned long)&scst_tasklets[i]);
14574+ }
14575+
14576+ TRACE_DBG("%d CPUs found, starting %d threads", scst_num_cpus,
14577+ scst_threads);
14578+
14579+ res = scst_start_global_threads(scst_threads);
14580+ if (res < 0)
14581+ goto out_thread_free;
14582+
14583+ PRINT_INFO("SCST version %s loaded successfully (max mem for "
14584+ "commands %dMB, per device %dMB)", SCST_VERSION_STRING,
14585+ scst_max_cmd_mem, scst_max_dev_cmd_mem);
14586+
14587+ scst_print_config();
14588+
14589+out:
14590+ TRACE_EXIT_RES(res);
14591+ return res;
14592+
14593+out_thread_free:
14594+ scst_stop_global_threads();
14595+
14596+ scsi_unregister_interface(&scst_interface);
14597+
14598+out_destroy_sgv_pool:
14599+ scst_sgv_pools_deinit();
14600+
14601+out_sysfs_cleanup:
14602+ scst_sysfs_cleanup();
14603+
14604+out_destroy_aen_mempool:
14605+ mempool_destroy(scst_aen_mempool);
14606+
14607+out_destroy_sense_mempool:
14608+ mempool_destroy(scst_sense_mempool);
14609+
14610+out_destroy_ua_mempool:
14611+ mempool_destroy(scst_ua_mempool);
14612+
14613+out_destroy_mgmt_stub_mempool:
14614+ mempool_destroy(scst_mgmt_stub_mempool);
14615+
14616+out_destroy_mgmt_mempool:
14617+ mempool_destroy(scst_mgmt_mempool);
14618+
14619+out_destroy_acg_cache:
14620+ kmem_cache_destroy(scst_acgd_cachep);
14621+
14622+out_destroy_tgt_cache:
14623+ kmem_cache_destroy(scst_tgtd_cachep);
14624+
14625+out_destroy_sess_cache:
14626+ kmem_cache_destroy(scst_sess_cachep);
14627+
14628+out_destroy_cmd_cache:
14629+ kmem_cache_destroy(scst_cmd_cachep);
14630+
14631+out_destroy_aen_cache:
14632+ kmem_cache_destroy(scst_aen_cachep);
14633+
14634+out_destroy_sense_cache:
14635+ kmem_cache_destroy(scst_sense_cachep);
14636+
14637+out_destroy_ua_cache:
14638+ kmem_cache_destroy(scst_ua_cachep);
14639+
14640+out_destroy_mgmt_stub_cache:
14641+ kmem_cache_destroy(scst_mgmt_stub_cachep);
14642+
14643+out_destroy_mgmt_cache:
14644+ kmem_cache_destroy(scst_mgmt_cachep);
14645+
14646+out_lib_exit:
14647+ scst_lib_exit();
14648+
14649+out_deinit_threads:
14650+ scst_deinit_threads(&scst_main_cmd_threads);
14651+ goto out;
14652+}
14653+
14654+static void __exit exit_scst(void)
14655+{
14656+ TRACE_ENTRY();
14657+
14658+ /* ToDo: unregister_cpu_notifier() */
14659+
14660+ scst_stop_global_threads();
14661+
14662+ scst_deinit_threads(&scst_main_cmd_threads);
14663+
14664+ scsi_unregister_interface(&scst_interface);
14665+
14666+ scst_sgv_pools_deinit();
14667+
14668+ scst_sysfs_cleanup();
14669+
14670+#define DEINIT_CACHEP(p) do { \
14671+ kmem_cache_destroy(p); \
14672+ p = NULL; \
14673+ } while (0)
14674+
14675+ mempool_destroy(scst_mgmt_mempool);
14676+ mempool_destroy(scst_mgmt_stub_mempool);
14677+ mempool_destroy(scst_ua_mempool);
14678+ mempool_destroy(scst_sense_mempool);
14679+ mempool_destroy(scst_aen_mempool);
14680+
14681+ DEINIT_CACHEP(scst_mgmt_cachep);
14682+ DEINIT_CACHEP(scst_mgmt_stub_cachep);
14683+ DEINIT_CACHEP(scst_ua_cachep);
14684+ DEINIT_CACHEP(scst_sense_cachep);
14685+ DEINIT_CACHEP(scst_aen_cachep);
14686+ DEINIT_CACHEP(scst_cmd_cachep);
14687+ DEINIT_CACHEP(scst_sess_cachep);
14688+ DEINIT_CACHEP(scst_tgtd_cachep);
14689+ DEINIT_CACHEP(scst_acgd_cachep);
14690+
14691+ scst_lib_exit();
14692+
14693+ PRINT_INFO("%s", "SCST unloaded");
14694+
14695+ TRACE_EXIT();
14696+ return;
14697+}
14698+
14699+module_init(init_scst);
14700+module_exit(exit_scst);
14701+
14702+MODULE_AUTHOR("Vladislav Bolkhovitin");
14703+MODULE_LICENSE("GPL");
14704+MODULE_DESCRIPTION("SCSI target core");
14705+MODULE_VERSION(SCST_VERSION_STRING);
14706diff -uprN orig/linux-2.6.35/drivers/scst/scst_module.c linux-2.6.35/drivers/scst/scst_module.c
14707--- orig/linux-2.6.35/drivers/scst/scst_module.c
14708+++ linux-2.6.35/drivers/scst/scst_module.c
14709@@ -0,0 +1,69 @@
14710+/*
14711+ * scst_module.c
14712+ *
14713+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
14714+ * Copyright (C) 2004 - 2005 Leonid Stoljar
14715+ * Copyright (C) 2007 - 2010 ID7 Ltd.
14716+ *
14717+ * Support for loading target modules. The usage is similar to scsi_module.c
14718+ *
14719+ * This program is free software; you can redistribute it and/or
14720+ * modify it under the terms of the GNU General Public License
14721+ * as published by the Free Software Foundation, version 2
14722+ * of the License.
14723+ *
14724+ * This program is distributed in the hope that it will be useful,
14725+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14726+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14727+ * GNU General Public License for more details.
14728+ */
14729+
14730+#include <linux/module.h>
14731+#include <linux/init.h>
14732+
14733+#include <scst.h>
14734+
14735+static int __init init_this_scst_driver(void)
14736+{
14737+ int res;
14738+
14739+ TRACE_ENTRY();
14740+
14741+ res = scst_register_target_template(&driver_target_template);
14742+ TRACE_DBG("scst_register_target_template() returned %d", res);
14743+ if (res < 0)
14744+ goto out;
14745+
14746+#ifdef SCST_REGISTER_INITIATOR_DRIVER
14747+ driver_template.module = THIS_MODULE;
14748+ scsi_register_module(MODULE_SCSI_HA, &driver_template);
14749+ TRACE_DBG("driver_template.present=%d",
14750+ driver_template.present);
14751+ if (driver_template.present == 0) {
14752+ res = -ENODEV;
14753+ MOD_DEC_USE_COUNT;
14754+ goto out;
14755+ }
14756+#endif
14757+
14758+out:
14759+ TRACE_EXIT_RES(res);
14760+ return res;
14761+}
14762+
14763+static void __exit exit_this_scst_driver(void)
14764+{
14765+ TRACE_ENTRY();
14766+
14767+#ifdef SCST_REGISTER_INITIATOR_DRIVER
14768+ scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
14769+#endif
14770+
14771+ scst_unregister_target_template(&driver_target_template);
14772+
14773+ TRACE_EXIT();
14774+ return;
14775+}
14776+
14777+module_init(init_this_scst_driver);
14778+module_exit(exit_this_scst_driver);
14779diff -uprN orig/linux-2.6.35/drivers/scst/scst_pres.c linux-2.6.35/drivers/scst/scst_pres.c
14780--- orig/linux-2.6.35/drivers/scst/scst_pres.c
14781+++ linux-2.6.35/drivers/scst/scst_pres.c
14782@@ -0,0 +1,2648 @@
14783+/*
14784+ * scst_pres.c
14785+ *
14786+ * Copyright (C) 2009 - 2010 Alexey Obitotskiy <alexeyo1@open-e.com>
14787+ * Copyright (C) 2009 - 2010 Open-E, Inc.
14788+ * Copyright (C) 2009 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
14789+ *
14790+ * This program is free software; you can redistribute it and/or
14791+ * modify it under the terms of the GNU General Public License
14792+ * as published by the Free Software Foundation, version 2
14793+ * of the License.
14794+ *
14795+ * This program is distributed in the hope that it will be useful,
14796+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14797+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14798+ * GNU General Public License for more details.
14799+ */
14800+
14801+#include <linux/init.h>
14802+#include <linux/kernel.h>
14803+#include <linux/errno.h>
14804+#include <linux/list.h>
14805+#include <linux/spinlock.h>
14806+#include <linux/slab.h>
14807+#include <linux/sched.h>
14808+#include <linux/smp_lock.h>
14809+#include <linux/unistd.h>
14810+#include <linux/string.h>
14811+#include <linux/kthread.h>
14812+#include <linux/delay.h>
14813+#include <linux/time.h>
14814+#include <linux/ctype.h>
14815+#include <asm/byteorder.h>
14816+#include <linux/syscalls.h>
14817+#include <linux/file.h>
14818+#include <linux/fs.h>
14819+#include <linux/fcntl.h>
14820+#include <linux/uaccess.h>
14821+#include <linux/namei.h>
14822+#include <linux/version.h>
14823+#include <linux/vmalloc.h>
14824+#include <asm/unaligned.h>
14825+
14826+#include <scst/scst.h>
14827+#include <scst/scst_const.h>
14828+#include "scst_priv.h"
14829+#include "scst_pres.h"
14830+
14831+#define SCST_PR_ROOT_ENTRY "pr"
14832+#define SCST_PR_FILE_SIGN 0xBBEEEEAAEEBBDD77LLU
14833+#define SCST_PR_FILE_VERSION 1LLU
14834+
14835+#define FILE_BUFFER_SIZE 512
14836+
14837+#ifndef isblank
14838+#define isblank(c) ((c) == ' ' || (c) == '\t')
14839+#endif
14840+
14841+static inline int tid_size(const uint8_t *tid)
14842+{
14843+ BUG_ON(tid == NULL);
14844+
14845+ if ((tid[0] & 0x0f) == SCSI_TRANSPORTID_PROTOCOLID_ISCSI)
14846+ return be16_to_cpu(get_unaligned((__be16 *)&tid[2])) + 4;
14847+ else
14848+ return TID_COMMON_SIZE;
14849+}
14850+
14851+/* Secures tid by setting 0 in the last byte of NULL-terminated tid's */
14852+static inline void tid_secure(uint8_t *tid)
14853+{
14854+ if ((tid[0] & 0x0f) == SCSI_TRANSPORTID_PROTOCOLID_ISCSI) {
14855+ int size = tid_size(tid);
14856+ tid[size - 1] = '\0';
14857+ }
14858+
14859+ return;
14860+}
14861+
14862+/* Returns false if tid's are not equal, true otherwise */
14863+static bool tid_equal(const uint8_t *tid_a, const uint8_t *tid_b)
14864+{
14865+ int len;
14866+
14867+ if (tid_a == NULL || tid_b == NULL)
14868+ return false;
14869+
14870+ if ((tid_a[0] & 0x0f) != (tid_b[0] & 0x0f)) {
14871+ TRACE_DBG("%s", "Different protocol IDs");
14872+ return false;
14873+ }
14874+
14875+ if ((tid_a[0] & 0x0f) == SCSI_TRANSPORTID_PROTOCOLID_ISCSI) {
14876+ const uint8_t tid_a_fmt = tid_a[0] & 0xc0;
14877+ const uint8_t tid_b_fmt = tid_b[0] & 0xc0;
14878+ int tid_a_len, tid_a_max = tid_size(tid_a) - 4;
14879+ int tid_b_len, tid_b_max = tid_size(tid_b) - 4;
14880+ int i;
14881+
14882+ tid_a += 4;
14883+ tid_b += 4;
14884+
14885+ if (tid_a_fmt == 0x00)
14886+ tid_a_len = strnlen(tid_a, tid_a_max);
14887+ else if (tid_a_fmt == 0x40) {
14888+ if (tid_a_fmt != tid_b_fmt) {
14889+ uint8_t *p = strnchr(tid_a, tid_a_max, ',');
14890+ if (p == NULL)
14891+ goto out_error;
14892+ tid_a_len = p - tid_a;
14893+
14894+ BUG_ON(tid_a_len > tid_a_max);
14895+ BUG_ON(tid_a_len < 0);
14896+ } else
14897+ tid_a_len = strnlen(tid_a, tid_a_max);
14898+ } else
14899+ goto out_error;
14900+
14901+ if (tid_b_fmt == 0x00)
14902+ tid_b_len = strnlen(tid_b, tid_b_max);
14903+ else if (tid_b_fmt == 0x40) {
14904+ if (tid_a_fmt != tid_b_fmt) {
14905+ uint8_t *p = strnchr(tid_b, tid_b_max, ',');
14906+ if (p == NULL)
14907+ goto out_error;
14908+ tid_b_len = p - tid_b;
14909+
14910+ BUG_ON(tid_b_len > tid_b_max);
14911+ BUG_ON(tid_b_len < 0);
14912+ } else
14913+ tid_b_len = strnlen(tid_b, tid_b_max);
14914+ } else
14915+ goto out_error;
14916+
14917+ if (tid_a_len != tid_b_len)
14918+ return false;
14919+
14920+ len = tid_a_len;
14921+
14922+ /* ISCSI names are case insensitive */
14923+ for (i = 0; i < len; i++)
14924+ if (tolower(tid_a[i]) != tolower(tid_b[i]))
14925+ return false;
14926+ return true;
14927+ } else
14928+ len = TID_COMMON_SIZE;
14929+
14930+ return (memcmp(tid_a, tid_b, len) == 0);
14931+
14932+out_error:
14933+ PRINT_ERROR("%s", "Invalid initiator port transport id");
14934+ return false;
14935+}
14936+
14937+/* Must be called under dev_pr_mutex */
14938+static inline void scst_pr_set_holder(struct scst_device *dev,
14939+ struct scst_dev_registrant *holder, uint8_t scope, uint8_t type)
14940+{
14941+ dev->pr_is_set = 1;
14942+ dev->pr_scope = scope;
14943+ dev->pr_type = type;
14944+ if (dev->pr_type != TYPE_EXCLUSIVE_ACCESS_ALL_REG &&
14945+ dev->pr_type != TYPE_WRITE_EXCLUSIVE_ALL_REG)
14946+ dev->pr_holder = holder;
14947+}
14948+
14949+/* Must be called under dev_pr_mutex */
14950+static bool scst_pr_is_holder(struct scst_device *dev,
14951+ struct scst_dev_registrant *reg)
14952+{
14953+ bool res = false;
14954+
14955+ TRACE_ENTRY();
14956+
14957+ if (!dev->pr_is_set)
14958+ goto out;
14959+
14960+ if (dev->pr_type == TYPE_EXCLUSIVE_ACCESS_ALL_REG ||
14961+ dev->pr_type == TYPE_WRITE_EXCLUSIVE_ALL_REG) {
14962+ res = (reg != NULL);
14963+ } else
14964+ res = (dev->pr_holder == reg);
14965+
14966+out:
14967+ TRACE_EXIT_RES(res);
14968+ return res;
14969+}
14970+
14971+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
14972+
14973+/* Must be called under dev_pr_mutex */
14974+void scst_pr_dump_prs(struct scst_device *dev, bool force)
14975+{
14976+ if (!force) {
14977+#if defined(CONFIG_SCST_DEBUG)
14978+ if ((trace_flag & TRACE_PRES) == 0)
14979+#endif
14980+ goto out;
14981+ }
14982+
14983+ PRINT_INFO("Persistent reservations for device %s:", dev->virt_name);
14984+
14985+ if (list_empty(&dev->dev_registrants_list))
14986+ PRINT_INFO("%s", " No registrants");
14987+ else {
14988+ struct scst_dev_registrant *reg;
14989+ int i = 0;
14990+ list_for_each_entry(reg, &dev->dev_registrants_list,
14991+ dev_registrants_list_entry) {
14992+ PRINT_INFO(" [%d] registrant %s/%d, key %016llx "
14993+ "(reg %p, tgt_dev %p)", i++,
14994+ debug_transport_id_to_initiator_name(
14995+ reg->transport_id),
14996+ reg->rel_tgt_id, reg->key, reg, reg->tgt_dev);
14997+ }
14998+ }
14999+
15000+ if (dev->pr_is_set) {
15001+ struct scst_dev_registrant *holder = dev->pr_holder;
15002+ if (holder != NULL)
15003+ PRINT_INFO("Reservation holder is %s/%d (key %016llx, "
15004+ "scope %x, type %x, reg %p, tgt_dev %p)",
15005+ debug_transport_id_to_initiator_name(
15006+ holder->transport_id),
15007+ holder->rel_tgt_id, holder->key, dev->pr_scope,
15008+ dev->pr_type, holder, holder->tgt_dev);
15009+ else
15010+ PRINT_INFO("All registrants are reservation holders "
15011+ "(scope %x, type %x)", dev->pr_scope,
15012+ dev->pr_type);
15013+ } else
15014+ PRINT_INFO("%s", "Not reserved");
15015+
15016+out:
15017+ return;
15018+}
15019+
15020+#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
15021+
15022+/* dev_pr_mutex must be locked */
15023+static void scst_pr_find_registrants_list_all(struct scst_device *dev,
15024+ struct scst_dev_registrant *exclude_reg, struct list_head *list)
15025+{
15026+ struct scst_dev_registrant *reg;
15027+
15028+ TRACE_ENTRY();
15029+
15030+ TRACE_PR("Finding all registered records for device '%s' "
15031+ "with exclude reg key %016llx",
15032+ dev->virt_name, exclude_reg->key);
15033+
15034+ list_for_each_entry(reg, &dev->dev_registrants_list,
15035+ dev_registrants_list_entry) {
15036+ if (reg == exclude_reg)
15037+ continue;
15038+ TRACE_PR("Adding registrant %s/%d (%p) to find list (key %016llx)",
15039+ debug_transport_id_to_initiator_name(reg->transport_id),
15040+ reg->rel_tgt_id, reg, reg->key);
15041+ list_add_tail(&reg->aux_list_entry, list);
15042+ }
15043+
15044+ TRACE_EXIT();
15045+ return;
15046+}
15047+
15048+/* dev_pr_mutex must be locked */
15049+static void scst_pr_find_registrants_list_key(struct scst_device *dev,
15050+ __be64 key, struct list_head *list)
15051+{
15052+ struct scst_dev_registrant *reg;
15053+
15054+ TRACE_ENTRY();
15055+
15056+ TRACE_PR("Finding registrants for device '%s' with key %016llx",
15057+ dev->virt_name, key);
15058+
15059+ list_for_each_entry(reg, &dev->dev_registrants_list,
15060+ dev_registrants_list_entry) {
15061+ if (reg->key == key) {
15062+ TRACE_PR("Adding registrant %s/%d (%p) to the find "
15063+ "list (key %016llx)",
15064+ debug_transport_id_to_initiator_name(
15065+ reg->transport_id),
15066+ reg->rel_tgt_id, reg->tgt_dev, key);
15067+ list_add_tail(&reg->aux_list_entry, list);
15068+ }
15069+ }
15070+
15071+ TRACE_EXIT();
15072+ return;
15073+}
15074+
15075+/* dev_pr_mutex must be locked */
15076+static struct scst_dev_registrant *scst_pr_find_reg(
15077+ struct scst_device *dev, const uint8_t *transport_id,
15078+ const uint16_t rel_tgt_id)
15079+{
15080+ struct scst_dev_registrant *reg, *res = NULL;
15081+
15082+ TRACE_ENTRY();
15083+
15084+ list_for_each_entry(reg, &dev->dev_registrants_list,
15085+ dev_registrants_list_entry) {
15086+ if ((reg->rel_tgt_id == rel_tgt_id) &&
15087+ tid_equal(reg->transport_id, transport_id)) {
15088+ res = reg;
15089+ break;
15090+ }
15091+ }
15092+
15093+ TRACE_EXIT_HRES(res);
15094+ return res;
15095+}
15096+
15097+/* Must be called under dev_pr_mutex */
15098+static void scst_pr_clear_reservation(struct scst_device *dev)
15099+{
15100+ TRACE_ENTRY();
15101+
15102+ WARN_ON(!dev->pr_is_set);
15103+
15104+ dev->pr_is_set = 0;
15105+ dev->pr_scope = SCOPE_LU;
15106+ dev->pr_type = TYPE_UNSPECIFIED;
15107+
15108+ dev->pr_holder = NULL;
15109+
15110+ TRACE_EXIT();
15111+ return;
15112+}
15113+
15114+/* Must be called under dev_pr_mutex */
15115+static void scst_pr_clear_holder(struct scst_device *dev)
15116+{
15117+ TRACE_ENTRY();
15118+
15119+ WARN_ON(!dev->pr_is_set);
15120+
15121+ if (dev->pr_type == TYPE_WRITE_EXCLUSIVE_ALL_REG ||
15122+ dev->pr_type == TYPE_EXCLUSIVE_ACCESS_ALL_REG) {
15123+ if (list_empty(&dev->dev_registrants_list))
15124+ scst_pr_clear_reservation(dev);
15125+ } else
15126+ scst_pr_clear_reservation(dev);
15127+
15128+ dev->pr_holder = NULL;
15129+
15130+ TRACE_EXIT();
15131+ return;
15132+}
15133+
15134+/* Must be called under dev_pr_mutex */
15135+static struct scst_dev_registrant *scst_pr_add_registrant(
15136+ struct scst_device *dev, const uint8_t *transport_id,
15137+ const uint16_t rel_tgt_id, __be64 key,
15138+ bool dev_lock_locked)
15139+{
15140+ struct scst_dev_registrant *reg;
15141+ struct scst_tgt_dev *t;
15142+ gfp_t gfp_flags = dev_lock_locked ? GFP_ATOMIC : GFP_KERNEL;
15143+
15144+ TRACE_ENTRY();
15145+
15146+ BUG_ON(dev == NULL);
15147+ BUG_ON(transport_id == NULL);
15148+
15149+ TRACE_PR("Registering %s/%d (dev %s)",
15150+ debug_transport_id_to_initiator_name(transport_id),
15151+ rel_tgt_id, dev->virt_name);
15152+
15153+ reg = scst_pr_find_reg(dev, transport_id, rel_tgt_id);
15154+ if (reg != NULL) {
15155+ /*
15156+ * It might happen when a target driver would make >1 session
15157+ * from the same initiator to the same target.
15158+ */
15159+ PRINT_ERROR("Registrant %p/%d (dev %s) already exists!", reg,
15160+ rel_tgt_id, dev->virt_name);
15161+ PRINT_BUFFER("TransportID", transport_id, 24);
15162+ WARN_ON(1);
15163+ reg = NULL;
15164+ goto out;
15165+ }
15166+
15167+ reg = kzalloc(sizeof(*reg), gfp_flags);
15168+ if (reg == NULL) {
15169+ PRINT_ERROR("%s", "Unable to allocate registration record");
15170+ goto out;
15171+ }
15172+
15173+ reg->transport_id = kmalloc(tid_size(transport_id), gfp_flags);
15174+ if (reg->transport_id == NULL) {
15175+ PRINT_ERROR("%s", "Unable to allocate initiator port "
15176+ "transport id");
15177+ goto out_free;
15178+ }
15179+ memcpy(reg->transport_id, transport_id, tid_size(transport_id));
15180+
15181+ reg->rel_tgt_id = rel_tgt_id;
15182+ reg->key = key;
15183+
15184+ /*
15185+ * We can't use scst_mutex here, because of the circular
15186+ * locking dependency with dev_pr_mutex.
15187+ */
15188+ if (!dev_lock_locked)
15189+ spin_lock_bh(&dev->dev_lock);
15190+ list_for_each_entry(t, &dev->dev_tgt_dev_list, dev_tgt_dev_list_entry) {
15191+ if (tid_equal(t->sess->transport_id, transport_id) &&
15192+ (t->sess->tgt->rel_tgt_id == rel_tgt_id) &&
15193+ (t->registrant == NULL)) {
15194+ /*
15195+ * We must assign here, because t can die
15196+ * immediately after we release dev_lock.
15197+ */
15198+ TRACE_PR("Found tgt_dev %p", t);
15199+ reg->tgt_dev = t;
15200+ t->registrant = reg;
15201+ break;
15202+ }
15203+ }
15204+ if (!dev_lock_locked)
15205+ spin_unlock_bh(&dev->dev_lock);
15206+
15207+ list_add_tail(&reg->dev_registrants_list_entry,
15208+ &dev->dev_registrants_list);
15209+
15210+ TRACE_PR("Reg %p registered (dev %s, tgt_dev %p)", reg,
15211+ dev->virt_name, reg->tgt_dev);
15212+
15213+out:
15214+ TRACE_EXIT_HRES((unsigned long)reg);
15215+ return reg;
15216+
15217+out_free:
15218+ kfree(reg);
15219+ reg = NULL;
15220+ goto out;
15221+}
15222+
15223+/* Must be called under dev_pr_mutex */
15224+static void scst_pr_remove_registrant(struct scst_device *dev,
15225+ struct scst_dev_registrant *reg)
15226+{
15227+ TRACE_ENTRY();
15228+
15229+ TRACE_PR("Removing registrant %s/%d (reg %p, tgt_dev %p, key %016llx, "
15230+ "dev %s)", debug_transport_id_to_initiator_name(reg->transport_id),
15231+ reg->rel_tgt_id, reg, reg->tgt_dev, reg->key, dev->virt_name);
15232+
15233+ list_del(&reg->dev_registrants_list_entry);
15234+
15235+ if (scst_pr_is_holder(dev, reg))
15236+ scst_pr_clear_holder(dev);
15237+
15238+ if (reg->tgt_dev)
15239+ reg->tgt_dev->registrant = NULL;
15240+
15241+ kfree(reg->transport_id);
15242+ kfree(reg);
15243+
15244+ TRACE_EXIT();
15245+ return;
15246+}
15247+
15248+/* Must be called under dev_pr_mutex */
15249+static void scst_pr_send_ua_reg(struct scst_device *dev,
15250+ struct scst_dev_registrant *reg,
15251+ int key, int asc, int ascq)
15252+{
15253+ static uint8_t ua[SCST_STANDARD_SENSE_LEN];
15254+
15255+ TRACE_ENTRY();
15256+
15257+ scst_set_sense(ua, sizeof(ua), dev->d_sense, key, asc, ascq);
15258+
15259+ TRACE_PR("Queuing UA [%x %x %x]: registrant %s/%d (%p), tgt_dev %p, "
15260+ "key %016llx", ua[2], ua[12], ua[13],
15261+ debug_transport_id_to_initiator_name(reg->transport_id),
15262+ reg->rel_tgt_id, reg, reg->tgt_dev, reg->key);
15263+
15264+ if (reg->tgt_dev)
15265+ scst_check_set_UA(reg->tgt_dev, ua, sizeof(ua), 0);
15266+
15267+ TRACE_EXIT();
15268+ return;
15269+}
15270+
15271+/* Must be called under dev_pr_mutex */
15272+static void scst_pr_send_ua_all(struct scst_device *dev,
15273+ struct scst_dev_registrant *exclude_reg,
15274+ int key, int asc, int ascq)
15275+{
15276+ struct scst_dev_registrant *reg;
15277+
15278+ TRACE_ENTRY();
15279+
15280+ list_for_each_entry(reg, &dev->dev_registrants_list,
15281+ dev_registrants_list_entry) {
15282+ if (reg != exclude_reg)
15283+ scst_pr_send_ua_reg(dev, reg, key, asc, ascq);
15284+ }
15285+
15286+ TRACE_EXIT();
15287+ return;
15288+}
15289+
15290+/* Must be called under dev_pr_mutex */
15291+static void scst_pr_abort_reg(struct scst_device *dev,
15292+ struct scst_cmd *pr_cmd, struct scst_dev_registrant *reg)
15293+{
15294+ struct scst_session *sess;
15295+ __be64 packed_lun;
15296+ int rc;
15297+
15298+ TRACE_ENTRY();
15299+
15300+ if (reg->tgt_dev == NULL) {
15301+ TRACE_PR("Registrant %s/%d (%p, key 0x%016llx) has no session",
15302+ debug_transport_id_to_initiator_name(reg->transport_id),
15303+ reg->rel_tgt_id, reg, reg->key);
15304+ goto out;
15305+ }
15306+
15307+ sess = reg->tgt_dev->sess;
15308+
15309+ TRACE_PR("Aborting %d commands for %s/%d (reg %p, key 0x%016llx, "
15310+ "tgt_dev %p, sess %p)",
15311+ atomic_read(&reg->tgt_dev->tgt_dev_cmd_count),
15312+ debug_transport_id_to_initiator_name(reg->transport_id),
15313+ reg->rel_tgt_id, reg, reg->key, reg->tgt_dev, sess);
15314+
15315+ packed_lun = scst_pack_lun(reg->tgt_dev->lun, sess->acg->addr_method);
15316+
15317+ rc = scst_rx_mgmt_fn_lun(sess, SCST_PR_ABORT_ALL,
15318+ (uint8_t *)&packed_lun, sizeof(packed_lun), SCST_NON_ATOMIC,
15319+ pr_cmd);
15320+ if (rc != 0) {
15321+ /*
15322+ * There's nothing more we can do here... Hopefully, it would
15323+ * never happen.
15324+ */
15325+ PRINT_ERROR("SCST_PR_ABORT_ALL failed %d (sess %p)",
15326+ rc, sess);
15327+ }
15328+
15329+out:
15330+ TRACE_EXIT();
15331+ return;
15332+}
15333+
15334+/* Abstract vfs_unlink & path_put for different kernel versions */
15335+static inline void scst_pr_vfs_unlink_and_put(struct nameidata *nd)
15336+{
15337+ vfs_unlink(nd->path.dentry->d_parent->d_inode,
15338+ nd->path.dentry);
15339+ path_put(&nd->path);
15340+}
15341+
15342+static inline void scst_pr_path_put(struct nameidata *nd)
15343+{
15344+ path_put(&nd->path);
15345+}
15346+
15347+/* Called under scst_mutex */
15348+static int scst_pr_do_load_device_file(struct scst_device *dev,
15349+ const char *file_name)
15350+{
15351+ int res = 0, rc;
15352+ struct file *file = NULL;
15353+ struct inode *inode;
15354+ char *buf = NULL;
15355+ loff_t file_size, pos, data_size;
15356+ uint64_t sign, version;
15357+ mm_segment_t old_fs;
15358+ uint8_t pr_is_set, aptpl;
15359+ __be64 key;
15360+ uint16_t rel_tgt_id;
15361+
15362+ TRACE_ENTRY();
15363+
15364+ old_fs = get_fs();
15365+ set_fs(KERNEL_DS);
15366+
15367+ TRACE_PR("Loading persistent file '%s'", file_name);
15368+
15369+ file = filp_open(file_name, O_RDONLY, 0);
15370+ if (IS_ERR(file)) {
15371+ res = PTR_ERR(file);
15372+ TRACE_PR("Unable to open file '%s' - error %d", file_name, res);
15373+ goto out;
15374+ }
15375+
15376+ inode = file->f_dentry->d_inode;
15377+
15378+ if (S_ISREG(inode->i_mode))
15379+ /* Nothing to do */;
15380+ else if (S_ISBLK(inode->i_mode))
15381+ inode = inode->i_bdev->bd_inode;
15382+ else {
15383+ PRINT_ERROR("Invalid file mode 0x%x", inode->i_mode);
15384+ goto out_close;
15385+ }
15386+
15387+ file_size = inode->i_size;
15388+
15389+ /* Let's limit the file size by some reasonable number */
15390+ if ((file_size == 0) || (file_size >= 15*1024*1024)) {
15391+ PRINT_ERROR("Invalid PR file size %d", (int)file_size);
15392+ res = -EINVAL;
15393+ goto out_close;
15394+ }
15395+
15396+ buf = vmalloc(file_size);
15397+ if (buf == NULL) {
15398+ res = -ENOMEM;
15399+ PRINT_ERROR("%s", "Unable to allocate buffer");
15400+ goto out_close;
15401+ }
15402+
15403+ pos = 0;
15404+ rc = vfs_read(file, (void __force __user *)buf, file_size, &pos);
15405+ if (rc != file_size) {
15406+ PRINT_ERROR("Unable to read file '%s' - error %d", file_name,
15407+ rc);
15408+ res = rc;
15409+ goto out_close;
15410+ }
15411+
15412+ data_size = 0;
15413+ data_size += sizeof(sign);
15414+ data_size += sizeof(version);
15415+ data_size += sizeof(aptpl);
15416+ data_size += sizeof(pr_is_set);
15417+ data_size += sizeof(dev->pr_type);
15418+ data_size += sizeof(dev->pr_scope);
15419+
15420+ if (file_size < data_size) {
15421+ res = -EINVAL;
15422+ PRINT_ERROR("Invalid file '%s' - size too small", file_name);
15423+ goto out_close;
15424+ }
15425+
15426+ pos = 0;
15427+
15428+ sign = get_unaligned((uint64_t *)&buf[pos]);
15429+ if (sign != SCST_PR_FILE_SIGN) {
15430+ res = -EINVAL;
15431+ PRINT_ERROR("Invalid persistent file signature %016llx "
15432+ "(expected %016llx)", sign, SCST_PR_FILE_SIGN);
15433+ goto out_close;
15434+ }
15435+ pos += sizeof(sign);
15436+
15437+ version = get_unaligned((uint64_t *)&buf[pos]);
15438+ if (version != SCST_PR_FILE_VERSION) {
15439+ res = -EINVAL;
15440+ PRINT_ERROR("Invalid persistent file version %016llx "
15441+ "(expected %016llx)", version, SCST_PR_FILE_VERSION);
15442+ goto out_close;
15443+ }
15444+ pos += sizeof(version);
15445+
15446+ while (data_size < file_size) {
15447+ uint8_t *tid;
15448+
15449+ data_size++;
15450+ tid = &buf[data_size];
15451+ data_size += tid_size(tid);
15452+ data_size += sizeof(key);
15453+ data_size += sizeof(rel_tgt_id);
15454+
15455+ if (data_size > file_size) {
15456+ res = -EINVAL;
15457+ PRINT_ERROR("Invalid file '%s' - size mismatch have "
15458+ "%lld expected %lld", file_name, file_size,
15459+ data_size);
15460+ goto out_close;
15461+ }
15462+ }
15463+
15464+ aptpl = buf[pos];
15465+ dev->pr_aptpl = aptpl ? 1 : 0;
15466+ pos += sizeof(aptpl);
15467+
15468+ pr_is_set = buf[pos];
15469+ dev->pr_is_set = pr_is_set ? 1 : 0;
15470+ pos += sizeof(pr_is_set);
15471+
15472+ dev->pr_type = buf[pos];
15473+ pos += sizeof(dev->pr_type);
15474+
15475+ dev->pr_scope = buf[pos];
15476+ pos += sizeof(dev->pr_scope);
15477+
15478+ while (pos < file_size) {
15479+ uint8_t is_holder;
15480+ uint8_t *tid;
15481+ struct scst_dev_registrant *reg = NULL;
15482+
15483+ is_holder = buf[pos++];
15484+
15485+ tid = &buf[pos];
15486+ pos += tid_size(tid);
15487+
15488+ key = get_unaligned((__be64 *)&buf[pos]);
15489+ pos += sizeof(key);
15490+
15491+ rel_tgt_id = get_unaligned((uint16_t *)&buf[pos]);
15492+ pos += sizeof(rel_tgt_id);
15493+
15494+ reg = scst_pr_add_registrant(dev, tid, rel_tgt_id, key, false);
15495+ if (reg == NULL) {
15496+ res = -ENOMEM;
15497+ goto out_close;
15498+ }
15499+
15500+ if (is_holder)
15501+ dev->pr_holder = reg;
15502+ }
15503+
15504+out_close:
15505+ filp_close(file, NULL);
15506+
15507+out:
15508+ if (buf != NULL)
15509+ vfree(buf);
15510+
15511+ set_fs(old_fs);
15512+
15513+ TRACE_EXIT_RES(res);
15514+ return res;
15515+}
15516+
15517+static int scst_pr_load_device_file(struct scst_device *dev)
15518+{
15519+ int res;
15520+
15521+ TRACE_ENTRY();
15522+
15523+ if (dev->pr_file_name == NULL || dev->pr_file_name1 == NULL) {
15524+ PRINT_ERROR("Invalid file paths for '%s'", dev->virt_name);
15525+ res = -EINVAL;
15526+ goto out;
15527+ }
15528+
15529+ res = scst_pr_do_load_device_file(dev, dev->pr_file_name);
15530+ if (res == 0)
15531+ goto out;
15532+ else if (res == -ENOMEM)
15533+ goto out;
15534+
15535+ res = scst_pr_do_load_device_file(dev, dev->pr_file_name1);
15536+
15537+ scst_pr_dump_prs(dev, false);
15538+
15539+out:
15540+ TRACE_EXIT_RES(res);
15541+ return res;
15542+}
15543+
15544+static int scst_pr_copy_file(const char *src, const char *dest)
15545+{
15546+ int res = 0;
15547+ struct inode *inode;
15548+ loff_t file_size, pos;
15549+ uint8_t *buf = NULL;
15550+ struct file *file_src = NULL, *file_dest = NULL;
15551+ mm_segment_t old_fs = get_fs();
15552+
15553+ TRACE_ENTRY();
15554+
15555+ if (src == NULL || dest == NULL) {
15556+ res = -EINVAL;
15557+ PRINT_ERROR("%s", "Invalid persistent files path - backup "
15558+ "skipped");
15559+ goto out;
15560+ }
15561+
15562+ TRACE_PR("Copying '%s' into '%s'", src, dest);
15563+
15564+ set_fs(KERNEL_DS);
15565+
15566+ file_src = filp_open(src, O_RDONLY, 0);
15567+ if (IS_ERR(file_src)) {
15568+ res = PTR_ERR(file_src);
15569+ TRACE_PR("Unable to open file '%s' - error %d", src,
15570+ res);
15571+ goto out_free;
15572+ }
15573+
15574+ file_dest = filp_open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0644);
15575+ if (IS_ERR(file_dest)) {
15576+ res = PTR_ERR(file_dest);
15577+ TRACE_PR("Unable to open backup file '%s' - error %d", dest,
15578+ res);
15579+ goto out_close;
15580+ }
15581+
15582+ inode = file_src->f_dentry->d_inode;
15583+
15584+ if (S_ISREG(inode->i_mode))
15585+ /* Nothing to do */;
15586+ else if (S_ISBLK(inode->i_mode))
15587+ inode = inode->i_bdev->bd_inode;
15588+ else {
15589+ PRINT_ERROR("Invalid file mode 0x%x", inode->i_mode);
15590+ res = -EINVAL;
15591+ set_fs(old_fs);
15592+ goto out_skip;
15593+ }
15594+
15595+ file_size = inode->i_size;
15596+
15597+ buf = vmalloc(file_size);
15598+ if (buf == NULL) {
15599+ res = -ENOMEM;
15600+ PRINT_ERROR("%s", "Unable to allocate temporary buffer");
15601+ goto out_skip;
15602+ }
15603+
15604+ pos = 0;
15605+ res = vfs_read(file_src, (void __force __user *)buf, file_size, &pos);
15606+ if (res != file_size) {
15607+ PRINT_ERROR("Unable to read file '%s' - error %d", src, res);
15608+ goto out_skip;
15609+ }
15610+
15611+ pos = 0;
15612+ res = vfs_write(file_dest, (void __force __user *)buf, file_size, &pos);
15613+ if (res != file_size) {
15614+ PRINT_ERROR("Unable to write to '%s' - error %d", dest, res);
15615+ goto out_skip;
15616+ }
15617+
15618+ res = vfs_fsync(file_dest, 0);
15619+ if (res != 0) {
15620+ PRINT_ERROR("fsync() of the backup PR file failed: %d", res);
15621+ goto out_skip;
15622+ }
15623+
15624+out_skip:
15625+ filp_close(file_dest, NULL);
15626+
15627+out_close:
15628+ filp_close(file_src, NULL);
15629+
15630+out_free:
15631+ if (buf != NULL)
15632+ vfree(buf);
15633+
15634+ set_fs(old_fs);
15635+
15636+out:
15637+ TRACE_EXIT_RES(res);
15638+ return res;
15639+}
15640+
15641+static void scst_pr_remove_device_files(struct scst_tgt_dev *tgt_dev)
15642+{
15643+ int res = 0;
15644+ struct scst_device *dev = tgt_dev->dev;
15645+ struct nameidata nd;
15646+ mm_segment_t old_fs = get_fs();
15647+
15648+ TRACE_ENTRY();
15649+
15650+ set_fs(KERNEL_DS);
15651+
15652+ res = path_lookup(dev->pr_file_name, 0, &nd);
15653+ if (!res)
15654+ scst_pr_vfs_unlink_and_put(&nd);
15655+ else
15656+ TRACE_DBG("Unable to lookup file '%s' - error %d",
15657+ dev->pr_file_name, res);
15658+
15659+ res = path_lookup(dev->pr_file_name1, 0, &nd);
15660+ if (!res)
15661+ scst_pr_vfs_unlink_and_put(&nd);
15662+ else
15663+ TRACE_DBG("Unable to lookup file '%s' - error %d",
15664+ dev->pr_file_name1, res);
15665+
15666+ set_fs(old_fs);
15667+
15668+ TRACE_EXIT();
15669+ return;
15670+}
15671+
15672+/* Must be called under dev_pr_mutex */
15673+void scst_pr_sync_device_file(struct scst_tgt_dev *tgt_dev, struct scst_cmd *cmd)
15674+{
15675+ int res = 0;
15676+ struct scst_device *dev = tgt_dev->dev;
15677+ struct file *file;
15678+ mm_segment_t old_fs = get_fs();
15679+ loff_t pos = 0;
15680+ uint64_t sign;
15681+ uint64_t version;
15682+ uint8_t pr_is_set, aptpl;
15683+
15684+ TRACE_ENTRY();
15685+
15686+ if ((dev->pr_aptpl == 0) || list_empty(&dev->dev_registrants_list)) {
15687+ scst_pr_remove_device_files(tgt_dev);
15688+ goto out;
15689+ }
15690+
15691+ scst_pr_copy_file(dev->pr_file_name, dev->pr_file_name1);
15692+
15693+ set_fs(KERNEL_DS);
15694+
15695+ file = filp_open(dev->pr_file_name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
15696+ if (IS_ERR(file)) {
15697+ res = PTR_ERR(file);
15698+ PRINT_ERROR("Unable to (re)create PR file '%s' - error %d",
15699+ dev->pr_file_name, res);
15700+ goto out_set_fs;
15701+ }
15702+
15703+ TRACE_PR("Updating pr file '%s'", dev->pr_file_name);
15704+
15705+ /*
15706+ * signature
15707+ */
15708+ sign = 0;
15709+ pos = 0;
15710+ res = vfs_write(file, (void __force __user *)&sign, sizeof(sign), &pos);
15711+ if (res != sizeof(sign))
15712+ goto write_error;
15713+
15714+ /*
15715+ * version
15716+ */
15717+ version = SCST_PR_FILE_VERSION;
15718+ res = vfs_write(file, (void __force __user *)&version, sizeof(version), &pos);
15719+ if (res != sizeof(version))
15720+ goto write_error;
15721+
15722+ /*
15723+ * APTPL
15724+ */
15725+ aptpl = dev->pr_aptpl;
15726+ res = vfs_write(file, (void __force __user *)&aptpl, sizeof(aptpl), &pos);
15727+ if (res != sizeof(aptpl))
15728+ goto write_error;
15729+
15730+ /*
15731+ * reservation
15732+ */
15733+ pr_is_set = dev->pr_is_set;
15734+ res = vfs_write(file, (void __force __user *)&pr_is_set, sizeof(pr_is_set), &pos);
15735+ if (res != sizeof(pr_is_set))
15736+ goto write_error;
15737+
15738+ res = vfs_write(file, (void __force __user *)&dev->pr_type, sizeof(dev->pr_type), &pos);
15739+ if (res != sizeof(dev->pr_type))
15740+ goto write_error;
15741+
15742+ res = vfs_write(file, (void __force __user *)&dev->pr_scope, sizeof(dev->pr_scope), &pos);
15743+ if (res != sizeof(dev->pr_scope))
15744+ goto write_error;
15745+
15746+ /*
15747+ * registration records
15748+ */
15749+ if (!list_empty(&dev->dev_registrants_list)) {
15750+ struct scst_dev_registrant *reg;
15751+
15752+ list_for_each_entry(reg, &dev->dev_registrants_list,
15753+ dev_registrants_list_entry) {
15754+ uint8_t is_holder = 0;
15755+ int size;
15756+
15757+ is_holder = (dev->pr_holder == reg);
15758+
15759+ res = vfs_write(file, (void __force __user *)&is_holder, sizeof(is_holder),
15760+ &pos);
15761+ if (res != sizeof(is_holder))
15762+ goto write_error;
15763+
15764+ size = tid_size(reg->transport_id);
15765+ res = vfs_write(file, (void __force __user *)reg->transport_id, size, &pos);
15766+ if (res != size)
15767+ goto write_error;
15768+
15769+ res = vfs_write(file, (void __force __user *)&reg->key,
15770+ sizeof(reg->key), &pos);
15771+ if (res != sizeof(reg->key))
15772+ goto write_error;
15773+
15774+ res = vfs_write(file, (void __force __user *)&reg->rel_tgt_id,
15775+ sizeof(reg->rel_tgt_id), &pos);
15776+ if (res != sizeof(reg->rel_tgt_id))
15777+ goto write_error;
15778+ }
15779+ }
15780+
15781+ res = vfs_fsync(file, 0);
15782+ if (res != 0) {
15783+ PRINT_ERROR("fsync() of the PR file failed: %d", res);
15784+ goto write_error_close;
15785+ }
15786+
15787+ sign = SCST_PR_FILE_SIGN;
15788+ pos = 0;
15789+ res = vfs_write(file, (void __force __user *)&sign, sizeof(sign), &pos);
15790+ if (res != sizeof(sign))
15791+ goto write_error;
15792+
15793+ res = vfs_fsync(file, 0);
15794+ if (res != 0) {
15795+ PRINT_ERROR("fsync() of the PR file failed: %d", res);
15796+ goto write_error_close;
15797+ }
15798+
15799+ res = 0;
15800+
15801+ filp_close(file, NULL);
15802+
15803+out_set_fs:
15804+ set_fs(old_fs);
15805+
15806+out:
15807+ if (res != 0) {
15808+ PRINT_CRIT_ERROR("Unable to save persistent information "
15809+ "(target %s, initiator %s, device %s)",
15810+ tgt_dev->sess->tgt->tgt_name,
15811+ tgt_dev->sess->initiator_name, dev->virt_name);
15812+#if 0 /*
15813+ * Looks like it's safer to return SUCCESS and expect operator's
15814+ * intervention to be able to save the PR's state next time, than
15815+ * to return HARDWARE ERROR and screw up all the interaction with
15816+ * the affected initiator.
15817+ */
15818+ if (cmd != NULL)
15819+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
15820+#endif
15821+ }
15822+
15823+ TRACE_EXIT_RES(res);
15824+ return;
15825+
15826+write_error:
15827+ PRINT_ERROR("Error writing to '%s' - error %d", dev->pr_file_name, res);
15828+
15829+write_error_close:
15830+ filp_close(file, NULL);
15831+ {
15832+ struct nameidata nd;
15833+ int rc;
15834+
15835+ rc = path_lookup(dev->pr_file_name, 0, &nd);
15836+ if (!rc)
15837+ scst_pr_vfs_unlink_and_put(&nd);
15838+ else
15839+ TRACE_PR("Unable to lookup '%s' - error %d",
15840+ dev->pr_file_name, rc);
15841+ }
15842+ goto out_set_fs;
15843+}
15844+
15845+static int scst_pr_check_pr_path(void)
15846+{
15847+ int res;
15848+ struct nameidata nd;
15849+ mm_segment_t old_fs = get_fs();
15850+
15851+ TRACE_ENTRY();
15852+
15853+ set_fs(KERNEL_DS);
15854+
15855+ res = path_lookup(SCST_PR_DIR, 0, &nd);
15856+ if (res != 0) {
15857+ PRINT_ERROR("Unable to find %s (err %d), you should create "
15858+ "this directory manually or reinstall SCST",
15859+ SCST_PR_DIR, res);
15860+ goto out_setfs;
15861+ }
15862+
15863+ scst_pr_path_put(&nd);
15864+
15865+out_setfs:
15866+ set_fs(old_fs);
15867+
15868+ TRACE_EXIT_RES(res);
15869+ return res;
15870+}
15871+
15872+/* Called under scst_mutex */
15873+int scst_pr_init_dev(struct scst_device *dev)
15874+{
15875+ int res = 0;
15876+ uint8_t q;
15877+ int name_len;
15878+
15879+ TRACE_ENTRY();
15880+
15881+ name_len = snprintf(&q, sizeof(q), "%s/%s", SCST_PR_DIR, dev->virt_name) + 1;
15882+ dev->pr_file_name = kmalloc(name_len, GFP_KERNEL);
15883+ if (dev->pr_file_name == NULL) {
15884+ PRINT_ERROR("Allocation of device '%s' file path failed",
15885+ dev->virt_name);
15886+ res = -ENOMEM;
15887+ goto out;
15888+ } else
15889+ snprintf(dev->pr_file_name, name_len, "%s/%s", SCST_PR_DIR,
15890+ dev->virt_name);
15891+
15892+ name_len = snprintf(&q, sizeof(q), "%s/%s.1", SCST_PR_DIR, dev->virt_name) + 1;
15893+ dev->pr_file_name1 = kmalloc(name_len, GFP_KERNEL);
15894+ if (dev->pr_file_name1 == NULL) {
15895+ PRINT_ERROR("Allocation of device '%s' backup file path failed",
15896+ dev->virt_name);
15897+ res = -ENOMEM;
15898+ goto out_free_name;
15899+ } else
15900+ snprintf(dev->pr_file_name1, name_len, "%s/%s.1", SCST_PR_DIR,
15901+ dev->virt_name);
15902+
15903+ res = scst_pr_check_pr_path();
15904+ if (res == 0) {
15905+ res = scst_pr_load_device_file(dev);
15906+ if (res == -ENOENT)
15907+ res = 0;
15908+ }
15909+
15910+ if (res != 0)
15911+ goto out_free_name1;
15912+
15913+out:
15914+ TRACE_EXIT_RES(res);
15915+ return res;
15916+
15917+out_free_name1:
15918+ kfree(dev->pr_file_name1);
15919+ dev->pr_file_name1 = NULL;
15920+
15921+out_free_name:
15922+ kfree(dev->pr_file_name);
15923+ dev->pr_file_name = NULL;
15924+ goto out;
15925+}
15926+
15927+/* Called under scst_mutex */
15928+void scst_pr_clear_dev(struct scst_device *dev)
15929+{
15930+ struct scst_dev_registrant *reg, *tmp_reg;
15931+
15932+ TRACE_ENTRY();
15933+
15934+ list_for_each_entry_safe(reg, tmp_reg, &dev->dev_registrants_list,
15935+ dev_registrants_list_entry) {
15936+ scst_pr_remove_registrant(dev, reg);
15937+ }
15938+
15939+ kfree(dev->pr_file_name);
15940+ kfree(dev->pr_file_name1);
15941+
15942+ TRACE_EXIT();
15943+ return;
15944+}
15945+
15946+/* Called under scst_mutex */
15947+int scst_pr_init_tgt_dev(struct scst_tgt_dev *tgt_dev)
15948+{
15949+ int res = 0;
15950+ struct scst_dev_registrant *reg;
15951+ struct scst_device *dev = tgt_dev->dev;
15952+ const uint8_t *transport_id = tgt_dev->sess->transport_id;
15953+ const uint16_t rel_tgt_id = tgt_dev->sess->tgt->rel_tgt_id;
15954+
15955+ TRACE_ENTRY();
15956+
15957+ if (tgt_dev->sess->transport_id == NULL)
15958+ goto out;
15959+
15960+ scst_pr_write_lock(dev);
15961+
15962+ reg = scst_pr_find_reg(dev, transport_id, rel_tgt_id);
15963+ if ((reg != NULL) && (reg->tgt_dev == NULL)) {
15964+ TRACE_PR("Assigning reg %s/%d (%p) to tgt_dev %p (dev %s)",
15965+ debug_transport_id_to_initiator_name(transport_id),
15966+ rel_tgt_id, reg, tgt_dev, dev->virt_name);
15967+ tgt_dev->registrant = reg;
15968+ reg->tgt_dev = tgt_dev;
15969+ }
15970+
15971+ scst_pr_write_unlock(dev);
15972+
15973+out:
15974+ TRACE_EXIT_RES(res);
15975+ return res;
15976+}
15977+
15978+/* Called under scst_mutex */
15979+void scst_pr_clear_tgt_dev(struct scst_tgt_dev *tgt_dev)
15980+{
15981+ TRACE_ENTRY();
15982+
15983+ if (tgt_dev->registrant != NULL) {
15984+ struct scst_dev_registrant *reg = tgt_dev->registrant;
15985+ struct scst_device *dev = tgt_dev->dev;
15986+ struct scst_tgt_dev *t;
15987+
15988+ scst_pr_write_lock(dev);
15989+
15990+ tgt_dev->registrant = NULL;
15991+ reg->tgt_dev = NULL;
15992+
15993+ /* Just in case, actually. It should never happen. */
15994+ list_for_each_entry(t, &dev->dev_tgt_dev_list,
15995+ dev_tgt_dev_list_entry) {
15996+ if (t == tgt_dev)
15997+ continue;
15998+ if ((t->sess->tgt->rel_tgt_id == reg->rel_tgt_id) &&
15999+ tid_equal(t->sess->transport_id, reg->transport_id)) {
16000+ TRACE_PR("Reassigning reg %s/%d (%p) to tgt_dev "
16001+ "%p (being cleared tgt_dev %p)",
16002+ debug_transport_id_to_initiator_name(
16003+ reg->transport_id),
16004+ reg->rel_tgt_id, reg, t, tgt_dev);
16005+ t->registrant = reg;
16006+ reg->tgt_dev = t;
16007+ break;
16008+ }
16009+ }
16010+
16011+ scst_pr_write_unlock(dev);
16012+ }
16013+
16014+ TRACE_EXIT();
16015+ return;
16016+}
16017+
16018+/* Called with dev_pr_mutex locked. Might also be called under scst_mutex2. */
16019+static int scst_pr_register_with_spec_i_pt(struct scst_cmd *cmd,
16020+ const uint16_t rel_tgt_id, uint8_t *buffer, int buffer_size,
16021+ struct list_head *rollback_list)
16022+{
16023+ int res = 0;
16024+ int offset, ext_size;
16025+ __be64 action_key;
16026+ struct scst_device *dev = cmd->dev;
16027+ struct scst_dev_registrant *reg;
16028+ uint8_t *transport_id;
16029+
16030+ action_key = get_unaligned((__be64 *)&buffer[8]);
16031+
16032+ ext_size = be32_to_cpu(get_unaligned((__be32 *)&buffer[24]));
16033+ if ((ext_size + 28) > buffer_size) {
16034+ TRACE_PR("Invalid buffer size %d (max %d)", buffer_size,
16035+ ext_size + 28);
16036+ scst_set_cmd_error(cmd,
16037+ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
16038+ res = -EINVAL;
16039+ goto out;
16040+ }
16041+
16042+ offset = 0;
16043+ while (offset < ext_size) {
16044+ transport_id = &buffer[28 + offset];
16045+
16046+ if ((offset + tid_size(transport_id)) > ext_size) {
16047+ TRACE_PR("Invalid transport_id size %d (max %d)",
16048+ tid_size(transport_id), ext_size - offset);
16049+ scst_set_cmd_error(cmd,
16050+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
16051+ res = -EINVAL;
16052+ goto out;
16053+ }
16054+ tid_secure(transport_id);
16055+ offset += tid_size(transport_id);
16056+ }
16057+
16058+ offset = 0;
16059+ while (offset < ext_size) {
16060+ struct scst_tgt_dev *t;
16061+
16062+ transport_id = &buffer[28 + offset];
16063+
16064+ TRACE_PR("rel_tgt_id %d, transport_id %s", rel_tgt_id,
16065+ debug_transport_id_to_initiator_name(transport_id));
16066+
16067+ if ((transport_id[0] & 0x0f) == SCSI_TRANSPORTID_PROTOCOLID_ISCSI &&
16068+ (transport_id[0] & 0xc0) == 0) {
16069+ TRACE_PR("Wildcard iSCSI TransportID %s",
16070+ &transport_id[4]);
16071+ /*
16072+ * We can't use scst_mutex here, because of the
16073+ * circular locking dependency with dev_pr_mutex.
16074+ */
16075+ spin_lock_bh(&dev->dev_lock);
16076+ list_for_each_entry(t, &dev->dev_tgt_dev_list,
16077+ dev_tgt_dev_list_entry) {
16078+ /*
16079+ * We must go over all matching tgt_devs and
16080+ * register them on the requested rel_tgt_id
16081+ */
16082+ if (!tid_equal(t->sess->transport_id,
16083+ transport_id))
16084+ continue;
16085+
16086+ reg = scst_pr_find_reg(dev,
16087+ t->sess->transport_id, rel_tgt_id);
16088+ if (reg == NULL) {
16089+ reg = scst_pr_add_registrant(dev,
16090+ t->sess->transport_id,
16091+ rel_tgt_id, action_key, true);
16092+ if (reg == NULL) {
16093+ spin_unlock_bh(&dev->dev_lock);
16094+ scst_set_busy(cmd);
16095+ res = -ENOMEM;
16096+ goto out;
16097+ }
16098+ } else if (reg->key != action_key) {
16099+ TRACE_PR("Changing key of reg %p "
16100+ "(tgt_dev %p)", reg, t);
16101+ reg->rollback_key = reg->key;
16102+ reg->key = action_key;
16103+ } else
16104+ continue;
16105+
16106+ list_add_tail(&reg->aux_list_entry,
16107+ rollback_list);
16108+ }
16109+ spin_unlock_bh(&dev->dev_lock);
16110+ } else {
16111+ reg = scst_pr_find_reg(dev, transport_id, rel_tgt_id);
16112+ if (reg != NULL) {
16113+ if (reg->key == action_key)
16114+ goto next;
16115+ TRACE_PR("Changing key of reg %p (tgt_dev %p)",
16116+ reg, reg->tgt_dev);
16117+ reg->rollback_key = reg->key;
16118+ reg->key = action_key;
16119+ } else {
16120+ reg = scst_pr_add_registrant(dev, transport_id,
16121+ rel_tgt_id, action_key, false);
16122+ if (reg == NULL) {
16123+ scst_set_busy(cmd);
16124+ res = -ENOMEM;
16125+ goto out;
16126+ }
16127+ }
16128+
16129+ list_add_tail(&reg->aux_list_entry,
16130+ rollback_list);
16131+ }
16132+next:
16133+ offset += tid_size(transport_id);
16134+ }
16135+out:
16136+ return res;
16137+}
16138+
16139+/* Called with dev_pr_mutex locked, no IRQ */
16140+static void scst_pr_unregister(struct scst_device *dev,
16141+ struct scst_dev_registrant *reg)
16142+{
16143+ bool is_holder;
16144+ uint8_t pr_type;
16145+
16146+ TRACE_ENTRY();
16147+
16148+ TRACE_PR("Unregistering key %0llx", reg->key);
16149+
16150+ is_holder = scst_pr_is_holder(dev, reg);
16151+ pr_type = dev->pr_type;
16152+
16153+ scst_pr_remove_registrant(dev, reg);
16154+
16155+ if (is_holder && !dev->pr_is_set) {
16156+ /* A registration just released */
16157+ switch (pr_type) {
16158+ case TYPE_WRITE_EXCLUSIVE_REGONLY:
16159+ case TYPE_EXCLUSIVE_ACCESS_REGONLY:
16160+ scst_pr_send_ua_all(dev, NULL,
16161+ SCST_LOAD_SENSE(scst_sense_reservation_released));
16162+ break;
16163+ }
16164+ }
16165+
16166+ TRACE_EXIT();
16167+ return;
16168+}
16169+
16170+/* Called with dev_pr_mutex locked, no IRQ */
16171+static void scst_pr_unregister_all_tg_pt(struct scst_device *dev,
16172+ const uint8_t *transport_id)
16173+{
16174+ struct scst_tgt_template *tgtt;
16175+ uint8_t proto_id = transport_id[0] & 0x0f;
16176+
16177+ TRACE_ENTRY();
16178+
16179+ /*
16180+ * We can't use scst_mutex here, because of the circular locking
16181+ * dependency with dev_pr_mutex.
16182+ */
16183+ mutex_lock(&scst_mutex2);
16184+
16185+ list_for_each_entry(tgtt, &scst_template_list, scst_template_list_entry) {
16186+ struct scst_tgt *tgt;
16187+
16188+ if (tgtt->get_initiator_port_transport_id == NULL)
16189+ continue;
16190+
16191+ if (tgtt->get_initiator_port_transport_id(NULL, NULL) != proto_id)
16192+ continue;
16193+
16194+ list_for_each_entry(tgt, &tgtt->tgt_list, tgt_list_entry) {
16195+ struct scst_dev_registrant *reg;
16196+
16197+ reg = scst_pr_find_reg(dev, transport_id,
16198+ tgt->rel_tgt_id);
16199+ if (reg == NULL)
16200+ continue;
16201+
16202+ scst_pr_unregister(dev, reg);
16203+ }
16204+ }
16205+
16206+ mutex_unlock(&scst_mutex2);
16207+
16208+ TRACE_EXIT();
16209+ return;
16210+}
16211+
16212+/* Called with dev_pr_mutex locked. Might also be called under scst_mutex2. */
16213+static int scst_pr_register_on_tgt_id(struct scst_cmd *cmd,
16214+ const uint16_t rel_tgt_id, uint8_t *buffer, int buffer_size,
16215+ bool spec_i_pt, struct list_head *rollback_list)
16216+{
16217+ int res;
16218+
16219+ TRACE_ENTRY();
16220+
16221+ TRACE_PR("rel_tgt_id %d, spec_i_pt %d", rel_tgt_id, spec_i_pt);
16222+
16223+ if (spec_i_pt) {
16224+ res = scst_pr_register_with_spec_i_pt(cmd, rel_tgt_id, buffer,
16225+ buffer_size, rollback_list);
16226+ if (res != 0)
16227+ goto out;
16228+ }
16229+
16230+ /* tgt_dev can be among TIDs for scst_pr_register_with_spec_i_pt() */
16231+
16232+ if (scst_pr_find_reg(cmd->dev, cmd->sess->transport_id, rel_tgt_id) == NULL) {
16233+ __be64 action_key;
16234+ struct scst_dev_registrant *reg;
16235+
16236+ action_key = get_unaligned((__be64 *)&buffer[8]);
16237+
16238+ reg = scst_pr_add_registrant(cmd->dev, cmd->sess->transport_id,
16239+ rel_tgt_id, action_key, false);
16240+ if (reg == NULL) {
16241+ res = -ENOMEM;
16242+ scst_set_busy(cmd);
16243+ goto out;
16244+ }
16245+
16246+ list_add_tail(&reg->aux_list_entry, rollback_list);
16247+ }
16248+
16249+ res = 0;
16250+
16251+out:
16252+ TRACE_EXIT_RES(res);
16253+ return res;
16254+}
16255+
16256+/* Called with dev_pr_mutex locked, no IRQ */
16257+static int scst_pr_register_all_tg_pt(struct scst_cmd *cmd, uint8_t *buffer,
16258+ int buffer_size, bool spec_i_pt, struct list_head *rollback_list)
16259+{
16260+ int res = 0;
16261+ struct scst_tgt_template *tgtt;
16262+ uint8_t proto_id = cmd->sess->transport_id[0] & 0x0f;
16263+
16264+ TRACE_ENTRY();
16265+
16266+ /*
16267+ * We can't use scst_mutex here, because of the circular locking
16268+ * dependency with dev_pr_mutex.
16269+ */
16270+ mutex_lock(&scst_mutex2);
16271+
16272+ list_for_each_entry(tgtt, &scst_template_list, scst_template_list_entry) {
16273+ struct scst_tgt *tgt;
16274+
16275+ if (tgtt->get_initiator_port_transport_id == NULL)
16276+ continue;
16277+
16278+ if (tgtt->get_initiator_port_transport_id(NULL, NULL) != proto_id)
16279+ continue;
16280+
16281+ TRACE_PR("tgtt %s, spec_i_pt %d", tgtt->name, spec_i_pt);
16282+
16283+ list_for_each_entry(tgt, &tgtt->tgt_list, tgt_list_entry) {
16284+ if (tgt->rel_tgt_id == 0)
16285+ continue;
16286+ TRACE_PR("tgt %s, rel_tgt_id %d", tgt->tgt_name,
16287+ tgt->rel_tgt_id);
16288+ res = scst_pr_register_on_tgt_id(cmd, tgt->rel_tgt_id,
16289+ buffer, buffer_size, spec_i_pt, rollback_list);
16290+ if (res != 0)
16291+ goto out_unlock;
16292+ }
16293+ }
16294+
16295+out_unlock:
16296+ mutex_unlock(&scst_mutex2);
16297+
16298+ TRACE_EXIT_RES(res);
16299+ return res;
16300+}
16301+
16302+/* Called with dev_pr_mutex locked, no IRQ */
16303+static int __scst_pr_register(struct scst_cmd *cmd, uint8_t *buffer,
16304+ int buffer_size, bool spec_i_pt, bool all_tg_pt)
16305+{
16306+ int res;
16307+ struct scst_dev_registrant *reg, *treg;
16308+ LIST_HEAD(rollback_list);
16309+
16310+ TRACE_ENTRY();
16311+
16312+ if (all_tg_pt) {
16313+ res = scst_pr_register_all_tg_pt(cmd, buffer, buffer_size,
16314+ spec_i_pt, &rollback_list);
16315+ if (res != 0)
16316+ goto out_rollback;
16317+ } else {
16318+ res = scst_pr_register_on_tgt_id(cmd,
16319+ cmd->sess->tgt->rel_tgt_id, buffer, buffer_size,
16320+ spec_i_pt, &rollback_list);
16321+ if (res != 0)
16322+ goto out_rollback;
16323+ }
16324+
16325+ list_for_each_entry(reg, &rollback_list, aux_list_entry) {
16326+ reg->rollback_key = 0;
16327+ }
16328+
16329+out:
16330+ TRACE_EXIT_RES(res);
16331+ return res;
16332+
16333+out_rollback:
16334+ list_for_each_entry_safe(reg, treg, &rollback_list, aux_list_entry) {
16335+ list_del(&reg->aux_list_entry);
16336+ if (reg->rollback_key == 0)
16337+ scst_pr_remove_registrant(cmd->dev, reg);
16338+ else {
16339+ reg->key = reg->rollback_key;
16340+ reg->rollback_key = 0;
16341+ }
16342+ }
16343+ goto out;
16344+}
16345+
16346+/* Called with dev_pr_mutex locked, no IRQ */
16347+void scst_pr_register(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
16348+{
16349+ int aptpl, spec_i_pt, all_tg_pt;
16350+ __be64 key, action_key;
16351+ struct scst_device *dev = cmd->dev;
16352+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
16353+ struct scst_session *sess = cmd->sess;
16354+ struct scst_dev_registrant *reg;
16355+
16356+ TRACE_ENTRY();
16357+
16358+ aptpl = buffer[20] & 0x01;
16359+ spec_i_pt = (buffer[20] >> 3) & 0x01;
16360+ all_tg_pt = (buffer[20] >> 2) & 0x01;
16361+ key = get_unaligned((__be64 *)&buffer[0]);
16362+ action_key = get_unaligned((__be64 *)&buffer[8]);
16363+
16364+ if (spec_i_pt == 0 && buffer_size != 24) {
16365+ TRACE_PR("Invalid buffer size %d", buffer_size);
16366+ scst_set_cmd_error(cmd,
16367+ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
16368+ goto out;
16369+ }
16370+
16371+ reg = tgt_dev->registrant;
16372+
16373+ TRACE_PR("Register: initiator %s/%d (%p), key %0llx, action_key %0llx "
16374+ "(tgt_dev %p)",
16375+ debug_transport_id_to_initiator_name(sess->transport_id),
16376+ sess->tgt->rel_tgt_id, reg, key, action_key, tgt_dev);
16377+
16378+ if (reg == NULL) {
16379+ TRACE_PR("tgt_dev %p is not registered yet - registering",
16380+ tgt_dev);
16381+ if (key) {
16382+ TRACE_PR("%s", "Key must be zero on new registration");
16383+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
16384+ goto out;
16385+ }
16386+ if (action_key) {
16387+ int rc = __scst_pr_register(cmd, buffer, buffer_size,
16388+ spec_i_pt, all_tg_pt);
16389+ if (rc != 0)
16390+ goto out;
16391+ } else
16392+ TRACE_PR("%s", "Doing nothing - action_key is zero");
16393+ } else {
16394+ if (reg->key != key) {
16395+ TRACE_PR("tgt_dev %p already registered - reservation "
16396+ "key %0llx mismatch", tgt_dev, reg->key);
16397+ scst_set_cmd_error_status(cmd,
16398+ SAM_STAT_RESERVATION_CONFLICT);
16399+ goto out;
16400+ }
16401+ if (spec_i_pt) {
16402+ TRACE_PR("%s", "spec_i_pt must be zero in this case");
16403+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
16404+ scst_sense_invalid_field_in_cdb));
16405+ goto out;
16406+ }
16407+ if (action_key == 0) {
16408+ if (all_tg_pt)
16409+ scst_pr_unregister_all_tg_pt(dev,
16410+ sess->transport_id);
16411+ else
16412+ scst_pr_unregister(dev, reg);
16413+ } else
16414+ reg->key = action_key;
16415+ }
16416+
16417+ dev->pr_generation++;
16418+
16419+ dev->pr_aptpl = aptpl;
16420+
16421+ scst_pr_dump_prs(dev, false);
16422+
16423+out:
16424+ TRACE_EXIT();
16425+ return;
16426+}
16427+
16428+/* Called with dev_pr_mutex locked, no IRQ */
16429+void scst_pr_register_and_ignore(struct scst_cmd *cmd, uint8_t *buffer,
16430+ int buffer_size)
16431+{
16432+ int aptpl, all_tg_pt;
16433+ __be64 action_key;
16434+ struct scst_dev_registrant *reg = NULL;
16435+ struct scst_device *dev = cmd->dev;
16436+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
16437+ struct scst_session *sess = cmd->sess;
16438+
16439+ TRACE_ENTRY();
16440+
16441+ aptpl = buffer[20] & 0x01;
16442+ all_tg_pt = (buffer[20] >> 2) & 0x01;
16443+ action_key = get_unaligned((__be64 *)&buffer[8]);
16444+
16445+ if (buffer_size != 24) {
16446+ TRACE_PR("Invalid buffer size %d", buffer_size);
16447+ scst_set_cmd_error(cmd,
16448+ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
16449+ goto out;
16450+ }
16451+
16452+ reg = tgt_dev->registrant;
16453+
16454+ TRACE_PR("Register and ignore: initiator %s/%d (%p), action_key "
16455+ "%016llx (tgt_dev %p)",
16456+ debug_transport_id_to_initiator_name(sess->transport_id),
16457+ sess->tgt->rel_tgt_id, reg, action_key, tgt_dev);
16458+
16459+ if (reg == NULL) {
16460+ TRACE_PR("Tgt_dev %p is not registered yet - trying to "
16461+ "register", tgt_dev);
16462+ if (action_key) {
16463+ int rc = __scst_pr_register(cmd, buffer, buffer_size,
16464+ false, all_tg_pt);
16465+ if (rc != 0)
16466+ goto out;
16467+ } else
16468+ TRACE_PR("%s", "Doing nothing, action_key is zero");
16469+ } else {
16470+ if (action_key == 0) {
16471+ if (all_tg_pt)
16472+ scst_pr_unregister_all_tg_pt(dev,
16473+ sess->transport_id);
16474+ else
16475+ scst_pr_unregister(dev, reg);
16476+ } else
16477+ reg->key = action_key;
16478+ }
16479+
16480+ dev->pr_generation++;
16481+
16482+ dev->pr_aptpl = aptpl;
16483+
16484+ scst_pr_dump_prs(dev, false);
16485+
16486+out:
16487+ TRACE_EXIT();
16488+ return;
16489+}
16490+
16491+/* Called with dev_pr_mutex locked, no IRQ */
16492+void scst_pr_register_and_move(struct scst_cmd *cmd, uint8_t *buffer,
16493+ int buffer_size)
16494+{
16495+ int aptpl;
16496+ int unreg;
16497+ int tid_buffer_size;
16498+ __be64 key, action_key;
16499+ struct scst_device *dev = cmd->dev;
16500+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
16501+ struct scst_session *sess = cmd->sess;
16502+ struct scst_dev_registrant *reg, *reg_move;
16503+ const uint8_t *transport_id = NULL;
16504+ uint8_t *transport_id_move = NULL;
16505+ uint16_t rel_tgt_id_move;
16506+
16507+ TRACE_ENTRY();
16508+
16509+ aptpl = buffer[17] & 0x01;
16510+ key = get_unaligned((__be64 *)&buffer[0]);
16511+ action_key = get_unaligned((__be64 *)&buffer[8]);
16512+ unreg = (buffer[17] >> 1) & 0x01;
16513+ tid_buffer_size = be32_to_cpu(get_unaligned((__be32 *)&buffer[20]));
16514+
16515+ if ((tid_buffer_size + 24) > buffer_size) {
16516+ TRACE_PR("Invalid buffer size %d (%d)",
16517+ buffer_size, tid_buffer_size + 24);
16518+ scst_set_cmd_error(cmd,
16519+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
16520+ goto out;
16521+ }
16522+
16523+ if (tid_buffer_size < 24) {
16524+ TRACE_PR("%s", "Transport id buffer too small");
16525+ scst_set_cmd_error(cmd,
16526+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
16527+ goto out;
16528+ }
16529+
16530+ reg = tgt_dev->registrant;
16531+ /* We already checked reg is not NULL */
16532+ if (reg->key != key) {
16533+ TRACE_PR("Registrant's %s/%d (%p) key %016llx mismatch with "
16534+ "%016llx (tgt_dev %p)",
16535+ debug_transport_id_to_initiator_name(reg->transport_id),
16536+ reg->rel_tgt_id, reg, reg->key, key, tgt_dev);
16537+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
16538+ goto out;
16539+ }
16540+
16541+ if (!dev->pr_is_set) {
16542+ TRACE_PR("%s", "There must be a PR");
16543+ scst_set_cmd_error(cmd,
16544+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
16545+ goto out;
16546+ }
16547+
16548+ /*
16549+ * This check also required by table "PERSISTENT RESERVE OUT service
16550+ * actions that are allowed in the presence of various reservations".
16551+ */
16552+ if (!scst_pr_is_holder(dev, reg)) {
16553+ TRACE_PR("Registrant %s/%d (%p) is not a holder (tgt_dev %p)",
16554+ debug_transport_id_to_initiator_name(
16555+ reg->transport_id), reg->rel_tgt_id,
16556+ reg, tgt_dev);
16557+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
16558+ goto out;
16559+ }
16560+
16561+ if (action_key == 0) {
16562+ TRACE_PR("%s", "Action key must be non-zero");
16563+ scst_set_cmd_error(cmd,
16564+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
16565+ goto out;
16566+ }
16567+
16568+ transport_id = sess->transport_id;
16569+ transport_id_move = (uint8_t *)&buffer[24];
16570+ rel_tgt_id_move = be16_to_cpu(get_unaligned((__be16 *)&buffer[18]));
16571+
16572+ if ((tid_size(transport_id_move) + 24) > buffer_size) {
16573+ TRACE_PR("Invalid buffer size %d (%d)",
16574+ buffer_size, tid_size(transport_id_move) + 24);
16575+ scst_set_cmd_error(cmd,
16576+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
16577+ goto out;
16578+ }
16579+
16580+ tid_secure(transport_id_move);
16581+
16582+ if (dev->pr_type == TYPE_WRITE_EXCLUSIVE_ALL_REG ||
16583+ dev->pr_type == TYPE_EXCLUSIVE_ACCESS_ALL_REG) {
16584+ TRACE_PR("Unable to finish operation due to wrong reservation "
16585+ "type %02x", dev->pr_type);
16586+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
16587+ goto out;
16588+ }
16589+
16590+ if (tid_equal(transport_id, transport_id_move)) {
16591+ TRACE_PR("%s", "Equal transport id's");
16592+ scst_set_cmd_error(cmd,
16593+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
16594+ goto out;
16595+ }
16596+
16597+ reg_move = scst_pr_find_reg(dev, transport_id_move, rel_tgt_id_move);
16598+ if (reg_move == NULL) {
16599+ reg_move = scst_pr_add_registrant(dev, transport_id_move,
16600+ rel_tgt_id_move, action_key, false);
16601+ if (reg_move == NULL) {
16602+ scst_set_busy(cmd);
16603+ goto out;
16604+ }
16605+ } else if (reg_move->key != action_key) {
16606+ TRACE_PR("Changing key for reg %p", reg);
16607+ reg_move->key = action_key;
16608+ }
16609+
16610+ TRACE_PR("Register and move: from initiator %s/%d (%p, tgt_dev %p) to "
16611+ "initiator %s/%d (%p, tgt_dev %p), key %016llx (unreg %d)",
16612+ debug_transport_id_to_initiator_name(reg->transport_id),
16613+ reg->rel_tgt_id, reg, reg->tgt_dev,
16614+ debug_transport_id_to_initiator_name(transport_id_move),
16615+ rel_tgt_id_move, reg_move, reg_move->tgt_dev, action_key,
16616+ unreg);
16617+
16618+ /* Move the holder */
16619+ scst_pr_set_holder(dev, reg_move, dev->pr_scope, dev->pr_type);
16620+
16621+ if (unreg)
16622+ scst_pr_remove_registrant(dev, reg);
16623+
16624+ dev->pr_generation++;
16625+
16626+ dev->pr_aptpl = aptpl;
16627+
16628+ scst_pr_dump_prs(dev, false);
16629+
16630+out:
16631+ TRACE_EXIT();
16632+ return;
16633+}
16634+
16635+/* Called with dev_pr_mutex locked, no IRQ */
16636+void scst_pr_reserve(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
16637+{
16638+ uint8_t scope, type;
16639+ __be64 key;
16640+ struct scst_device *dev = cmd->dev;
16641+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
16642+ struct scst_dev_registrant *reg;
16643+
16644+ TRACE_ENTRY();
16645+
16646+ key = get_unaligned((__be64 *)&buffer[0]);
16647+ scope = (cmd->cdb[2] & 0x0f) >> 4;
16648+ type = cmd->cdb[2] & 0x0f;
16649+
16650+ if (buffer_size != 24) {
16651+ TRACE_PR("Invalid buffer size %d", buffer_size);
16652+ scst_set_cmd_error(cmd,
16653+ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
16654+ goto out;
16655+ }
16656+
16657+ if (!scst_pr_type_valid(type)) {
16658+ TRACE_PR("Invalid reservation type %d", type);
16659+ scst_set_cmd_error(cmd,
16660+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
16661+ goto out;
16662+ }
16663+
16664+ if (((cmd->cdb[2] & 0x0f) >> 4) != SCOPE_LU) {
16665+ TRACE_PR("Invalid reservation scope %d", scope);
16666+ scst_set_cmd_error(cmd,
16667+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
16668+ goto out;
16669+ }
16670+
16671+ reg = tgt_dev->registrant;
16672+
16673+ TRACE_PR("Reserve: initiator %s/%d (%p), key %016llx, scope %d, "
16674+ "type %d (tgt_dev %p)",
16675+ debug_transport_id_to_initiator_name(cmd->sess->transport_id),
16676+ cmd->sess->tgt->rel_tgt_id, reg, key, scope, type, tgt_dev);
16677+
16678+ /* We already checked reg is not NULL */
16679+ if (reg->key != key) {
16680+ TRACE_PR("Registrant's %p key %016llx mismatch with %016llx",
16681+ reg, reg->key, key);
16682+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
16683+ goto out;
16684+ }
16685+
16686+ if (!dev->pr_is_set)
16687+ scst_pr_set_holder(dev, reg, scope, type);
16688+ else {
16689+ if (!scst_pr_is_holder(dev, reg)) {
16690+ /*
16691+ * This check also required by table "PERSISTENT
16692+ * RESERVE OUT service actions that are allowed in the
16693+ * presence of various reservations".
16694+ */
16695+ TRACE_PR("Only holder can override - reg %p is not a "
16696+ "holder", reg);
16697+ scst_set_cmd_error_status(cmd,
16698+ SAM_STAT_RESERVATION_CONFLICT);
16699+ goto out;
16700+ } else {
16701+ if (dev->pr_scope != scope || dev->pr_type != type) {
16702+ TRACE_PR("Error overriding scope or type for "
16703+ "reg %p", reg);
16704+ scst_set_cmd_error_status(cmd,
16705+ SAM_STAT_RESERVATION_CONFLICT);
16706+ goto out;
16707+ } else
16708+ TRACE_PR("Do nothing: reservation of reg %p "
16709+ "is the same", reg);
16710+ }
16711+ }
16712+
16713+ scst_pr_dump_prs(dev, false);
16714+
16715+out:
16716+ TRACE_EXIT();
16717+ return;
16718+}
16719+
16720+/* Called with dev_pr_mutex locked, no IRQ */
16721+void scst_pr_release(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
16722+{
16723+ int scope, type;
16724+ __be64 key;
16725+ struct scst_device *dev = cmd->dev;
16726+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
16727+ struct scst_dev_registrant *reg;
16728+ uint8_t cur_pr_type;
16729+
16730+ TRACE_ENTRY();
16731+
16732+ key = get_unaligned((__be64 *)&buffer[0]);
16733+ scope = (cmd->cdb[2] & 0x0f) >> 4;
16734+ type = cmd->cdb[2] & 0x0f;
16735+
16736+ if (buffer_size != 24) {
16737+ TRACE_PR("Invalid buffer size %d", buffer_size);
16738+ scst_set_cmd_error(cmd,
16739+ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
16740+ goto out;
16741+ }
16742+
16743+ if (!dev->pr_is_set) {
16744+ TRACE_PR("%s", "There is no PR - do nothing");
16745+ goto out;
16746+ }
16747+
16748+ reg = tgt_dev->registrant;
16749+
16750+ TRACE_PR("Release: initiator %s/%d (%p), key %016llx, scope %d, type "
16751+ "%d (tgt_dev %p)", debug_transport_id_to_initiator_name(
16752+ cmd->sess->transport_id),
16753+ cmd->sess->tgt->rel_tgt_id, reg, key, scope, type, tgt_dev);
16754+
16755+ /* We already checked reg is not NULL */
16756+ if (reg->key != key) {
16757+ TRACE_PR("Registrant's %p key %016llx mismatch with %016llx",
16758+ reg, reg->key, key);
16759+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
16760+ goto out;
16761+ }
16762+
16763+ if (!scst_pr_is_holder(dev, reg)) {
16764+ TRACE_PR("Registrant %p is not a holder - do nothing", reg);
16765+ goto out;
16766+ }
16767+
16768+ if (dev->pr_scope != scope || dev->pr_type != type) {
16769+ TRACE_PR("%s", "Released scope or type do not match with "
16770+ "holder");
16771+ scst_set_cmd_error(cmd,
16772+ SCST_LOAD_SENSE(scst_sense_invalid_release));
16773+ goto out;
16774+ }
16775+
16776+ cur_pr_type = dev->pr_type; /* it will be cleared */
16777+
16778+ scst_pr_clear_reservation(dev);
16779+
16780+ switch (cur_pr_type) {
16781+ case TYPE_WRITE_EXCLUSIVE_REGONLY:
16782+ case TYPE_EXCLUSIVE_ACCESS_REGONLY:
16783+ case TYPE_WRITE_EXCLUSIVE_ALL_REG:
16784+ case TYPE_EXCLUSIVE_ACCESS_ALL_REG:
16785+ scst_pr_send_ua_all(dev, reg,
16786+ SCST_LOAD_SENSE(scst_sense_reservation_released));
16787+ }
16788+
16789+ scst_pr_dump_prs(dev, false);
16790+
16791+out:
16792+ TRACE_EXIT();
16793+ return;
16794+}
16795+
16796+/* Called with dev_pr_mutex locked, no IRQ */
16797+void scst_pr_clear(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
16798+{
16799+ int scope, type;
16800+ __be64 key;
16801+ struct scst_device *dev = cmd->dev;
16802+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
16803+ struct scst_dev_registrant *reg, *r, *t;
16804+
16805+ TRACE_ENTRY();
16806+
16807+ key = get_unaligned((__be64 *)&buffer[0]);
16808+ scope = (cmd->cdb[2] & 0x0f) >> 4;
16809+ type = cmd->cdb[2] & 0x0f;
16810+
16811+ if (buffer_size != 24) {
16812+ TRACE_PR("Invalid buffer size %d", buffer_size);
16813+ scst_set_cmd_error(cmd,
16814+ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
16815+ goto out;
16816+ }
16817+
16818+ reg = tgt_dev->registrant;
16819+
16820+ TRACE_PR("Clear: initiator %s/%d (%p), key %016llx (tgt_dev %p)",
16821+ debug_transport_id_to_initiator_name(cmd->sess->transport_id),
16822+ cmd->sess->tgt->rel_tgt_id, reg, key, tgt_dev);
16823+
16824+ /* We already checked reg is not NULL */
16825+ if (reg->key != key) {
16826+ TRACE_PR("Registrant's %p key %016llx mismatch with %016llx",
16827+ reg, reg->key, key);
16828+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
16829+ goto out;
16830+ }
16831+
16832+ scst_pr_send_ua_all(dev, reg,
16833+ SCST_LOAD_SENSE(scst_sense_reservation_preempted));
16834+
16835+ list_for_each_entry_safe(r, t, &dev->dev_registrants_list,
16836+ dev_registrants_list_entry) {
16837+ scst_pr_remove_registrant(dev, r);
16838+ }
16839+
16840+ dev->pr_generation++;
16841+
16842+ scst_pr_dump_prs(dev, false);
16843+
16844+out:
16845+ TRACE_EXIT();
16846+ return;
16847+}
16848+
16849+static void scst_pr_do_preempt(struct scst_cmd *cmd, uint8_t *buffer,
16850+ int buffer_size, bool abort)
16851+{
16852+ __be64 key, action_key;
16853+ int scope, type;
16854+ struct scst_device *dev = cmd->dev;
16855+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
16856+ struct scst_dev_registrant *reg, *r, *rt;
16857+ int existing_pr_type = dev->pr_type;
16858+ int existing_pr_scope = dev->pr_scope;
16859+ LIST_HEAD(preempt_list);
16860+
16861+ TRACE_ENTRY();
16862+
16863+ key = get_unaligned((__be64 *)&buffer[0]);
16864+ action_key = get_unaligned((__be64 *)&buffer[8]);
16865+ scope = (cmd->cdb[2] & 0x0f) >> 4;
16866+ type = cmd->cdb[2] & 0x0f;
16867+
16868+ if (buffer_size != 24) {
16869+ TRACE_PR("Invalid buffer size %d", buffer_size);
16870+ scst_set_cmd_error(cmd,
16871+ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
16872+ goto out;
16873+ }
16874+
16875+ if (!scst_pr_type_valid(type)) {
16876+ TRACE_PR("Invalid reservation type %d", type);
16877+ scst_set_cmd_error(cmd,
16878+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
16879+ goto out;
16880+ }
16881+
16882+ reg = tgt_dev->registrant;
16883+
16884+ TRACE_PR("Preempt%s: initiator %s/%d (%p), key %016llx, action_key "
16885+ "%016llx, scope %x type %x (tgt_dev %p)",
16886+ abort ? " and abort" : "",
16887+ debug_transport_id_to_initiator_name(cmd->sess->transport_id),
16888+ cmd->sess->tgt->rel_tgt_id, reg, key, action_key, scope, type,
16889+ tgt_dev);
16890+
16891+ /* We already checked reg is not NULL */
16892+ if (reg->key != key) {
16893+ TRACE_PR("Registrant's %p key %016llx mismatch with %016llx",
16894+ reg, reg->key, key);
16895+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
16896+ goto out;
16897+ }
16898+
16899+ if (!dev->pr_is_set) {
16900+ scst_pr_find_registrants_list_key(dev, action_key,
16901+ &preempt_list);
16902+ if (list_empty(&preempt_list))
16903+ goto out_error;
16904+ list_for_each_entry_safe(r, rt, &preempt_list, aux_list_entry) {
16905+ if (abort)
16906+ scst_pr_abort_reg(dev, cmd, r);
16907+ if (r != reg) {
16908+ scst_pr_send_ua_reg(dev, r, SCST_LOAD_SENSE(
16909+ scst_sense_registrations_preempted));
16910+ scst_pr_remove_registrant(dev, r);
16911+ }
16912+ }
16913+ goto done;
16914+ }
16915+
16916+ if (dev->pr_type == TYPE_WRITE_EXCLUSIVE_ALL_REG ||
16917+ dev->pr_type == TYPE_EXCLUSIVE_ACCESS_ALL_REG) {
16918+ if (action_key == 0) {
16919+ scst_pr_find_registrants_list_all(dev, reg,
16920+ &preempt_list);
16921+ list_for_each_entry_safe(r, rt, &preempt_list,
16922+ aux_list_entry) {
16923+ BUG_ON(r == reg);
16924+ if (abort)
16925+ scst_pr_abort_reg(dev, cmd, r);
16926+ scst_pr_send_ua_reg(dev, r,
16927+ SCST_LOAD_SENSE(
16928+ scst_sense_registrations_preempted));
16929+ scst_pr_remove_registrant(dev, r);
16930+ }
16931+ scst_pr_set_holder(dev, reg, scope, type);
16932+ } else {
16933+ scst_pr_find_registrants_list_key(dev, action_key,
16934+ &preempt_list);
16935+ if (list_empty(&preempt_list))
16936+ goto out_error;
16937+ list_for_each_entry_safe(r, rt, &preempt_list,
16938+ aux_list_entry) {
16939+ if (abort)
16940+ scst_pr_abort_reg(dev, cmd, r);
16941+ if (r != reg) {
16942+ scst_pr_send_ua_reg(dev, r,
16943+ SCST_LOAD_SENSE(
16944+ scst_sense_registrations_preempted));
16945+ scst_pr_remove_registrant(dev, r);
16946+ }
16947+ }
16948+ }
16949+ goto done;
16950+ }
16951+
16952+ if (dev->pr_holder->key != action_key) {
16953+ if (action_key == 0) {
16954+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
16955+ scst_sense_invalid_field_in_parm_list));
16956+ goto out;
16957+ } else {
16958+ scst_pr_find_registrants_list_key(dev, action_key,
16959+ &preempt_list);
16960+ if (list_empty(&preempt_list))
16961+ goto out_error;
16962+ list_for_each_entry_safe(r, rt, &preempt_list,
16963+ aux_list_entry) {
16964+ if (abort)
16965+ scst_pr_abort_reg(dev, cmd, r);
16966+ if (r != reg)
16967+ scst_pr_send_ua_reg(dev, r,
16968+ SCST_LOAD_SENSE(
16969+ scst_sense_registrations_preempted));
16970+ scst_pr_remove_registrant(dev, r);
16971+ }
16972+ goto done;
16973+ }
16974+ }
16975+
16976+ scst_pr_find_registrants_list_key(dev, action_key,
16977+ &preempt_list);
16978+
16979+ list_for_each_entry_safe(r, rt, &preempt_list, aux_list_entry) {
16980+ if (abort)
16981+ scst_pr_abort_reg(dev, cmd, r);
16982+ if (r != reg) {
16983+ scst_pr_send_ua_reg(dev, r, SCST_LOAD_SENSE(
16984+ scst_sense_registrations_preempted));
16985+ scst_pr_remove_registrant(dev, r);
16986+ }
16987+ }
16988+
16989+ scst_pr_set_holder(dev, reg, scope, type);
16990+
16991+ if (existing_pr_type != type || existing_pr_scope != scope) {
16992+ list_for_each_entry(r, &dev->dev_registrants_list,
16993+ dev_registrants_list_entry) {
16994+ if (r != reg)
16995+ scst_pr_send_ua_reg(dev, r, SCST_LOAD_SENSE(
16996+ scst_sense_reservation_released));
16997+ }
16998+ }
16999+
17000+done:
17001+ dev->pr_generation++;
17002+
17003+ scst_pr_dump_prs(dev, false);
17004+
17005+out:
17006+ TRACE_EXIT();
17007+ return;
17008+
17009+out_error:
17010+ TRACE_PR("Invalid key %016llx", action_key);
17011+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
17012+ goto out;
17013+}
17014+
17015+/* Called with dev_pr_mutex locked, no IRQ */
17016+void scst_pr_preempt(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
17017+{
17018+ TRACE_ENTRY();
17019+
17020+ scst_pr_do_preempt(cmd, buffer, buffer_size, false);
17021+
17022+ TRACE_EXIT();
17023+ return;
17024+}
17025+
17026+static void scst_cmd_done_pr_preempt(struct scst_cmd *cmd, int next_state,
17027+ enum scst_exec_context pref_context)
17028+{
17029+ void (*saved_cmd_done) (struct scst_cmd *cmd, int next_state,
17030+ enum scst_exec_context pref_context);
17031+
17032+ TRACE_ENTRY();
17033+
17034+ saved_cmd_done = NULL; /* to remove warning that it's used not inited */
17035+
17036+ if (cmd->pr_abort_counter != NULL) {
17037+ if (!atomic_dec_and_test(&cmd->pr_abort_counter->pr_abort_pending_cnt))
17038+ goto out;
17039+ saved_cmd_done = cmd->pr_abort_counter->saved_cmd_done;
17040+ kfree(cmd->pr_abort_counter);
17041+ cmd->pr_abort_counter = NULL;
17042+ }
17043+
17044+ saved_cmd_done(cmd, next_state, pref_context);
17045+
17046+out:
17047+ TRACE_EXIT();
17048+ return;
17049+}
17050+
17051+/*
17052+ * Called with dev_pr_mutex locked, no IRQ. Expects session_list_lock
17053+ * not locked
17054+ */
17055+void scst_pr_preempt_and_abort(struct scst_cmd *cmd, uint8_t *buffer,
17056+ int buffer_size)
17057+{
17058+ TRACE_ENTRY();
17059+
17060+ cmd->pr_abort_counter = kzalloc(sizeof(*cmd->pr_abort_counter),
17061+ GFP_KERNEL);
17062+ if (cmd->pr_abort_counter == NULL) {
17063+ PRINT_ERROR("Unable to allocate PR abort counter (size %zd)",
17064+ sizeof(*cmd->pr_abort_counter));
17065+ scst_set_busy(cmd);
17066+ goto out;
17067+ }
17068+
17069+ /* 1 to protect cmd from be done by the TM thread too early */
17070+ atomic_set(&cmd->pr_abort_counter->pr_abort_pending_cnt, 1);
17071+ atomic_set(&cmd->pr_abort_counter->pr_aborting_cnt, 1);
17072+ init_completion(&cmd->pr_abort_counter->pr_aborting_cmpl);
17073+
17074+ cmd->pr_abort_counter->saved_cmd_done = cmd->scst_cmd_done;
17075+ cmd->scst_cmd_done = scst_cmd_done_pr_preempt;
17076+
17077+ scst_pr_do_preempt(cmd, buffer, buffer_size, true);
17078+
17079+ if (!atomic_dec_and_test(&cmd->pr_abort_counter->pr_aborting_cnt))
17080+ wait_for_completion(&cmd->pr_abort_counter->pr_aborting_cmpl);
17081+
17082+out:
17083+ TRACE_EXIT();
17084+ return;
17085+}
17086+
17087+/* Checks if this is a Compatible Reservation Handling (CRH) case */
17088+bool scst_pr_crh_case(struct scst_cmd *cmd)
17089+{
17090+ bool allowed;
17091+ struct scst_device *dev = cmd->dev;
17092+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
17093+ struct scst_dev_registrant *reg;
17094+ uint8_t type;
17095+
17096+ TRACE_ENTRY();
17097+
17098+ TRACE_DBG("Test if there is a CRH case for command %s (0x%x) from "
17099+ "%s", cmd->op_name, cmd->cdb[0], cmd->sess->initiator_name);
17100+
17101+ if (!dev->pr_is_set) {
17102+ TRACE_PR("%s", "PR not set");
17103+ allowed = false;
17104+ goto out;
17105+ }
17106+
17107+ reg = tgt_dev->registrant;
17108+ type = dev->pr_type;
17109+
17110+ switch (type) {
17111+ case TYPE_WRITE_EXCLUSIVE:
17112+ case TYPE_EXCLUSIVE_ACCESS:
17113+ WARN_ON(dev->pr_holder == NULL);
17114+ if (reg == dev->pr_holder)
17115+ allowed = true;
17116+ else
17117+ allowed = false;
17118+ break;
17119+
17120+ case TYPE_WRITE_EXCLUSIVE_REGONLY:
17121+ case TYPE_EXCLUSIVE_ACCESS_REGONLY:
17122+ case TYPE_WRITE_EXCLUSIVE_ALL_REG:
17123+ case TYPE_EXCLUSIVE_ACCESS_ALL_REG:
17124+ allowed = (reg != NULL);
17125+ break;
17126+
17127+ default:
17128+ PRINT_ERROR("Invalid PR type %x", type);
17129+ allowed = false;
17130+ break;
17131+ }
17132+
17133+ if (!allowed)
17134+ TRACE_PR("Command %s (0x%x) from %s rejected due to not CRH "
17135+ "reservation", cmd->op_name, cmd->cdb[0],
17136+ cmd->sess->initiator_name);
17137+ else
17138+ TRACE_DBG("Command %s (0x%x) from %s is allowed to execute "
17139+ "due to CRH", cmd->op_name, cmd->cdb[0],
17140+ cmd->sess->initiator_name);
17141+
17142+out:
17143+ TRACE_EXIT_RES(allowed);
17144+ return allowed;
17145+
17146+}
17147+
17148+/* Check if command allowed in presence of reservation */
17149+bool scst_pr_is_cmd_allowed(struct scst_cmd *cmd)
17150+{
17151+ bool allowed;
17152+ struct scst_device *dev = cmd->dev;
17153+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
17154+ struct scst_dev_registrant *reg;
17155+ uint8_t type;
17156+ bool unlock;
17157+
17158+ TRACE_ENTRY();
17159+
17160+ unlock = scst_pr_read_lock(dev);
17161+
17162+ TRACE_DBG("Testing if command %s (0x%x) from %s allowed to execute",
17163+ cmd->op_name, cmd->cdb[0], cmd->sess->initiator_name);
17164+
17165+ /* Recheck, because it can change while we were waiting for the lock */
17166+ if (unlikely(!dev->pr_is_set)) {
17167+ allowed = true;
17168+ goto out_unlock;
17169+ }
17170+
17171+ reg = tgt_dev->registrant;
17172+ type = dev->pr_type;
17173+
17174+ switch (type) {
17175+ case TYPE_WRITE_EXCLUSIVE:
17176+ if (reg && reg == dev->pr_holder)
17177+ allowed = true;
17178+ else
17179+ allowed = (cmd->op_flags & SCST_WRITE_EXCL_ALLOWED) != 0;
17180+ break;
17181+
17182+ case TYPE_EXCLUSIVE_ACCESS:
17183+ if (reg && reg == dev->pr_holder)
17184+ allowed = true;
17185+ else
17186+ allowed = (cmd->op_flags & SCST_EXCL_ACCESS_ALLOWED) != 0;
17187+ break;
17188+
17189+ case TYPE_WRITE_EXCLUSIVE_REGONLY:
17190+ case TYPE_WRITE_EXCLUSIVE_ALL_REG:
17191+ if (reg)
17192+ allowed = true;
17193+ else
17194+ allowed = (cmd->op_flags & SCST_WRITE_EXCL_ALLOWED) != 0;
17195+ break;
17196+
17197+ case TYPE_EXCLUSIVE_ACCESS_REGONLY:
17198+ case TYPE_EXCLUSIVE_ACCESS_ALL_REG:
17199+ if (reg)
17200+ allowed = true;
17201+ else
17202+ allowed = (cmd->op_flags & SCST_EXCL_ACCESS_ALLOWED) != 0;
17203+ break;
17204+
17205+ default:
17206+ PRINT_ERROR("Invalid PR type %x", type);
17207+ allowed = false;
17208+ break;
17209+ }
17210+
17211+ if (!allowed)
17212+ TRACE_PR("Command %s (0x%x) from %s rejected due "
17213+ "to PR", cmd->op_name, cmd->cdb[0],
17214+ cmd->sess->initiator_name);
17215+ else
17216+ TRACE_DBG("Command %s (0x%x) from %s is allowed to execute",
17217+ cmd->op_name, cmd->cdb[0], cmd->sess->initiator_name);
17218+
17219+out_unlock:
17220+ scst_pr_read_unlock(dev, unlock);
17221+
17222+ TRACE_EXIT_RES(allowed);
17223+ return allowed;
17224+}
17225+
17226+/* Called with dev_pr_mutex locked, no IRQ */
17227+void scst_pr_read_keys(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
17228+{
17229+ int i, offset = 0, size, size_max;
17230+ struct scst_device *dev = cmd->dev;
17231+ struct scst_dev_registrant *reg;
17232+
17233+ TRACE_ENTRY();
17234+
17235+ if (buffer_size < 8) {
17236+ TRACE_PR("buffer_size too small: %d. expected >= 8 "
17237+ "(buffer %p)", buffer_size, buffer);
17238+ goto skip;
17239+ }
17240+
17241+ TRACE_PR("Read Keys (dev %s): PRGen %d", dev->virt_name,
17242+ dev->pr_generation);
17243+
17244+ put_unaligned(cpu_to_be32(dev->pr_generation), (__be32 *)&buffer[0]);
17245+
17246+ offset = 8;
17247+ size = 0;
17248+ size_max = buffer_size - 8;
17249+
17250+ i = 0;
17251+ list_for_each_entry(reg, &dev->dev_registrants_list,
17252+ dev_registrants_list_entry) {
17253+ if (size_max - size >= 8) {
17254+ TRACE_PR("Read Keys (dev %s): key 0x%llx",
17255+ dev->virt_name, reg->key);
17256+
17257+ WARN_ON(reg->key == 0);
17258+
17259+ put_unaligned(reg->key,
17260+ (__be64 *)&buffer[offset + 8 * i]);
17261+
17262+ offset += 8;
17263+ }
17264+ size += 8;
17265+ }
17266+
17267+ put_unaligned(cpu_to_be32(size), (__be32 *)&buffer[4]);
17268+
17269+skip:
17270+ scst_set_resp_data_len(cmd, offset);
17271+
17272+ TRACE_EXIT();
17273+ return;
17274+}
17275+
17276+/* Called with dev_pr_mutex locked, no IRQ */
17277+void scst_pr_read_reservation(struct scst_cmd *cmd, uint8_t *buffer,
17278+ int buffer_size)
17279+{
17280+ struct scst_device *dev = cmd->dev;
17281+ uint8_t b[24];
17282+ int size = 0;
17283+
17284+ TRACE_ENTRY();
17285+
17286+ if (buffer_size < 8) {
17287+ TRACE_PR("buffer_size too small: %d. expected >= 8 "
17288+ "(buffer %p)", buffer_size, buffer);
17289+ goto skip;
17290+ }
17291+
17292+ memset(b, 0, sizeof(b));
17293+
17294+ put_unaligned(cpu_to_be32(dev->pr_generation), (__be32 *)&b[0]);
17295+
17296+ if (!dev->pr_is_set) {
17297+ TRACE_PR("Read Reservation: no reservations for dev %s",
17298+ dev->virt_name);
17299+ b[4] =
17300+ b[5] =
17301+ b[6] =
17302+ b[7] = 0;
17303+
17304+ size = 8;
17305+ } else {
17306+ __be64 key = dev->pr_holder ? dev->pr_holder->key : 0;
17307+
17308+ TRACE_PR("Read Reservation: dev %s, holder %p, key 0x%llx, "
17309+ "scope %d, type %d", dev->virt_name, dev->pr_holder,
17310+ key, dev->pr_scope, dev->pr_type);
17311+
17312+ b[4] =
17313+ b[5] =
17314+ b[6] = 0;
17315+ b[7] = 0x10;
17316+
17317+ put_unaligned(key, (__be64 *)&b[8]);
17318+ b[21] = dev->pr_scope << 4 | dev->pr_type;
17319+
17320+ size = 24;
17321+ }
17322+
17323+ memset(buffer, 0, buffer_size);
17324+ memcpy(buffer, b, min(size, buffer_size));
17325+
17326+skip:
17327+ scst_set_resp_data_len(cmd, size);
17328+
17329+ TRACE_EXIT();
17330+ return;
17331+}
17332+
17333+/* Called with dev_pr_mutex locked, no IRQ */
17334+void scst_pr_report_caps(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
17335+{
17336+ int offset = 0;
17337+ unsigned int crh = 1;
17338+ unsigned int atp_c = 1;
17339+ unsigned int sip_c = 1;
17340+ unsigned int ptpl_c = 1;
17341+ struct scst_device *dev = cmd->dev;
17342+
17343+ TRACE_ENTRY();
17344+
17345+ if (buffer_size < 8) {
17346+ TRACE_PR("buffer_size too small: %d. expected >= 8 "
17347+ "(buffer %p)", buffer_size, buffer);
17348+ goto skip;
17349+ }
17350+
17351+ TRACE_PR("Reporting capabilities (dev %s): crh %x, sip_c %x, "
17352+ "atp_c %x, ptpl_c %x, pr_aptpl %x", dev->virt_name,
17353+ crh, sip_c, atp_c, ptpl_c, dev->pr_aptpl);
17354+
17355+ buffer[0] = 0;
17356+ buffer[1] = 8;
17357+
17358+ buffer[2] = crh << 4 | sip_c << 3 | atp_c << 2 | ptpl_c;
17359+ buffer[3] = (1 << 7) | (dev->pr_aptpl > 0 ? 1 : 0);
17360+
17361+ /* All commands supported */
17362+ buffer[4] = 0xEA;
17363+ buffer[5] = 0x1;
17364+
17365+ offset += 8;
17366+
17367+skip:
17368+ scst_set_resp_data_len(cmd, offset);
17369+
17370+ TRACE_EXIT();
17371+ return;
17372+}
17373+
17374+/* Called with dev_pr_mutex locked, no IRQ */
17375+void scst_pr_read_full_status(struct scst_cmd *cmd, uint8_t *buffer,
17376+ int buffer_size)
17377+{
17378+ int offset = 0, size, size_max;
17379+ struct scst_device *dev = cmd->dev;
17380+ struct scst_dev_registrant *reg;
17381+
17382+ TRACE_ENTRY();
17383+
17384+ if (buffer_size < 8)
17385+ goto skip;
17386+
17387+ put_unaligned(cpu_to_be32(dev->pr_generation), (__be32 *)&buffer[0]);
17388+ offset += 8;
17389+
17390+ size = 0;
17391+ size_max = buffer_size - 8;
17392+
17393+ list_for_each_entry(reg, &dev->dev_registrants_list,
17394+ dev_registrants_list_entry) {
17395+ int ts;
17396+ int rec_len;
17397+
17398+ ts = tid_size(reg->transport_id);
17399+ rec_len = 24 + ts;
17400+
17401+ if (size_max - size > rec_len) {
17402+ memset(&buffer[offset], 0, rec_len);
17403+
17404+ put_unaligned(reg->key, (__be64 *)(&buffer[offset]));
17405+
17406+ if (dev->pr_is_set && scst_pr_is_holder(dev, reg)) {
17407+ buffer[offset + 12] = 1;
17408+ buffer[offset + 13] = (dev->pr_scope << 8) | dev->pr_type;
17409+ }
17410+
17411+ put_unaligned(cpu_to_be16(reg->rel_tgt_id),
17412+ (__be16 *)&buffer[offset + 18]);
17413+ put_unaligned(cpu_to_be32(ts),
17414+ (__be32 *)&buffer[offset + 20]);
17415+
17416+ memcpy(&buffer[offset + 24], reg->transport_id, ts);
17417+
17418+ offset += rec_len;
17419+ }
17420+ size += rec_len;
17421+ }
17422+
17423+ put_unaligned(cpu_to_be32(size), (__be32 *)&buffer[4]);
17424+
17425+skip:
17426+ scst_set_resp_data_len(cmd, offset);
17427+
17428+ TRACE_EXIT();
17429+ return;
17430+}
17431diff -uprN orig/linux-2.6.35/drivers/scst/scst_pres.h linux-2.6.35/drivers/scst/scst_pres.h
17432--- orig/linux-2.6.35/drivers/scst/scst_pres.h
17433+++ linux-2.6.35/drivers/scst/scst_pres.h
17434@@ -0,0 +1,170 @@
17435+/*
17436+ * scst_pres.c
17437+ *
17438+ * Copyright (C) 2009 - 2010 Alexey Obitotskiy <alexeyo1@open-e.com>
17439+ * Copyright (C) 2009 - 2010 Open-E, Inc.
17440+ * Copyright (C) 2009 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
17441+ *
17442+ * This program is free software; you can redistribute it and/or
17443+ * modify it under the terms of the GNU General Public License
17444+ * as published by the Free Software Foundation, version 2
17445+ * of the License.
17446+ *
17447+ * This program is distributed in the hope that it will be useful,
17448+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17449+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17450+ * GNU General Public License for more details.
17451+ */
17452+
17453+#ifndef SCST_PRES_H_
17454+#define SCST_PRES_H_
17455+
17456+#include <linux/delay.h>
17457+
17458+#define PR_REGISTER 0x00
17459+#define PR_RESERVE 0x01
17460+#define PR_RELEASE 0x02
17461+#define PR_CLEAR 0x03
17462+#define PR_PREEMPT 0x04
17463+#define PR_PREEMPT_AND_ABORT 0x05
17464+#define PR_REGISTER_AND_IGNORE 0x06
17465+#define PR_REGISTER_AND_MOVE 0x07
17466+
17467+#define PR_READ_KEYS 0x00
17468+#define PR_READ_RESERVATION 0x01
17469+#define PR_REPORT_CAPS 0x02
17470+#define PR_READ_FULL_STATUS 0x03
17471+
17472+#define TYPE_UNSPECIFIED (-1)
17473+#define TYPE_WRITE_EXCLUSIVE 0x01
17474+#define TYPE_EXCLUSIVE_ACCESS 0x03
17475+#define TYPE_WRITE_EXCLUSIVE_REGONLY 0x05
17476+#define TYPE_EXCLUSIVE_ACCESS_REGONLY 0x06
17477+#define TYPE_WRITE_EXCLUSIVE_ALL_REG 0x07
17478+#define TYPE_EXCLUSIVE_ACCESS_ALL_REG 0x08
17479+
17480+#define SCOPE_LU 0x00
17481+
17482+static inline bool scst_pr_type_valid(uint8_t type)
17483+{
17484+ switch (type) {
17485+ case TYPE_WRITE_EXCLUSIVE:
17486+ case TYPE_EXCLUSIVE_ACCESS:
17487+ case TYPE_WRITE_EXCLUSIVE_REGONLY:
17488+ case TYPE_EXCLUSIVE_ACCESS_REGONLY:
17489+ case TYPE_WRITE_EXCLUSIVE_ALL_REG:
17490+ case TYPE_EXCLUSIVE_ACCESS_ALL_REG:
17491+ return true;
17492+ default:
17493+ return false;
17494+ }
17495+}
17496+
17497+static inline bool scst_pr_read_lock(struct scst_device *dev)
17498+{
17499+ bool unlock = false;
17500+
17501+ TRACE_ENTRY();
17502+
17503+ atomic_inc(&dev->pr_readers_count);
17504+ smp_mb__after_atomic_inc(); /* to sync with scst_pr_write_lock() */
17505+
17506+ if (unlikely(dev->pr_writer_active)) {
17507+ unlock = true;
17508+ atomic_dec(&dev->pr_readers_count);
17509+ mutex_lock(&dev->dev_pr_mutex);
17510+ }
17511+
17512+ TRACE_EXIT_RES(unlock);
17513+ return unlock;
17514+}
17515+
17516+static inline void scst_pr_read_unlock(struct scst_device *dev, bool unlock)
17517+{
17518+ TRACE_ENTRY();
17519+
17520+ if (unlikely(unlock))
17521+ mutex_unlock(&dev->dev_pr_mutex);
17522+ else {
17523+ /*
17524+ * To sync with scst_pr_write_lock(). We need it to ensure
17525+ * order of our reads with the writer's writes.
17526+ */
17527+ smp_mb__before_atomic_dec();
17528+ atomic_dec(&dev->pr_readers_count);
17529+ }
17530+
17531+ TRACE_EXIT();
17532+ return;
17533+}
17534+
17535+static inline void scst_pr_write_lock(struct scst_device *dev)
17536+{
17537+ TRACE_ENTRY();
17538+
17539+ mutex_lock(&dev->dev_pr_mutex);
17540+
17541+ dev->pr_writer_active = 1;
17542+
17543+ /* to sync with scst_pr_read_lock() and unlock() */
17544+ smp_mb();
17545+
17546+ while (atomic_read(&dev->pr_readers_count) != 0) {
17547+ TRACE_DBG("Waiting for %d readers (dev %p)",
17548+ atomic_read(&dev->pr_readers_count), dev);
17549+ msleep(1);
17550+ }
17551+
17552+ TRACE_EXIT();
17553+ return;
17554+}
17555+
17556+static inline void scst_pr_write_unlock(struct scst_device *dev)
17557+{
17558+ TRACE_ENTRY();
17559+
17560+ dev->pr_writer_active = 0;
17561+
17562+ mutex_unlock(&dev->dev_pr_mutex);
17563+
17564+ TRACE_EXIT();
17565+ return;
17566+}
17567+
17568+int scst_pr_init_dev(struct scst_device *dev);
17569+void scst_pr_clear_dev(struct scst_device *dev);
17570+
17571+int scst_pr_init_tgt_dev(struct scst_tgt_dev *tgt_dev);
17572+void scst_pr_clear_tgt_dev(struct scst_tgt_dev *tgt_dev);
17573+
17574+bool scst_pr_crh_case(struct scst_cmd *cmd);
17575+bool scst_pr_is_cmd_allowed(struct scst_cmd *cmd);
17576+
17577+void scst_pr_register(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
17578+void scst_pr_register_and_ignore(struct scst_cmd *cmd, uint8_t *buffer,
17579+ int buffer_size);
17580+void scst_pr_register_and_move(struct scst_cmd *cmd, uint8_t *buffer,
17581+ int buffer_size);
17582+void scst_pr_reserve(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
17583+void scst_pr_release(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
17584+void scst_pr_clear(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
17585+void scst_pr_preempt(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
17586+void scst_pr_preempt_and_abort(struct scst_cmd *cmd, uint8_t *buffer,
17587+ int buffer_size);
17588+
17589+void scst_pr_read_keys(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
17590+void scst_pr_read_reservation(struct scst_cmd *cmd, uint8_t *buffer,
17591+ int buffer_size);
17592+void scst_pr_report_caps(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
17593+void scst_pr_read_full_status(struct scst_cmd *cmd, uint8_t *buffer,
17594+ int buffer_size);
17595+
17596+void scst_pr_sync_device_file(struct scst_tgt_dev *tgt_dev, struct scst_cmd *cmd);
17597+
17598+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
17599+void scst_pr_dump_prs(struct scst_device *dev, bool force);
17600+#else
17601+static inline void scst_pr_dump_prs(struct scst_device *dev, bool force) {}
17602+#endif
17603+
17604+#endif /* SCST_PRES_H_ */
17605diff -uprN orig/linux-2.6.35/drivers/scst/scst_priv.h linux-2.6.35/drivers/scst/scst_priv.h
17606--- orig/linux-2.6.35/drivers/scst/scst_priv.h
17607+++ linux-2.6.35/drivers/scst/scst_priv.h
17608@@ -0,0 +1,599 @@
17609+/*
17610+ * scst_priv.h
17611+ *
17612+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
17613+ * Copyright (C) 2004 - 2005 Leonid Stoljar
17614+ * Copyright (C) 2007 - 2010 ID7 Ltd.
17615+ *
17616+ * This program is free software; you can redistribute it and/or
17617+ * modify it under the terms of the GNU General Public License
17618+ * as published by the Free Software Foundation, version 2
17619+ * of the License.
17620+ *
17621+ * This program is distributed in the hope that it will be useful,
17622+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17623+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17624+ * GNU General Public License for more details.
17625+ */
17626+
17627+#ifndef __SCST_PRIV_H
17628+#define __SCST_PRIV_H
17629+
17630+#include <linux/types.h>
17631+
17632+#include <scsi/scsi.h>
17633+#include <scsi/scsi_cmnd.h>
17634+#include <scsi/scsi_driver.h>
17635+#include <scsi/scsi_device.h>
17636+#include <scsi/scsi_host.h>
17637+
17638+#define LOG_PREFIX "scst"
17639+
17640+#include <scst/scst_debug.h>
17641+
17642+#define TRACE_RTRY 0x80000000
17643+#define TRACE_SCSI_SERIALIZING 0x40000000
17644+/** top being the edge away from the interupt */
17645+#define TRACE_SND_TOP 0x20000000
17646+#define TRACE_RCV_TOP 0x01000000
17647+/** bottom being the edge toward the interupt */
17648+#define TRACE_SND_BOT 0x08000000
17649+#define TRACE_RCV_BOT 0x04000000
17650+
17651+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
17652+#define trace_flag scst_trace_flag
17653+extern unsigned long scst_trace_flag;
17654+#endif
17655+
17656+#ifdef CONFIG_SCST_DEBUG
17657+
17658+#define SCST_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MINOR | TRACE_PID | \
17659+ TRACE_LINE | TRACE_FUNCTION | TRACE_SPECIAL | TRACE_MGMT | \
17660+ TRACE_MGMT_DEBUG | TRACE_RTRY)
17661+
17662+#define TRACE_RETRY(args...) TRACE_DBG_FLAG(TRACE_RTRY, args)
17663+#define TRACE_SN(args...) TRACE_DBG_FLAG(TRACE_SCSI_SERIALIZING, args)
17664+#define TRACE_SEND_TOP(args...) TRACE_DBG_FLAG(TRACE_SND_TOP, args)
17665+#define TRACE_RECV_TOP(args...) TRACE_DBG_FLAG(TRACE_RCV_TOP, args)
17666+#define TRACE_SEND_BOT(args...) TRACE_DBG_FLAG(TRACE_SND_BOT, args)
17667+#define TRACE_RECV_BOT(args...) TRACE_DBG_FLAG(TRACE_RCV_BOT, args)
17668+
17669+#else /* CONFIG_SCST_DEBUG */
17670+
17671+# ifdef CONFIG_SCST_TRACING
17672+#define SCST_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
17673+ TRACE_SPECIAL)
17674+# else
17675+#define SCST_DEFAULT_LOG_FLAGS 0
17676+# endif
17677+
17678+#define TRACE_RETRY(args...)
17679+#define TRACE_SN(args...)
17680+#define TRACE_SEND_TOP(args...)
17681+#define TRACE_RECV_TOP(args...)
17682+#define TRACE_SEND_BOT(args...)
17683+#define TRACE_RECV_BOT(args...)
17684+
17685+#endif
17686+
17687+/**
17688+ ** Bits for scst_flags
17689+ **/
17690+
17691+/*
17692+ * Set if new commands initialization is being suspended for a while.
17693+ * Used to let TM commands execute while preparing the suspend, since
17694+ * RESET or ABORT could be necessary to free SCSI commands.
17695+ */
17696+#define SCST_FLAG_SUSPENDING 0
17697+
17698+/* Set if new commands initialization is suspended for a while */
17699+#define SCST_FLAG_SUSPENDED 1
17700+
17701+/**
17702+ ** Return codes for cmd state process functions. Codes are the same as
17703+ ** for SCST_EXEC_* to avoid translation to them and, hence, have better code.
17704+ **/
17705+#define SCST_CMD_STATE_RES_CONT_NEXT SCST_EXEC_COMPLETED
17706+#define SCST_CMD_STATE_RES_CONT_SAME SCST_EXEC_NOT_COMPLETED
17707+#define SCST_CMD_STATE_RES_NEED_THREAD (SCST_EXEC_NOT_COMPLETED+1)
17708+
17709+/**
17710+ ** Maximum count of uncompleted commands that an initiator could
17711+ ** queue on any device. Then it will start getting TASK QUEUE FULL status.
17712+ **/
17713+#define SCST_MAX_TGT_DEV_COMMANDS 48
17714+
17715+/**
17716+ ** Maximum count of uncompleted commands that could be queued on any device.
17717+ ** Then initiators sending commands to this device will start getting
17718+ ** TASK QUEUE FULL status.
17719+ **/
17720+#define SCST_MAX_DEV_COMMANDS 256
17721+
17722+#define SCST_TGT_RETRY_TIMEOUT (3/2*HZ)
17723+
17724+/* Definitions of symbolic constants for LUN addressing method */
17725+#define SCST_LUN_ADDR_METHOD_PERIPHERAL 0
17726+#define SCST_LUN_ADDR_METHOD_FLAT 1
17727+
17728+/* Activities suspending timeout */
17729+#define SCST_SUSPENDING_TIMEOUT (90 * HZ)
17730+
17731+extern struct mutex scst_mutex2;
17732+
17733+extern int scst_threads;
17734+
17735+extern unsigned int scst_max_dev_cmd_mem;
17736+
17737+extern mempool_t *scst_mgmt_mempool;
17738+extern mempool_t *scst_mgmt_stub_mempool;
17739+extern mempool_t *scst_ua_mempool;
17740+extern mempool_t *scst_sense_mempool;
17741+extern mempool_t *scst_aen_mempool;
17742+
17743+extern struct kmem_cache *scst_cmd_cachep;
17744+extern struct kmem_cache *scst_sess_cachep;
17745+extern struct kmem_cache *scst_tgtd_cachep;
17746+extern struct kmem_cache *scst_acgd_cachep;
17747+
17748+extern spinlock_t scst_main_lock;
17749+
17750+extern struct scst_sgv_pools scst_sgv;
17751+
17752+extern unsigned long scst_flags;
17753+extern atomic_t scst_cmd_count;
17754+extern struct list_head scst_template_list;
17755+extern struct list_head scst_dev_list;
17756+extern struct list_head scst_dev_type_list;
17757+extern struct list_head scst_virtual_dev_type_list;
17758+extern wait_queue_head_t scst_dev_cmd_waitQ;
17759+
17760+extern unsigned int scst_setup_id;
17761+
17762+extern spinlock_t scst_init_lock;
17763+extern struct list_head scst_init_cmd_list;
17764+extern wait_queue_head_t scst_init_cmd_list_waitQ;
17765+extern unsigned int scst_init_poll_cnt;
17766+
17767+extern struct scst_cmd_threads scst_main_cmd_threads;
17768+
17769+extern spinlock_t scst_mcmd_lock;
17770+/* The following lists protected by scst_mcmd_lock */
17771+extern struct list_head scst_active_mgmt_cmd_list;
17772+extern struct list_head scst_delayed_mgmt_cmd_list;
17773+extern wait_queue_head_t scst_mgmt_cmd_list_waitQ;
17774+
17775+struct scst_tasklet {
17776+ spinlock_t tasklet_lock;
17777+ struct list_head tasklet_cmd_list;
17778+ struct tasklet_struct tasklet;
17779+};
17780+extern struct scst_tasklet scst_tasklets[NR_CPUS];
17781+
17782+extern wait_queue_head_t scst_mgmt_waitQ;
17783+extern spinlock_t scst_mgmt_lock;
17784+extern struct list_head scst_sess_init_list;
17785+extern struct list_head scst_sess_shut_list;
17786+
17787+struct scst_cmd_thread_t {
17788+ struct task_struct *cmd_thread;
17789+ struct list_head thread_list_entry;
17790+};
17791+
17792+static inline bool scst_set_io_context(struct scst_cmd *cmd,
17793+ struct io_context **old)
17794+{
17795+ bool res;
17796+
17797+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
17798+ return false;
17799+#endif
17800+
17801+ if (cmd->cmd_threads == &scst_main_cmd_threads) {
17802+ EXTRACHECKS_BUG_ON(in_interrupt());
17803+ /*
17804+ * No need for any ref counting action, because io_context
17805+ * supposed to be cleared in the end of the caller function.
17806+ */
17807+ current->io_context = cmd->tgt_dev->async_io_context;
17808+ res = true;
17809+ TRACE_DBG("io_context %p (tgt_dev %p)", current->io_context,
17810+ cmd->tgt_dev);
17811+ EXTRACHECKS_BUG_ON(current->io_context == NULL);
17812+ } else
17813+ res = false;
17814+
17815+ return res;
17816+}
17817+
17818+static inline void scst_reset_io_context(struct scst_tgt_dev *tgt_dev,
17819+ struct io_context *old)
17820+{
17821+ current->io_context = old;
17822+ TRACE_DBG("io_context %p reset", current->io_context);
17823+ return;
17824+}
17825+
17826+/*
17827+ * Converts string presentation of threads pool type to enum.
17828+ * Returns SCST_THREADS_POOL_TYPE_INVALID if the string is invalid.
17829+ */
17830+extern enum scst_dev_type_threads_pool_type scst_parse_threads_pool_type(
17831+ const char *p, int len);
17832+
17833+extern int scst_add_threads(struct scst_cmd_threads *cmd_threads,
17834+ struct scst_device *dev, struct scst_tgt_dev *tgt_dev, int num);
17835+extern void scst_del_threads(struct scst_cmd_threads *cmd_threads, int num);
17836+
17837+extern int scst_create_dev_threads(struct scst_device *dev);
17838+extern void scst_stop_dev_threads(struct scst_device *dev);
17839+
17840+extern int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev);
17841+extern void scst_tgt_dev_stop_threads(struct scst_tgt_dev *tgt_dev);
17842+
17843+extern bool scst_del_thr_data(struct scst_tgt_dev *tgt_dev,
17844+ struct task_struct *tsk);
17845+
17846+extern struct scst_dev_type scst_null_devtype;
17847+
17848+extern struct scst_cmd *__scst_check_deferred_commands(
17849+ struct scst_tgt_dev *tgt_dev);
17850+
17851+/* Used to save the function call on the fast path */
17852+static inline struct scst_cmd *scst_check_deferred_commands(
17853+ struct scst_tgt_dev *tgt_dev)
17854+{
17855+ if (tgt_dev->def_cmd_count == 0)
17856+ return NULL;
17857+ else
17858+ return __scst_check_deferred_commands(tgt_dev);
17859+}
17860+
17861+static inline void scst_make_deferred_commands_active(
17862+ struct scst_tgt_dev *tgt_dev)
17863+{
17864+ struct scst_cmd *c;
17865+
17866+ c = __scst_check_deferred_commands(tgt_dev);
17867+ if (c != NULL) {
17868+ TRACE_SN("Adding cmd %p to active cmd list", c);
17869+ spin_lock_irq(&c->cmd_threads->cmd_list_lock);
17870+ list_add_tail(&c->cmd_list_entry,
17871+ &c->cmd_threads->active_cmd_list);
17872+ wake_up(&c->cmd_threads->cmd_list_waitQ);
17873+ spin_unlock_irq(&c->cmd_threads->cmd_list_lock);
17874+ }
17875+
17876+ return;
17877+}
17878+
17879+void scst_inc_expected_sn(struct scst_tgt_dev *tgt_dev, atomic_t *slot);
17880+int scst_check_hq_cmd(struct scst_cmd *cmd);
17881+
17882+void scst_unblock_deferred(struct scst_tgt_dev *tgt_dev,
17883+ struct scst_cmd *cmd_sn);
17884+
17885+void scst_on_hq_cmd_response(struct scst_cmd *cmd);
17886+void scst_xmit_process_aborted_cmd(struct scst_cmd *cmd);
17887+
17888+int scst_cmd_thread(void *arg);
17889+void scst_cmd_tasklet(long p);
17890+int scst_init_thread(void *arg);
17891+int scst_tm_thread(void *arg);
17892+int scst_global_mgmt_thread(void *arg);
17893+
17894+void scst_zero_write_rest(struct scst_cmd *cmd);
17895+void scst_limit_sg_write_len(struct scst_cmd *cmd);
17896+void scst_adjust_resp_data_len(struct scst_cmd *cmd);
17897+
17898+int scst_queue_retry_cmd(struct scst_cmd *cmd, int finished_cmds);
17899+
17900+int scst_alloc_tgt(struct scst_tgt_template *tgtt, struct scst_tgt **tgt);
17901+void scst_free_tgt(struct scst_tgt *tgt);
17902+
17903+int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev);
17904+void scst_free_device(struct scst_device *dev);
17905+
17906+struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
17907+ const char *acg_name, bool tgt_acg);
17908+void scst_del_free_acg(struct scst_acg *acg);
17909+
17910+struct scst_acg *scst_tgt_find_acg(struct scst_tgt *tgt, const char *name);
17911+struct scst_acg *scst_find_acg(const struct scst_session *sess);
17912+
17913+void scst_check_reassign_sessions(void);
17914+
17915+int scst_sess_alloc_tgt_devs(struct scst_session *sess);
17916+void scst_sess_free_tgt_devs(struct scst_session *sess);
17917+void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA);
17918+
17919+int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
17920+ struct scst_device *dev, uint64_t lun, int read_only,
17921+ bool gen_scst_report_luns_changed, struct scst_acg_dev **out_acg_dev);
17922+int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
17923+ bool gen_scst_report_luns_changed);
17924+
17925+int scst_acg_add_acn(struct scst_acg *acg, const char *name);
17926+void scst_del_free_acn(struct scst_acn *acn, bool reassign);
17927+struct scst_acn *scst_find_acn(struct scst_acg *acg, const char *name);
17928+
17929+/* The activity supposed to be suspended and scst_mutex held */
17930+static inline bool scst_acg_sess_is_empty(struct scst_acg *acg)
17931+{
17932+ return list_empty(&acg->acg_sess_list);
17933+}
17934+
17935+int scst_prepare_request_sense(struct scst_cmd *orig_cmd);
17936+int scst_finish_internal_cmd(struct scst_cmd *cmd);
17937+
17938+void scst_store_sense(struct scst_cmd *cmd);
17939+
17940+int scst_assign_dev_handler(struct scst_device *dev,
17941+ struct scst_dev_type *handler);
17942+
17943+struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask,
17944+ const char *initiator_name);
17945+void scst_free_session(struct scst_session *sess);
17946+void scst_free_session_callback(struct scst_session *sess);
17947+
17948+struct scst_cmd *scst_alloc_cmd(gfp_t gfp_mask);
17949+void scst_free_cmd(struct scst_cmd *cmd);
17950+static inline void scst_destroy_cmd(struct scst_cmd *cmd)
17951+{
17952+ kmem_cache_free(scst_cmd_cachep, cmd);
17953+ return;
17954+}
17955+
17956+void scst_check_retries(struct scst_tgt *tgt);
17957+
17958+int scst_scsi_exec_async(struct scst_cmd *cmd,
17959+ void (*done)(void *, char *, int, int));
17960+
17961+int scst_alloc_space(struct scst_cmd *cmd);
17962+
17963+int scst_lib_init(void);
17964+void scst_lib_exit(void);
17965+
17966+int scst_get_full_buf(struct scst_cmd *cmd, uint8_t **buf);
17967+void scst_put_full_buf(struct scst_cmd *cmd, uint8_t *buf);
17968+
17969+__be64 scst_pack_lun(const uint64_t lun, unsigned int addr_method);
17970+uint64_t scst_unpack_lun(const uint8_t *lun, int len);
17971+
17972+struct scst_mgmt_cmd *scst_alloc_mgmt_cmd(gfp_t gfp_mask);
17973+void scst_free_mgmt_cmd(struct scst_mgmt_cmd *mcmd);
17974+void scst_done_cmd_mgmt(struct scst_cmd *cmd);
17975+
17976+static inline void scst_devt_cleanup(struct scst_dev_type *devt) { }
17977+
17978+int scst_sysfs_init(void);
17979+void scst_sysfs_cleanup(void);
17980+int scst_tgtt_sysfs_create(struct scst_tgt_template *tgtt);
17981+void scst_tgtt_sysfs_del(struct scst_tgt_template *tgtt);
17982+int scst_tgt_sysfs_create(struct scst_tgt *tgt);
17983+void scst_tgt_sysfs_prepare_put(struct scst_tgt *tgt);
17984+void scst_tgt_sysfs_del(struct scst_tgt *tgt);
17985+int scst_sess_sysfs_create(struct scst_session *sess);
17986+void scst_sess_sysfs_del(struct scst_session *sess);
17987+int scst_recreate_sess_luns_link(struct scst_session *sess);
17988+int scst_sgv_sysfs_create(struct sgv_pool *pool);
17989+void scst_sgv_sysfs_del(struct sgv_pool *pool);
17990+int scst_devt_sysfs_create(struct scst_dev_type *devt);
17991+void scst_devt_sysfs_del(struct scst_dev_type *devt);
17992+int scst_dev_sysfs_create(struct scst_device *dev);
17993+void scst_dev_sysfs_del(struct scst_device *dev);
17994+int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev);
17995+void scst_tgt_dev_sysfs_del(struct scst_tgt_dev *tgt_dev);
17996+int scst_devt_dev_sysfs_create(struct scst_device *dev);
17997+void scst_devt_dev_sysfs_del(struct scst_device *dev);
17998+int scst_acg_sysfs_create(struct scst_tgt *tgt,
17999+ struct scst_acg *acg);
18000+void scst_acg_sysfs_del(struct scst_acg *acg);
18001+int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev,
18002+ struct kobject *parent);
18003+void scst_acg_dev_sysfs_del(struct scst_acg_dev *acg_dev);
18004+int scst_acn_sysfs_create(struct scst_acn *acn);
18005+void scst_acn_sysfs_del(struct scst_acn *acn);
18006+
18007+void __scst_dev_check_set_UA(struct scst_device *dev, struct scst_cmd *exclude,
18008+ const uint8_t *sense, int sense_len);
18009+static inline void scst_dev_check_set_UA(struct scst_device *dev,
18010+ struct scst_cmd *exclude, const uint8_t *sense, int sense_len)
18011+{
18012+ spin_lock_bh(&dev->dev_lock);
18013+ __scst_dev_check_set_UA(dev, exclude, sense, sense_len);
18014+ spin_unlock_bh(&dev->dev_lock);
18015+ return;
18016+}
18017+void scst_dev_check_set_local_UA(struct scst_device *dev,
18018+ struct scst_cmd *exclude, const uint8_t *sense, int sense_len);
18019+
18020+#define SCST_SET_UA_FLAG_AT_HEAD 1
18021+#define SCST_SET_UA_FLAG_GLOBAL 2
18022+
18023+void scst_check_set_UA(struct scst_tgt_dev *tgt_dev,
18024+ const uint8_t *sense, int sense_len, int flags);
18025+int scst_set_pending_UA(struct scst_cmd *cmd);
18026+
18027+void scst_report_luns_changed(struct scst_acg *acg);
18028+
18029+void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
18030+ bool other_ini, bool call_dev_task_mgmt_fn);
18031+void scst_process_reset(struct scst_device *dev,
18032+ struct scst_session *originator, struct scst_cmd *exclude_cmd,
18033+ struct scst_mgmt_cmd *mcmd, bool setUA);
18034+
18035+bool scst_is_ua_global(const uint8_t *sense, int len);
18036+void scst_requeue_ua(struct scst_cmd *cmd);
18037+
18038+void scst_gen_aen_or_ua(struct scst_tgt_dev *tgt_dev,
18039+ int key, int asc, int ascq);
18040+
18041+static inline bool scst_is_implicit_hq(struct scst_cmd *cmd)
18042+{
18043+ return (cmd->op_flags & SCST_IMPLICIT_HQ) != 0;
18044+}
18045+
18046+/*
18047+ * Some notes on devices "blocking". Blocking means that no
18048+ * commands will go from SCST to underlying SCSI device until it
18049+ * is unblocked. But we don't care about all commands that
18050+ * already on the device.
18051+ */
18052+
18053+extern void scst_block_dev(struct scst_device *dev);
18054+extern void scst_unblock_dev(struct scst_device *dev);
18055+
18056+extern bool __scst_check_blocked_dev(struct scst_cmd *cmd);
18057+
18058+static inline bool scst_check_blocked_dev(struct scst_cmd *cmd)
18059+{
18060+ if (unlikely(cmd->dev->block_count > 0) ||
18061+ unlikely(cmd->dev->dev_double_ua_possible))
18062+ return __scst_check_blocked_dev(cmd);
18063+ else
18064+ return false;
18065+}
18066+
18067+/* No locks */
18068+static inline void scst_check_unblock_dev(struct scst_cmd *cmd)
18069+{
18070+ if (unlikely(cmd->unblock_dev)) {
18071+ TRACE_MGMT_DBG("cmd %p (tag %llu): unblocking dev %p", cmd,
18072+ (long long unsigned int)cmd->tag, cmd->dev);
18073+ cmd->unblock_dev = 0;
18074+ scst_unblock_dev(cmd->dev);
18075+ }
18076+ return;
18077+}
18078+
18079+static inline void __scst_get(void)
18080+{
18081+ atomic_inc(&scst_cmd_count);
18082+ TRACE_DBG("Incrementing scst_cmd_count(new value %d)",
18083+ atomic_read(&scst_cmd_count));
18084+ /* See comment about smp_mb() in scst_suspend_activity() */
18085+ smp_mb__after_atomic_inc();
18086+}
18087+
18088+static inline void __scst_put(void)
18089+{
18090+ int f;
18091+ f = atomic_dec_and_test(&scst_cmd_count);
18092+ /* See comment about smp_mb() in scst_suspend_activity() */
18093+ if (f && unlikely(test_bit(SCST_FLAG_SUSPENDED, &scst_flags))) {
18094+ TRACE_MGMT_DBG("%s", "Waking up scst_dev_cmd_waitQ");
18095+ wake_up_all(&scst_dev_cmd_waitQ);
18096+ }
18097+ TRACE_DBG("Decrementing scst_cmd_count(new value %d)",
18098+ atomic_read(&scst_cmd_count));
18099+}
18100+
18101+void scst_sched_session_free(struct scst_session *sess);
18102+
18103+static inline void scst_sess_get(struct scst_session *sess)
18104+{
18105+ atomic_inc(&sess->refcnt);
18106+ TRACE_DBG("Incrementing sess %p refcnt (new value %d)",
18107+ sess, atomic_read(&sess->refcnt));
18108+}
18109+
18110+static inline void scst_sess_put(struct scst_session *sess)
18111+{
18112+ TRACE_DBG("Decrementing sess %p refcnt (new value %d)",
18113+ sess, atomic_read(&sess->refcnt)-1);
18114+ if (atomic_dec_and_test(&sess->refcnt))
18115+ scst_sched_session_free(sess);
18116+}
18117+
18118+static inline void __scst_cmd_get(struct scst_cmd *cmd)
18119+{
18120+ atomic_inc(&cmd->cmd_ref);
18121+ TRACE_DBG("Incrementing cmd %p ref (new value %d)",
18122+ cmd, atomic_read(&cmd->cmd_ref));
18123+}
18124+
18125+static inline void __scst_cmd_put(struct scst_cmd *cmd)
18126+{
18127+ TRACE_DBG("Decrementing cmd %p ref (new value %d)",
18128+ cmd, atomic_read(&cmd->cmd_ref)-1);
18129+ if (atomic_dec_and_test(&cmd->cmd_ref))
18130+ scst_free_cmd(cmd);
18131+}
18132+
18133+extern void scst_throttle_cmd(struct scst_cmd *cmd);
18134+extern void scst_unthrottle_cmd(struct scst_cmd *cmd);
18135+
18136+#ifdef CONFIG_SCST_DEBUG_TM
18137+extern void tm_dbg_check_released_cmds(void);
18138+extern int tm_dbg_check_cmd(struct scst_cmd *cmd);
18139+extern void tm_dbg_release_cmd(struct scst_cmd *cmd);
18140+extern void tm_dbg_task_mgmt(struct scst_device *dev, const char *fn,
18141+ int force);
18142+extern int tm_dbg_is_release(void);
18143+#else
18144+static inline void tm_dbg_check_released_cmds(void) {}
18145+static inline int tm_dbg_check_cmd(struct scst_cmd *cmd)
18146+{
18147+ return 0;
18148+}
18149+static inline void tm_dbg_release_cmd(struct scst_cmd *cmd) {}
18150+static inline void tm_dbg_task_mgmt(struct scst_device *dev, const char *fn,
18151+ int force) {}
18152+static inline int tm_dbg_is_release(void)
18153+{
18154+ return 0;
18155+}
18156+#endif /* CONFIG_SCST_DEBUG_TM */
18157+
18158+#ifdef CONFIG_SCST_DEBUG_SN
18159+void scst_check_debug_sn(struct scst_cmd *cmd);
18160+#else
18161+static inline void scst_check_debug_sn(struct scst_cmd *cmd) {}
18162+#endif
18163+
18164+static inline int scst_sn_before(uint32_t seq1, uint32_t seq2)
18165+{
18166+ return (int32_t)(seq1-seq2) < 0;
18167+}
18168+
18169+int gen_relative_target_port_id(uint16_t *id);
18170+bool scst_is_relative_target_port_id_unique(uint16_t id,
18171+ const struct scst_tgt *t);
18172+
18173+#ifdef CONFIG_SCST_MEASURE_LATENCY
18174+
18175+void scst_set_start_time(struct scst_cmd *cmd);
18176+void scst_set_cur_start(struct scst_cmd *cmd);
18177+void scst_set_parse_time(struct scst_cmd *cmd);
18178+void scst_set_alloc_buf_time(struct scst_cmd *cmd);
18179+void scst_set_restart_waiting_time(struct scst_cmd *cmd);
18180+void scst_set_rdy_to_xfer_time(struct scst_cmd *cmd);
18181+void scst_set_pre_exec_time(struct scst_cmd *cmd);
18182+void scst_set_exec_time(struct scst_cmd *cmd);
18183+void scst_set_dev_done_time(struct scst_cmd *cmd);
18184+void scst_set_xmit_time(struct scst_cmd *cmd);
18185+void scst_set_tgt_on_free_time(struct scst_cmd *cmd);
18186+void scst_set_dev_on_free_time(struct scst_cmd *cmd);
18187+void scst_update_lat_stats(struct scst_cmd *cmd);
18188+
18189+#else
18190+
18191+static inline void scst_set_start_time(struct scst_cmd *cmd) {}
18192+static inline void scst_set_cur_start(struct scst_cmd *cmd) {}
18193+static inline void scst_set_parse_time(struct scst_cmd *cmd) {}
18194+static inline void scst_set_alloc_buf_time(struct scst_cmd *cmd) {}
18195+static inline void scst_set_restart_waiting_time(struct scst_cmd *cmd) {}
18196+static inline void scst_set_rdy_to_xfer_time(struct scst_cmd *cmd) {}
18197+static inline void scst_set_pre_exec_time(struct scst_cmd *cmd) {}
18198+static inline void scst_set_exec_time(struct scst_cmd *cmd) {}
18199+static inline void scst_set_dev_done_time(struct scst_cmd *cmd) {}
18200+static inline void scst_set_xmit_time(struct scst_cmd *cmd) {}
18201+static inline void scst_set_tgt_on_free_time(struct scst_cmd *cmd) {}
18202+static inline void scst_set_dev_on_free_time(struct scst_cmd *cmd) {}
18203+static inline void scst_update_lat_stats(struct scst_cmd *cmd) {}
18204+
18205+#endif /* CONFIG_SCST_MEASURE_LATENCY */
18206+
18207+#endif /* __SCST_PRIV_H */
18208diff -uprN orig/linux-2.6.35/drivers/scst/scst_sysfs.c linux-2.6.35/drivers/scst/scst_sysfs.c
18209--- orig/linux-2.6.35/drivers/scst/scst_sysfs.c
18210+++ linux-2.6.35/drivers/scst/scst_sysfs.c
18211@@ -0,0 +1,5292 @@
18212+/*
18213+ * scst_sysfs.c
18214+ *
18215+ * Copyright (C) 2009 Daniel Henrique Debonzi <debonzi@linux.vnet.ibm.com>
18216+ * Copyright (C) 2009 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
18217+ * Copyright (C) 2009 - 2010 ID7 Ltd.
18218+ *
18219+ * This program is free software; you can redistribute it and/or
18220+ * modify it under the terms of the GNU General Public License
18221+ * as published by the Free Software Foundation, version 2
18222+ * of the License.
18223+ *
18224+ * This program is distributed in the hope that it will be useful,
18225+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18226+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18227+ * GNU General Public License for more details.
18228+ */
18229+
18230+#include <linux/kobject.h>
18231+#include <linux/string.h>
18232+#include <linux/sysfs.h>
18233+#include <linux/module.h>
18234+#include <linux/init.h>
18235+#include <linux/ctype.h>
18236+#include <linux/slab.h>
18237+#include <linux/kthread.h>
18238+
18239+#include <scst/scst.h>
18240+#include "scst_priv.h"
18241+#include "scst_mem.h"
18242+#include "scst_pres.h"
18243+
18244+static DECLARE_COMPLETION(scst_sysfs_root_release_completion);
18245+
18246+static struct kobject scst_sysfs_root_kobj;
18247+static struct kobject *scst_targets_kobj;
18248+static struct kobject *scst_devices_kobj;
18249+static struct kobject *scst_sgv_kobj;
18250+static struct kobject *scst_handlers_kobj;
18251+
18252+static const char *scst_dev_handler_types[] = {
18253+ "Direct-access device (e.g., magnetic disk)",
18254+ "Sequential-access device (e.g., magnetic tape)",
18255+ "Printer device",
18256+ "Processor device",
18257+ "Write-once device (e.g., some optical disks)",
18258+ "CD-ROM device",
18259+ "Scanner device (obsolete)",
18260+ "Optical memory device (e.g., some optical disks)",
18261+ "Medium changer device (e.g., jukeboxes)",
18262+ "Communications device (obsolete)",
18263+ "Defined by ASC IT8 (Graphic arts pre-press devices)",
18264+ "Defined by ASC IT8 (Graphic arts pre-press devices)",
18265+ "Storage array controller device (e.g., RAID)",
18266+ "Enclosure services device",
18267+ "Simplified direct-access device (e.g., magnetic disk)",
18268+ "Optical card reader/writer device"
18269+};
18270+
18271+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
18272+
18273+static DEFINE_MUTEX(scst_log_mutex);
18274+
18275+static struct scst_trace_log scst_trace_tbl[] = {
18276+ { TRACE_OUT_OF_MEM, "out_of_mem" },
18277+ { TRACE_MINOR, "minor" },
18278+ { TRACE_SG_OP, "sg" },
18279+ { TRACE_MEMORY, "mem" },
18280+ { TRACE_BUFF, "buff" },
18281+#ifndef GENERATING_UPSTREAM_PATCH
18282+ { TRACE_ENTRYEXIT, "entryexit" },
18283+#endif
18284+ { TRACE_PID, "pid" },
18285+ { TRACE_LINE, "line" },
18286+ { TRACE_FUNCTION, "function" },
18287+ { TRACE_DEBUG, "debug" },
18288+ { TRACE_SPECIAL, "special" },
18289+ { TRACE_SCSI, "scsi" },
18290+ { TRACE_MGMT, "mgmt" },
18291+ { TRACE_MGMT_DEBUG, "mgmt_dbg" },
18292+ { TRACE_FLOW_CONTROL, "flow_control" },
18293+ { TRACE_PRES, "pr" },
18294+ { 0, NULL }
18295+};
18296+
18297+static struct scst_trace_log scst_local_trace_tbl[] = {
18298+ { TRACE_RTRY, "retry" },
18299+ { TRACE_SCSI_SERIALIZING, "scsi_serializing" },
18300+ { TRACE_RCV_BOT, "recv_bot" },
18301+ { TRACE_SND_BOT, "send_bot" },
18302+ { TRACE_RCV_TOP, "recv_top" },
18303+ { TRACE_SND_TOP, "send_top" },
18304+ { 0, NULL }
18305+};
18306+
18307+static ssize_t scst_trace_level_show(const struct scst_trace_log *local_tbl,
18308+ unsigned long log_level, char *buf, const char *help);
18309+static int scst_write_trace(const char *buf, size_t length,
18310+ unsigned long *log_level, unsigned long default_level,
18311+ const char *name, const struct scst_trace_log *tbl);
18312+
18313+#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
18314+
18315+static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
18316+ struct kobj_attribute *attr,
18317+ char *buf);
18318+static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
18319+ struct kobj_attribute *attr,
18320+ const char *buf, size_t count);
18321+static ssize_t scst_tgt_addr_method_show(struct kobject *kobj,
18322+ struct kobj_attribute *attr,
18323+ char *buf);
18324+static ssize_t scst_tgt_addr_method_store(struct kobject *kobj,
18325+ struct kobj_attribute *attr,
18326+ const char *buf, size_t count);
18327+static ssize_t scst_tgt_io_grouping_type_show(struct kobject *kobj,
18328+ struct kobj_attribute *attr,
18329+ char *buf);
18330+static ssize_t scst_tgt_io_grouping_type_store(struct kobject *kobj,
18331+ struct kobj_attribute *attr,
18332+ const char *buf, size_t count);
18333+static ssize_t scst_ini_group_mgmt_show(struct kobject *kobj,
18334+ struct kobj_attribute *attr,
18335+ char *buf);
18336+static ssize_t scst_ini_group_mgmt_store(struct kobject *kobj,
18337+ struct kobj_attribute *attr,
18338+ const char *buf, size_t count);
18339+static ssize_t scst_rel_tgt_id_show(struct kobject *kobj,
18340+ struct kobj_attribute *attr,
18341+ char *buf);
18342+static ssize_t scst_rel_tgt_id_store(struct kobject *kobj,
18343+ struct kobj_attribute *attr,
18344+ const char *buf, size_t count);
18345+static ssize_t scst_acg_luns_mgmt_store(struct kobject *kobj,
18346+ struct kobj_attribute *attr,
18347+ const char *buf, size_t count);
18348+static ssize_t scst_acg_ini_mgmt_show(struct kobject *kobj,
18349+ struct kobj_attribute *attr,
18350+ char *buf);
18351+static ssize_t scst_acg_ini_mgmt_store(struct kobject *kobj,
18352+ struct kobj_attribute *attr,
18353+ const char *buf, size_t count);
18354+static ssize_t scst_acg_addr_method_show(struct kobject *kobj,
18355+ struct kobj_attribute *attr,
18356+ char *buf);
18357+static ssize_t scst_acg_addr_method_store(struct kobject *kobj,
18358+ struct kobj_attribute *attr,
18359+ const char *buf, size_t count);
18360+static ssize_t scst_acg_io_grouping_type_show(struct kobject *kobj,
18361+ struct kobj_attribute *attr,
18362+ char *buf);
18363+static ssize_t scst_acg_io_grouping_type_store(struct kobject *kobj,
18364+ struct kobj_attribute *attr,
18365+ const char *buf, size_t count);
18366+static ssize_t scst_acn_file_show(struct kobject *kobj,
18367+ struct kobj_attribute *attr, char *buf);
18368+
18369+/**
18370+ ** Sysfs work
18371+ **/
18372+
18373+static DEFINE_SPINLOCK(sysfs_work_lock);
18374+static LIST_HEAD(sysfs_work_list);
18375+static DECLARE_WAIT_QUEUE_HEAD(sysfs_work_waitQ);
18376+static int active_sysfs_works;
18377+static int last_sysfs_work_res;
18378+static struct task_struct *sysfs_work_thread;
18379+
18380+/**
18381+ * scst_alloc_sysfs_work() - allocates a sysfs work
18382+ */
18383+int scst_alloc_sysfs_work(int (*sysfs_work_fn)(struct scst_sysfs_work_item *),
18384+ bool read_only_action, struct scst_sysfs_work_item **res_work)
18385+{
18386+ int res = 0;
18387+ struct scst_sysfs_work_item *work;
18388+
18389+ TRACE_ENTRY();
18390+
18391+ if (sysfs_work_fn == NULL) {
18392+ PRINT_ERROR("%s", "sysfs_work_fn is NULL");
18393+ res = -EINVAL;
18394+ goto out;
18395+ }
18396+
18397+ *res_work = NULL;
18398+
18399+ work = kzalloc(sizeof(*work), GFP_KERNEL);
18400+ if (work == NULL) {
18401+ PRINT_ERROR("Unable to alloc sysfs work (size %zd)",
18402+ sizeof(*work));
18403+ res = -ENOMEM;
18404+ goto out;
18405+ }
18406+
18407+ work->read_only_action = read_only_action;
18408+ kref_init(&work->sysfs_work_kref);
18409+ init_completion(&work->sysfs_work_done);
18410+ work->sysfs_work_fn = sysfs_work_fn;
18411+
18412+ *res_work = work;
18413+
18414+out:
18415+ TRACE_EXIT_RES(res);
18416+ return res;
18417+}
18418+EXPORT_SYMBOL(scst_alloc_sysfs_work);
18419+
18420+static void scst_sysfs_work_release(struct kref *kref)
18421+{
18422+ struct scst_sysfs_work_item *work;
18423+
18424+ TRACE_ENTRY();
18425+
18426+ work = container_of(kref, struct scst_sysfs_work_item,
18427+ sysfs_work_kref);
18428+
18429+ TRACE_DBG("Freeing sysfs work %p (buf %p)", work, work->buf);
18430+
18431+ kfree(work->buf);
18432+ kfree(work->res_buf);
18433+ kfree(work);
18434+
18435+ TRACE_EXIT();
18436+ return;
18437+}
18438+
18439+/**
18440+ * scst_sysfs_work_get() - increases ref counter of the sysfs work
18441+ */
18442+void scst_sysfs_work_get(struct scst_sysfs_work_item *work)
18443+{
18444+ kref_get(&work->sysfs_work_kref);
18445+}
18446+EXPORT_SYMBOL(scst_sysfs_work_get);
18447+
18448+/**
18449+ * scst_sysfs_work_put() - decreases ref counter of the sysfs work
18450+ */
18451+void scst_sysfs_work_put(struct scst_sysfs_work_item *work)
18452+{
18453+ kref_put(&work->sysfs_work_kref, scst_sysfs_work_release);
18454+}
18455+EXPORT_SYMBOL(scst_sysfs_work_put);
18456+
18457+/**
18458+ * scst_sysfs_queue_wait_work() - waits for the work to complete
18459+ *
18460+ * Returnes status of the completed work or -EAGAIN if the work not
18461+ * completed before timeout. In the latter case a user should poll
18462+ * last_sysfs_mgmt_res until it returns the result of the processing.
18463+ */
18464+int scst_sysfs_queue_wait_work(struct scst_sysfs_work_item *work)
18465+{
18466+ int res = 0, rc;
18467+ unsigned long timeout = 15*HZ;
18468+
18469+ TRACE_ENTRY();
18470+
18471+ spin_lock(&sysfs_work_lock);
18472+
18473+ TRACE_DBG("Adding sysfs work %p to the list", work);
18474+ list_add_tail(&work->sysfs_work_list_entry, &sysfs_work_list);
18475+
18476+ active_sysfs_works++;
18477+
18478+ spin_unlock(&sysfs_work_lock);
18479+
18480+ kref_get(&work->sysfs_work_kref);
18481+
18482+ wake_up(&sysfs_work_waitQ);
18483+
18484+ while (1) {
18485+ rc = wait_for_completion_interruptible_timeout(
18486+ &work->sysfs_work_done, timeout);
18487+ if (rc == 0) {
18488+ if (!mutex_is_locked(&scst_mutex)) {
18489+ TRACE_DBG("scst_mutex not locked, continue "
18490+ "waiting (work %p)", work);
18491+ timeout = 5*HZ;
18492+ continue;
18493+ }
18494+ TRACE_MGMT_DBG("Time out waiting for work %p",
18495+ work);
18496+ res = -EAGAIN;
18497+ goto out_put;
18498+ } else if (rc < 0) {
18499+ res = rc;
18500+ goto out_put;
18501+ }
18502+ break;
18503+ }
18504+
18505+ res = work->work_res;
18506+
18507+out_put:
18508+ kref_put(&work->sysfs_work_kref, scst_sysfs_work_release);
18509+
18510+ TRACE_EXIT_RES(res);
18511+ return res;
18512+}
18513+EXPORT_SYMBOL(scst_sysfs_queue_wait_work);
18514+
18515+/* Called under sysfs_work_lock and drops/reaquire it inside */
18516+static void scst_process_sysfs_works(void)
18517+{
18518+ struct scst_sysfs_work_item *work;
18519+
18520+ TRACE_ENTRY();
18521+
18522+ while (!list_empty(&sysfs_work_list)) {
18523+ work = list_entry(sysfs_work_list.next,
18524+ struct scst_sysfs_work_item, sysfs_work_list_entry);
18525+ list_del(&work->sysfs_work_list_entry);
18526+ spin_unlock(&sysfs_work_lock);
18527+
18528+ TRACE_DBG("Sysfs work %p", work);
18529+
18530+ work->work_res = work->sysfs_work_fn(work);
18531+
18532+ spin_lock(&sysfs_work_lock);
18533+ if (!work->read_only_action)
18534+ last_sysfs_work_res = work->work_res;
18535+ active_sysfs_works--;
18536+ spin_unlock(&sysfs_work_lock);
18537+
18538+ complete_all(&work->sysfs_work_done);
18539+ kref_put(&work->sysfs_work_kref, scst_sysfs_work_release);
18540+
18541+ spin_lock(&sysfs_work_lock);
18542+ }
18543+
18544+ TRACE_EXIT();
18545+ return;
18546+}
18547+
18548+static inline int test_sysfs_work_list(void)
18549+{
18550+ int res = !list_empty(&sysfs_work_list) ||
18551+ unlikely(kthread_should_stop());
18552+ return res;
18553+}
18554+
18555+static int sysfs_work_thread_fn(void *arg)
18556+{
18557+ TRACE_ENTRY();
18558+
18559+ PRINT_INFO("User interface thread started, PID %d", current->pid);
18560+
18561+ current->flags |= PF_NOFREEZE;
18562+
18563+ set_user_nice(current, -10);
18564+
18565+ spin_lock(&sysfs_work_lock);
18566+ while (!kthread_should_stop()) {
18567+ wait_queue_t wait;
18568+ init_waitqueue_entry(&wait, current);
18569+
18570+ if (!test_sysfs_work_list()) {
18571+ add_wait_queue_exclusive(&sysfs_work_waitQ, &wait);
18572+ for (;;) {
18573+ set_current_state(TASK_INTERRUPTIBLE);
18574+ if (test_sysfs_work_list())
18575+ break;
18576+ spin_unlock(&sysfs_work_lock);
18577+ schedule();
18578+ spin_lock(&sysfs_work_lock);
18579+ }
18580+ set_current_state(TASK_RUNNING);
18581+ remove_wait_queue(&sysfs_work_waitQ, &wait);
18582+ }
18583+
18584+ scst_process_sysfs_works();
18585+ }
18586+ spin_unlock(&sysfs_work_lock);
18587+
18588+ /*
18589+ * If kthread_should_stop() is true, we are guaranteed to be
18590+ * on the module unload, so both lists must be empty.
18591+ */
18592+ BUG_ON(!list_empty(&sysfs_work_list));
18593+
18594+ PRINT_INFO("User interface thread PID %d finished", current->pid);
18595+
18596+ TRACE_EXIT();
18597+ return 0;
18598+}
18599+
18600+/* No locks */
18601+static int scst_check_grab_tgtt_ptr(struct scst_tgt_template *tgtt)
18602+{
18603+ int res = 0;
18604+ struct scst_tgt_template *tt;
18605+
18606+ TRACE_ENTRY();
18607+
18608+ mutex_lock(&scst_mutex);
18609+
18610+ list_for_each_entry(tt, &scst_template_list, scst_template_list_entry) {
18611+ if (tt == tgtt) {
18612+ tgtt->tgtt_active_sysfs_works_count++;
18613+ goto out_unlock;
18614+ }
18615+ }
18616+
18617+ TRACE_DBG("Tgtt %p not found", tgtt);
18618+ res = -ENOENT;
18619+
18620+out_unlock:
18621+ mutex_unlock(&scst_mutex);
18622+
18623+ TRACE_EXIT_RES(res);
18624+ return res;
18625+}
18626+
18627+/* No locks */
18628+static void scst_ungrab_tgtt_ptr(struct scst_tgt_template *tgtt)
18629+{
18630+ TRACE_ENTRY();
18631+
18632+ mutex_lock(&scst_mutex);
18633+ tgtt->tgtt_active_sysfs_works_count--;
18634+ mutex_unlock(&scst_mutex);
18635+
18636+ TRACE_EXIT();
18637+ return;
18638+}
18639+
18640+/* scst_mutex supposed to be locked */
18641+static int scst_check_tgt_acg_ptrs(struct scst_tgt *tgt, struct scst_acg *acg)
18642+{
18643+ int res = 0;
18644+ struct scst_tgt_template *tgtt;
18645+
18646+ list_for_each_entry(tgtt, &scst_template_list, scst_template_list_entry) {
18647+ struct scst_tgt *t;
18648+ list_for_each_entry(t, &tgtt->tgt_list, tgt_list_entry) {
18649+ if (t == tgt) {
18650+ struct scst_acg *a;
18651+ if (acg == NULL)
18652+ goto out;
18653+ if (acg == tgt->default_acg)
18654+ goto out;
18655+ list_for_each_entry(a, &tgt->tgt_acg_list,
18656+ acg_list_entry) {
18657+ if (a == acg)
18658+ goto out;
18659+ }
18660+ }
18661+ }
18662+ }
18663+
18664+ TRACE_DBG("Tgt %p/ACG %p not found", tgt, acg);
18665+ res = -ENOENT;
18666+
18667+out:
18668+ TRACE_EXIT_RES(res);
18669+ return res;
18670+}
18671+
18672+/* scst_mutex supposed to be locked */
18673+static int scst_check_devt_ptr(struct scst_dev_type *devt,
18674+ struct list_head *list)
18675+{
18676+ int res = 0;
18677+ struct scst_dev_type *dt;
18678+
18679+ TRACE_ENTRY();
18680+
18681+ list_for_each_entry(dt, list, dev_type_list_entry) {
18682+ if (dt == devt)
18683+ goto out;
18684+ }
18685+
18686+ TRACE_DBG("Devt %p not found", devt);
18687+ res = -ENOENT;
18688+
18689+out:
18690+ TRACE_EXIT_RES(res);
18691+ return res;
18692+}
18693+
18694+/* scst_mutex supposed to be locked */
18695+static int scst_check_dev_ptr(struct scst_device *dev)
18696+{
18697+ int res = 0;
18698+ struct scst_device *d;
18699+
18700+ TRACE_ENTRY();
18701+
18702+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
18703+ if (d == dev)
18704+ goto out;
18705+ }
18706+
18707+ TRACE_DBG("Dev %p not found", dev);
18708+ res = -ENOENT;
18709+
18710+out:
18711+ TRACE_EXIT_RES(res);
18712+ return res;
18713+}
18714+
18715+/* No locks */
18716+static int scst_check_grab_devt_ptr(struct scst_dev_type *devt,
18717+ struct list_head *list)
18718+{
18719+ int res = 0;
18720+ struct scst_dev_type *dt;
18721+
18722+ TRACE_ENTRY();
18723+
18724+ mutex_lock(&scst_mutex);
18725+
18726+ list_for_each_entry(dt, list, dev_type_list_entry) {
18727+ if (dt == devt) {
18728+ devt->devt_active_sysfs_works_count++;
18729+ goto out_unlock;
18730+ }
18731+ }
18732+
18733+ TRACE_DBG("Devt %p not found", devt);
18734+ res = -ENOENT;
18735+
18736+out_unlock:
18737+ mutex_unlock(&scst_mutex);
18738+
18739+ TRACE_EXIT_RES(res);
18740+ return res;
18741+}
18742+
18743+/* No locks */
18744+static void scst_ungrab_devt_ptr(struct scst_dev_type *devt)
18745+{
18746+ TRACE_ENTRY();
18747+
18748+ mutex_lock(&scst_mutex);
18749+ devt->devt_active_sysfs_works_count--;
18750+ mutex_unlock(&scst_mutex);
18751+
18752+ TRACE_EXIT();
18753+ return;
18754+}
18755+
18756+/**
18757+ ** Regilar SCST sysfs ops
18758+ **/
18759+static ssize_t scst_show(struct kobject *kobj, struct attribute *attr,
18760+ char *buf)
18761+{
18762+ struct kobj_attribute *kobj_attr;
18763+ kobj_attr = container_of(attr, struct kobj_attribute, attr);
18764+
18765+ return kobj_attr->show(kobj, kobj_attr, buf);
18766+}
18767+
18768+static ssize_t scst_store(struct kobject *kobj, struct attribute *attr,
18769+ const char *buf, size_t count)
18770+{
18771+ struct kobj_attribute *kobj_attr;
18772+ kobj_attr = container_of(attr, struct kobj_attribute, attr);
18773+
18774+ if (kobj_attr->store)
18775+ return kobj_attr->store(kobj, kobj_attr, buf, count);
18776+ else
18777+ return -EIO;
18778+}
18779+
18780+static const struct sysfs_ops scst_sysfs_ops = {
18781+ .show = scst_show,
18782+ .store = scst_store,
18783+};
18784+
18785+const struct sysfs_ops *scst_sysfs_get_sysfs_ops(void)
18786+{
18787+ return &scst_sysfs_ops;
18788+}
18789+EXPORT_SYMBOL_GPL(scst_sysfs_get_sysfs_ops);
18790+
18791+/**
18792+ ** Target Template
18793+ **/
18794+
18795+static void scst_tgtt_release(struct kobject *kobj)
18796+{
18797+ struct scst_tgt_template *tgtt;
18798+
18799+ TRACE_ENTRY();
18800+
18801+ tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
18802+ complete_all(&tgtt->tgtt_kobj_release_cmpl);
18803+
18804+ TRACE_EXIT();
18805+ return;
18806+}
18807+
18808+static struct kobj_type tgtt_ktype = {
18809+ .sysfs_ops = &scst_sysfs_ops,
18810+ .release = scst_tgtt_release,
18811+};
18812+
18813+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
18814+
18815+static ssize_t scst_tgtt_trace_level_show(struct kobject *kobj,
18816+ struct kobj_attribute *attr, char *buf)
18817+{
18818+ struct scst_tgt_template *tgtt;
18819+
18820+ tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
18821+
18822+ return scst_trace_level_show(tgtt->trace_tbl,
18823+ tgtt->trace_flags ? *tgtt->trace_flags : 0, buf,
18824+ tgtt->trace_tbl_help);
18825+}
18826+
18827+static ssize_t scst_tgtt_trace_level_store(struct kobject *kobj,
18828+ struct kobj_attribute *attr, const char *buf, size_t count)
18829+{
18830+ int res;
18831+ struct scst_tgt_template *tgtt;
18832+
18833+ TRACE_ENTRY();
18834+
18835+ tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
18836+
18837+ if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
18838+ res = -EINTR;
18839+ goto out;
18840+ }
18841+
18842+ res = scst_write_trace(buf, count, tgtt->trace_flags,
18843+ tgtt->default_trace_flags, tgtt->name, tgtt->trace_tbl);
18844+
18845+ mutex_unlock(&scst_log_mutex);
18846+
18847+out:
18848+ TRACE_EXIT_RES(res);
18849+ return res;
18850+}
18851+
18852+static struct kobj_attribute tgtt_trace_attr =
18853+ __ATTR(trace_level, S_IRUGO | S_IWUSR,
18854+ scst_tgtt_trace_level_show, scst_tgtt_trace_level_store);
18855+
18856+#endif /* #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
18857+
18858+static ssize_t scst_tgtt_mgmt_show(struct kobject *kobj,
18859+ struct kobj_attribute *attr, char *buf)
18860+{
18861+char *help = "Usage: echo \"add_target target_name [parameters]\" "
18862+ ">mgmt\n"
18863+ " echo \"del_target target_name\" >mgmt\n"
18864+ "%s%s"
18865+ "%s"
18866+ "\n"
18867+ "where parameters are one or more "
18868+ "param_name=value pairs separated by ';'\n\n"
18869+ "%s%s%s%s%s%s%s%s\n";
18870+ struct scst_tgt_template *tgtt;
18871+
18872+ tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
18873+
18874+ return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, help,
18875+ (tgtt->tgtt_optional_attributes != NULL) ?
18876+ " echo \"add_attribute <attribute> <value>\" >mgmt\n"
18877+ " echo \"del_attribute <attribute> <value>\" >mgmt\n" : "",
18878+ (tgtt->tgt_optional_attributes != NULL) ?
18879+ " echo \"add_target_attribute target_name <attribute> <value>\" >mgmt\n"
18880+ " echo \"del_target_attribute target_name <attribute> <value>\" >mgmt\n" : "",
18881+ (tgtt->mgmt_cmd_help) ? tgtt->mgmt_cmd_help : "",
18882+ (tgtt->add_target_parameters != NULL) ?
18883+ "The following parameters available: " : "",
18884+ (tgtt->add_target_parameters != NULL) ?
18885+ tgtt->add_target_parameters : "",
18886+ (tgtt->tgtt_optional_attributes != NULL) ?
18887+ "The following target driver attributes available: " : "",
18888+ (tgtt->tgtt_optional_attributes != NULL) ?
18889+ tgtt->tgtt_optional_attributes : "",
18890+ (tgtt->tgtt_optional_attributes != NULL) ? "\n" : "",
18891+ (tgtt->tgt_optional_attributes != NULL) ?
18892+ "The following target attributes available: " : "",
18893+ (tgtt->tgt_optional_attributes != NULL) ?
18894+ tgtt->tgt_optional_attributes : "",
18895+ (tgtt->tgt_optional_attributes != NULL) ? "\n" : "");
18896+}
18897+
18898+static int scst_process_tgtt_mgmt_store(char *buffer,
18899+ struct scst_tgt_template *tgtt)
18900+{
18901+ int res = 0;
18902+ char *p, *pp, *target_name;
18903+
18904+ TRACE_ENTRY();
18905+
18906+ TRACE_DBG("buffer %s", buffer);
18907+
18908+ /* Check if our pointer is still alive and, if yes, grab it */
18909+ if (scst_check_grab_tgtt_ptr(tgtt) != 0)
18910+ goto out;
18911+
18912+ pp = buffer;
18913+ if (pp[strlen(pp) - 1] == '\n')
18914+ pp[strlen(pp) - 1] = '\0';
18915+
18916+ p = scst_get_next_lexem(&pp);
18917+
18918+ if (strcasecmp("add_target", p) == 0) {
18919+ target_name = scst_get_next_lexem(&pp);
18920+ if (*target_name == '\0') {
18921+ PRINT_ERROR("%s", "Target name required");
18922+ res = -EINVAL;
18923+ goto out_ungrab;
18924+ }
18925+ res = tgtt->add_target(target_name, pp);
18926+ } else if (strcasecmp("del_target", p) == 0) {
18927+ target_name = scst_get_next_lexem(&pp);
18928+ if (*target_name == '\0') {
18929+ PRINT_ERROR("%s", "Target name required");
18930+ res = -EINVAL;
18931+ goto out_ungrab;
18932+ }
18933+
18934+ p = scst_get_next_lexem(&pp);
18935+ if (*p != '\0')
18936+ goto out_syntax_err;
18937+
18938+ res = tgtt->del_target(target_name);
18939+ } else if (tgtt->mgmt_cmd != NULL) {
18940+ scst_restore_token_str(p, pp);
18941+ res = tgtt->mgmt_cmd(buffer);
18942+ } else {
18943+ PRINT_ERROR("Unknown action \"%s\"", p);
18944+ res = -EINVAL;
18945+ goto out_ungrab;
18946+ }
18947+
18948+out_ungrab:
18949+ scst_ungrab_tgtt_ptr(tgtt);
18950+
18951+out:
18952+ TRACE_EXIT_RES(res);
18953+ return res;
18954+
18955+out_syntax_err:
18956+ PRINT_ERROR("Syntax error on \"%s\"", p);
18957+ res = -EINVAL;
18958+ goto out_ungrab;
18959+}
18960+
18961+static int scst_tgtt_mgmt_store_work_fn(struct scst_sysfs_work_item *work)
18962+{
18963+ return scst_process_tgtt_mgmt_store(work->buf, work->tgtt);
18964+}
18965+
18966+static ssize_t scst_tgtt_mgmt_store(struct kobject *kobj,
18967+ struct kobj_attribute *attr, const char *buf, size_t count)
18968+{
18969+ int res;
18970+ char *buffer;
18971+ struct scst_sysfs_work_item *work;
18972+ struct scst_tgt_template *tgtt;
18973+
18974+ TRACE_ENTRY();
18975+
18976+ tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
18977+
18978+ buffer = kzalloc(count+1, GFP_KERNEL);
18979+ if (buffer == NULL) {
18980+ res = -ENOMEM;
18981+ goto out;
18982+ }
18983+ memcpy(buffer, buf, count);
18984+ buffer[count] = '\0';
18985+
18986+ res = scst_alloc_sysfs_work(scst_tgtt_mgmt_store_work_fn, false, &work);
18987+ if (res != 0)
18988+ goto out_free;
18989+
18990+ work->buf = buffer;
18991+ work->tgtt = tgtt;
18992+
18993+ res = scst_sysfs_queue_wait_work(work);
18994+ if (res == 0)
18995+ res = count;
18996+
18997+out:
18998+ TRACE_EXIT_RES(res);
18999+ return res;
19000+
19001+out_free:
19002+ kfree(buffer);
19003+ goto out;
19004+}
19005+
19006+static struct kobj_attribute scst_tgtt_mgmt =
19007+ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_tgtt_mgmt_show,
19008+ scst_tgtt_mgmt_store);
19009+
19010+int scst_tgtt_sysfs_create(struct scst_tgt_template *tgtt)
19011+{
19012+ int res = 0;
19013+ const struct attribute **pattr;
19014+
19015+ TRACE_ENTRY();
19016+
19017+ init_completion(&tgtt->tgtt_kobj_release_cmpl);
19018+
19019+ res = kobject_init_and_add(&tgtt->tgtt_kobj, &tgtt_ktype,
19020+ scst_targets_kobj, tgtt->name);
19021+ if (res != 0) {
19022+ PRINT_ERROR("Can't add tgtt %s to sysfs", tgtt->name);
19023+ goto out;
19024+ }
19025+
19026+ if (tgtt->add_target != NULL) {
19027+ res = sysfs_create_file(&tgtt->tgtt_kobj,
19028+ &scst_tgtt_mgmt.attr);
19029+ if (res != 0) {
19030+ PRINT_ERROR("Can't add mgmt attr for target driver %s",
19031+ tgtt->name);
19032+ goto out_del;
19033+ }
19034+ }
19035+
19036+ pattr = tgtt->tgtt_attrs;
19037+ if (pattr != NULL) {
19038+ while (*pattr != NULL) {
19039+ TRACE_DBG("Creating attr %s for target driver %s",
19040+ (*pattr)->name, tgtt->name);
19041+ res = sysfs_create_file(&tgtt->tgtt_kobj, *pattr);
19042+ if (res != 0) {
19043+ PRINT_ERROR("Can't add attr %s for target "
19044+ "driver %s", (*pattr)->name,
19045+ tgtt->name);
19046+ goto out_del;
19047+ }
19048+ pattr++;
19049+ }
19050+ }
19051+
19052+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
19053+ if (tgtt->trace_flags != NULL) {
19054+ res = sysfs_create_file(&tgtt->tgtt_kobj,
19055+ &tgtt_trace_attr.attr);
19056+ if (res != 0) {
19057+ PRINT_ERROR("Can't add trace_flag for target "
19058+ "driver %s", tgtt->name);
19059+ goto out_del;
19060+ }
19061+ }
19062+#endif
19063+
19064+out:
19065+ TRACE_EXIT_RES(res);
19066+ return res;
19067+
19068+out_del:
19069+ scst_tgtt_sysfs_del(tgtt);
19070+ goto out;
19071+}
19072+
19073+/*
19074+ * Must not be called under scst_mutex, due to possible deadlock with
19075+ * sysfs ref counting in sysfs works (it is waiting for the last put, but
19076+ * the last ref counter holder is waiting for scst_mutex)
19077+ */
19078+void scst_tgtt_sysfs_del(struct scst_tgt_template *tgtt)
19079+{
19080+ int rc;
19081+
19082+ TRACE_ENTRY();
19083+
19084+ kobject_del(&tgtt->tgtt_kobj);
19085+ kobject_put(&tgtt->tgtt_kobj);
19086+
19087+ rc = wait_for_completion_timeout(&tgtt->tgtt_kobj_release_cmpl, HZ);
19088+ if (rc == 0) {
19089+ PRINT_INFO("Waiting for releasing sysfs entry "
19090+ "for target template %s (%d refs)...", tgtt->name,
19091+ atomic_read(&tgtt->tgtt_kobj.kref.refcount));
19092+ wait_for_completion(&tgtt->tgtt_kobj_release_cmpl);
19093+ PRINT_INFO("Done waiting for releasing sysfs "
19094+ "entry for target template %s", tgtt->name);
19095+ }
19096+
19097+ TRACE_EXIT();
19098+ return;
19099+}
19100+
19101+/**
19102+ ** Target directory implementation
19103+ **/
19104+
19105+static void scst_tgt_release(struct kobject *kobj)
19106+{
19107+ struct scst_tgt *tgt;
19108+
19109+ TRACE_ENTRY();
19110+
19111+ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
19112+ complete_all(&tgt->tgt_kobj_release_cmpl);
19113+
19114+ TRACE_EXIT();
19115+ return;
19116+}
19117+
19118+static struct kobj_type tgt_ktype = {
19119+ .sysfs_ops = &scst_sysfs_ops,
19120+ .release = scst_tgt_release,
19121+};
19122+
19123+static void scst_acg_release(struct kobject *kobj)
19124+{
19125+ struct scst_acg *acg;
19126+
19127+ TRACE_ENTRY();
19128+
19129+ acg = container_of(kobj, struct scst_acg, acg_kobj);
19130+ complete_all(&acg->acg_kobj_release_cmpl);
19131+
19132+ TRACE_EXIT();
19133+ return;
19134+}
19135+
19136+static struct kobj_type acg_ktype = {
19137+ .sysfs_ops = &scst_sysfs_ops,
19138+ .release = scst_acg_release,
19139+};
19140+
19141+static struct kobj_attribute scst_luns_mgmt =
19142+ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_luns_mgmt_show,
19143+ scst_luns_mgmt_store);
19144+
19145+static struct kobj_attribute scst_acg_luns_mgmt =
19146+ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_luns_mgmt_show,
19147+ scst_acg_luns_mgmt_store);
19148+
19149+static struct kobj_attribute scst_acg_ini_mgmt =
19150+ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_acg_ini_mgmt_show,
19151+ scst_acg_ini_mgmt_store);
19152+
19153+static struct kobj_attribute scst_ini_group_mgmt =
19154+ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_ini_group_mgmt_show,
19155+ scst_ini_group_mgmt_store);
19156+
19157+static struct kobj_attribute scst_tgt_addr_method =
19158+ __ATTR(addr_method, S_IRUGO | S_IWUSR, scst_tgt_addr_method_show,
19159+ scst_tgt_addr_method_store);
19160+
19161+static struct kobj_attribute scst_tgt_io_grouping_type =
19162+ __ATTR(io_grouping_type, S_IRUGO | S_IWUSR,
19163+ scst_tgt_io_grouping_type_show,
19164+ scst_tgt_io_grouping_type_store);
19165+
19166+static struct kobj_attribute scst_rel_tgt_id =
19167+ __ATTR(rel_tgt_id, S_IRUGO | S_IWUSR, scst_rel_tgt_id_show,
19168+ scst_rel_tgt_id_store);
19169+
19170+static struct kobj_attribute scst_acg_addr_method =
19171+ __ATTR(addr_method, S_IRUGO | S_IWUSR, scst_acg_addr_method_show,
19172+ scst_acg_addr_method_store);
19173+
19174+static struct kobj_attribute scst_acg_io_grouping_type =
19175+ __ATTR(io_grouping_type, S_IRUGO | S_IWUSR,
19176+ scst_acg_io_grouping_type_show,
19177+ scst_acg_io_grouping_type_store);
19178+
19179+static ssize_t scst_tgt_enable_show(struct kobject *kobj,
19180+ struct kobj_attribute *attr, char *buf)
19181+{
19182+ struct scst_tgt *tgt;
19183+ int res;
19184+ bool enabled;
19185+
19186+ TRACE_ENTRY();
19187+
19188+ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
19189+
19190+ enabled = tgt->tgtt->is_target_enabled(tgt);
19191+
19192+ res = sprintf(buf, "%d\n", enabled ? 1 : 0);
19193+
19194+ TRACE_EXIT_RES(res);
19195+ return res;
19196+}
19197+
19198+static int scst_process_tgt_enable_store(struct scst_tgt *tgt, bool enable)
19199+{
19200+ int res;
19201+
19202+ TRACE_ENTRY();
19203+
19204+ /* Tgt protected by kobject reference */
19205+
19206+ TRACE_DBG("tgt %s, enable %d", tgt->tgt_name, enable);
19207+
19208+ if (enable) {
19209+ if (tgt->rel_tgt_id == 0) {
19210+ res = gen_relative_target_port_id(&tgt->rel_tgt_id);
19211+ if (res != 0)
19212+ goto out_put;
19213+ PRINT_INFO("Using autogenerated rel ID %d for target "
19214+ "%s", tgt->rel_tgt_id, tgt->tgt_name);
19215+ } else {
19216+ if (!scst_is_relative_target_port_id_unique(
19217+ tgt->rel_tgt_id, tgt)) {
19218+ PRINT_ERROR("Relative port id %d is not unique",
19219+ tgt->rel_tgt_id);
19220+ res = -EBADSLT;
19221+ goto out_put;
19222+ }
19223+ }
19224+ }
19225+
19226+ res = tgt->tgtt->enable_target(tgt, enable);
19227+
19228+out_put:
19229+ kobject_put(&tgt->tgt_kobj);
19230+
19231+ TRACE_EXIT_RES(res);
19232+ return res;
19233+}
19234+
19235+static int scst_tgt_enable_store_work_fn(struct scst_sysfs_work_item *work)
19236+{
19237+ return scst_process_tgt_enable_store(work->tgt, work->enable);
19238+}
19239+
19240+static ssize_t scst_tgt_enable_store(struct kobject *kobj,
19241+ struct kobj_attribute *attr, const char *buf, size_t count)
19242+{
19243+ int res;
19244+ struct scst_tgt *tgt;
19245+ bool enable;
19246+ struct scst_sysfs_work_item *work;
19247+
19248+ TRACE_ENTRY();
19249+
19250+ if (buf == NULL) {
19251+ PRINT_ERROR("%s: NULL buffer?", __func__);
19252+ res = -EINVAL;
19253+ goto out;
19254+ }
19255+
19256+ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
19257+
19258+ switch (buf[0]) {
19259+ case '0':
19260+ enable = false;
19261+ break;
19262+ case '1':
19263+ enable = true;
19264+ break;
19265+ default:
19266+ PRINT_ERROR("%s: Requested action not understood: %s",
19267+ __func__, buf);
19268+ res = -EINVAL;
19269+ goto out;
19270+ }
19271+
19272+ res = scst_alloc_sysfs_work(scst_tgt_enable_store_work_fn, false,
19273+ &work);
19274+ if (res != 0)
19275+ goto out;
19276+
19277+ work->tgt = tgt;
19278+ work->enable = enable;
19279+
19280+ kobject_get(&tgt->tgt_kobj);
19281+
19282+ res = scst_sysfs_queue_wait_work(work);
19283+ if (res == 0)
19284+ res = count;
19285+
19286+out:
19287+ TRACE_EXIT_RES(res);
19288+ return res;
19289+}
19290+
19291+static struct kobj_attribute tgt_enable_attr =
19292+ __ATTR(enabled, S_IRUGO | S_IWUSR,
19293+ scst_tgt_enable_show, scst_tgt_enable_store);
19294+
19295+/*
19296+ * Supposed to be called under scst_mutex. In case of error will drop,
19297+ * then reacquire it.
19298+ */
19299+int scst_tgt_sysfs_create(struct scst_tgt *tgt)
19300+{
19301+ int res;
19302+ const struct attribute **pattr;
19303+
19304+ TRACE_ENTRY();
19305+
19306+ init_completion(&tgt->tgt_kobj_release_cmpl);
19307+
19308+ res = kobject_init_and_add(&tgt->tgt_kobj, &tgt_ktype,
19309+ &tgt->tgtt->tgtt_kobj, tgt->tgt_name);
19310+ if (res != 0) {
19311+ PRINT_ERROR("Can't add tgt %s to sysfs", tgt->tgt_name);
19312+ goto out;
19313+ }
19314+
19315+ if ((tgt->tgtt->enable_target != NULL) &&
19316+ (tgt->tgtt->is_target_enabled != NULL)) {
19317+ res = sysfs_create_file(&tgt->tgt_kobj,
19318+ &tgt_enable_attr.attr);
19319+ if (res != 0) {
19320+ PRINT_ERROR("Can't add attr %s to sysfs",
19321+ tgt_enable_attr.attr.name);
19322+ goto out_err;
19323+ }
19324+ }
19325+
19326+ tgt->tgt_sess_kobj = kobject_create_and_add("sessions", &tgt->tgt_kobj);
19327+ if (tgt->tgt_sess_kobj == NULL) {
19328+ PRINT_ERROR("Can't create sess kobj for tgt %s", tgt->tgt_name);
19329+ goto out_nomem;
19330+ }
19331+
19332+ tgt->tgt_luns_kobj = kobject_create_and_add("luns", &tgt->tgt_kobj);
19333+ if (tgt->tgt_luns_kobj == NULL) {
19334+ PRINT_ERROR("Can't create luns kobj for tgt %s", tgt->tgt_name);
19335+ goto out_nomem;
19336+ }
19337+
19338+ res = sysfs_create_file(tgt->tgt_luns_kobj, &scst_luns_mgmt.attr);
19339+ if (res != 0) {
19340+ PRINT_ERROR("Can't add attribute %s for tgt %s",
19341+ scst_luns_mgmt.attr.name, tgt->tgt_name);
19342+ goto out_err;
19343+ }
19344+
19345+ tgt->tgt_ini_grp_kobj = kobject_create_and_add("ini_groups",
19346+ &tgt->tgt_kobj);
19347+ if (tgt->tgt_ini_grp_kobj == NULL) {
19348+ PRINT_ERROR("Can't create ini_grp kobj for tgt %s",
19349+ tgt->tgt_name);
19350+ goto out_nomem;
19351+ }
19352+
19353+ res = sysfs_create_file(tgt->tgt_ini_grp_kobj,
19354+ &scst_ini_group_mgmt.attr);
19355+ if (res != 0) {
19356+ PRINT_ERROR("Can't add attribute %s for tgt %s",
19357+ scst_ini_group_mgmt.attr.name, tgt->tgt_name);
19358+ goto out_err;
19359+ }
19360+
19361+ res = sysfs_create_file(&tgt->tgt_kobj,
19362+ &scst_rel_tgt_id.attr);
19363+ if (res != 0) {
19364+ PRINT_ERROR("Can't add attribute %s for tgt %s",
19365+ scst_rel_tgt_id.attr.name, tgt->tgt_name);
19366+ goto out_err;
19367+ }
19368+
19369+ res = sysfs_create_file(&tgt->tgt_kobj,
19370+ &scst_tgt_addr_method.attr);
19371+ if (res != 0) {
19372+ PRINT_ERROR("Can't add attribute %s for tgt %s",
19373+ scst_tgt_addr_method.attr.name, tgt->tgt_name);
19374+ goto out_err;
19375+ }
19376+
19377+ res = sysfs_create_file(&tgt->tgt_kobj,
19378+ &scst_tgt_io_grouping_type.attr);
19379+ if (res != 0) {
19380+ PRINT_ERROR("Can't add attribute %s for tgt %s",
19381+ scst_tgt_io_grouping_type.attr.name, tgt->tgt_name);
19382+ goto out_err;
19383+ }
19384+
19385+ pattr = tgt->tgtt->tgt_attrs;
19386+ if (pattr != NULL) {
19387+ while (*pattr != NULL) {
19388+ TRACE_DBG("Creating attr %s for tgt %s", (*pattr)->name,
19389+ tgt->tgt_name);
19390+ res = sysfs_create_file(&tgt->tgt_kobj, *pattr);
19391+ if (res != 0) {
19392+ PRINT_ERROR("Can't add tgt attr %s for tgt %s",
19393+ (*pattr)->name, tgt->tgt_name);
19394+ goto out_err;
19395+ }
19396+ pattr++;
19397+ }
19398+ }
19399+
19400+out:
19401+ TRACE_EXIT_RES(res);
19402+ return res;
19403+
19404+out_nomem:
19405+ res = -ENOMEM;
19406+
19407+out_err:
19408+ mutex_unlock(&scst_mutex);
19409+ scst_tgt_sysfs_del(tgt);
19410+ mutex_lock(&scst_mutex);
19411+ goto out;
19412+}
19413+
19414+/*
19415+ * Must not be called under scst_mutex, due to possible deadlock with
19416+ * sysfs ref counting in sysfs works (it is waiting for the last put, but
19417+ * the last ref counter holder is waiting for scst_mutex)
19418+ */
19419+void scst_tgt_sysfs_del(struct scst_tgt *tgt)
19420+{
19421+ int rc;
19422+
19423+ TRACE_ENTRY();
19424+
19425+ kobject_del(tgt->tgt_sess_kobj);
19426+ kobject_del(tgt->tgt_luns_kobj);
19427+ kobject_del(tgt->tgt_ini_grp_kobj);
19428+ kobject_del(&tgt->tgt_kobj);
19429+
19430+ kobject_put(tgt->tgt_sess_kobj);
19431+ kobject_put(tgt->tgt_luns_kobj);
19432+ kobject_put(tgt->tgt_ini_grp_kobj);
19433+ kobject_put(&tgt->tgt_kobj);
19434+
19435+ rc = wait_for_completion_timeout(&tgt->tgt_kobj_release_cmpl, HZ);
19436+ if (rc == 0) {
19437+ PRINT_INFO("Waiting for releasing sysfs entry "
19438+ "for target %s (%d refs)...", tgt->tgt_name,
19439+ atomic_read(&tgt->tgt_kobj.kref.refcount));
19440+ wait_for_completion(&tgt->tgt_kobj_release_cmpl);
19441+ PRINT_INFO("Done waiting for releasing sysfs "
19442+ "entry for target %s", tgt->tgt_name);
19443+ }
19444+
19445+ TRACE_EXIT();
19446+ return;
19447+}
19448+
19449+/**
19450+ ** Devices directory implementation
19451+ **/
19452+
19453+static ssize_t scst_dev_sysfs_type_show(struct kobject *kobj,
19454+ struct kobj_attribute *attr, char *buf)
19455+{
19456+ int pos = 0;
19457+
19458+ struct scst_device *dev;
19459+
19460+ dev = container_of(kobj, struct scst_device, dev_kobj);
19461+
19462+ pos = sprintf(buf, "%d - %s\n", dev->type,
19463+ (unsigned)dev->type > ARRAY_SIZE(scst_dev_handler_types) ?
19464+ "unknown" : scst_dev_handler_types[dev->type]);
19465+
19466+ return pos;
19467+}
19468+
19469+static struct kobj_attribute dev_type_attr =
19470+ __ATTR(type, S_IRUGO, scst_dev_sysfs_type_show, NULL);
19471+
19472+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
19473+
19474+static ssize_t scst_dev_sysfs_dump_prs(struct kobject *kobj,
19475+ struct kobj_attribute *attr, const char *buf, size_t count)
19476+{
19477+ struct scst_device *dev;
19478+
19479+ TRACE_ENTRY();
19480+
19481+ dev = container_of(kobj, struct scst_device, dev_kobj);
19482+
19483+ scst_pr_dump_prs(dev, true);
19484+
19485+ TRACE_EXIT_RES(count);
19486+ return count;
19487+}
19488+
19489+static struct kobj_attribute dev_dump_prs_attr =
19490+ __ATTR(dump_prs, S_IWUSR, NULL, scst_dev_sysfs_dump_prs);
19491+
19492+#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
19493+
19494+static int scst_process_dev_sysfs_threads_data_store(
19495+ struct scst_device *dev, int threads_num,
19496+ enum scst_dev_type_threads_pool_type threads_pool_type)
19497+{
19498+ int res = 0;
19499+ int oldtn = dev->threads_num;
19500+ enum scst_dev_type_threads_pool_type oldtt = dev->threads_pool_type;
19501+
19502+ TRACE_ENTRY();
19503+
19504+ TRACE_DBG("dev %p, threads_num %d, threads_pool_type %d", dev,
19505+ threads_num, threads_pool_type);
19506+
19507+ res = scst_suspend_activity(true);
19508+ if (res != 0)
19509+ goto out;
19510+
19511+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
19512+ res = -EINTR;
19513+ goto out_resume;
19514+ }
19515+
19516+ /* Check if our pointer is still alive */
19517+ if (scst_check_dev_ptr(dev) != 0)
19518+ goto out_unlock;
19519+
19520+ scst_stop_dev_threads(dev);
19521+
19522+ dev->threads_num = threads_num;
19523+ dev->threads_pool_type = threads_pool_type;
19524+
19525+ res = scst_create_dev_threads(dev);
19526+ if (res != 0)
19527+ goto out_unlock;
19528+
19529+ if (oldtn != dev->threads_num)
19530+ PRINT_INFO("Changed cmd threads num to %d", dev->threads_num);
19531+ else if (oldtt != dev->threads_pool_type)
19532+ PRINT_INFO("Changed cmd threads pool type to %d",
19533+ dev->threads_pool_type);
19534+
19535+out_unlock:
19536+ mutex_unlock(&scst_mutex);
19537+
19538+out_resume:
19539+ scst_resume_activity();
19540+
19541+out:
19542+ TRACE_EXIT_RES(res);
19543+ return res;
19544+}
19545+
19546+static int scst_dev_sysfs_threads_data_store_work_fn(
19547+ struct scst_sysfs_work_item *work)
19548+{
19549+ return scst_process_dev_sysfs_threads_data_store(work->dev,
19550+ work->new_threads_num, work->new_threads_pool_type);
19551+}
19552+
19553+static ssize_t scst_dev_sysfs_check_threads_data(
19554+ struct scst_device *dev, int threads_num,
19555+ enum scst_dev_type_threads_pool_type threads_pool_type, bool *stop)
19556+{
19557+ int res = 0;
19558+
19559+ *stop = false;
19560+
19561+ if (dev->threads_num < 0) {
19562+ PRINT_ERROR("Threads pool disabled for device %s",
19563+ dev->virt_name);
19564+ res = -EPERM;
19565+ goto out;
19566+ }
19567+
19568+ if ((threads_num == dev->threads_num) &&
19569+ (threads_pool_type == dev->threads_pool_type)) {
19570+ *stop = true;
19571+ goto out;
19572+ }
19573+
19574+out:
19575+ return res;
19576+}
19577+
19578+static ssize_t scst_dev_sysfs_threads_num_show(struct kobject *kobj,
19579+ struct kobj_attribute *attr, char *buf)
19580+{
19581+ int pos = 0;
19582+ struct scst_device *dev;
19583+
19584+ TRACE_ENTRY();
19585+
19586+ dev = container_of(kobj, struct scst_device, dev_kobj);
19587+
19588+ pos = sprintf(buf, "%d\n%s", dev->threads_num,
19589+ (dev->threads_num != dev->handler->threads_num) ?
19590+ SCST_SYSFS_KEY_MARK "\n" : "");
19591+
19592+ TRACE_EXIT_RES(pos);
19593+ return pos;
19594+}
19595+
19596+static ssize_t scst_dev_sysfs_threads_num_store(struct kobject *kobj,
19597+ struct kobj_attribute *attr, const char *buf, size_t count)
19598+{
19599+ int res;
19600+ struct scst_device *dev;
19601+ long newtn;
19602+ bool stop;
19603+ struct scst_sysfs_work_item *work;
19604+
19605+ TRACE_ENTRY();
19606+
19607+ dev = container_of(kobj, struct scst_device, dev_kobj);
19608+
19609+ res = strict_strtol(buf, 0, &newtn);
19610+ if (res != 0) {
19611+ PRINT_ERROR("strict_strtol() for %s failed: %d ", buf, res);
19612+ goto out;
19613+ }
19614+ if (newtn < 0) {
19615+ PRINT_ERROR("Illegal threads num value %ld", newtn);
19616+ res = -EINVAL;
19617+ goto out;
19618+ }
19619+
19620+ res = scst_dev_sysfs_check_threads_data(dev, newtn,
19621+ dev->threads_pool_type, &stop);
19622+ if ((res != 0) || stop)
19623+ goto out;
19624+
19625+ res = scst_alloc_sysfs_work(scst_dev_sysfs_threads_data_store_work_fn,
19626+ false, &work);
19627+ if (res != 0)
19628+ goto out;
19629+
19630+ work->dev = dev;
19631+ work->new_threads_num = newtn;
19632+ work->new_threads_pool_type = dev->threads_pool_type;
19633+
19634+ res = scst_sysfs_queue_wait_work(work);
19635+ if (res == 0)
19636+ res = count;
19637+
19638+out:
19639+ TRACE_EXIT_RES(res);
19640+ return res;
19641+}
19642+
19643+static struct kobj_attribute dev_threads_num_attr =
19644+ __ATTR(threads_num, S_IRUGO | S_IWUSR,
19645+ scst_dev_sysfs_threads_num_show,
19646+ scst_dev_sysfs_threads_num_store);
19647+
19648+static ssize_t scst_dev_sysfs_threads_pool_type_show(struct kobject *kobj,
19649+ struct kobj_attribute *attr, char *buf)
19650+{
19651+ int pos = 0;
19652+ struct scst_device *dev;
19653+
19654+ TRACE_ENTRY();
19655+
19656+ dev = container_of(kobj, struct scst_device, dev_kobj);
19657+
19658+ if (dev->threads_num == 0) {
19659+ pos = sprintf(buf, "Async\n");
19660+ goto out;
19661+ } else if (dev->threads_num < 0) {
19662+ pos = sprintf(buf, "Not valid\n");
19663+ goto out;
19664+ }
19665+
19666+ switch (dev->threads_pool_type) {
19667+ case SCST_THREADS_POOL_PER_INITIATOR:
19668+ pos = sprintf(buf, "%s\n%s", SCST_THREADS_POOL_PER_INITIATOR_STR,
19669+ (dev->threads_pool_type != dev->handler->threads_pool_type) ?
19670+ SCST_SYSFS_KEY_MARK "\n" : "");
19671+ break;
19672+ case SCST_THREADS_POOL_SHARED:
19673+ pos = sprintf(buf, "%s\n%s", SCST_THREADS_POOL_SHARED_STR,
19674+ (dev->threads_pool_type != dev->handler->threads_pool_type) ?
19675+ SCST_SYSFS_KEY_MARK "\n" : "");
19676+ break;
19677+ default:
19678+ pos = sprintf(buf, "Unknown\n");
19679+ break;
19680+ }
19681+
19682+out:
19683+ TRACE_EXIT_RES(pos);
19684+ return pos;
19685+}
19686+
19687+static ssize_t scst_dev_sysfs_threads_pool_type_store(struct kobject *kobj,
19688+ struct kobj_attribute *attr, const char *buf, size_t count)
19689+{
19690+ int res;
19691+ struct scst_device *dev;
19692+ enum scst_dev_type_threads_pool_type newtpt;
19693+ struct scst_sysfs_work_item *work;
19694+ bool stop;
19695+
19696+ TRACE_ENTRY();
19697+
19698+ dev = container_of(kobj, struct scst_device, dev_kobj);
19699+
19700+ newtpt = scst_parse_threads_pool_type(buf, count);
19701+ if (newtpt == SCST_THREADS_POOL_TYPE_INVALID) {
19702+ PRINT_ERROR("Illegal threads pool type %s", buf);
19703+ res = -EINVAL;
19704+ goto out;
19705+ }
19706+
19707+ TRACE_DBG("buf %s, count %zd, newtpt %d", buf, count, newtpt);
19708+
19709+ res = scst_dev_sysfs_check_threads_data(dev, dev->threads_num,
19710+ newtpt, &stop);
19711+ if ((res != 0) || stop)
19712+ goto out;
19713+
19714+ res = scst_alloc_sysfs_work(scst_dev_sysfs_threads_data_store_work_fn,
19715+ false, &work);
19716+ if (res != 0)
19717+ goto out;
19718+
19719+ work->dev = dev;
19720+ work->new_threads_num = dev->threads_num;
19721+ work->new_threads_pool_type = newtpt;
19722+
19723+ res = scst_sysfs_queue_wait_work(work);
19724+ if (res == 0)
19725+ res = count;
19726+
19727+out:
19728+ TRACE_EXIT_RES(res);
19729+ return res;
19730+}
19731+
19732+static struct kobj_attribute dev_threads_pool_type_attr =
19733+ __ATTR(threads_pool_type, S_IRUGO | S_IWUSR,
19734+ scst_dev_sysfs_threads_pool_type_show,
19735+ scst_dev_sysfs_threads_pool_type_store);
19736+
19737+static struct attribute *scst_dev_attrs[] = {
19738+ &dev_type_attr.attr,
19739+ NULL,
19740+};
19741+
19742+static void scst_sysfs_dev_release(struct kobject *kobj)
19743+{
19744+ struct scst_device *dev;
19745+
19746+ TRACE_ENTRY();
19747+
19748+ dev = container_of(kobj, struct scst_device, dev_kobj);
19749+ complete_all(&dev->dev_kobj_release_cmpl);
19750+
19751+ TRACE_EXIT();
19752+ return;
19753+}
19754+
19755+int scst_devt_dev_sysfs_create(struct scst_device *dev)
19756+{
19757+ int res = 0;
19758+ const struct attribute **pattr;
19759+
19760+ TRACE_ENTRY();
19761+
19762+ if (dev->handler == &scst_null_devtype)
19763+ goto out;
19764+
19765+ res = sysfs_create_link(&dev->dev_kobj,
19766+ &dev->handler->devt_kobj, "handler");
19767+ if (res != 0) {
19768+ PRINT_ERROR("Can't create handler link for dev %s",
19769+ dev->virt_name);
19770+ goto out;
19771+ }
19772+
19773+ res = sysfs_create_link(&dev->handler->devt_kobj,
19774+ &dev->dev_kobj, dev->virt_name);
19775+ if (res != 0) {
19776+ PRINT_ERROR("Can't create handler link for dev %s",
19777+ dev->virt_name);
19778+ goto out_err;
19779+ }
19780+
19781+ if (dev->handler->threads_num >= 0) {
19782+ res = sysfs_create_file(&dev->dev_kobj,
19783+ &dev_threads_num_attr.attr);
19784+ if (res != 0) {
19785+ PRINT_ERROR("Can't add dev attr %s for dev %s",
19786+ dev_threads_num_attr.attr.name,
19787+ dev->virt_name);
19788+ goto out_err;
19789+ }
19790+ res = sysfs_create_file(&dev->dev_kobj,
19791+ &dev_threads_pool_type_attr.attr);
19792+ if (res != 0) {
19793+ PRINT_ERROR("Can't add dev attr %s for dev %s",
19794+ dev_threads_pool_type_attr.attr.name,
19795+ dev->virt_name);
19796+ goto out_err;
19797+ }
19798+ }
19799+
19800+ pattr = dev->handler->dev_attrs;
19801+ if (pattr != NULL) {
19802+ while (*pattr != NULL) {
19803+ res = sysfs_create_file(&dev->dev_kobj, *pattr);
19804+ if (res != 0) {
19805+ PRINT_ERROR("Can't add dev attr %s for dev %s",
19806+ (*pattr)->name, dev->virt_name);
19807+ goto out_err;
19808+ }
19809+ pattr++;
19810+ }
19811+ }
19812+
19813+out:
19814+ TRACE_EXIT_RES(res);
19815+ return res;
19816+
19817+out_err:
19818+ scst_devt_dev_sysfs_del(dev);
19819+ goto out;
19820+}
19821+
19822+void scst_devt_dev_sysfs_del(struct scst_device *dev)
19823+{
19824+ const struct attribute **pattr;
19825+
19826+ TRACE_ENTRY();
19827+
19828+ if (dev->handler == &scst_null_devtype)
19829+ goto out;
19830+
19831+ pattr = dev->handler->dev_attrs;
19832+ if (pattr != NULL) {
19833+ while (*pattr != NULL) {
19834+ sysfs_remove_file(&dev->dev_kobj, *pattr);
19835+ pattr++;
19836+ }
19837+ }
19838+
19839+ sysfs_remove_link(&dev->dev_kobj, "handler");
19840+ sysfs_remove_link(&dev->handler->devt_kobj, dev->virt_name);
19841+
19842+ if (dev->handler->threads_num >= 0) {
19843+ sysfs_remove_file(&dev->dev_kobj,
19844+ &dev_threads_num_attr.attr);
19845+ sysfs_remove_file(&dev->dev_kobj,
19846+ &dev_threads_pool_type_attr.attr);
19847+ }
19848+
19849+out:
19850+ TRACE_EXIT();
19851+ return;
19852+}
19853+
19854+static struct kobj_type scst_dev_ktype = {
19855+ .sysfs_ops = &scst_sysfs_ops,
19856+ .release = scst_sysfs_dev_release,
19857+ .default_attrs = scst_dev_attrs,
19858+};
19859+
19860+/*
19861+ * Must not be called under scst_mutex, because it can call
19862+ * scst_dev_sysfs_del()
19863+ */
19864+int scst_dev_sysfs_create(struct scst_device *dev)
19865+{
19866+ int res = 0;
19867+
19868+ TRACE_ENTRY();
19869+
19870+ init_completion(&dev->dev_kobj_release_cmpl);
19871+
19872+ res = kobject_init_and_add(&dev->dev_kobj, &scst_dev_ktype,
19873+ scst_devices_kobj, dev->virt_name);
19874+ if (res != 0) {
19875+ PRINT_ERROR("Can't add device %s to sysfs", dev->virt_name);
19876+ goto out;
19877+ }
19878+
19879+ dev->dev_exp_kobj = kobject_create_and_add("exported",
19880+ &dev->dev_kobj);
19881+ if (dev->dev_exp_kobj == NULL) {
19882+ PRINT_ERROR("Can't create exported link for device %s",
19883+ dev->virt_name);
19884+ res = -ENOMEM;
19885+ goto out_del;
19886+ }
19887+
19888+ if (dev->scsi_dev != NULL) {
19889+ res = sysfs_create_link(&dev->dev_kobj,
19890+ &dev->scsi_dev->sdev_dev.kobj, "scsi_device");
19891+ if (res != 0) {
19892+ PRINT_ERROR("Can't create scsi_device link for dev %s",
19893+ dev->virt_name);
19894+ goto out_del;
19895+ }
19896+ }
19897+
19898+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
19899+ if (dev->scsi_dev == NULL) {
19900+ res = sysfs_create_file(&dev->dev_kobj,
19901+ &dev_dump_prs_attr.attr);
19902+ if (res != 0) {
19903+ PRINT_ERROR("Can't create attr %s for dev %s",
19904+ dev_dump_prs_attr.attr.name, dev->virt_name);
19905+ goto out_del;
19906+ }
19907+ }
19908+#endif
19909+
19910+out:
19911+ TRACE_EXIT_RES(res);
19912+ return res;
19913+
19914+out_del:
19915+ scst_dev_sysfs_del(dev);
19916+ goto out;
19917+}
19918+
19919+/*
19920+ * Must not be called under scst_mutex, due to possible deadlock with
19921+ * sysfs ref counting in sysfs works (it is waiting for the last put, but
19922+ * the last ref counter holder is waiting for scst_mutex)
19923+ */
19924+void scst_dev_sysfs_del(struct scst_device *dev)
19925+{
19926+ int rc;
19927+
19928+ TRACE_ENTRY();
19929+
19930+ kobject_del(dev->dev_exp_kobj);
19931+ kobject_del(&dev->dev_kobj);
19932+
19933+ kobject_put(dev->dev_exp_kobj);
19934+ kobject_put(&dev->dev_kobj);
19935+
19936+ rc = wait_for_completion_timeout(&dev->dev_kobj_release_cmpl, HZ);
19937+ if (rc == 0) {
19938+ PRINT_INFO("Waiting for releasing sysfs entry "
19939+ "for device %s (%d refs)...", dev->virt_name,
19940+ atomic_read(&dev->dev_kobj.kref.refcount));
19941+ wait_for_completion(&dev->dev_kobj_release_cmpl);
19942+ PRINT_INFO("Done waiting for releasing sysfs "
19943+ "entry for device %s", dev->virt_name);
19944+ }
19945+
19946+ TRACE_EXIT();
19947+ return;
19948+}
19949+
19950+/**
19951+ ** Tgt_dev's directory implementation
19952+ **/
19953+
19954+#ifdef CONFIG_SCST_MEASURE_LATENCY
19955+
19956+static char *scst_io_size_names[] = {
19957+ "<=8K ",
19958+ "<=32K ",
19959+ "<=128K",
19960+ "<=512K",
19961+ ">512K "
19962+};
19963+
19964+static ssize_t scst_tgt_dev_latency_show(struct kobject *kobj,
19965+ struct kobj_attribute *attr, char *buffer)
19966+{
19967+ int res = 0, i;
19968+ char buf[50];
19969+ struct scst_tgt_dev *tgt_dev;
19970+
19971+ TRACE_ENTRY();
19972+
19973+ tgt_dev = container_of(kobj, struct scst_tgt_dev, tgt_dev_kobj);
19974+
19975+ for (i = 0; i < SCST_LATENCY_STATS_NUM; i++) {
19976+ uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
19977+ unsigned int processed_cmds_wr;
19978+ uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
19979+ unsigned int processed_cmds_rd;
19980+ struct scst_ext_latency_stat *latency_stat;
19981+
19982+ latency_stat = &tgt_dev->dev_latency_stat[i];
19983+ scst_time_wr = latency_stat->scst_time_wr;
19984+ scst_time_rd = latency_stat->scst_time_rd;
19985+ tgt_time_wr = latency_stat->tgt_time_wr;
19986+ tgt_time_rd = latency_stat->tgt_time_rd;
19987+ dev_time_wr = latency_stat->dev_time_wr;
19988+ dev_time_rd = latency_stat->dev_time_rd;
19989+ processed_cmds_wr = latency_stat->processed_cmds_wr;
19990+ processed_cmds_rd = latency_stat->processed_cmds_rd;
19991+
19992+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
19993+ "%-5s %-9s %-15lu ", "Write", scst_io_size_names[i],
19994+ (unsigned long)processed_cmds_wr);
19995+ if (processed_cmds_wr == 0)
19996+ processed_cmds_wr = 1;
19997+
19998+ do_div(scst_time_wr, processed_cmds_wr);
19999+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20000+ (unsigned long)latency_stat->min_scst_time_wr,
20001+ (unsigned long)scst_time_wr,
20002+ (unsigned long)latency_stat->max_scst_time_wr,
20003+ (unsigned long)latency_stat->scst_time_wr);
20004+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20005+ "%-47s", buf);
20006+
20007+ do_div(tgt_time_wr, processed_cmds_wr);
20008+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20009+ (unsigned long)latency_stat->min_tgt_time_wr,
20010+ (unsigned long)tgt_time_wr,
20011+ (unsigned long)latency_stat->max_tgt_time_wr,
20012+ (unsigned long)latency_stat->tgt_time_wr);
20013+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20014+ "%-47s", buf);
20015+
20016+ do_div(dev_time_wr, processed_cmds_wr);
20017+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20018+ (unsigned long)latency_stat->min_dev_time_wr,
20019+ (unsigned long)dev_time_wr,
20020+ (unsigned long)latency_stat->max_dev_time_wr,
20021+ (unsigned long)latency_stat->dev_time_wr);
20022+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20023+ "%-47s\n", buf);
20024+
20025+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20026+ "%-5s %-9s %-15lu ", "Read", scst_io_size_names[i],
20027+ (unsigned long)processed_cmds_rd);
20028+ if (processed_cmds_rd == 0)
20029+ processed_cmds_rd = 1;
20030+
20031+ do_div(scst_time_rd, processed_cmds_rd);
20032+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20033+ (unsigned long)latency_stat->min_scst_time_rd,
20034+ (unsigned long)scst_time_rd,
20035+ (unsigned long)latency_stat->max_scst_time_rd,
20036+ (unsigned long)latency_stat->scst_time_rd);
20037+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20038+ "%-47s", buf);
20039+
20040+ do_div(tgt_time_rd, processed_cmds_rd);
20041+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20042+ (unsigned long)latency_stat->min_tgt_time_rd,
20043+ (unsigned long)tgt_time_rd,
20044+ (unsigned long)latency_stat->max_tgt_time_rd,
20045+ (unsigned long)latency_stat->tgt_time_rd);
20046+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20047+ "%-47s", buf);
20048+
20049+ do_div(dev_time_rd, processed_cmds_rd);
20050+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20051+ (unsigned long)latency_stat->min_dev_time_rd,
20052+ (unsigned long)dev_time_rd,
20053+ (unsigned long)latency_stat->max_dev_time_rd,
20054+ (unsigned long)latency_stat->dev_time_rd);
20055+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20056+ "%-47s\n", buf);
20057+ }
20058+
20059+ TRACE_EXIT_RES(res);
20060+ return res;
20061+}
20062+
20063+static struct kobj_attribute tgt_dev_latency_attr =
20064+ __ATTR(latency, S_IRUGO,
20065+ scst_tgt_dev_latency_show, NULL);
20066+
20067+#endif /* CONFIG_SCST_MEASURE_LATENCY */
20068+
20069+static ssize_t scst_tgt_dev_active_commands_show(struct kobject *kobj,
20070+ struct kobj_attribute *attr, char *buf)
20071+{
20072+ int pos = 0;
20073+ struct scst_tgt_dev *tgt_dev;
20074+
20075+ tgt_dev = container_of(kobj, struct scst_tgt_dev, tgt_dev_kobj);
20076+
20077+ pos = sprintf(buf, "%d\n", atomic_read(&tgt_dev->tgt_dev_cmd_count));
20078+
20079+ return pos;
20080+}
20081+
20082+static struct kobj_attribute tgt_dev_active_commands_attr =
20083+ __ATTR(active_commands, S_IRUGO,
20084+ scst_tgt_dev_active_commands_show, NULL);
20085+
20086+static struct attribute *scst_tgt_dev_attrs[] = {
20087+ &tgt_dev_active_commands_attr.attr,
20088+#ifdef CONFIG_SCST_MEASURE_LATENCY
20089+ &tgt_dev_latency_attr.attr,
20090+#endif
20091+ NULL,
20092+};
20093+
20094+static void scst_sysfs_tgt_dev_release(struct kobject *kobj)
20095+{
20096+ struct scst_tgt_dev *tgt_dev;
20097+
20098+ TRACE_ENTRY();
20099+
20100+ tgt_dev = container_of(kobj, struct scst_tgt_dev, tgt_dev_kobj);
20101+ complete_all(&tgt_dev->tgt_dev_kobj_release_cmpl);
20102+
20103+ TRACE_EXIT();
20104+ return;
20105+}
20106+
20107+static struct kobj_type scst_tgt_dev_ktype = {
20108+ .sysfs_ops = &scst_sysfs_ops,
20109+ .release = scst_sysfs_tgt_dev_release,
20110+ .default_attrs = scst_tgt_dev_attrs,
20111+};
20112+
20113+int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev)
20114+{
20115+ int res = 0;
20116+
20117+ TRACE_ENTRY();
20118+
20119+ init_completion(&tgt_dev->tgt_dev_kobj_release_cmpl);
20120+
20121+ res = kobject_init_and_add(&tgt_dev->tgt_dev_kobj, &scst_tgt_dev_ktype,
20122+ &tgt_dev->sess->sess_kobj, "lun%lld",
20123+ (unsigned long long)tgt_dev->lun);
20124+ if (res != 0) {
20125+ PRINT_ERROR("Can't add tgt_dev %lld to sysfs",
20126+ (unsigned long long)tgt_dev->lun);
20127+ goto out;
20128+ }
20129+
20130+out:
20131+ TRACE_EXIT_RES(res);
20132+ return res;
20133+}
20134+
20135+/*
20136+ * Called with scst_mutex held.
20137+ *
20138+ * !! No sysfs works must use kobject_get() to protect tgt_dev, due to possible
20139+ * !! deadlock with scst_mutex (it is waiting for the last put, but
20140+ * !! the last ref counter holder is waiting for scst_mutex)
20141+ */
20142+void scst_tgt_dev_sysfs_del(struct scst_tgt_dev *tgt_dev)
20143+{
20144+ int rc;
20145+
20146+ TRACE_ENTRY();
20147+
20148+ kobject_del(&tgt_dev->tgt_dev_kobj);
20149+ kobject_put(&tgt_dev->tgt_dev_kobj);
20150+
20151+ rc = wait_for_completion_timeout(
20152+ &tgt_dev->tgt_dev_kobj_release_cmpl, HZ);
20153+ if (rc == 0) {
20154+ PRINT_INFO("Waiting for releasing sysfs entry "
20155+ "for tgt_dev %lld (%d refs)...",
20156+ (unsigned long long)tgt_dev->lun,
20157+ atomic_read(&tgt_dev->tgt_dev_kobj.kref.refcount));
20158+ wait_for_completion(&tgt_dev->tgt_dev_kobj_release_cmpl);
20159+ PRINT_INFO("Done waiting for releasing sysfs entry for "
20160+ "tgt_dev %lld", (unsigned long long)tgt_dev->lun);
20161+ }
20162+
20163+ TRACE_EXIT();
20164+ return;
20165+}
20166+
20167+/**
20168+ ** Sessions subdirectory implementation
20169+ **/
20170+
20171+#ifdef CONFIG_SCST_MEASURE_LATENCY
20172+
20173+static ssize_t scst_sess_latency_show(struct kobject *kobj,
20174+ struct kobj_attribute *attr, char *buffer)
20175+{
20176+ ssize_t res = 0;
20177+ struct scst_session *sess;
20178+ int i;
20179+ char buf[50];
20180+ uint64_t scst_time, tgt_time, dev_time;
20181+ unsigned int processed_cmds;
20182+
20183+ TRACE_ENTRY();
20184+
20185+ sess = container_of(kobj, struct scst_session, sess_kobj);
20186+
20187+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20188+ "%-15s %-15s %-46s %-46s %-46s\n",
20189+ "T-L names", "Total commands", "SCST latency",
20190+ "Target latency", "Dev latency (min/avg/max/all ns)");
20191+
20192+ spin_lock_bh(&sess->lat_lock);
20193+
20194+ for (i = 0; i < SCST_LATENCY_STATS_NUM ; i++) {
20195+ uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
20196+ unsigned int processed_cmds_wr;
20197+ uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
20198+ unsigned int processed_cmds_rd;
20199+ struct scst_ext_latency_stat *latency_stat;
20200+
20201+ latency_stat = &sess->sess_latency_stat[i];
20202+ scst_time_wr = latency_stat->scst_time_wr;
20203+ scst_time_rd = latency_stat->scst_time_rd;
20204+ tgt_time_wr = latency_stat->tgt_time_wr;
20205+ tgt_time_rd = latency_stat->tgt_time_rd;
20206+ dev_time_wr = latency_stat->dev_time_wr;
20207+ dev_time_rd = latency_stat->dev_time_rd;
20208+ processed_cmds_wr = latency_stat->processed_cmds_wr;
20209+ processed_cmds_rd = latency_stat->processed_cmds_rd;
20210+
20211+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20212+ "%-5s %-9s %-15lu ",
20213+ "Write", scst_io_size_names[i],
20214+ (unsigned long)processed_cmds_wr);
20215+ if (processed_cmds_wr == 0)
20216+ processed_cmds_wr = 1;
20217+
20218+ do_div(scst_time_wr, processed_cmds_wr);
20219+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20220+ (unsigned long)latency_stat->min_scst_time_wr,
20221+ (unsigned long)scst_time_wr,
20222+ (unsigned long)latency_stat->max_scst_time_wr,
20223+ (unsigned long)latency_stat->scst_time_wr);
20224+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20225+ "%-47s", buf);
20226+
20227+ do_div(tgt_time_wr, processed_cmds_wr);
20228+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20229+ (unsigned long)latency_stat->min_tgt_time_wr,
20230+ (unsigned long)tgt_time_wr,
20231+ (unsigned long)latency_stat->max_tgt_time_wr,
20232+ (unsigned long)latency_stat->tgt_time_wr);
20233+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20234+ "%-47s", buf);
20235+
20236+ do_div(dev_time_wr, processed_cmds_wr);
20237+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20238+ (unsigned long)latency_stat->min_dev_time_wr,
20239+ (unsigned long)dev_time_wr,
20240+ (unsigned long)latency_stat->max_dev_time_wr,
20241+ (unsigned long)latency_stat->dev_time_wr);
20242+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20243+ "%-47s\n", buf);
20244+
20245+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20246+ "%-5s %-9s %-15lu ",
20247+ "Read", scst_io_size_names[i],
20248+ (unsigned long)processed_cmds_rd);
20249+ if (processed_cmds_rd == 0)
20250+ processed_cmds_rd = 1;
20251+
20252+ do_div(scst_time_rd, processed_cmds_rd);
20253+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20254+ (unsigned long)latency_stat->min_scst_time_rd,
20255+ (unsigned long)scst_time_rd,
20256+ (unsigned long)latency_stat->max_scst_time_rd,
20257+ (unsigned long)latency_stat->scst_time_rd);
20258+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20259+ "%-47s", buf);
20260+
20261+ do_div(tgt_time_rd, processed_cmds_rd);
20262+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20263+ (unsigned long)latency_stat->min_tgt_time_rd,
20264+ (unsigned long)tgt_time_rd,
20265+ (unsigned long)latency_stat->max_tgt_time_rd,
20266+ (unsigned long)latency_stat->tgt_time_rd);
20267+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20268+ "%-47s", buf);
20269+
20270+ do_div(dev_time_rd, processed_cmds_rd);
20271+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20272+ (unsigned long)latency_stat->min_dev_time_rd,
20273+ (unsigned long)dev_time_rd,
20274+ (unsigned long)latency_stat->max_dev_time_rd,
20275+ (unsigned long)latency_stat->dev_time_rd);
20276+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20277+ "%-47s\n", buf);
20278+ }
20279+
20280+ scst_time = sess->scst_time;
20281+ tgt_time = sess->tgt_time;
20282+ dev_time = sess->dev_time;
20283+ processed_cmds = sess->processed_cmds;
20284+
20285+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20286+ "\n%-15s %-16d", "Overall ", processed_cmds);
20287+
20288+ if (processed_cmds == 0)
20289+ processed_cmds = 1;
20290+
20291+ do_div(scst_time, processed_cmds);
20292+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20293+ (unsigned long)sess->min_scst_time,
20294+ (unsigned long)scst_time,
20295+ (unsigned long)sess->max_scst_time,
20296+ (unsigned long)sess->scst_time);
20297+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20298+ "%-47s", buf);
20299+
20300+ do_div(tgt_time, processed_cmds);
20301+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20302+ (unsigned long)sess->min_tgt_time,
20303+ (unsigned long)tgt_time,
20304+ (unsigned long)sess->max_tgt_time,
20305+ (unsigned long)sess->tgt_time);
20306+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20307+ "%-47s", buf);
20308+
20309+ do_div(dev_time, processed_cmds);
20310+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
20311+ (unsigned long)sess->min_dev_time,
20312+ (unsigned long)dev_time,
20313+ (unsigned long)sess->max_dev_time,
20314+ (unsigned long)sess->dev_time);
20315+ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
20316+ "%-47s\n\n", buf);
20317+
20318+ spin_unlock_bh(&sess->lat_lock);
20319+
20320+ TRACE_EXIT_RES(res);
20321+ return res;
20322+}
20323+
20324+static int scst_sess_zero_latency(struct scst_sysfs_work_item *work)
20325+{
20326+ int res = 0, t;
20327+ struct scst_session *sess = work->sess;
20328+
20329+ TRACE_ENTRY();
20330+
20331+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
20332+ res = -EINTR;
20333+ goto out_put;
20334+ }
20335+
20336+ PRINT_INFO("Zeroing latency statistics for initiator "
20337+ "%s", sess->initiator_name);
20338+
20339+ spin_lock_bh(&sess->lat_lock);
20340+
20341+ sess->scst_time = 0;
20342+ sess->tgt_time = 0;
20343+ sess->dev_time = 0;
20344+ sess->min_scst_time = 0;
20345+ sess->min_tgt_time = 0;
20346+ sess->min_dev_time = 0;
20347+ sess->max_scst_time = 0;
20348+ sess->max_tgt_time = 0;
20349+ sess->max_dev_time = 0;
20350+ sess->processed_cmds = 0;
20351+ memset(sess->sess_latency_stat, 0,
20352+ sizeof(sess->sess_latency_stat));
20353+
20354+ for (t = TGT_DEV_HASH_SIZE-1; t >= 0; t--) {
20355+ struct list_head *sess_tgt_dev_list_head =
20356+ &sess->sess_tgt_dev_list_hash[t];
20357+ struct scst_tgt_dev *tgt_dev;
20358+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
20359+ sess_tgt_dev_list_entry) {
20360+ tgt_dev->scst_time = 0;
20361+ tgt_dev->tgt_time = 0;
20362+ tgt_dev->dev_time = 0;
20363+ tgt_dev->processed_cmds = 0;
20364+ memset(tgt_dev->dev_latency_stat, 0,
20365+ sizeof(tgt_dev->dev_latency_stat));
20366+ }
20367+ }
20368+
20369+ spin_unlock_bh(&sess->lat_lock);
20370+
20371+ mutex_unlock(&scst_mutex);
20372+
20373+out_put:
20374+ kobject_put(&sess->sess_kobj);
20375+
20376+ TRACE_EXIT_RES(res);
20377+ return res;
20378+}
20379+
20380+static ssize_t scst_sess_latency_store(struct kobject *kobj,
20381+ struct kobj_attribute *attr, const char *buf, size_t count)
20382+{
20383+ int res;
20384+ struct scst_session *sess;
20385+ struct scst_sysfs_work_item *work;
20386+
20387+ TRACE_ENTRY();
20388+
20389+ sess = container_of(kobj, struct scst_session, sess_kobj);
20390+
20391+ res = scst_alloc_sysfs_work(scst_sess_zero_latency, false, &work);
20392+ if (res != 0)
20393+ goto out;
20394+
20395+ work->sess = sess;
20396+
20397+ kobject_get(&sess->sess_kobj);
20398+
20399+ res = scst_sysfs_queue_wait_work(work);
20400+ if (res == 0)
20401+ res = count;
20402+
20403+out:
20404+ TRACE_EXIT_RES(res);
20405+ return res;
20406+}
20407+
20408+static struct kobj_attribute session_latency_attr =
20409+ __ATTR(latency, S_IRUGO | S_IWUSR, scst_sess_latency_show,
20410+ scst_sess_latency_store);
20411+
20412+#endif /* CONFIG_SCST_MEASURE_LATENCY */
20413+
20414+static ssize_t scst_sess_sysfs_commands_show(struct kobject *kobj,
20415+ struct kobj_attribute *attr, char *buf)
20416+{
20417+ struct scst_session *sess;
20418+
20419+ sess = container_of(kobj, struct scst_session, sess_kobj);
20420+
20421+ return sprintf(buf, "%i\n", atomic_read(&sess->sess_cmd_count));
20422+}
20423+
20424+static struct kobj_attribute session_commands_attr =
20425+ __ATTR(commands, S_IRUGO, scst_sess_sysfs_commands_show, NULL);
20426+
20427+static int scst_sysfs_sess_get_active_commands(struct scst_session *sess)
20428+{
20429+ int res;
20430+ int active_cmds = 0, t;
20431+
20432+ TRACE_ENTRY();
20433+
20434+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
20435+ res = -EINTR;
20436+ goto out_put;
20437+ }
20438+
20439+ for (t = TGT_DEV_HASH_SIZE-1; t >= 0; t--) {
20440+ struct list_head *sess_tgt_dev_list_head =
20441+ &sess->sess_tgt_dev_list_hash[t];
20442+ struct scst_tgt_dev *tgt_dev;
20443+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
20444+ sess_tgt_dev_list_entry) {
20445+ active_cmds += atomic_read(&tgt_dev->tgt_dev_cmd_count);
20446+ }
20447+ }
20448+
20449+ mutex_unlock(&scst_mutex);
20450+
20451+ res = active_cmds;
20452+
20453+out_put:
20454+ kobject_put(&sess->sess_kobj);
20455+
20456+ TRACE_EXIT_RES(res);
20457+ return res;
20458+}
20459+
20460+static int scst_sysfs_sess_get_active_commands_work_fn(struct scst_sysfs_work_item *work)
20461+{
20462+ return scst_sysfs_sess_get_active_commands(work->sess);
20463+}
20464+
20465+static ssize_t scst_sess_sysfs_active_commands_show(struct kobject *kobj,
20466+ struct kobj_attribute *attr, char *buf)
20467+{
20468+ int res;
20469+ struct scst_session *sess;
20470+ struct scst_sysfs_work_item *work;
20471+
20472+ sess = container_of(kobj, struct scst_session, sess_kobj);
20473+
20474+ res = scst_alloc_sysfs_work(scst_sysfs_sess_get_active_commands_work_fn,
20475+ true, &work);
20476+ if (res != 0)
20477+ goto out;
20478+
20479+ work->sess = sess;
20480+
20481+ kobject_get(&sess->sess_kobj);
20482+
20483+ res = scst_sysfs_queue_wait_work(work);
20484+ if (res != -EAGAIN)
20485+ res = sprintf(buf, "%i\n", res);
20486+
20487+out:
20488+ return res;
20489+}
20490+
20491+static struct kobj_attribute session_active_commands_attr =
20492+ __ATTR(active_commands, S_IRUGO, scst_sess_sysfs_active_commands_show,
20493+ NULL);
20494+
20495+static ssize_t scst_sess_sysfs_initiator_name_show(struct kobject *kobj,
20496+ struct kobj_attribute *attr, char *buf)
20497+{
20498+ struct scst_session *sess;
20499+
20500+ sess = container_of(kobj, struct scst_session, sess_kobj);
20501+
20502+ return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n",
20503+ sess->initiator_name);
20504+}
20505+
20506+static struct kobj_attribute session_initiator_name_attr =
20507+ __ATTR(initiator_name, S_IRUGO, scst_sess_sysfs_initiator_name_show, NULL);
20508+
20509+static struct attribute *scst_session_attrs[] = {
20510+ &session_commands_attr.attr,
20511+ &session_active_commands_attr.attr,
20512+ &session_initiator_name_attr.attr,
20513+#ifdef CONFIG_SCST_MEASURE_LATENCY
20514+ &session_latency_attr.attr,
20515+#endif /* CONFIG_SCST_MEASURE_LATENCY */
20516+ NULL,
20517+};
20518+
20519+static void scst_sysfs_session_release(struct kobject *kobj)
20520+{
20521+ struct scst_session *sess;
20522+
20523+ TRACE_ENTRY();
20524+
20525+ sess = container_of(kobj, struct scst_session, sess_kobj);
20526+ complete_all(&sess->sess_kobj_release_cmpl);
20527+
20528+ TRACE_EXIT();
20529+ return;
20530+}
20531+
20532+static struct kobj_type scst_session_ktype = {
20533+ .sysfs_ops = &scst_sysfs_ops,
20534+ .release = scst_sysfs_session_release,
20535+ .default_attrs = scst_session_attrs,
20536+};
20537+
20538+static int scst_create_sess_luns_link(struct scst_session *sess)
20539+{
20540+ int res;
20541+
20542+ /*
20543+ * No locks are needed, because sess supposed to be in acg->acg_sess_list
20544+ * and tgt->sess_list, so blocking them from disappearing.
20545+ */
20546+
20547+ if (sess->acg == sess->tgt->default_acg)
20548+ res = sysfs_create_link(&sess->sess_kobj,
20549+ sess->tgt->tgt_luns_kobj, "luns");
20550+ else
20551+ res = sysfs_create_link(&sess->sess_kobj,
20552+ sess->acg->luns_kobj, "luns");
20553+
20554+ if (res != 0)
20555+ PRINT_ERROR("Can't create luns link for initiator %s",
20556+ sess->initiator_name);
20557+
20558+ return res;
20559+}
20560+
20561+int scst_recreate_sess_luns_link(struct scst_session *sess)
20562+{
20563+ sysfs_remove_link(&sess->sess_kobj, "luns");
20564+ return scst_create_sess_luns_link(sess);
20565+}
20566+
20567+/* Supposed to be called under scst_mutex */
20568+int scst_sess_sysfs_create(struct scst_session *sess)
20569+{
20570+ int res = 0;
20571+ struct scst_session *s;
20572+ const struct attribute **pattr;
20573+ char *name = (char *)sess->initiator_name;
20574+ int len = strlen(name) + 1, n = 1;
20575+
20576+ TRACE_ENTRY();
20577+
20578+restart:
20579+ list_for_each_entry(s, &sess->tgt->sess_list, sess_list_entry) {
20580+ if (!s->sess_kobj_ready)
20581+ continue;
20582+
20583+ if (strcmp(name, kobject_name(&s->sess_kobj)) == 0) {
20584+ if (s == sess)
20585+ continue;
20586+
20587+ TRACE_DBG("Dublicated session from the same initiator "
20588+ "%s found", name);
20589+
20590+ if (name == sess->initiator_name) {
20591+ len = strlen(sess->initiator_name);
20592+ len += 20;
20593+ name = kmalloc(len, GFP_KERNEL);
20594+ if (name == NULL) {
20595+ PRINT_ERROR("Unable to allocate a "
20596+ "replacement name (size %d)",
20597+ len);
20598+ }
20599+ }
20600+
20601+ snprintf(name, len, "%s_%d", sess->initiator_name, n);
20602+ n++;
20603+ goto restart;
20604+ }
20605+ }
20606+
20607+ init_completion(&sess->sess_kobj_release_cmpl);
20608+
20609+ TRACE_DBG("Adding session %s to sysfs", name);
20610+
20611+ res = kobject_init_and_add(&sess->sess_kobj, &scst_session_ktype,
20612+ sess->tgt->tgt_sess_kobj, name);
20613+ if (res != 0) {
20614+ PRINT_ERROR("Can't add session %s to sysfs", name);
20615+ goto out_free;
20616+ }
20617+
20618+ sess->sess_kobj_ready = 1;
20619+
20620+ pattr = sess->tgt->tgtt->sess_attrs;
20621+ if (pattr != NULL) {
20622+ while (*pattr != NULL) {
20623+ res = sysfs_create_file(&sess->sess_kobj, *pattr);
20624+ if (res != 0) {
20625+ PRINT_ERROR("Can't add sess attr %s for sess "
20626+ "for initiator %s", (*pattr)->name,
20627+ name);
20628+ goto out_free;
20629+ }
20630+ pattr++;
20631+ }
20632+ }
20633+
20634+ res = scst_create_sess_luns_link(sess);
20635+
20636+out_free:
20637+ if (name != sess->initiator_name)
20638+ kfree(name);
20639+
20640+ TRACE_EXIT_RES(res);
20641+ return res;
20642+}
20643+
20644+/*
20645+ * Must not be called under scst_mutex, due to possible deadlock with
20646+ * sysfs ref counting in sysfs works (it is waiting for the last put, but
20647+ * the last ref counter holder is waiting for scst_mutex)
20648+ */
20649+void scst_sess_sysfs_del(struct scst_session *sess)
20650+{
20651+ int rc;
20652+
20653+ TRACE_ENTRY();
20654+
20655+ if (!sess->sess_kobj_ready)
20656+ goto out;
20657+
20658+ TRACE_DBG("Deleting session %s from sysfs",
20659+ kobject_name(&sess->sess_kobj));
20660+
20661+ kobject_del(&sess->sess_kobj);
20662+ kobject_put(&sess->sess_kobj);
20663+
20664+ rc = wait_for_completion_timeout(&sess->sess_kobj_release_cmpl, HZ);
20665+ if (rc == 0) {
20666+ PRINT_INFO("Waiting for releasing sysfs entry "
20667+ "for session from %s (%d refs)...", sess->initiator_name,
20668+ atomic_read(&sess->sess_kobj.kref.refcount));
20669+ wait_for_completion(&sess->sess_kobj_release_cmpl);
20670+ PRINT_INFO("Done waiting for releasing sysfs "
20671+ "entry for session %s", sess->initiator_name);
20672+ }
20673+
20674+out:
20675+ TRACE_EXIT();
20676+ return;
20677+}
20678+
20679+/**
20680+ ** Target luns directory implementation
20681+ **/
20682+
20683+static void scst_acg_dev_release(struct kobject *kobj)
20684+{
20685+ struct scst_acg_dev *acg_dev;
20686+
20687+ TRACE_ENTRY();
20688+
20689+ acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
20690+ complete_all(&acg_dev->acg_dev_kobj_release_cmpl);
20691+
20692+ TRACE_EXIT();
20693+ return;
20694+}
20695+
20696+static ssize_t scst_lun_rd_only_show(struct kobject *kobj,
20697+ struct kobj_attribute *attr,
20698+ char *buf)
20699+{
20700+ struct scst_acg_dev *acg_dev;
20701+
20702+ acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
20703+
20704+ if (acg_dev->rd_only || acg_dev->dev->rd_only)
20705+ return sprintf(buf, "%d\n%s\n", 1, SCST_SYSFS_KEY_MARK);
20706+ else
20707+ return sprintf(buf, "%d\n", 0);
20708+}
20709+
20710+static struct kobj_attribute lun_options_attr =
20711+ __ATTR(read_only, S_IRUGO, scst_lun_rd_only_show, NULL);
20712+
20713+static struct attribute *lun_attrs[] = {
20714+ &lun_options_attr.attr,
20715+ NULL,
20716+};
20717+
20718+static struct kobj_type acg_dev_ktype = {
20719+ .sysfs_ops = &scst_sysfs_ops,
20720+ .release = scst_acg_dev_release,
20721+ .default_attrs = lun_attrs,
20722+};
20723+
20724+/*
20725+ * Called with scst_mutex held.
20726+ *
20727+ * !! No sysfs works must use kobject_get() to protect acg_dev, due to possible
20728+ * !! deadlock with scst_mutex (it is waiting for the last put, but
20729+ * !! the last ref counter holder is waiting for scst_mutex)
20730+ */
20731+void scst_acg_dev_sysfs_del(struct scst_acg_dev *acg_dev)
20732+{
20733+ int rc;
20734+
20735+ TRACE_ENTRY();
20736+
20737+ if (acg_dev->dev != NULL) {
20738+ sysfs_remove_link(acg_dev->dev->dev_exp_kobj,
20739+ acg_dev->acg_dev_link_name);
20740+ kobject_put(&acg_dev->dev->dev_kobj);
20741+ }
20742+
20743+ kobject_del(&acg_dev->acg_dev_kobj);
20744+ kobject_put(&acg_dev->acg_dev_kobj);
20745+
20746+ rc = wait_for_completion_timeout(&acg_dev->acg_dev_kobj_release_cmpl, HZ);
20747+ if (rc == 0) {
20748+ PRINT_INFO("Waiting for releasing sysfs entry "
20749+ "for acg_dev %p (%d refs)...", acg_dev,
20750+ atomic_read(&acg_dev->acg_dev_kobj.kref.refcount));
20751+ wait_for_completion(&acg_dev->acg_dev_kobj_release_cmpl);
20752+ PRINT_INFO("Done waiting for releasing sysfs "
20753+ "entry for acg_dev %p", acg_dev);
20754+ }
20755+
20756+ TRACE_EXIT();
20757+ return;
20758+}
20759+
20760+int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev,
20761+ struct kobject *parent)
20762+{
20763+ int res;
20764+
20765+ TRACE_ENTRY();
20766+
20767+ init_completion(&acg_dev->acg_dev_kobj_release_cmpl);
20768+
20769+ res = kobject_init_and_add(&acg_dev->acg_dev_kobj, &acg_dev_ktype,
20770+ parent, "%u", acg_dev->lun);
20771+ if (res != 0) {
20772+ PRINT_ERROR("Can't add acg_dev %p to sysfs", acg_dev);
20773+ goto out;
20774+ }
20775+
20776+ kobject_get(&acg_dev->dev->dev_kobj);
20777+
20778+ snprintf(acg_dev->acg_dev_link_name, sizeof(acg_dev->acg_dev_link_name),
20779+ "export%u", acg_dev->dev->dev_exported_lun_num++);
20780+
20781+ res = sysfs_create_link(acg_dev->dev->dev_exp_kobj,
20782+ &acg_dev->acg_dev_kobj, acg_dev->acg_dev_link_name);
20783+ if (res != 0) {
20784+ PRINT_ERROR("Can't create acg %s LUN link",
20785+ acg_dev->acg->acg_name);
20786+ goto out_del;
20787+ }
20788+
20789+ res = sysfs_create_link(&acg_dev->acg_dev_kobj,
20790+ &acg_dev->dev->dev_kobj, "device");
20791+ if (res != 0) {
20792+ PRINT_ERROR("Can't create acg %s device link",
20793+ acg_dev->acg->acg_name);
20794+ goto out_del;
20795+ }
20796+
20797+out:
20798+ return res;
20799+
20800+out_del:
20801+ scst_acg_dev_sysfs_del(acg_dev);
20802+ goto out;
20803+}
20804+
20805+static int __scst_process_luns_mgmt_store(char *buffer,
20806+ struct scst_tgt *tgt, struct scst_acg *acg, bool tgt_kobj)
20807+{
20808+ int res, read_only = 0, action;
20809+ char *p, *e = NULL;
20810+ unsigned int virt_lun;
20811+ struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
20812+ struct scst_device *d, *dev = NULL;
20813+
20814+#define SCST_LUN_ACTION_ADD 1
20815+#define SCST_LUN_ACTION_DEL 2
20816+#define SCST_LUN_ACTION_REPLACE 3
20817+#define SCST_LUN_ACTION_CLEAR 4
20818+
20819+ TRACE_ENTRY();
20820+
20821+ TRACE_DBG("buffer %s", buffer);
20822+
20823+ p = buffer;
20824+ if (p[strlen(p) - 1] == '\n')
20825+ p[strlen(p) - 1] = '\0';
20826+ if (strncasecmp("add", p, 3) == 0) {
20827+ p += 3;
20828+ action = SCST_LUN_ACTION_ADD;
20829+ } else if (strncasecmp("del", p, 3) == 0) {
20830+ p += 3;
20831+ action = SCST_LUN_ACTION_DEL;
20832+ } else if (!strncasecmp("replace", p, 7)) {
20833+ p += 7;
20834+ action = SCST_LUN_ACTION_REPLACE;
20835+ } else if (!strncasecmp("clear", p, 5)) {
20836+ p += 5;
20837+ action = SCST_LUN_ACTION_CLEAR;
20838+ } else {
20839+ PRINT_ERROR("Unknown action \"%s\"", p);
20840+ res = -EINVAL;
20841+ goto out;
20842+ }
20843+
20844+ res = scst_suspend_activity(true);
20845+ if (res != 0)
20846+ goto out;
20847+
20848+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
20849+ res = -EINTR;
20850+ goto out_resume;
20851+ }
20852+
20853+ /* Check if tgt and acg not already freed while we were coming here */
20854+ if (scst_check_tgt_acg_ptrs(tgt, acg) != 0)
20855+ goto out_unlock;
20856+
20857+ if ((action != SCST_LUN_ACTION_CLEAR) &&
20858+ (action != SCST_LUN_ACTION_DEL)) {
20859+ if (!isspace(*p)) {
20860+ PRINT_ERROR("%s", "Syntax error");
20861+ res = -EINVAL;
20862+ goto out_unlock;
20863+ }
20864+
20865+ while (isspace(*p) && *p != '\0')
20866+ p++;
20867+ e = p; /* save p */
20868+ while (!isspace(*e) && *e != '\0')
20869+ e++;
20870+ *e = '\0';
20871+
20872+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
20873+ if (!strcmp(d->virt_name, p)) {
20874+ dev = d;
20875+ TRACE_DBG("Device %p (%s) found", dev, p);
20876+ break;
20877+ }
20878+ }
20879+ if (dev == NULL) {
20880+ PRINT_ERROR("Device '%s' not found", p);
20881+ res = -EINVAL;
20882+ goto out_unlock;
20883+ }
20884+ }
20885+
20886+ switch (action) {
20887+ case SCST_LUN_ACTION_ADD:
20888+ case SCST_LUN_ACTION_REPLACE:
20889+ {
20890+ bool dev_replaced = false;
20891+
20892+ e++;
20893+ while (isspace(*e) && *e != '\0')
20894+ e++;
20895+ virt_lun = simple_strtoul(e, &e, 0);
20896+
20897+ while (isspace(*e) && *e != '\0')
20898+ e++;
20899+
20900+ while (1) {
20901+ char *pp;
20902+ unsigned long val;
20903+ char *param = scst_get_next_token_str(&e);
20904+ if (param == NULL)
20905+ break;
20906+
20907+ p = scst_get_next_lexem(&param);
20908+ if (*p == '\0') {
20909+ PRINT_ERROR("Syntax error at %s (device %s)",
20910+ param, dev->virt_name);
20911+ res = -EINVAL;
20912+ goto out_unlock;
20913+ }
20914+
20915+ pp = scst_get_next_lexem(&param);
20916+ if (*pp == '\0') {
20917+ PRINT_ERROR("Parameter %s value missed for device %s",
20918+ p, dev->virt_name);
20919+ res = -EINVAL;
20920+ goto out_unlock;
20921+ }
20922+
20923+ if (scst_get_next_lexem(&param)[0] != '\0') {
20924+ PRINT_ERROR("Too many parameter's %s values (device %s)",
20925+ p, dev->virt_name);
20926+ res = -EINVAL;
20927+ goto out_unlock;
20928+ }
20929+
20930+ res = strict_strtoul(pp, 0, &val);
20931+ if (res != 0) {
20932+ PRINT_ERROR("strict_strtoul() for %s failed: %d "
20933+ "(device %s)", pp, res, dev->virt_name);
20934+ goto out_unlock;
20935+ }
20936+
20937+ if (!strcasecmp("read_only", p)) {
20938+ read_only = val;
20939+ TRACE_DBG("READ ONLY %d", read_only);
20940+ } else {
20941+ PRINT_ERROR("Unknown parameter %s (device %s)",
20942+ p, dev->virt_name);
20943+ res = -EINVAL;
20944+ goto out_unlock;
20945+ }
20946+ }
20947+
20948+ acg_dev = NULL;
20949+ list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
20950+ acg_dev_list_entry) {
20951+ if (acg_dev_tmp->lun == virt_lun) {
20952+ acg_dev = acg_dev_tmp;
20953+ break;
20954+ }
20955+ }
20956+
20957+ if (acg_dev != NULL) {
20958+ if (action == SCST_LUN_ACTION_ADD) {
20959+ PRINT_ERROR("virt lun %d already exists in "
20960+ "group %s", virt_lun, acg->acg_name);
20961+ res = -EEXIST;
20962+ goto out_unlock;
20963+ } else {
20964+ /* Replace */
20965+ res = scst_acg_del_lun(acg, acg_dev->lun,
20966+ false);
20967+ if (res != 0)
20968+ goto out_unlock;
20969+
20970+ dev_replaced = true;
20971+ }
20972+ }
20973+
20974+ res = scst_acg_add_lun(acg,
20975+ tgt_kobj ? tgt->tgt_luns_kobj : acg->luns_kobj,
20976+ dev, virt_lun, read_only, !dev_replaced, NULL);
20977+ if (res != 0)
20978+ goto out_unlock;
20979+
20980+ if (dev_replaced) {
20981+ struct scst_tgt_dev *tgt_dev;
20982+
20983+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
20984+ dev_tgt_dev_list_entry) {
20985+ if ((tgt_dev->acg_dev->acg == acg) &&
20986+ (tgt_dev->lun == virt_lun)) {
20987+ TRACE_MGMT_DBG("INQUIRY DATA HAS CHANGED"
20988+ " on tgt_dev %p", tgt_dev);
20989+ scst_gen_aen_or_ua(tgt_dev,
20990+ SCST_LOAD_SENSE(scst_sense_inquery_data_changed));
20991+ }
20992+ }
20993+ }
20994+
20995+ break;
20996+ }
20997+ case SCST_LUN_ACTION_DEL:
20998+ while (isspace(*p) && *p != '\0')
20999+ p++;
21000+ virt_lun = simple_strtoul(p, &p, 0);
21001+
21002+ res = scst_acg_del_lun(acg, virt_lun, true);
21003+ if (res != 0)
21004+ goto out_unlock;
21005+ break;
21006+ case SCST_LUN_ACTION_CLEAR:
21007+ PRINT_INFO("Removed all devices from group %s",
21008+ acg->acg_name);
21009+ list_for_each_entry_safe(acg_dev, acg_dev_tmp,
21010+ &acg->acg_dev_list,
21011+ acg_dev_list_entry) {
21012+ res = scst_acg_del_lun(acg, acg_dev->lun,
21013+ list_is_last(&acg_dev->acg_dev_list_entry,
21014+ &acg->acg_dev_list));
21015+ if (res)
21016+ goto out_unlock;
21017+ }
21018+ break;
21019+ }
21020+
21021+ res = 0;
21022+
21023+out_unlock:
21024+ mutex_unlock(&scst_mutex);
21025+
21026+out_resume:
21027+ scst_resume_activity();
21028+
21029+out:
21030+ TRACE_EXIT_RES(res);
21031+ return res;
21032+
21033+#undef SCST_LUN_ACTION_ADD
21034+#undef SCST_LUN_ACTION_DEL
21035+#undef SCST_LUN_ACTION_REPLACE
21036+#undef SCST_LUN_ACTION_CLEAR
21037+}
21038+
21039+static int scst_luns_mgmt_store_work_fn(struct scst_sysfs_work_item *work)
21040+{
21041+ return __scst_process_luns_mgmt_store(work->buf, work->tgt, work->acg,
21042+ work->is_tgt_kobj);
21043+}
21044+
21045+static ssize_t __scst_acg_mgmt_store(struct scst_acg *acg,
21046+ const char *buf, size_t count, bool is_tgt_kobj,
21047+ int (*sysfs_work_fn)(struct scst_sysfs_work_item *))
21048+{
21049+ int res;
21050+ char *buffer;
21051+ struct scst_sysfs_work_item *work;
21052+
21053+ TRACE_ENTRY();
21054+
21055+ buffer = kzalloc(count+1, GFP_KERNEL);
21056+ if (buffer == NULL) {
21057+ res = -ENOMEM;
21058+ goto out;
21059+ }
21060+ memcpy(buffer, buf, count);
21061+ buffer[count] = '\0';
21062+
21063+ res = scst_alloc_sysfs_work(sysfs_work_fn, false, &work);
21064+ if (res != 0)
21065+ goto out_free;
21066+
21067+ work->buf = buffer;
21068+ work->tgt = acg->tgt;
21069+ work->acg = acg;
21070+ work->is_tgt_kobj = is_tgt_kobj;
21071+
21072+ res = scst_sysfs_queue_wait_work(work);
21073+ if (res == 0)
21074+ res = count;
21075+
21076+out:
21077+ TRACE_EXIT_RES(res);
21078+ return res;
21079+
21080+out_free:
21081+ kfree(buffer);
21082+ goto out;
21083+}
21084+
21085+static ssize_t __scst_luns_mgmt_store(struct scst_acg *acg,
21086+ bool tgt_kobj, const char *buf, size_t count)
21087+{
21088+ return __scst_acg_mgmt_store(acg, buf, count, tgt_kobj,
21089+ scst_luns_mgmt_store_work_fn);
21090+}
21091+
21092+static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
21093+ struct kobj_attribute *attr,
21094+ char *buf)
21095+{
21096+ static char *help = "Usage: echo \"add|del H:C:I:L lun [parameters]\" >mgmt\n"
21097+ " echo \"add VNAME lun [parameters]\" >mgmt\n"
21098+ " echo \"del lun\" >mgmt\n"
21099+ " echo \"replace H:C:I:L lun [parameters]\" >mgmt\n"
21100+ " echo \"replace VNAME lun [parameters]\" >mgmt\n"
21101+ " echo \"clear\" >mgmt\n"
21102+ "\n"
21103+ "where parameters are one or more "
21104+ "param_name=value pairs separated by ';'\n"
21105+ "\nThe following parameters available: read_only.";
21106+
21107+ return sprintf(buf, "%s", help);
21108+}
21109+
21110+static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
21111+ struct kobj_attribute *attr,
21112+ const char *buf, size_t count)
21113+{
21114+ int res;
21115+ struct scst_acg *acg;
21116+ struct scst_tgt *tgt;
21117+
21118+ tgt = container_of(kobj->parent, struct scst_tgt, tgt_kobj);
21119+ acg = tgt->default_acg;
21120+
21121+ res = __scst_luns_mgmt_store(acg, true, buf, count);
21122+
21123+ TRACE_EXIT_RES(res);
21124+ return res;
21125+}
21126+
21127+static ssize_t __scst_acg_addr_method_show(struct scst_acg *acg, char *buf)
21128+{
21129+ int res;
21130+
21131+ switch (acg->addr_method) {
21132+ case SCST_LUN_ADDR_METHOD_FLAT:
21133+ res = sprintf(buf, "FLAT\n%s\n", SCST_SYSFS_KEY_MARK);
21134+ break;
21135+ case SCST_LUN_ADDR_METHOD_PERIPHERAL:
21136+ res = sprintf(buf, "PERIPHERAL\n");
21137+ break;
21138+ default:
21139+ res = sprintf(buf, "UNKNOWN\n");
21140+ break;
21141+ }
21142+
21143+ return res;
21144+}
21145+
21146+static ssize_t __scst_acg_addr_method_store(struct scst_acg *acg,
21147+ const char *buf, size_t count)
21148+{
21149+ int res = count;
21150+
21151+ if (strncasecmp(buf, "FLAT", min_t(int, 4, count)) == 0)
21152+ acg->addr_method = SCST_LUN_ADDR_METHOD_FLAT;
21153+ else if (strncasecmp(buf, "PERIPHERAL", min_t(int, 10, count)) == 0)
21154+ acg->addr_method = SCST_LUN_ADDR_METHOD_PERIPHERAL;
21155+ else {
21156+ PRINT_ERROR("Unknown address method %s", buf);
21157+ res = -EINVAL;
21158+ }
21159+
21160+ TRACE_DBG("acg %p, addr_method %d", acg, acg->addr_method);
21161+
21162+ return res;
21163+}
21164+
21165+static ssize_t scst_tgt_addr_method_show(struct kobject *kobj,
21166+ struct kobj_attribute *attr, char *buf)
21167+{
21168+ struct scst_acg *acg;
21169+ struct scst_tgt *tgt;
21170+
21171+ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
21172+ acg = tgt->default_acg;
21173+
21174+ return __scst_acg_addr_method_show(acg, buf);
21175+}
21176+
21177+static ssize_t scst_tgt_addr_method_store(struct kobject *kobj,
21178+ struct kobj_attribute *attr, const char *buf, size_t count)
21179+{
21180+ int res;
21181+ struct scst_acg *acg;
21182+ struct scst_tgt *tgt;
21183+
21184+ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
21185+ acg = tgt->default_acg;
21186+
21187+ res = __scst_acg_addr_method_store(acg, buf, count);
21188+
21189+ TRACE_EXIT_RES(res);
21190+ return res;
21191+}
21192+
21193+static ssize_t __scst_acg_io_grouping_type_show(struct scst_acg *acg, char *buf)
21194+{
21195+ int res;
21196+
21197+ switch (acg->acg_io_grouping_type) {
21198+ case SCST_IO_GROUPING_AUTO:
21199+ res = sprintf(buf, "%s\n", SCST_IO_GROUPING_AUTO_STR);
21200+ break;
21201+ case SCST_IO_GROUPING_THIS_GROUP_ONLY:
21202+ res = sprintf(buf, "%s\n%s\n",
21203+ SCST_IO_GROUPING_THIS_GROUP_ONLY_STR,
21204+ SCST_SYSFS_KEY_MARK);
21205+ break;
21206+ case SCST_IO_GROUPING_NEVER:
21207+ res = sprintf(buf, "%s\n%s\n", SCST_IO_GROUPING_NEVER_STR,
21208+ SCST_SYSFS_KEY_MARK);
21209+ break;
21210+ default:
21211+ res = sprintf(buf, "%d\n%s\n", acg->acg_io_grouping_type,
21212+ SCST_SYSFS_KEY_MARK);
21213+ break;
21214+ }
21215+
21216+ return res;
21217+}
21218+
21219+static int __scst_acg_process_io_grouping_type_store(struct scst_tgt *tgt,
21220+ struct scst_acg *acg, int io_grouping_type)
21221+{
21222+ int res = 0;
21223+ struct scst_acg_dev *acg_dev;
21224+
21225+ TRACE_DBG("tgt %p, acg %p, io_grouping_type %d", tgt, acg,
21226+ io_grouping_type);
21227+
21228+ res = scst_suspend_activity(true);
21229+ if (res != 0)
21230+ goto out;
21231+
21232+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
21233+ res = -EINTR;
21234+ goto out_resume;
21235+ }
21236+
21237+ /* Check if tgt and acg not already freed while we were coming here */
21238+ if (scst_check_tgt_acg_ptrs(tgt, acg) != 0)
21239+ goto out_unlock;
21240+
21241+ acg->acg_io_grouping_type = io_grouping_type;
21242+
21243+ list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
21244+ int rc;
21245+
21246+ scst_stop_dev_threads(acg_dev->dev);
21247+
21248+ rc = scst_create_dev_threads(acg_dev->dev);
21249+ if (rc != 0)
21250+ res = rc;
21251+ }
21252+
21253+out_unlock:
21254+ mutex_unlock(&scst_mutex);
21255+
21256+out_resume:
21257+ scst_resume_activity();
21258+
21259+out:
21260+ return res;
21261+}
21262+
21263+static int __scst_acg_io_grouping_type_store_work_fn(struct scst_sysfs_work_item *work)
21264+{
21265+ return __scst_acg_process_io_grouping_type_store(work->tgt, work->acg,
21266+ work->io_grouping_type);
21267+}
21268+
21269+static ssize_t __scst_acg_io_grouping_type_store(struct scst_acg *acg,
21270+ const char *buf, size_t count)
21271+{
21272+ int res = 0;
21273+ int prev = acg->acg_io_grouping_type;
21274+ long io_grouping_type;
21275+ struct scst_sysfs_work_item *work;
21276+
21277+ if (strncasecmp(buf, SCST_IO_GROUPING_AUTO_STR,
21278+ min_t(int, strlen(SCST_IO_GROUPING_AUTO_STR), count)) == 0)
21279+ io_grouping_type = SCST_IO_GROUPING_AUTO;
21280+ else if (strncasecmp(buf, SCST_IO_GROUPING_THIS_GROUP_ONLY_STR,
21281+ min_t(int, strlen(SCST_IO_GROUPING_THIS_GROUP_ONLY_STR), count)) == 0)
21282+ io_grouping_type = SCST_IO_GROUPING_THIS_GROUP_ONLY;
21283+ else if (strncasecmp(buf, SCST_IO_GROUPING_NEVER_STR,
21284+ min_t(int, strlen(SCST_IO_GROUPING_NEVER_STR), count)) == 0)
21285+ io_grouping_type = SCST_IO_GROUPING_NEVER;
21286+ else {
21287+ res = strict_strtol(buf, 0, &io_grouping_type);
21288+ if ((res != 0) || (io_grouping_type <= 0)) {
21289+ PRINT_ERROR("Unknown or not allowed I/O grouping type "
21290+ "%s", buf);
21291+ res = -EINVAL;
21292+ goto out;
21293+ }
21294+ }
21295+
21296+ if (prev == io_grouping_type)
21297+ goto out;
21298+
21299+ res = scst_alloc_sysfs_work(__scst_acg_io_grouping_type_store_work_fn,
21300+ false, &work);
21301+ if (res != 0)
21302+ goto out;
21303+
21304+ work->tgt = acg->tgt;
21305+ work->acg = acg;
21306+ work->io_grouping_type = io_grouping_type;
21307+
21308+ res = scst_sysfs_queue_wait_work(work);
21309+
21310+out:
21311+ return res;
21312+}
21313+
21314+static ssize_t scst_tgt_io_grouping_type_show(struct kobject *kobj,
21315+ struct kobj_attribute *attr, char *buf)
21316+{
21317+ struct scst_acg *acg;
21318+ struct scst_tgt *tgt;
21319+
21320+ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
21321+ acg = tgt->default_acg;
21322+
21323+ return __scst_acg_io_grouping_type_show(acg, buf);
21324+}
21325+
21326+static ssize_t scst_tgt_io_grouping_type_store(struct kobject *kobj,
21327+ struct kobj_attribute *attr, const char *buf, size_t count)
21328+{
21329+ int res;
21330+ struct scst_acg *acg;
21331+ struct scst_tgt *tgt;
21332+
21333+ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
21334+ acg = tgt->default_acg;
21335+
21336+ res = __scst_acg_io_grouping_type_store(acg, buf, count);
21337+ if (res != 0)
21338+ goto out;
21339+
21340+ res = count;
21341+
21342+out:
21343+ TRACE_EXIT_RES(res);
21344+ return res;
21345+}
21346+
21347+/*
21348+ * Called with scst_mutex held.
21349+ *
21350+ * !! No sysfs works must use kobject_get() to protect acg, due to possible
21351+ * !! deadlock with scst_mutex (it is waiting for the last put, but
21352+ * !! the last ref counter holder is waiting for scst_mutex)
21353+ */
21354+void scst_acg_sysfs_del(struct scst_acg *acg)
21355+{
21356+ int rc;
21357+
21358+ TRACE_ENTRY();
21359+
21360+ kobject_del(acg->luns_kobj);
21361+ kobject_del(acg->initiators_kobj);
21362+ kobject_del(&acg->acg_kobj);
21363+
21364+ kobject_put(acg->luns_kobj);
21365+ kobject_put(acg->initiators_kobj);
21366+ kobject_put(&acg->acg_kobj);
21367+
21368+ rc = wait_for_completion_timeout(&acg->acg_kobj_release_cmpl, HZ);
21369+ if (rc == 0) {
21370+ PRINT_INFO("Waiting for releasing sysfs entry "
21371+ "for acg %s (%d refs)...", acg->acg_name,
21372+ atomic_read(&acg->acg_kobj.kref.refcount));
21373+ wait_for_completion(&acg->acg_kobj_release_cmpl);
21374+ PRINT_INFO("Done waiting for releasing sysfs "
21375+ "entry for acg %s", acg->acg_name);
21376+ }
21377+
21378+ TRACE_EXIT();
21379+ return;
21380+}
21381+
21382+int scst_acg_sysfs_create(struct scst_tgt *tgt,
21383+ struct scst_acg *acg)
21384+{
21385+ int res = 0;
21386+
21387+ TRACE_ENTRY();
21388+
21389+ init_completion(&acg->acg_kobj_release_cmpl);
21390+
21391+ res = kobject_init_and_add(&acg->acg_kobj, &acg_ktype,
21392+ tgt->tgt_ini_grp_kobj, acg->acg_name);
21393+ if (res != 0) {
21394+ PRINT_ERROR("Can't add acg '%s' to sysfs", acg->acg_name);
21395+ goto out;
21396+ }
21397+
21398+ acg->luns_kobj = kobject_create_and_add("luns", &acg->acg_kobj);
21399+ if (acg->luns_kobj == NULL) {
21400+ PRINT_ERROR("Can't create luns kobj for tgt %s",
21401+ tgt->tgt_name);
21402+ res = -ENOMEM;
21403+ goto out_del;
21404+ }
21405+
21406+ res = sysfs_create_file(acg->luns_kobj, &scst_acg_luns_mgmt.attr);
21407+ if (res != 0) {
21408+ PRINT_ERROR("Can't add tgt attr %s for tgt %s",
21409+ scst_acg_luns_mgmt.attr.name, tgt->tgt_name);
21410+ goto out_del;
21411+ }
21412+
21413+ acg->initiators_kobj = kobject_create_and_add("initiators",
21414+ &acg->acg_kobj);
21415+ if (acg->initiators_kobj == NULL) {
21416+ PRINT_ERROR("Can't create initiators kobj for tgt %s",
21417+ tgt->tgt_name);
21418+ res = -ENOMEM;
21419+ goto out_del;
21420+ }
21421+
21422+ res = sysfs_create_file(acg->initiators_kobj,
21423+ &scst_acg_ini_mgmt.attr);
21424+ if (res != 0) {
21425+ PRINT_ERROR("Can't add tgt attr %s for tgt %s",
21426+ scst_acg_ini_mgmt.attr.name, tgt->tgt_name);
21427+ goto out_del;
21428+ }
21429+
21430+ res = sysfs_create_file(&acg->acg_kobj, &scst_acg_addr_method.attr);
21431+ if (res != 0) {
21432+ PRINT_ERROR("Can't add tgt attr %s for tgt %s",
21433+ scst_acg_addr_method.attr.name, tgt->tgt_name);
21434+ goto out_del;
21435+ }
21436+
21437+ res = sysfs_create_file(&acg->acg_kobj, &scst_acg_io_grouping_type.attr);
21438+ if (res != 0) {
21439+ PRINT_ERROR("Can't add tgt attr %s for tgt %s",
21440+ scst_acg_io_grouping_type.attr.name, tgt->tgt_name);
21441+ goto out_del;
21442+ }
21443+
21444+out:
21445+ TRACE_EXIT_RES(res);
21446+ return res;
21447+
21448+out_del:
21449+ scst_acg_sysfs_del(acg);
21450+ goto out;
21451+}
21452+
21453+static ssize_t scst_acg_addr_method_show(struct kobject *kobj,
21454+ struct kobj_attribute *attr, char *buf)
21455+{
21456+ struct scst_acg *acg;
21457+
21458+ acg = container_of(kobj, struct scst_acg, acg_kobj);
21459+
21460+ return __scst_acg_addr_method_show(acg, buf);
21461+}
21462+
21463+static ssize_t scst_acg_addr_method_store(struct kobject *kobj,
21464+ struct kobj_attribute *attr, const char *buf, size_t count)
21465+{
21466+ int res;
21467+ struct scst_acg *acg;
21468+
21469+ acg = container_of(kobj, struct scst_acg, acg_kobj);
21470+
21471+ res = __scst_acg_addr_method_store(acg, buf, count);
21472+
21473+ TRACE_EXIT_RES(res);
21474+ return res;
21475+}
21476+
21477+static ssize_t scst_acg_io_grouping_type_show(struct kobject *kobj,
21478+ struct kobj_attribute *attr, char *buf)
21479+{
21480+ struct scst_acg *acg;
21481+
21482+ acg = container_of(kobj, struct scst_acg, acg_kobj);
21483+
21484+ return __scst_acg_io_grouping_type_show(acg, buf);
21485+}
21486+
21487+static ssize_t scst_acg_io_grouping_type_store(struct kobject *kobj,
21488+ struct kobj_attribute *attr, const char *buf, size_t count)
21489+{
21490+ int res;
21491+ struct scst_acg *acg;
21492+
21493+ acg = container_of(kobj, struct scst_acg, acg_kobj);
21494+
21495+ res = __scst_acg_io_grouping_type_store(acg, buf, count);
21496+ if (res != 0)
21497+ goto out;
21498+
21499+ res = count;
21500+
21501+out:
21502+ TRACE_EXIT_RES(res);
21503+ return res;
21504+}
21505+
21506+static ssize_t scst_ini_group_mgmt_show(struct kobject *kobj,
21507+ struct kobj_attribute *attr, char *buf)
21508+{
21509+ static char *help = "Usage: echo \"create GROUP_NAME\" >mgmt\n"
21510+ " echo \"del GROUP_NAME\" >mgmt\n";
21511+
21512+ return sprintf(buf, "%s", help);
21513+}
21514+
21515+static int scst_process_ini_group_mgmt_store(char *buffer,
21516+ struct scst_tgt *tgt)
21517+{
21518+ int res, action;
21519+ int len;
21520+ char *name;
21521+ char *p, *e = NULL;
21522+ struct scst_acg *a, *acg = NULL;
21523+
21524+#define SCST_INI_GROUP_ACTION_CREATE 1
21525+#define SCST_INI_GROUP_ACTION_DEL 2
21526+
21527+ TRACE_ENTRY();
21528+
21529+ TRACE_DBG("tgt %p, buffer %s", tgt, buffer);
21530+
21531+ p = buffer;
21532+ if (p[strlen(p) - 1] == '\n')
21533+ p[strlen(p) - 1] = '\0';
21534+ if (strncasecmp("create ", p, 7) == 0) {
21535+ p += 7;
21536+ action = SCST_INI_GROUP_ACTION_CREATE;
21537+ } else if (strncasecmp("del ", p, 4) == 0) {
21538+ p += 4;
21539+ action = SCST_INI_GROUP_ACTION_DEL;
21540+ } else {
21541+ PRINT_ERROR("Unknown action \"%s\"", p);
21542+ res = -EINVAL;
21543+ goto out;
21544+ }
21545+
21546+ res = scst_suspend_activity(true);
21547+ if (res != 0)
21548+ goto out;
21549+
21550+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
21551+ res = -EINTR;
21552+ goto out_resume;
21553+ }
21554+
21555+ /* Check if our pointer is still alive */
21556+ if (scst_check_tgt_acg_ptrs(tgt, NULL) != 0)
21557+ goto out_unlock;
21558+
21559+ while (isspace(*p) && *p != '\0')
21560+ p++;
21561+ e = p;
21562+ while (!isspace(*e) && *e != '\0')
21563+ e++;
21564+ *e = '\0';
21565+
21566+ if (p[0] == '\0') {
21567+ PRINT_ERROR("%s", "Group name required");
21568+ res = -EINVAL;
21569+ goto out_unlock;
21570+ }
21571+
21572+ list_for_each_entry(a, &tgt->tgt_acg_list, acg_list_entry) {
21573+ if (strcmp(a->acg_name, p) == 0) {
21574+ TRACE_DBG("group (acg) %p %s found",
21575+ a, a->acg_name);
21576+ acg = a;
21577+ break;
21578+ }
21579+ }
21580+
21581+ switch (action) {
21582+ case SCST_INI_GROUP_ACTION_CREATE:
21583+ TRACE_DBG("Creating group '%s'", p);
21584+ if (acg != NULL) {
21585+ PRINT_ERROR("acg name %s exist", p);
21586+ res = -EINVAL;
21587+ goto out_unlock;
21588+ }
21589+
21590+ len = strlen(p) + 1;
21591+ name = kmalloc(len, GFP_KERNEL);
21592+ if (name == NULL) {
21593+ PRINT_ERROR("%s", "Allocation of name failed");
21594+ res = -ENOMEM;
21595+ goto out_unlock;
21596+ }
21597+ strlcpy(name, p, len);
21598+
21599+ acg = scst_alloc_add_acg(tgt, name, true);
21600+ kfree(name);
21601+ if (acg == NULL)
21602+ goto out_unlock;
21603+ break;
21604+ case SCST_INI_GROUP_ACTION_DEL:
21605+ TRACE_DBG("Deleting group '%s'", p);
21606+ if (acg == NULL) {
21607+ PRINT_ERROR("Group %s not found", p);
21608+ res = -EINVAL;
21609+ goto out_unlock;
21610+ }
21611+ if (!scst_acg_sess_is_empty(acg)) {
21612+ PRINT_ERROR("Group %s is not empty", acg->acg_name);
21613+ res = -EBUSY;
21614+ goto out_unlock;
21615+ }
21616+ scst_del_free_acg(acg);
21617+ break;
21618+ }
21619+
21620+ res = 0;
21621+
21622+out_unlock:
21623+ mutex_unlock(&scst_mutex);
21624+
21625+out_resume:
21626+ scst_resume_activity();
21627+
21628+out:
21629+ TRACE_EXIT_RES(res);
21630+ return res;
21631+
21632+#undef SCST_LUN_ACTION_CREATE
21633+#undef SCST_LUN_ACTION_DEL
21634+}
21635+
21636+static int scst_ini_group_mgmt_store_work_fn(struct scst_sysfs_work_item *work)
21637+{
21638+ return scst_process_ini_group_mgmt_store(work->buf, work->tgt);
21639+}
21640+
21641+static ssize_t scst_ini_group_mgmt_store(struct kobject *kobj,
21642+ struct kobj_attribute *attr, const char *buf, size_t count)
21643+{
21644+ int res;
21645+ char *buffer;
21646+ struct scst_tgt *tgt;
21647+ struct scst_sysfs_work_item *work;
21648+
21649+ TRACE_ENTRY();
21650+
21651+ tgt = container_of(kobj->parent, struct scst_tgt, tgt_kobj);
21652+
21653+ buffer = kzalloc(count+1, GFP_KERNEL);
21654+ if (buffer == NULL) {
21655+ res = -ENOMEM;
21656+ goto out;
21657+ }
21658+ memcpy(buffer, buf, count);
21659+ buffer[count] = '\0';
21660+
21661+ res = scst_alloc_sysfs_work(scst_ini_group_mgmt_store_work_fn, false,
21662+ &work);
21663+ if (res != 0)
21664+ goto out_free;
21665+
21666+ work->buf = buffer;
21667+ work->tgt = tgt;
21668+
21669+ res = scst_sysfs_queue_wait_work(work);
21670+ if (res == 0)
21671+ res = count;
21672+
21673+out:
21674+ TRACE_EXIT_RES(res);
21675+ return res;
21676+
21677+out_free:
21678+ kfree(buffer);
21679+ goto out;
21680+}
21681+
21682+static ssize_t scst_rel_tgt_id_show(struct kobject *kobj,
21683+ struct kobj_attribute *attr, char *buf)
21684+{
21685+ struct scst_tgt *tgt;
21686+ int res;
21687+
21688+ TRACE_ENTRY();
21689+
21690+ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
21691+
21692+ res = sprintf(buf, "%d\n%s", tgt->rel_tgt_id,
21693+ (tgt->rel_tgt_id != 0) ? SCST_SYSFS_KEY_MARK "\n" : "");
21694+
21695+ TRACE_EXIT_RES(res);
21696+ return res;
21697+}
21698+
21699+static int scst_process_rel_tgt_id_store(struct scst_sysfs_work_item *work)
21700+{
21701+ int res = 0;
21702+ struct scst_tgt *tgt = work->tgt;
21703+ unsigned long rel_tgt_id = work->l;
21704+
21705+ TRACE_ENTRY();
21706+
21707+ /* tgt protected by kobject_get() */
21708+
21709+ TRACE_DBG("Trying to set relative target port id %d",
21710+ (uint16_t)rel_tgt_id);
21711+
21712+ if (tgt->tgtt->is_target_enabled(tgt) &&
21713+ rel_tgt_id != tgt->rel_tgt_id) {
21714+ if (!scst_is_relative_target_port_id_unique(rel_tgt_id, tgt)) {
21715+ PRINT_ERROR("Relative port id %d is not unique",
21716+ (uint16_t)rel_tgt_id);
21717+ res = -EBADSLT;
21718+ goto out_put;
21719+ }
21720+ }
21721+
21722+ if (rel_tgt_id < SCST_MIN_REL_TGT_ID ||
21723+ rel_tgt_id > SCST_MAX_REL_TGT_ID) {
21724+ if ((rel_tgt_id == 0) && !tgt->tgtt->is_target_enabled(tgt))
21725+ goto set;
21726+
21727+ PRINT_ERROR("Invalid relative port id %d",
21728+ (uint16_t)rel_tgt_id);
21729+ res = -EINVAL;
21730+ goto out_put;
21731+ }
21732+
21733+set:
21734+ tgt->rel_tgt_id = (uint16_t)rel_tgt_id;
21735+
21736+out_put:
21737+ kobject_put(&tgt->tgt_kobj);
21738+
21739+ TRACE_EXIT_RES(res);
21740+ return res;
21741+}
21742+
21743+static ssize_t scst_rel_tgt_id_store(struct kobject *kobj,
21744+ struct kobj_attribute *attr, const char *buf, size_t count)
21745+{
21746+ int res = 0;
21747+ struct scst_tgt *tgt;
21748+ unsigned long rel_tgt_id;
21749+ struct scst_sysfs_work_item *work;
21750+
21751+ TRACE_ENTRY();
21752+
21753+ if (buf == NULL)
21754+ goto out;
21755+
21756+ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
21757+
21758+ res = strict_strtoul(buf, 0, &rel_tgt_id);
21759+ if (res != 0) {
21760+ PRINT_ERROR("%s", "Wrong rel_tgt_id");
21761+ res = -EINVAL;
21762+ goto out;
21763+ }
21764+
21765+ res = scst_alloc_sysfs_work(scst_process_rel_tgt_id_store, false,
21766+ &work);
21767+ if (res != 0)
21768+ goto out;
21769+
21770+ work->tgt = tgt;
21771+ work->l = rel_tgt_id;
21772+
21773+ kobject_get(&tgt->tgt_kobj);
21774+
21775+ res = scst_sysfs_queue_wait_work(work);
21776+ if (res == 0)
21777+ res = count;
21778+
21779+out:
21780+ TRACE_EXIT_RES(res);
21781+ return res;
21782+}
21783+
21784+int scst_acn_sysfs_create(struct scst_acn *acn)
21785+{
21786+ int res = 0;
21787+ int len;
21788+ struct scst_acg *acg = acn->acg;
21789+ struct kobj_attribute *attr = NULL;
21790+#ifdef CONFIG_DEBUG_LOCK_ALLOC
21791+ static struct lock_class_key __key;
21792+#endif
21793+
21794+ TRACE_ENTRY();
21795+
21796+ acn->acn_attr = NULL;
21797+
21798+ attr = kzalloc(sizeof(struct kobj_attribute), GFP_KERNEL);
21799+ if (attr == NULL) {
21800+ PRINT_ERROR("Unable to allocate attributes for initiator '%s'",
21801+ acn->name);
21802+ res = -ENOMEM;
21803+ goto out;
21804+ }
21805+
21806+ len = strlen(acn->name) + 1;
21807+ attr->attr.name = kzalloc(len, GFP_KERNEL);
21808+ if (attr->attr.name == NULL) {
21809+ PRINT_ERROR("Unable to allocate attributes for initiator '%s'",
21810+ acn->name);
21811+ res = -ENOMEM;
21812+ goto out_free;
21813+ }
21814+ strlcpy((char *)attr->attr.name, acn->name, len);
21815+
21816+ attr->attr.owner = THIS_MODULE;
21817+#ifdef CONFIG_DEBUG_LOCK_ALLOC
21818+ attr->attr.key = &__key;
21819+#endif
21820+
21821+ attr->attr.mode = S_IRUGO;
21822+ attr->show = scst_acn_file_show;
21823+ attr->store = NULL;
21824+
21825+ res = sysfs_create_file(acg->initiators_kobj, &attr->attr);
21826+ if (res != 0) {
21827+ PRINT_ERROR("Unable to create acn '%s' for group '%s'",
21828+ acn->name, acg->acg_name);
21829+ kfree(attr->attr.name);
21830+ goto out_free;
21831+ }
21832+
21833+ acn->acn_attr = attr;
21834+
21835+out:
21836+ TRACE_EXIT_RES(res);
21837+ return res;
21838+
21839+out_free:
21840+ kfree(attr);
21841+ goto out;
21842+}
21843+
21844+void scst_acn_sysfs_del(struct scst_acn *acn)
21845+{
21846+ struct scst_acg *acg = acn->acg;
21847+
21848+ TRACE_ENTRY();
21849+
21850+ if (acn->acn_attr != NULL) {
21851+ sysfs_remove_file(acg->initiators_kobj,
21852+ &acn->acn_attr->attr);
21853+ kfree(acn->acn_attr->attr.name);
21854+ kfree(acn->acn_attr);
21855+ }
21856+
21857+ TRACE_EXIT();
21858+ return;
21859+}
21860+
21861+static ssize_t scst_acn_file_show(struct kobject *kobj,
21862+ struct kobj_attribute *attr, char *buf)
21863+{
21864+ return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n",
21865+ attr->attr.name);
21866+}
21867+
21868+static ssize_t scst_acg_luns_mgmt_store(struct kobject *kobj,
21869+ struct kobj_attribute *attr,
21870+ const char *buf, size_t count)
21871+{
21872+ int res;
21873+ struct scst_acg *acg;
21874+
21875+ acg = container_of(kobj->parent, struct scst_acg, acg_kobj);
21876+ res = __scst_luns_mgmt_store(acg, false, buf, count);
21877+
21878+ TRACE_EXIT_RES(res);
21879+ return res;
21880+}
21881+
21882+static ssize_t scst_acg_ini_mgmt_show(struct kobject *kobj,
21883+ struct kobj_attribute *attr, char *buf)
21884+{
21885+ static char *help = "Usage: echo \"add INITIATOR_NAME\" "
21886+ ">mgmt\n"
21887+ " echo \"del INITIATOR_NAME\" "
21888+ ">mgmt\n"
21889+ " echo \"move INITIATOR_NAME DEST_GROUP_NAME\" "
21890+ ">mgmt\n"
21891+ " echo \"clear\" "
21892+ ">mgmt\n";
21893+
21894+ return sprintf(buf, "%s", help);
21895+}
21896+
21897+static int scst_process_acg_ini_mgmt_store(char *buffer,
21898+ struct scst_tgt *tgt, struct scst_acg *acg)
21899+{
21900+ int res, action;
21901+ char *p, *e = NULL;
21902+ char *name = NULL, *group = NULL;
21903+ struct scst_acg *acg_dest = NULL;
21904+ struct scst_acn *acn = NULL, *acn_tmp;
21905+
21906+#define SCST_ACG_ACTION_INI_ADD 1
21907+#define SCST_ACG_ACTION_INI_DEL 2
21908+#define SCST_ACG_ACTION_INI_CLEAR 3
21909+#define SCST_ACG_ACTION_INI_MOVE 4
21910+
21911+ TRACE_ENTRY();
21912+
21913+ TRACE_DBG("tgt %p, acg %p, buffer %s", tgt, acg, buffer);
21914+
21915+ p = buffer;
21916+ if (p[strlen(p) - 1] == '\n')
21917+ p[strlen(p) - 1] = '\0';
21918+
21919+ if (strncasecmp("add", p, 3) == 0) {
21920+ p += 3;
21921+ action = SCST_ACG_ACTION_INI_ADD;
21922+ } else if (strncasecmp("del", p, 3) == 0) {
21923+ p += 3;
21924+ action = SCST_ACG_ACTION_INI_DEL;
21925+ } else if (strncasecmp("clear", p, 5) == 0) {
21926+ p += 5;
21927+ action = SCST_ACG_ACTION_INI_CLEAR;
21928+ } else if (strncasecmp("move", p, 4) == 0) {
21929+ p += 4;
21930+ action = SCST_ACG_ACTION_INI_MOVE;
21931+ } else {
21932+ PRINT_ERROR("Unknown action \"%s\"", p);
21933+ res = -EINVAL;
21934+ goto out;
21935+ }
21936+
21937+ if (action != SCST_ACG_ACTION_INI_CLEAR)
21938+ if (!isspace(*p)) {
21939+ PRINT_ERROR("%s", "Syntax error");
21940+ res = -EINVAL;
21941+ goto out;
21942+ }
21943+
21944+ res = scst_suspend_activity(true);
21945+ if (res != 0)
21946+ goto out;
21947+
21948+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
21949+ res = -EINTR;
21950+ goto out_resume;
21951+ }
21952+
21953+ /* Check if tgt and acg not already freed while we were coming here */
21954+ if (scst_check_tgt_acg_ptrs(tgt, acg) != 0)
21955+ goto out_unlock;
21956+
21957+ if (action != SCST_ACG_ACTION_INI_CLEAR)
21958+ while (isspace(*p) && *p != '\0')
21959+ p++;
21960+
21961+ switch (action) {
21962+ case SCST_ACG_ACTION_INI_ADD:
21963+ e = p;
21964+ while (!isspace(*e) && *e != '\0')
21965+ e++;
21966+ *e = '\0';
21967+ name = p;
21968+
21969+ if (name[0] == '\0') {
21970+ PRINT_ERROR("%s", "Invalid initiator name");
21971+ res = -EINVAL;
21972+ goto out_unlock;
21973+ }
21974+
21975+ res = scst_acg_add_acn(acg, name);
21976+ if (res != 0)
21977+ goto out_unlock;
21978+ break;
21979+ case SCST_ACG_ACTION_INI_DEL:
21980+ e = p;
21981+ while (!isspace(*e) && *e != '\0')
21982+ e++;
21983+ *e = '\0';
21984+ name = p;
21985+
21986+ if (name[0] == '\0') {
21987+ PRINT_ERROR("%s", "Invalid initiator name");
21988+ res = -EINVAL;
21989+ goto out_unlock;
21990+ }
21991+
21992+ acn = scst_find_acn(acg, name);
21993+ if (acn == NULL) {
21994+ PRINT_ERROR("Unable to find "
21995+ "initiator '%s' in group '%s'",
21996+ name, acg->acg_name);
21997+ res = -EINVAL;
21998+ goto out_unlock;
21999+ }
22000+ scst_del_free_acn(acn, true);
22001+ break;
22002+ case SCST_ACG_ACTION_INI_CLEAR:
22003+ list_for_each_entry_safe(acn, acn_tmp, &acg->acn_list,
22004+ acn_list_entry) {
22005+ scst_del_free_acn(acn, false);
22006+ }
22007+ scst_check_reassign_sessions();
22008+ break;
22009+ case SCST_ACG_ACTION_INI_MOVE:
22010+ e = p;
22011+ while (!isspace(*e) && *e != '\0')
22012+ e++;
22013+ if (*e == '\0') {
22014+ PRINT_ERROR("%s", "Too few parameters");
22015+ res = -EINVAL;
22016+ goto out_unlock;
22017+ }
22018+ *e = '\0';
22019+ name = p;
22020+
22021+ if (name[0] == '\0') {
22022+ PRINT_ERROR("%s", "Invalid initiator name");
22023+ res = -EINVAL;
22024+ goto out_unlock;
22025+ }
22026+
22027+ e++;
22028+ p = e;
22029+ while (!isspace(*e) && *e != '\0')
22030+ e++;
22031+ *e = '\0';
22032+ group = p;
22033+
22034+ if (group[0] == '\0') {
22035+ PRINT_ERROR("%s", "Invalid group name");
22036+ res = -EINVAL;
22037+ goto out_unlock;
22038+ }
22039+
22040+ TRACE_DBG("Move initiator '%s' to group '%s'",
22041+ name, group);
22042+
22043+ acn = scst_find_acn(acg, name);
22044+ if (acn == NULL) {
22045+ PRINT_ERROR("Unable to find "
22046+ "initiator '%s' in group '%s'",
22047+ name, acg->acg_name);
22048+ res = -EINVAL;
22049+ goto out_unlock;
22050+ }
22051+ acg_dest = scst_tgt_find_acg(tgt, group);
22052+ if (acg_dest == NULL) {
22053+ PRINT_ERROR("Unable to find group '%s' in target '%s'",
22054+ group, tgt->tgt_name);
22055+ res = -EINVAL;
22056+ goto out_unlock;
22057+ }
22058+ if (scst_find_acn(acg_dest, name) != NULL) {
22059+ PRINT_ERROR("Initiator '%s' already exists in group '%s'",
22060+ name, acg_dest->acg_name);
22061+ res = -EEXIST;
22062+ goto out_unlock;
22063+ }
22064+ scst_del_free_acn(acn, false);
22065+
22066+ res = scst_acg_add_acn(acg_dest, name);
22067+ if (res != 0)
22068+ goto out_unlock;
22069+ break;
22070+ }
22071+
22072+ res = 0;
22073+
22074+out_unlock:
22075+ mutex_unlock(&scst_mutex);
22076+
22077+out_resume:
22078+ scst_resume_activity();
22079+
22080+out:
22081+ TRACE_EXIT_RES(res);
22082+ return res;
22083+
22084+#undef SCST_ACG_ACTION_INI_ADD
22085+#undef SCST_ACG_ACTION_INI_DEL
22086+#undef SCST_ACG_ACTION_INI_CLEAR
22087+#undef SCST_ACG_ACTION_INI_MOVE
22088+}
22089+
22090+static int scst_acg_ini_mgmt_store_work_fn(struct scst_sysfs_work_item *work)
22091+{
22092+ return scst_process_acg_ini_mgmt_store(work->buf, work->tgt, work->acg);
22093+}
22094+
22095+static ssize_t scst_acg_ini_mgmt_store(struct kobject *kobj,
22096+ struct kobj_attribute *attr, const char *buf, size_t count)
22097+{
22098+ struct scst_acg *acg;
22099+
22100+ acg = container_of(kobj->parent, struct scst_acg, acg_kobj);
22101+
22102+ return __scst_acg_mgmt_store(acg, buf, count, false,
22103+ scst_acg_ini_mgmt_store_work_fn);
22104+}
22105+
22106+/**
22107+ ** SGV directory implementation
22108+ **/
22109+
22110+static struct kobj_attribute sgv_stat_attr =
22111+ __ATTR(stats, S_IRUGO | S_IWUSR, sgv_sysfs_stat_show,
22112+ sgv_sysfs_stat_reset);
22113+
22114+static struct attribute *sgv_attrs[] = {
22115+ &sgv_stat_attr.attr,
22116+ NULL,
22117+};
22118+
22119+static void sgv_kobj_release(struct kobject *kobj)
22120+{
22121+ struct sgv_pool *pool;
22122+
22123+ TRACE_ENTRY();
22124+
22125+ pool = container_of(kobj, struct sgv_pool, sgv_kobj);
22126+ complete_all(&pool->sgv_kobj_release_cmpl);
22127+
22128+ TRACE_EXIT();
22129+ return;
22130+}
22131+
22132+static struct kobj_type sgv_pool_ktype = {
22133+ .sysfs_ops = &scst_sysfs_ops,
22134+ .release = sgv_kobj_release,
22135+ .default_attrs = sgv_attrs,
22136+};
22137+
22138+int scst_sgv_sysfs_create(struct sgv_pool *pool)
22139+{
22140+ int res;
22141+
22142+ TRACE_ENTRY();
22143+
22144+ init_completion(&pool->sgv_kobj_release_cmpl);
22145+
22146+ res = kobject_init_and_add(&pool->sgv_kobj, &sgv_pool_ktype,
22147+ scst_sgv_kobj, pool->name);
22148+ if (res != 0) {
22149+ PRINT_ERROR("Can't add sgv pool %s to sysfs", pool->name);
22150+ goto out;
22151+ }
22152+
22153+out:
22154+ TRACE_EXIT_RES(res);
22155+ return res;
22156+}
22157+
22158+void scst_sgv_sysfs_del(struct sgv_pool *pool)
22159+{
22160+ int rc;
22161+
22162+ TRACE_ENTRY();
22163+
22164+ kobject_del(&pool->sgv_kobj);
22165+ kobject_put(&pool->sgv_kobj);
22166+
22167+ rc = wait_for_completion_timeout(&pool->sgv_kobj_release_cmpl, HZ);
22168+ if (rc == 0) {
22169+ PRINT_INFO("Waiting for releasing sysfs entry "
22170+ "for SGV pool %s (%d refs)...", pool->name,
22171+ atomic_read(&pool->sgv_kobj.kref.refcount));
22172+ wait_for_completion(&pool->sgv_kobj_release_cmpl);
22173+ PRINT_INFO("Done waiting for releasing sysfs "
22174+ "entry for SGV pool %s", pool->name);
22175+ }
22176+
22177+ TRACE_EXIT();
22178+ return;
22179+}
22180+
22181+static struct kobj_attribute sgv_global_stat_attr =
22182+ __ATTR(global_stats, S_IRUGO | S_IWUSR, sgv_sysfs_global_stat_show,
22183+ sgv_sysfs_global_stat_reset);
22184+
22185+static struct attribute *sgv_default_attrs[] = {
22186+ &sgv_global_stat_attr.attr,
22187+ NULL,
22188+};
22189+
22190+static void scst_sysfs_release(struct kobject *kobj)
22191+{
22192+ kfree(kobj);
22193+}
22194+
22195+static struct kobj_type sgv_ktype = {
22196+ .sysfs_ops = &scst_sysfs_ops,
22197+ .release = scst_sysfs_release,
22198+ .default_attrs = sgv_default_attrs,
22199+};
22200+
22201+/**
22202+ ** SCST sysfs root directory implementation
22203+ **/
22204+
22205+static ssize_t scst_threads_show(struct kobject *kobj,
22206+ struct kobj_attribute *attr, char *buf)
22207+{
22208+ int count;
22209+
22210+ TRACE_ENTRY();
22211+
22212+ count = sprintf(buf, "%d\n%s", scst_main_cmd_threads.nr_threads,
22213+ (scst_main_cmd_threads.nr_threads != scst_threads) ?
22214+ SCST_SYSFS_KEY_MARK "\n" : "");
22215+
22216+ TRACE_EXIT();
22217+ return count;
22218+}
22219+
22220+static int scst_process_threads_store(int newtn)
22221+{
22222+ int res;
22223+ long oldtn, delta;
22224+
22225+ TRACE_ENTRY();
22226+
22227+ TRACE_DBG("newtn %d", newtn);
22228+
22229+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
22230+ res = -EINTR;
22231+ goto out;
22232+ }
22233+
22234+ oldtn = scst_main_cmd_threads.nr_threads;
22235+
22236+ delta = newtn - oldtn;
22237+ if (delta < 0)
22238+ scst_del_threads(&scst_main_cmd_threads, -delta);
22239+ else {
22240+ res = scst_add_threads(&scst_main_cmd_threads, NULL, NULL, delta);
22241+ if (res != 0)
22242+ goto out_up;
22243+ }
22244+
22245+ PRINT_INFO("Changed cmd threads num: old %ld, new %d", oldtn, newtn);
22246+
22247+out_up:
22248+ mutex_unlock(&scst_mutex);
22249+
22250+out:
22251+ TRACE_EXIT_RES(res);
22252+ return res;
22253+}
22254+
22255+static int scst_threads_store_work_fn(struct scst_sysfs_work_item *work)
22256+{
22257+ return scst_process_threads_store(work->new_threads_num);
22258+}
22259+
22260+static ssize_t scst_threads_store(struct kobject *kobj,
22261+ struct kobj_attribute *attr, const char *buf, size_t count)
22262+{
22263+ int res;
22264+ long newtn;
22265+ struct scst_sysfs_work_item *work;
22266+
22267+ TRACE_ENTRY();
22268+
22269+ res = strict_strtol(buf, 0, &newtn);
22270+ if (res != 0) {
22271+ PRINT_ERROR("strict_strtol() for %s failed: %d ", buf, res);
22272+ goto out;
22273+ }
22274+ if (newtn <= 0) {
22275+ PRINT_ERROR("Illegal threads num value %ld", newtn);
22276+ res = -EINVAL;
22277+ goto out;
22278+ }
22279+
22280+ res = scst_alloc_sysfs_work(scst_threads_store_work_fn, false, &work);
22281+ if (res != 0)
22282+ goto out;
22283+
22284+ work->new_threads_num = newtn;
22285+
22286+ res = scst_sysfs_queue_wait_work(work);
22287+ if (res == 0)
22288+ res = count;
22289+
22290+out:
22291+ TRACE_EXIT_RES(res);
22292+ return res;
22293+}
22294+
22295+static ssize_t scst_setup_id_show(struct kobject *kobj,
22296+ struct kobj_attribute *attr, char *buf)
22297+{
22298+ int count;
22299+
22300+ TRACE_ENTRY();
22301+
22302+ count = sprintf(buf, "0x%x\n%s\n", scst_setup_id,
22303+ (scst_setup_id == 0) ? "" : SCST_SYSFS_KEY_MARK);
22304+
22305+ TRACE_EXIT();
22306+ return count;
22307+}
22308+
22309+static ssize_t scst_setup_id_store(struct kobject *kobj,
22310+ struct kobj_attribute *attr, const char *buf, size_t count)
22311+{
22312+ int res;
22313+ unsigned long val;
22314+
22315+ TRACE_ENTRY();
22316+
22317+ res = strict_strtoul(buf, 0, &val);
22318+ if (res != 0) {
22319+ PRINT_ERROR("strict_strtoul() for %s failed: %d ", buf, res);
22320+ goto out;
22321+ }
22322+
22323+ scst_setup_id = val;
22324+ PRINT_INFO("Changed scst_setup_id to %x", scst_setup_id);
22325+
22326+ res = count;
22327+
22328+out:
22329+ TRACE_EXIT_RES(res);
22330+ return res;
22331+}
22332+
22333+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
22334+
22335+static void scst_read_trace_tlb(const struct scst_trace_log *tbl, char *buf,
22336+ unsigned long log_level, int *pos)
22337+{
22338+ const struct scst_trace_log *t = tbl;
22339+
22340+ if (t == NULL)
22341+ goto out;
22342+
22343+ while (t->token) {
22344+ if (log_level & t->val) {
22345+ *pos += sprintf(&buf[*pos], "%s%s",
22346+ (*pos == 0) ? "" : " | ",
22347+ t->token);
22348+ }
22349+ t++;
22350+ }
22351+out:
22352+ return;
22353+}
22354+
22355+static ssize_t scst_trace_level_show(const struct scst_trace_log *local_tbl,
22356+ unsigned long log_level, char *buf, const char *help)
22357+{
22358+ int pos = 0;
22359+
22360+ scst_read_trace_tlb(scst_trace_tbl, buf, log_level, &pos);
22361+ scst_read_trace_tlb(local_tbl, buf, log_level, &pos);
22362+
22363+ pos += sprintf(&buf[pos], "\n\n\nUsage:\n"
22364+ " echo \"all|none|default\" >trace_level\n"
22365+ " echo \"value DEC|0xHEX|0OCT\" >trace_level\n"
22366+ " echo \"add|del TOKEN\" >trace_level\n"
22367+ "\nwhere TOKEN is one of [debug, function, line, pid,\n"
22368+#ifndef GENERATING_UPSTREAM_PATCH
22369+ " entryexit, buff, mem, sg, out_of_mem,\n"
22370+#else
22371+ " buff, mem, sg, out_of_mem,\n"
22372+#endif
22373+ " special, scsi, mgmt, minor,\n"
22374+ " mgmt_dbg, scsi_serializing,\n"
22375+ " retry, recv_bot, send_bot, recv_top, pr,\n"
22376+ " send_top%s]", help != NULL ? help : "");
22377+
22378+ return pos;
22379+}
22380+
22381+static ssize_t scst_main_trace_level_show(struct kobject *kobj,
22382+ struct kobj_attribute *attr, char *buf)
22383+{
22384+ return scst_trace_level_show(scst_local_trace_tbl, trace_flag,
22385+ buf, NULL);
22386+}
22387+
22388+static int scst_write_trace(const char *buf, size_t length,
22389+ unsigned long *log_level, unsigned long default_level,
22390+ const char *name, const struct scst_trace_log *tbl)
22391+{
22392+ int res = length;
22393+ int action;
22394+ unsigned long level = 0, oldlevel;
22395+ char *buffer, *p, *e;
22396+ const struct scst_trace_log *t;
22397+
22398+#define SCST_TRACE_ACTION_ALL 1
22399+#define SCST_TRACE_ACTION_NONE 2
22400+#define SCST_TRACE_ACTION_DEFAULT 3
22401+#define SCST_TRACE_ACTION_ADD 4
22402+#define SCST_TRACE_ACTION_DEL 5
22403+#define SCST_TRACE_ACTION_VALUE 6
22404+
22405+ TRACE_ENTRY();
22406+
22407+ if ((buf == NULL) || (length == 0)) {
22408+ res = -EINVAL;
22409+ goto out;
22410+ }
22411+
22412+ buffer = kmalloc(length+1, GFP_KERNEL);
22413+ if (buffer == NULL) {
22414+ PRINT_ERROR("Unable to alloc intermediate buffer (size %zd)",
22415+ length+1);
22416+ res = -ENOMEM;
22417+ goto out;
22418+ }
22419+ memcpy(buffer, buf, length);
22420+ buffer[length] = '\0';
22421+
22422+ TRACE_DBG("buffer %s", buffer);
22423+
22424+ p = buffer;
22425+ if (!strncasecmp("all", p, 3)) {
22426+ action = SCST_TRACE_ACTION_ALL;
22427+ } else if (!strncasecmp("none", p, 4) || !strncasecmp("null", p, 4)) {
22428+ action = SCST_TRACE_ACTION_NONE;
22429+ } else if (!strncasecmp("default", p, 7)) {
22430+ action = SCST_TRACE_ACTION_DEFAULT;
22431+ } else if (!strncasecmp("add", p, 3)) {
22432+ p += 3;
22433+ action = SCST_TRACE_ACTION_ADD;
22434+ } else if (!strncasecmp("del", p, 3)) {
22435+ p += 3;
22436+ action = SCST_TRACE_ACTION_DEL;
22437+ } else if (!strncasecmp("value", p, 5)) {
22438+ p += 5;
22439+ action = SCST_TRACE_ACTION_VALUE;
22440+ } else {
22441+ if (p[strlen(p) - 1] == '\n')
22442+ p[strlen(p) - 1] = '\0';
22443+ PRINT_ERROR("Unknown action \"%s\"", p);
22444+ res = -EINVAL;
22445+ goto out_free;
22446+ }
22447+
22448+ switch (action) {
22449+ case SCST_TRACE_ACTION_ADD:
22450+ case SCST_TRACE_ACTION_DEL:
22451+ case SCST_TRACE_ACTION_VALUE:
22452+ if (!isspace(*p)) {
22453+ PRINT_ERROR("%s", "Syntax error");
22454+ res = -EINVAL;
22455+ goto out_free;
22456+ }
22457+ }
22458+
22459+ switch (action) {
22460+ case SCST_TRACE_ACTION_ALL:
22461+ level = TRACE_ALL;
22462+ break;
22463+ case SCST_TRACE_ACTION_DEFAULT:
22464+ level = default_level;
22465+ break;
22466+ case SCST_TRACE_ACTION_NONE:
22467+ level = TRACE_NULL;
22468+ break;
22469+ case SCST_TRACE_ACTION_ADD:
22470+ case SCST_TRACE_ACTION_DEL:
22471+ while (isspace(*p) && *p != '\0')
22472+ p++;
22473+ e = p;
22474+ while (!isspace(*e) && *e != '\0')
22475+ e++;
22476+ *e = 0;
22477+ if (tbl) {
22478+ t = tbl;
22479+ while (t->token) {
22480+ if (!strcasecmp(p, t->token)) {
22481+ level = t->val;
22482+ break;
22483+ }
22484+ t++;
22485+ }
22486+ }
22487+ if (level == 0) {
22488+ t = scst_trace_tbl;
22489+ while (t->token) {
22490+ if (!strcasecmp(p, t->token)) {
22491+ level = t->val;
22492+ break;
22493+ }
22494+ t++;
22495+ }
22496+ }
22497+ if (level == 0) {
22498+ PRINT_ERROR("Unknown token \"%s\"", p);
22499+ res = -EINVAL;
22500+ goto out_free;
22501+ }
22502+ break;
22503+ case SCST_TRACE_ACTION_VALUE:
22504+ while (isspace(*p) && *p != '\0')
22505+ p++;
22506+ res = strict_strtoul(p, 0, &level);
22507+ if (res != 0) {
22508+ PRINT_ERROR("Invalid trace value \"%s\"", p);
22509+ res = -EINVAL;
22510+ goto out_free;
22511+ }
22512+ break;
22513+ }
22514+
22515+ oldlevel = *log_level;
22516+
22517+ switch (action) {
22518+ case SCST_TRACE_ACTION_ADD:
22519+ *log_level |= level;
22520+ break;
22521+ case SCST_TRACE_ACTION_DEL:
22522+ *log_level &= ~level;
22523+ break;
22524+ default:
22525+ *log_level = level;
22526+ break;
22527+ }
22528+
22529+ PRINT_INFO("Changed trace level for \"%s\": old 0x%08lx, new 0x%08lx",
22530+ name, oldlevel, *log_level);
22531+
22532+out_free:
22533+ kfree(buffer);
22534+out:
22535+ TRACE_EXIT_RES(res);
22536+ return res;
22537+
22538+#undef SCST_TRACE_ACTION_ALL
22539+#undef SCST_TRACE_ACTION_NONE
22540+#undef SCST_TRACE_ACTION_DEFAULT
22541+#undef SCST_TRACE_ACTION_ADD
22542+#undef SCST_TRACE_ACTION_DEL
22543+#undef SCST_TRACE_ACTION_VALUE
22544+}
22545+
22546+static ssize_t scst_main_trace_level_store(struct kobject *kobj,
22547+ struct kobj_attribute *attr, const char *buf, size_t count)
22548+{
22549+ int res;
22550+
22551+ TRACE_ENTRY();
22552+
22553+ if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
22554+ res = -EINTR;
22555+ goto out;
22556+ }
22557+
22558+ res = scst_write_trace(buf, count, &trace_flag,
22559+ SCST_DEFAULT_LOG_FLAGS, "scst", scst_local_trace_tbl);
22560+
22561+ mutex_unlock(&scst_log_mutex);
22562+
22563+out:
22564+ TRACE_EXIT_RES(res);
22565+ return res;
22566+}
22567+
22568+#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
22569+
22570+static ssize_t scst_version_show(struct kobject *kobj,
22571+ struct kobj_attribute *attr,
22572+ char *buf)
22573+{
22574+ TRACE_ENTRY();
22575+
22576+ sprintf(buf, "%s\n", SCST_VERSION_STRING);
22577+
22578+#ifdef CONFIG_SCST_STRICT_SERIALIZING
22579+ strcat(buf, "STRICT_SERIALIZING\n");
22580+#endif
22581+
22582+#ifdef CONFIG_SCST_EXTRACHECKS
22583+ strcat(buf, "EXTRACHECKS\n");
22584+#endif
22585+
22586+#ifdef CONFIG_SCST_TRACING
22587+ strcat(buf, "TRACING\n");
22588+#endif
22589+
22590+#ifdef CONFIG_SCST_DEBUG
22591+ strcat(buf, "DEBUG\n");
22592+#endif
22593+
22594+#ifdef CONFIG_SCST_DEBUG_TM
22595+ strcat(buf, "DEBUG_TM\n");
22596+#endif
22597+
22598+#ifdef CONFIG_SCST_DEBUG_RETRY
22599+ strcat(buf, "DEBUG_RETRY\n");
22600+#endif
22601+
22602+#ifdef CONFIG_SCST_DEBUG_OOM
22603+ strcat(buf, "DEBUG_OOM\n");
22604+#endif
22605+
22606+#ifdef CONFIG_SCST_DEBUG_SN
22607+ strcat(buf, "DEBUG_SN\n");
22608+#endif
22609+
22610+#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
22611+ strcat(buf, "USE_EXPECTED_VALUES\n");
22612+#endif
22613+
22614+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
22615+ strcat(buf, "TEST_IO_IN_SIRQ\n");
22616+#endif
22617+
22618+#ifdef CONFIG_SCST_STRICT_SECURITY
22619+ strcat(buf, "STRICT_SECURITY\n");
22620+#endif
22621+
22622+ TRACE_EXIT();
22623+ return strlen(buf);
22624+}
22625+
22626+static ssize_t scst_last_sysfs_mgmt_res_show(struct kobject *kobj,
22627+ struct kobj_attribute *attr, char *buf)
22628+{
22629+ int res;
22630+
22631+ TRACE_ENTRY();
22632+
22633+ spin_lock(&sysfs_work_lock);
22634+ TRACE_DBG("active_sysfs_works %d", active_sysfs_works);
22635+ if (active_sysfs_works > 0)
22636+ res = -EAGAIN;
22637+ else
22638+ res = sprintf(buf, "%d\n", last_sysfs_work_res);
22639+ spin_unlock(&sysfs_work_lock);
22640+
22641+ TRACE_EXIT_RES(res);
22642+ return res;
22643+}
22644+
22645+static struct kobj_attribute scst_threads_attr =
22646+ __ATTR(threads, S_IRUGO | S_IWUSR, scst_threads_show,
22647+ scst_threads_store);
22648+
22649+static struct kobj_attribute scst_setup_id_attr =
22650+ __ATTR(setup_id, S_IRUGO | S_IWUSR, scst_setup_id_show,
22651+ scst_setup_id_store);
22652+
22653+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
22654+static struct kobj_attribute scst_trace_level_attr =
22655+ __ATTR(trace_level, S_IRUGO | S_IWUSR, scst_main_trace_level_show,
22656+ scst_main_trace_level_store);
22657+#endif
22658+
22659+static struct kobj_attribute scst_version_attr =
22660+ __ATTR(version, S_IRUGO, scst_version_show, NULL);
22661+
22662+static struct kobj_attribute scst_last_sysfs_mgmt_res_attr =
22663+ __ATTR(last_sysfs_mgmt_res, S_IRUGO,
22664+ scst_last_sysfs_mgmt_res_show, NULL);
22665+
22666+static struct attribute *scst_sysfs_root_default_attrs[] = {
22667+ &scst_threads_attr.attr,
22668+ &scst_setup_id_attr.attr,
22669+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
22670+ &scst_trace_level_attr.attr,
22671+#endif
22672+ &scst_version_attr.attr,
22673+ &scst_last_sysfs_mgmt_res_attr.attr,
22674+ NULL,
22675+};
22676+
22677+static void scst_sysfs_root_release(struct kobject *kobj)
22678+{
22679+ complete_all(&scst_sysfs_root_release_completion);
22680+}
22681+
22682+static struct kobj_type scst_sysfs_root_ktype = {
22683+ .sysfs_ops = &scst_sysfs_ops,
22684+ .release = scst_sysfs_root_release,
22685+ .default_attrs = scst_sysfs_root_default_attrs,
22686+};
22687+
22688+/**
22689+ ** Dev handlers
22690+ **/
22691+
22692+static void scst_devt_release(struct kobject *kobj)
22693+{
22694+ struct scst_dev_type *devt;
22695+
22696+ TRACE_ENTRY();
22697+
22698+ devt = container_of(kobj, struct scst_dev_type, devt_kobj);
22699+ complete_all(&devt->devt_kobj_release_compl);
22700+
22701+ TRACE_EXIT();
22702+ return;
22703+}
22704+
22705+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
22706+
22707+static ssize_t scst_devt_trace_level_show(struct kobject *kobj,
22708+ struct kobj_attribute *attr, char *buf)
22709+{
22710+ struct scst_dev_type *devt;
22711+
22712+ devt = container_of(kobj, struct scst_dev_type, devt_kobj);
22713+
22714+ return scst_trace_level_show(devt->trace_tbl,
22715+ devt->trace_flags ? *devt->trace_flags : 0, buf,
22716+ devt->trace_tbl_help);
22717+}
22718+
22719+static ssize_t scst_devt_trace_level_store(struct kobject *kobj,
22720+ struct kobj_attribute *attr, const char *buf, size_t count)
22721+{
22722+ int res;
22723+ struct scst_dev_type *devt;
22724+
22725+ TRACE_ENTRY();
22726+
22727+ devt = container_of(kobj, struct scst_dev_type, devt_kobj);
22728+
22729+ if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
22730+ res = -EINTR;
22731+ goto out;
22732+ }
22733+
22734+ res = scst_write_trace(buf, count, devt->trace_flags,
22735+ devt->default_trace_flags, devt->name, devt->trace_tbl);
22736+
22737+ mutex_unlock(&scst_log_mutex);
22738+
22739+out:
22740+ TRACE_EXIT_RES(res);
22741+ return res;
22742+}
22743+
22744+static struct kobj_attribute devt_trace_attr =
22745+ __ATTR(trace_level, S_IRUGO | S_IWUSR,
22746+ scst_devt_trace_level_show, scst_devt_trace_level_store);
22747+
22748+#endif /* #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
22749+
22750+static ssize_t scst_devt_type_show(struct kobject *kobj,
22751+ struct kobj_attribute *attr, char *buf)
22752+{
22753+ int pos;
22754+ struct scst_dev_type *devt;
22755+
22756+ devt = container_of(kobj, struct scst_dev_type, devt_kobj);
22757+
22758+ pos = sprintf(buf, "%d - %s\n", devt->type,
22759+ (unsigned)devt->type > ARRAY_SIZE(scst_dev_handler_types) ?
22760+ "unknown" : scst_dev_handler_types[devt->type]);
22761+
22762+ return pos;
22763+}
22764+
22765+static struct kobj_attribute scst_devt_type_attr =
22766+ __ATTR(type, S_IRUGO, scst_devt_type_show, NULL);
22767+
22768+static struct attribute *scst_devt_default_attrs[] = {
22769+ &scst_devt_type_attr.attr,
22770+ NULL,
22771+};
22772+
22773+static struct kobj_type scst_devt_ktype = {
22774+ .sysfs_ops = &scst_sysfs_ops,
22775+ .release = scst_devt_release,
22776+ .default_attrs = scst_devt_default_attrs,
22777+};
22778+
22779+static ssize_t scst_devt_mgmt_show(struct kobject *kobj,
22780+ struct kobj_attribute *attr, char *buf)
22781+{
22782+ char *help = "Usage: echo \"add_device device_name [parameters]\" "
22783+ ">mgmt\n"
22784+ " echo \"del_device device_name\" >mgmt\n"
22785+ "%s%s"
22786+ "%s"
22787+ "\n"
22788+ "where parameters are one or more "
22789+ "param_name=value pairs separated by ';'\n\n"
22790+ "%s%s%s%s%s%s%s%s\n";
22791+ struct scst_dev_type *devt;
22792+
22793+ devt = container_of(kobj, struct scst_dev_type, devt_kobj);
22794+
22795+ return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, help,
22796+ (devt->devt_optional_attributes != NULL) ?
22797+ " echo \"add_attribute <attribute> <value>\" >mgmt\n"
22798+ " echo \"del_attribute <attribute> <value>\" >mgmt\n" : "",
22799+ (devt->dev_optional_attributes != NULL) ?
22800+ " echo \"add_device_attribute device_name <attribute> <value>\" >mgmt"
22801+ " echo \"del_device_attribute device_name <attribute> <value>\" >mgmt\n" : "",
22802+ (devt->mgmt_cmd_help) ? devt->mgmt_cmd_help : "",
22803+ (devt->add_device_parameters != NULL) ?
22804+ "The following parameters available: " : "",
22805+ (devt->add_device_parameters != NULL) ?
22806+ devt->add_device_parameters : "",
22807+ (devt->devt_optional_attributes != NULL) ?
22808+ "The following dev handler attributes available: " : "",
22809+ (devt->devt_optional_attributes != NULL) ?
22810+ devt->devt_optional_attributes : "",
22811+ (devt->devt_optional_attributes != NULL) ? "\n" : "",
22812+ (devt->dev_optional_attributes != NULL) ?
22813+ "The following device attributes available: " : "",
22814+ (devt->dev_optional_attributes != NULL) ?
22815+ devt->dev_optional_attributes : "",
22816+ (devt->dev_optional_attributes != NULL) ? "\n" : "");
22817+}
22818+
22819+static int scst_process_devt_mgmt_store(char *buffer,
22820+ struct scst_dev_type *devt)
22821+{
22822+ int res = 0;
22823+ char *p, *pp, *dev_name;
22824+
22825+ TRACE_ENTRY();
22826+
22827+ /* Check if our pointer is still alive and, if yes, grab it */
22828+ if (scst_check_grab_devt_ptr(devt, &scst_virtual_dev_type_list) != 0)
22829+ goto out;
22830+
22831+ TRACE_DBG("devt %p, buffer %s", devt, buffer);
22832+
22833+ pp = buffer;
22834+ if (pp[strlen(pp) - 1] == '\n')
22835+ pp[strlen(pp) - 1] = '\0';
22836+
22837+ p = scst_get_next_lexem(&pp);
22838+
22839+ if (strcasecmp("add_device", p) == 0) {
22840+ dev_name = scst_get_next_lexem(&pp);
22841+ if (*dev_name == '\0') {
22842+ PRINT_ERROR("%s", "Device name required");
22843+ res = -EINVAL;
22844+ goto out_ungrab;
22845+ }
22846+ res = devt->add_device(dev_name, pp);
22847+ } else if (strcasecmp("del_device", p) == 0) {
22848+ dev_name = scst_get_next_lexem(&pp);
22849+ if (*dev_name == '\0') {
22850+ PRINT_ERROR("%s", "Device name required");
22851+ res = -EINVAL;
22852+ goto out_ungrab;
22853+ }
22854+
22855+ p = scst_get_next_lexem(&pp);
22856+ if (*p != '\0')
22857+ goto out_syntax_err;
22858+
22859+ res = devt->del_device(dev_name);
22860+ } else if (devt->mgmt_cmd != NULL) {
22861+ scst_restore_token_str(p, pp);
22862+ res = devt->mgmt_cmd(buffer);
22863+ } else {
22864+ PRINT_ERROR("Unknown action \"%s\"", p);
22865+ res = -EINVAL;
22866+ goto out_ungrab;
22867+ }
22868+
22869+out_ungrab:
22870+ scst_ungrab_devt_ptr(devt);
22871+
22872+out:
22873+ TRACE_EXIT_RES(res);
22874+ return res;
22875+
22876+out_syntax_err:
22877+ PRINT_ERROR("Syntax error on \"%s\"", p);
22878+ res = -EINVAL;
22879+ goto out_ungrab;
22880+}
22881+
22882+static int scst_devt_mgmt_store_work_fn(struct scst_sysfs_work_item *work)
22883+{
22884+ return scst_process_devt_mgmt_store(work->buf, work->devt);
22885+}
22886+
22887+static ssize_t __scst_devt_mgmt_store(struct kobject *kobj,
22888+ struct kobj_attribute *attr, const char *buf, size_t count,
22889+ int (*sysfs_work_fn)(struct scst_sysfs_work_item *work))
22890+{
22891+ int res;
22892+ char *buffer;
22893+ struct scst_dev_type *devt;
22894+ struct scst_sysfs_work_item *work;
22895+
22896+ TRACE_ENTRY();
22897+
22898+ devt = container_of(kobj, struct scst_dev_type, devt_kobj);
22899+
22900+ buffer = kzalloc(count+1, GFP_KERNEL);
22901+ if (buffer == NULL) {
22902+ res = -ENOMEM;
22903+ goto out;
22904+ }
22905+ memcpy(buffer, buf, count);
22906+ buffer[count] = '\0';
22907+
22908+ res = scst_alloc_sysfs_work(sysfs_work_fn, false, &work);
22909+ if (res != 0)
22910+ goto out_free;
22911+
22912+ work->buf = buffer;
22913+ work->devt = devt;
22914+
22915+ res = scst_sysfs_queue_wait_work(work);
22916+ if (res == 0)
22917+ res = count;
22918+
22919+out:
22920+ TRACE_EXIT_RES(res);
22921+ return res;
22922+
22923+out_free:
22924+ kfree(buffer);
22925+ goto out;
22926+}
22927+
22928+static ssize_t scst_devt_mgmt_store(struct kobject *kobj,
22929+ struct kobj_attribute *attr, const char *buf, size_t count)
22930+{
22931+ return __scst_devt_mgmt_store(kobj, attr, buf, count,
22932+ scst_devt_mgmt_store_work_fn);
22933+}
22934+
22935+static struct kobj_attribute scst_devt_mgmt =
22936+ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_devt_mgmt_show,
22937+ scst_devt_mgmt_store);
22938+
22939+static ssize_t scst_devt_pass_through_mgmt_show(struct kobject *kobj,
22940+ struct kobj_attribute *attr, char *buf)
22941+{
22942+ char *help = "Usage: echo \"add_device H:C:I:L\" >mgmt\n"
22943+ " echo \"del_device H:C:I:L\" >mgmt\n";
22944+ return sprintf(buf, "%s", help);
22945+}
22946+
22947+static int scst_process_devt_pass_through_mgmt_store(char *buffer,
22948+ struct scst_dev_type *devt)
22949+{
22950+ int res = 0;
22951+ char *p, *pp, *action;
22952+ unsigned long host, channel, id, lun;
22953+ struct scst_device *d, *dev = NULL;
22954+
22955+ TRACE_ENTRY();
22956+
22957+ TRACE_DBG("devt %p, buffer %s", devt, buffer);
22958+
22959+ pp = buffer;
22960+ if (pp[strlen(pp) - 1] == '\n')
22961+ pp[strlen(pp) - 1] = '\0';
22962+
22963+ action = scst_get_next_lexem(&pp);
22964+ p = scst_get_next_lexem(&pp);
22965+ if (*p == '\0') {
22966+ PRINT_ERROR("%s", "Device required");
22967+ res = -EINVAL;
22968+ goto out;
22969+ }
22970+
22971+ if (*scst_get_next_lexem(&pp) != '\0') {
22972+ PRINT_ERROR("%s", "Too many parameters");
22973+ res = -EINVAL;
22974+ goto out_syntax_err;
22975+ }
22976+
22977+ host = simple_strtoul(p, &p, 0);
22978+ if ((host == ULONG_MAX) || (*p != ':'))
22979+ goto out_syntax_err;
22980+ p++;
22981+ channel = simple_strtoul(p, &p, 0);
22982+ if ((channel == ULONG_MAX) || (*p != ':'))
22983+ goto out_syntax_err;
22984+ p++;
22985+ id = simple_strtoul(p, &p, 0);
22986+ if ((channel == ULONG_MAX) || (*p != ':'))
22987+ goto out_syntax_err;
22988+ p++;
22989+ lun = simple_strtoul(p, &p, 0);
22990+ if (lun == ULONG_MAX)
22991+ goto out_syntax_err;
22992+
22993+ TRACE_DBG("Dev %ld:%ld:%ld:%ld", host, channel, id, lun);
22994+
22995+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
22996+ res = -EINTR;
22997+ goto out;
22998+ }
22999+
23000+ /* Check if devt not be already freed while we were coming here */
23001+ if (scst_check_devt_ptr(devt, &scst_dev_type_list) != 0)
23002+ goto out_unlock;
23003+
23004+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
23005+ if ((d->virt_id == 0) &&
23006+ d->scsi_dev->host->host_no == host &&
23007+ d->scsi_dev->channel == channel &&
23008+ d->scsi_dev->id == id &&
23009+ d->scsi_dev->lun == lun) {
23010+ dev = d;
23011+ TRACE_DBG("Dev %p (%ld:%ld:%ld:%ld) found",
23012+ dev, host, channel, id, lun);
23013+ break;
23014+ }
23015+ }
23016+ if (dev == NULL) {
23017+ PRINT_ERROR("Device %ld:%ld:%ld:%ld not found",
23018+ host, channel, id, lun);
23019+ res = -EINVAL;
23020+ goto out_unlock;
23021+ }
23022+
23023+ if (dev->scsi_dev->type != devt->type) {
23024+ PRINT_ERROR("Type %d of device %s differs from type "
23025+ "%d of dev handler %s", dev->type,
23026+ dev->virt_name, devt->type, devt->name);
23027+ res = -EINVAL;
23028+ goto out_unlock;
23029+ }
23030+
23031+ if (strcasecmp("add_device", action) == 0) {
23032+ res = scst_assign_dev_handler(dev, devt);
23033+ if (res == 0)
23034+ PRINT_INFO("Device %s assigned to dev handler %s",
23035+ dev->virt_name, devt->name);
23036+ } else if (strcasecmp("del_device", action) == 0) {
23037+ if (dev->handler != devt) {
23038+ PRINT_ERROR("Device %s is not assigned to handler %s",
23039+ dev->virt_name, devt->name);
23040+ res = -EINVAL;
23041+ goto out_unlock;
23042+ }
23043+ res = scst_assign_dev_handler(dev, &scst_null_devtype);
23044+ if (res == 0)
23045+ PRINT_INFO("Device %s unassigned from dev handler %s",
23046+ dev->virt_name, devt->name);
23047+ } else {
23048+ PRINT_ERROR("Unknown action \"%s\"", action);
23049+ res = -EINVAL;
23050+ goto out_unlock;
23051+ }
23052+
23053+out_unlock:
23054+ mutex_unlock(&scst_mutex);
23055+
23056+out:
23057+ TRACE_EXIT_RES(res);
23058+ return res;
23059+
23060+out_syntax_err:
23061+ PRINT_ERROR("Syntax error on \"%s\"", p);
23062+ res = -EINVAL;
23063+ goto out;
23064+}
23065+
23066+static int scst_devt_pass_through_mgmt_store_work_fn(
23067+ struct scst_sysfs_work_item *work)
23068+{
23069+ return scst_process_devt_pass_through_mgmt_store(work->buf, work->devt);
23070+}
23071+
23072+static ssize_t scst_devt_pass_through_mgmt_store(struct kobject *kobj,
23073+ struct kobj_attribute *attr, const char *buf, size_t count)
23074+{
23075+ return __scst_devt_mgmt_store(kobj, attr, buf, count,
23076+ scst_devt_pass_through_mgmt_store_work_fn);
23077+}
23078+
23079+static struct kobj_attribute scst_devt_pass_through_mgmt =
23080+ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_devt_pass_through_mgmt_show,
23081+ scst_devt_pass_through_mgmt_store);
23082+
23083+int scst_devt_sysfs_create(struct scst_dev_type *devt)
23084+{
23085+ int res;
23086+ struct kobject *parent;
23087+ const struct attribute **pattr;
23088+
23089+ TRACE_ENTRY();
23090+
23091+ init_completion(&devt->devt_kobj_release_compl);
23092+
23093+ if (devt->parent != NULL)
23094+ parent = &devt->parent->devt_kobj;
23095+ else
23096+ parent = scst_handlers_kobj;
23097+
23098+ res = kobject_init_and_add(&devt->devt_kobj, &scst_devt_ktype,
23099+ parent, devt->name);
23100+ if (res != 0) {
23101+ PRINT_ERROR("Can't add devt %s to sysfs", devt->name);
23102+ goto out;
23103+ }
23104+
23105+ if (devt->add_device != NULL) {
23106+ res = sysfs_create_file(&devt->devt_kobj,
23107+ &scst_devt_mgmt.attr);
23108+ } else {
23109+ res = sysfs_create_file(&devt->devt_kobj,
23110+ &scst_devt_pass_through_mgmt.attr);
23111+ }
23112+ if (res != 0) {
23113+ PRINT_ERROR("Can't add mgmt attr for dev handler %s",
23114+ devt->name);
23115+ goto out_err;
23116+ }
23117+
23118+ pattr = devt->devt_attrs;
23119+ if (pattr != NULL) {
23120+ while (*pattr != NULL) {
23121+ res = sysfs_create_file(&devt->devt_kobj, *pattr);
23122+ if (res != 0) {
23123+ PRINT_ERROR("Can't add devt attr %s for dev "
23124+ "handler %s", (*pattr)->name,
23125+ devt->name);
23126+ goto out_err;
23127+ }
23128+ pattr++;
23129+ }
23130+ }
23131+
23132+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
23133+ if (devt->trace_flags != NULL) {
23134+ res = sysfs_create_file(&devt->devt_kobj,
23135+ &devt_trace_attr.attr);
23136+ if (res != 0) {
23137+ PRINT_ERROR("Can't add devt trace_flag for dev "
23138+ "handler %s", devt->name);
23139+ goto out_err;
23140+ }
23141+ }
23142+#endif
23143+
23144+out:
23145+ TRACE_EXIT_RES(res);
23146+ return res;
23147+
23148+out_err:
23149+ scst_devt_sysfs_del(devt);
23150+ goto out;
23151+}
23152+
23153+void scst_devt_sysfs_del(struct scst_dev_type *devt)
23154+{
23155+ int rc;
23156+
23157+ TRACE_ENTRY();
23158+
23159+ kobject_del(&devt->devt_kobj);
23160+ kobject_put(&devt->devt_kobj);
23161+
23162+ rc = wait_for_completion_timeout(&devt->devt_kobj_release_compl, HZ);
23163+ if (rc == 0) {
23164+ PRINT_INFO("Waiting for releasing of sysfs entry "
23165+ "for dev handler template %s (%d refs)...", devt->name,
23166+ atomic_read(&devt->devt_kobj.kref.refcount));
23167+ wait_for_completion(&devt->devt_kobj_release_compl);
23168+ PRINT_INFO("Done waiting for releasing sysfs entry "
23169+ "for dev handler template %s", devt->name);
23170+ }
23171+
23172+ TRACE_EXIT();
23173+ return;
23174+}
23175+
23176+/**
23177+ ** Sysfs user info
23178+ **/
23179+
23180+static DEFINE_MUTEX(scst_sysfs_user_info_mutex);
23181+
23182+/* All protected by scst_sysfs_user_info_mutex */
23183+static LIST_HEAD(scst_sysfs_user_info_list);
23184+static uint32_t scst_sysfs_info_cur_cookie;
23185+
23186+/* scst_sysfs_user_info_mutex supposed to be held */
23187+static struct scst_sysfs_user_info *scst_sysfs_user_find_info(uint32_t cookie)
23188+{
23189+ struct scst_sysfs_user_info *info, *res = NULL;
23190+
23191+ TRACE_ENTRY();
23192+
23193+ list_for_each_entry(info, &scst_sysfs_user_info_list,
23194+ info_list_entry) {
23195+ if (info->info_cookie == cookie) {
23196+ res = info;
23197+ break;
23198+ }
23199+ }
23200+
23201+ TRACE_EXIT_HRES(res);
23202+ return res;
23203+}
23204+
23205+/**
23206+ * scst_sysfs_user_get_info() - get user_info
23207+ *
23208+ * Finds the user_info based on cookie and mark it as received the reply by
23209+ * setting for it flag info_being_executed.
23210+ *
23211+ * Returns found entry or NULL.
23212+ */
23213+struct scst_sysfs_user_info *scst_sysfs_user_get_info(uint32_t cookie)
23214+{
23215+ struct scst_sysfs_user_info *res = NULL;
23216+
23217+ TRACE_ENTRY();
23218+
23219+ mutex_lock(&scst_sysfs_user_info_mutex);
23220+
23221+ res = scst_sysfs_user_find_info(cookie);
23222+ if (res != NULL) {
23223+ if (!res->info_being_executed)
23224+ res->info_being_executed = 1;
23225+ }
23226+
23227+ mutex_unlock(&scst_sysfs_user_info_mutex);
23228+
23229+ TRACE_EXIT_HRES(res);
23230+ return res;
23231+}
23232+EXPORT_SYMBOL_GPL(scst_sysfs_user_get_info);
23233+
23234+/**
23235+ ** Helper functionality to help target drivers and dev handlers support
23236+ ** sending events to user space and wait for their completion in a safe
23237+ ** manner. See samples how to use it in iscsi-scst or scst_user.
23238+ **/
23239+
23240+/**
23241+ * scst_sysfs_user_add_info() - create and add user_info in the global list
23242+ *
23243+ * Creates an info structure and adds it in the info_list.
23244+ * Returns 0 and out_info on success, error code otherwise.
23245+ */
23246+int scst_sysfs_user_add_info(struct scst_sysfs_user_info **out_info)
23247+{
23248+ int res = 0;
23249+ struct scst_sysfs_user_info *info;
23250+
23251+ TRACE_ENTRY();
23252+
23253+ info = kzalloc(sizeof(*info), GFP_KERNEL);
23254+ if (info == NULL) {
23255+ PRINT_ERROR("Unable to allocate sysfs user info (size %zd)",
23256+ sizeof(*info));
23257+ res = -ENOMEM;
23258+ goto out;
23259+ }
23260+
23261+ mutex_lock(&scst_sysfs_user_info_mutex);
23262+
23263+ while ((info->info_cookie == 0) ||
23264+ (scst_sysfs_user_find_info(info->info_cookie) != NULL))
23265+ info->info_cookie = scst_sysfs_info_cur_cookie++;
23266+
23267+ init_completion(&info->info_completion);
23268+
23269+ list_add_tail(&info->info_list_entry, &scst_sysfs_user_info_list);
23270+ info->info_in_list = 1;
23271+
23272+ *out_info = info;
23273+
23274+ mutex_unlock(&scst_sysfs_user_info_mutex);
23275+
23276+out:
23277+ TRACE_EXIT_RES(res);
23278+ return res;
23279+}
23280+EXPORT_SYMBOL_GPL(scst_sysfs_user_add_info);
23281+
23282+/**
23283+ * scst_sysfs_user_del_info - delete and frees user_info
23284+ */
23285+void scst_sysfs_user_del_info(struct scst_sysfs_user_info *info)
23286+{
23287+ TRACE_ENTRY();
23288+
23289+ mutex_lock(&scst_sysfs_user_info_mutex);
23290+
23291+ if (info->info_in_list)
23292+ list_del(&info->info_list_entry);
23293+
23294+ mutex_unlock(&scst_sysfs_user_info_mutex);
23295+
23296+ kfree(info);
23297+
23298+ TRACE_EXIT();
23299+ return;
23300+}
23301+EXPORT_SYMBOL_GPL(scst_sysfs_user_del_info);
23302+
23303+/*
23304+ * Returns true if the reply received and being processed by another part of
23305+ * the kernel, false otherwise. Also removes the user_info from the list to
23306+ * fix for the user space that it missed the timeout.
23307+ */
23308+static bool scst_sysfs_user_info_executing(struct scst_sysfs_user_info *info)
23309+{
23310+ bool res;
23311+
23312+ TRACE_ENTRY();
23313+
23314+ mutex_lock(&scst_sysfs_user_info_mutex);
23315+
23316+ res = info->info_being_executed;
23317+
23318+ if (info->info_in_list) {
23319+ list_del(&info->info_list_entry);
23320+ info->info_in_list = 0;
23321+ }
23322+
23323+ mutex_unlock(&scst_sysfs_user_info_mutex);
23324+
23325+ TRACE_EXIT_RES(res);
23326+ return res;
23327+}
23328+
23329+/**
23330+ * scst_wait_info_completion() - wait an user space event's completion
23331+ *
23332+ * Waits for the info request been completed by user space at most timeout
23333+ * jiffies. If the reply received before timeout and being processed by
23334+ * another part of the kernel, i.e. scst_sysfs_user_info_executing()
23335+ * returned true, waits for it to complete indefinitely.
23336+ *
23337+ * Returns status of the request completion.
23338+ */
23339+int scst_wait_info_completion(struct scst_sysfs_user_info *info,
23340+ unsigned long timeout)
23341+{
23342+ int res, rc;
23343+
23344+ TRACE_ENTRY();
23345+
23346+ TRACE_DBG("Waiting for info %p completion", info);
23347+
23348+ while (1) {
23349+ rc = wait_for_completion_interruptible_timeout(
23350+ &info->info_completion, timeout);
23351+ if (rc > 0) {
23352+ TRACE_DBG("Waiting for info %p finished with %d",
23353+ info, rc);
23354+ break;
23355+ } else if (rc == 0) {
23356+ if (!scst_sysfs_user_info_executing(info)) {
23357+ PRINT_ERROR("Timeout waiting for user "
23358+ "space event %p", info);
23359+ res = -EBUSY;
23360+ goto out;
23361+ } else {
23362+ /* Req is being executed in the kernel */
23363+ TRACE_DBG("Keep waiting for info %p completion",
23364+ info);
23365+ wait_for_completion(&info->info_completion);
23366+ break;
23367+ }
23368+ } else if (rc != -ERESTARTSYS) {
23369+ res = rc;
23370+ PRINT_ERROR("wait_for_completion() failed: %d",
23371+ res);
23372+ goto out;
23373+ } else {
23374+ TRACE_DBG("Waiting for info %p finished with %d, "
23375+ "retrying", info, rc);
23376+ }
23377+ }
23378+
23379+ TRACE_DBG("info %p, status %d", info, info->info_status);
23380+ res = info->info_status;
23381+
23382+out:
23383+ TRACE_EXIT_RES(res);
23384+ return res;
23385+}
23386+EXPORT_SYMBOL_GPL(scst_wait_info_completion);
23387+
23388+int __init scst_sysfs_init(void)
23389+{
23390+ int res = 0;
23391+
23392+ TRACE_ENTRY();
23393+
23394+ sysfs_work_thread = kthread_run(sysfs_work_thread_fn,
23395+ NULL, "scst_uid");
23396+ if (IS_ERR(sysfs_work_thread)) {
23397+ res = PTR_ERR(sysfs_work_thread);
23398+ PRINT_ERROR("kthread_create() for user interface thread "
23399+ "failed: %d", res);
23400+ sysfs_work_thread = NULL;
23401+ goto out;
23402+ }
23403+
23404+ res = kobject_init_and_add(&scst_sysfs_root_kobj,
23405+ &scst_sysfs_root_ktype, kernel_kobj, "%s", "scst_tgt");
23406+ if (res != 0)
23407+ goto sysfs_root_add_error;
23408+
23409+ scst_targets_kobj = kobject_create_and_add("targets",
23410+ &scst_sysfs_root_kobj);
23411+ if (scst_targets_kobj == NULL)
23412+ goto targets_kobj_error;
23413+
23414+ scst_devices_kobj = kobject_create_and_add("devices",
23415+ &scst_sysfs_root_kobj);
23416+ if (scst_devices_kobj == NULL)
23417+ goto devices_kobj_error;
23418+
23419+ scst_sgv_kobj = kzalloc(sizeof(*scst_sgv_kobj), GFP_KERNEL);
23420+ if (scst_sgv_kobj == NULL)
23421+ goto sgv_kobj_error;
23422+
23423+ res = kobject_init_and_add(scst_sgv_kobj, &sgv_ktype,
23424+ &scst_sysfs_root_kobj, "%s", "sgv");
23425+ if (res != 0)
23426+ goto sgv_kobj_add_error;
23427+
23428+ scst_handlers_kobj = kobject_create_and_add("handlers",
23429+ &scst_sysfs_root_kobj);
23430+ if (scst_handlers_kobj == NULL)
23431+ goto handlers_kobj_error;
23432+
23433+out:
23434+ TRACE_EXIT_RES(res);
23435+ return res;
23436+
23437+handlers_kobj_error:
23438+ kobject_del(scst_sgv_kobj);
23439+
23440+sgv_kobj_add_error:
23441+ kobject_put(scst_sgv_kobj);
23442+
23443+sgv_kobj_error:
23444+ kobject_del(scst_devices_kobj);
23445+ kobject_put(scst_devices_kobj);
23446+
23447+devices_kobj_error:
23448+ kobject_del(scst_targets_kobj);
23449+ kobject_put(scst_targets_kobj);
23450+
23451+targets_kobj_error:
23452+ kobject_del(&scst_sysfs_root_kobj);
23453+
23454+sysfs_root_add_error:
23455+ kobject_put(&scst_sysfs_root_kobj);
23456+
23457+ kthread_stop(sysfs_work_thread);
23458+
23459+ if (res == 0)
23460+ res = -EINVAL;
23461+
23462+ goto out;
23463+}
23464+
23465+void scst_sysfs_cleanup(void)
23466+{
23467+ TRACE_ENTRY();
23468+
23469+ PRINT_INFO("%s", "Exiting SCST sysfs hierarchy...");
23470+
23471+ kobject_del(scst_sgv_kobj);
23472+ kobject_put(scst_sgv_kobj);
23473+
23474+ kobject_del(scst_devices_kobj);
23475+ kobject_put(scst_devices_kobj);
23476+
23477+ kobject_del(scst_targets_kobj);
23478+ kobject_put(scst_targets_kobj);
23479+
23480+ kobject_del(scst_handlers_kobj);
23481+ kobject_put(scst_handlers_kobj);
23482+
23483+ kobject_del(&scst_sysfs_root_kobj);
23484+ kobject_put(&scst_sysfs_root_kobj);
23485+
23486+ wait_for_completion(&scst_sysfs_root_release_completion);
23487+ /*
23488+ * There is a race, when in the release() schedule happens just after
23489+ * calling complete(), so if we exit and unload scst module immediately,
23490+ * there will be oops there. So let's give it a chance to quit
23491+ * gracefully. Unfortunately, current kobjects implementation
23492+ * doesn't allow better ways to handle it.
23493+ */
23494+ msleep(3000);
23495+
23496+ if (sysfs_work_thread)
23497+ kthread_stop(sysfs_work_thread);
23498+
23499+ PRINT_INFO("%s", "Exiting SCST sysfs hierarchy done");
23500+
23501+ TRACE_EXIT();
23502+ return;
23503+}
23504diff -uprN orig/linux-2.6.35/drivers/scst/scst_targ.c linux-2.6.35/drivers/scst/scst_targ.c
23505--- orig/linux-2.6.35/drivers/scst/scst_targ.c
23506+++ linux-2.6.35/drivers/scst/scst_targ.c
23507@@ -0,0 +1,6582 @@
23508+/*
23509+ * scst_targ.c
23510+ *
23511+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
23512+ * Copyright (C) 2004 - 2005 Leonid Stoljar
23513+ * Copyright (C) 2007 - 2010 ID7 Ltd.
23514+ *
23515+ * This program is free software; you can redistribute it and/or
23516+ * modify it under the terms of the GNU General Public License
23517+ * as published by the Free Software Foundation, version 2
23518+ * of the License.
23519+ *
23520+ * This program is distributed in the hope that it will be useful,
23521+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23522+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23523+ * GNU General Public License for more details.
23524+ */
23525+
23526+#include <linux/init.h>
23527+#include <linux/kernel.h>
23528+#include <linux/errno.h>
23529+#include <linux/list.h>
23530+#include <linux/spinlock.h>
23531+#include <linux/slab.h>
23532+#include <linux/sched.h>
23533+#include <linux/smp_lock.h>
23534+#include <linux/unistd.h>
23535+#include <linux/string.h>
23536+#include <linux/kthread.h>
23537+#include <linux/delay.h>
23538+#include <linux/ktime.h>
23539+
23540+#include <scst/scst.h>
23541+#include "scst_priv.h"
23542+#include "scst_pres.h"
23543+
23544+#if 0 /* Temporary left for future performance investigations */
23545+/* Deleting it don't forget to delete write_cmd_count */
23546+#define CONFIG_SCST_ORDERED_READS
23547+#endif
23548+
23549+#if 0 /* Let's disable it for now to see if users will complain about it */
23550+/* Deleting it don't forget to delete write_cmd_count */
23551+#define CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT
23552+#endif
23553+
23554+static void scst_cmd_set_sn(struct scst_cmd *cmd);
23555+static int __scst_init_cmd(struct scst_cmd *cmd);
23556+static void scst_finish_cmd_mgmt(struct scst_cmd *cmd);
23557+static struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess,
23558+ uint64_t tag, bool to_abort);
23559+static void scst_process_redirect_cmd(struct scst_cmd *cmd,
23560+ enum scst_exec_context context, int check_retries);
23561+
23562+/**
23563+ * scst_post_parse() - do post parse actions
23564+ *
23565+ * This function must be called by dev handler after its parse() callback
23566+ * returned SCST_CMD_STATE_STOP before calling scst_process_active_cmd().
23567+ */
23568+void scst_post_parse(struct scst_cmd *cmd)
23569+{
23570+ scst_set_parse_time(cmd);
23571+}
23572+EXPORT_SYMBOL_GPL(scst_post_parse);
23573+
23574+/**
23575+ * scst_post_alloc_data_buf() - do post alloc_data_buf actions
23576+ *
23577+ * This function must be called by dev handler after its alloc_data_buf()
23578+ * callback returned SCST_CMD_STATE_STOP before calling
23579+ * scst_process_active_cmd().
23580+ */
23581+void scst_post_alloc_data_buf(struct scst_cmd *cmd)
23582+{
23583+ scst_set_alloc_buf_time(cmd);
23584+}
23585+EXPORT_SYMBOL_GPL(scst_post_alloc_data_buf);
23586+
23587+static inline void scst_schedule_tasklet(struct scst_cmd *cmd)
23588+{
23589+ struct scst_tasklet *t = &scst_tasklets[smp_processor_id()];
23590+ unsigned long flags;
23591+
23592+ spin_lock_irqsave(&t->tasklet_lock, flags);
23593+ TRACE_DBG("Adding cmd %p to tasklet %d cmd list", cmd,
23594+ smp_processor_id());
23595+ list_add_tail(&cmd->cmd_list_entry, &t->tasklet_cmd_list);
23596+ spin_unlock_irqrestore(&t->tasklet_lock, flags);
23597+
23598+ tasklet_schedule(&t->tasklet);
23599+}
23600+
23601+/**
23602+ * scst_rx_cmd() - create new command
23603+ * @sess: SCST session
23604+ * @lun: LUN for the command
23605+ * @lun_len: length of the LUN in bytes
23606+ * @cdb: CDB of the command
23607+ * @cdb_len: length of the CDB in bytes
23608+ * @atomic: true, if current context is atomic
23609+ *
23610+ * Description:
23611+ * Creates new SCST command. Returns new command on success or
23612+ * NULL otherwise.
23613+ *
23614+ * Must not be called in parallel with scst_unregister_session() for the
23615+ * same session.
23616+ */
23617+struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
23618+ const uint8_t *lun, int lun_len, const uint8_t *cdb,
23619+ unsigned int cdb_len, int atomic)
23620+{
23621+ struct scst_cmd *cmd;
23622+
23623+ TRACE_ENTRY();
23624+
23625+#ifdef CONFIG_SCST_EXTRACHECKS
23626+ if (unlikely(sess->shut_phase != SCST_SESS_SPH_READY)) {
23627+ PRINT_CRIT_ERROR("%s",
23628+ "New cmd while shutting down the session");
23629+ BUG();
23630+ }
23631+#endif
23632+
23633+ cmd = scst_alloc_cmd(atomic ? GFP_ATOMIC : GFP_KERNEL);
23634+ if (cmd == NULL)
23635+ goto out;
23636+
23637+ cmd->sess = sess;
23638+ cmd->tgt = sess->tgt;
23639+ cmd->tgtt = sess->tgt->tgtt;
23640+
23641+ cmd->lun = scst_unpack_lun(lun, lun_len);
23642+ if (unlikely(cmd->lun == NO_SUCH_LUN)) {
23643+ PRINT_ERROR("Wrong LUN %d, finishing cmd", -1);
23644+ scst_set_cmd_error(cmd,
23645+ SCST_LOAD_SENSE(scst_sense_lun_not_supported));
23646+ }
23647+
23648+ /*
23649+ * For cdb_len 0 defer the error reporting until scst_cmd_init_done(),
23650+ * scst_set_cmd_error() supports nested calls.
23651+ */
23652+ if (unlikely(cdb_len > SCST_MAX_CDB_SIZE)) {
23653+ PRINT_ERROR("Too big CDB len %d, finishing cmd", cdb_len);
23654+ cdb_len = SCST_MAX_CDB_SIZE;
23655+ scst_set_cmd_error(cmd,
23656+ SCST_LOAD_SENSE(scst_sense_invalid_message));
23657+ }
23658+
23659+ memcpy(cmd->cdb, cdb, cdb_len);
23660+ cmd->cdb_len = cdb_len;
23661+
23662+ TRACE_DBG("cmd %p, sess %p", cmd, sess);
23663+ scst_sess_get(sess);
23664+
23665+out:
23666+ TRACE_EXIT();
23667+ return cmd;
23668+}
23669+EXPORT_SYMBOL(scst_rx_cmd);
23670+
23671+/*
23672+ * No locks, but might be on IRQ. Returns 0 on success, <0 if processing of
23673+ * this command should be stopped.
23674+ */
23675+static int scst_init_cmd(struct scst_cmd *cmd, enum scst_exec_context *context)
23676+{
23677+ int rc, res = 0;
23678+
23679+ TRACE_ENTRY();
23680+
23681+ /* See the comment in scst_do_job_init() */
23682+ if (unlikely(!list_empty(&scst_init_cmd_list))) {
23683+ TRACE_MGMT_DBG("%s", "init cmd list busy");
23684+ goto out_redirect;
23685+ }
23686+ /*
23687+ * Memory barrier isn't necessary here, because CPU appears to
23688+ * be self-consistent and we don't care about the race, described
23689+ * in comment in scst_do_job_init().
23690+ */
23691+
23692+ rc = __scst_init_cmd(cmd);
23693+ if (unlikely(rc > 0))
23694+ goto out_redirect;
23695+ else if (unlikely(rc != 0)) {
23696+ res = 1;
23697+ goto out;
23698+ }
23699+
23700+ EXTRACHECKS_BUG_ON(*context == SCST_CONTEXT_SAME);
23701+
23702+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
23703+ scst_get_cdb_info(cmd);
23704+ if (cmd->op_flags & SCST_TEST_IO_IN_SIRQ_ALLOWED)
23705+ goto out;
23706+#endif
23707+
23708+ /* Small context optimization */
23709+ if (((*context == SCST_CONTEXT_TASKLET) ||
23710+ (*context == SCST_CONTEXT_DIRECT_ATOMIC)) &&
23711+ scst_cmd_is_expected_set(cmd)) {
23712+ if (cmd->expected_data_direction & SCST_DATA_WRITE) {
23713+ if (!test_bit(SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC,
23714+ &cmd->tgt_dev->tgt_dev_flags))
23715+ *context = SCST_CONTEXT_THREAD;
23716+ } else
23717+ *context = SCST_CONTEXT_THREAD;
23718+ }
23719+
23720+out:
23721+ TRACE_EXIT_RES(res);
23722+ return res;
23723+
23724+out_redirect:
23725+ if (cmd->preprocessing_only) {
23726+ /*
23727+ * Poor man solution for single threaded targets, where
23728+ * blocking receiver at least sometimes means blocking all.
23729+ * For instance, iSCSI target won't be able to receive
23730+ * Data-Out PDUs.
23731+ */
23732+ BUG_ON(*context != SCST_CONTEXT_DIRECT);
23733+ scst_set_busy(cmd);
23734+ scst_set_cmd_abnormal_done_state(cmd);
23735+ res = 1;
23736+ /* Keep initiator away from too many BUSY commands */
23737+ msleep(50);
23738+ } else {
23739+ unsigned long flags;
23740+ spin_lock_irqsave(&scst_init_lock, flags);
23741+ TRACE_MGMT_DBG("Adding cmd %p to init cmd list (scst_cmd_count "
23742+ "%d)", cmd, atomic_read(&scst_cmd_count));
23743+ list_add_tail(&cmd->cmd_list_entry, &scst_init_cmd_list);
23744+ if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))
23745+ scst_init_poll_cnt++;
23746+ spin_unlock_irqrestore(&scst_init_lock, flags);
23747+ wake_up(&scst_init_cmd_list_waitQ);
23748+ res = -1;
23749+ }
23750+ goto out;
23751+}
23752+
23753+/**
23754+ * scst_cmd_init_done() - the command's initialization done
23755+ * @cmd: SCST command
23756+ * @pref_context: preferred command execution context
23757+ *
23758+ * Description:
23759+ * Notifies SCST that the driver finished its part of the command
23760+ * initialization, and the command is ready for execution.
23761+ * The second argument sets preferred command execition context.
23762+ * See SCST_CONTEXT_* constants for details.
23763+ *
23764+ * !!IMPORTANT!!
23765+ *
23766+ * If cmd->set_sn_on_restart_cmd not set, this function, as well as
23767+ * scst_cmd_init_stage1_done() and scst_restart_cmd(), must not be
23768+ * called simultaneously for the same session (more precisely,
23769+ * for the same session/LUN, i.e. tgt_dev), i.e. they must be
23770+ * somehow externally serialized. This is needed to have lock free fast
23771+ * path in scst_cmd_set_sn(). For majority of targets those functions are
23772+ * naturally serialized by the single source of commands. Only iSCSI
23773+ * immediate commands with multiple connections per session seems to be an
23774+ * exception. For it, some mutex/lock shall be used for the serialization.
23775+ */
23776+void scst_cmd_init_done(struct scst_cmd *cmd,
23777+ enum scst_exec_context pref_context)
23778+{
23779+ unsigned long flags;
23780+ struct scst_session *sess = cmd->sess;
23781+ int rc;
23782+
23783+ TRACE_ENTRY();
23784+
23785+ scst_set_start_time(cmd);
23786+
23787+ TRACE_DBG("Preferred context: %d (cmd %p)", pref_context, cmd);
23788+ TRACE(TRACE_SCSI, "tag=%llu, lun=%lld, CDB len=%d, queue_type=%x "
23789+ "(cmd %p)", (long long unsigned int)cmd->tag,
23790+ (long long unsigned int)cmd->lun, cmd->cdb_len,
23791+ cmd->queue_type, cmd);
23792+ PRINT_BUFF_FLAG(TRACE_SCSI|TRACE_RCV_BOT, "Recieving CDB",
23793+ cmd->cdb, cmd->cdb_len);
23794+
23795+#ifdef CONFIG_SCST_EXTRACHECKS
23796+ if (unlikely((in_irq() || irqs_disabled())) &&
23797+ ((pref_context == SCST_CONTEXT_DIRECT) ||
23798+ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC))) {
23799+ PRINT_ERROR("Wrong context %d in IRQ from target %s, use "
23800+ "SCST_CONTEXT_THREAD instead", pref_context,
23801+ cmd->tgtt->name);
23802+ pref_context = SCST_CONTEXT_THREAD;
23803+ }
23804+#endif
23805+
23806+ atomic_inc(&sess->sess_cmd_count);
23807+
23808+ spin_lock_irqsave(&sess->sess_list_lock, flags);
23809+
23810+ if (unlikely(sess->init_phase != SCST_SESS_IPH_READY)) {
23811+ /*
23812+ * We must always keep commands in the sess list from the
23813+ * very beginning, because otherwise they can be missed during
23814+ * TM processing. This check is needed because there might be
23815+ * old, i.e. deferred, commands and new, i.e. just coming, ones.
23816+ */
23817+ if (cmd->sess_cmd_list_entry.next == NULL)
23818+ list_add_tail(&cmd->sess_cmd_list_entry,
23819+ &sess->sess_cmd_list);
23820+ switch (sess->init_phase) {
23821+ case SCST_SESS_IPH_SUCCESS:
23822+ break;
23823+ case SCST_SESS_IPH_INITING:
23824+ TRACE_DBG("Adding cmd %p to init deferred cmd list",
23825+ cmd);
23826+ list_add_tail(&cmd->cmd_list_entry,
23827+ &sess->init_deferred_cmd_list);
23828+ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
23829+ goto out;
23830+ case SCST_SESS_IPH_FAILED:
23831+ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
23832+ scst_set_busy(cmd);
23833+ scst_set_cmd_abnormal_done_state(cmd);
23834+ goto active;
23835+ default:
23836+ BUG();
23837+ }
23838+ } else
23839+ list_add_tail(&cmd->sess_cmd_list_entry,
23840+ &sess->sess_cmd_list);
23841+
23842+ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
23843+
23844+ if (unlikely(cmd->cdb_len == 0)) {
23845+ PRINT_ERROR("%s", "Wrong CDB len 0, finishing cmd");
23846+ scst_set_cmd_error(cmd,
23847+ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
23848+ scst_set_cmd_abnormal_done_state(cmd);
23849+ goto active;
23850+ }
23851+
23852+ if (unlikely(cmd->queue_type >= SCST_CMD_QUEUE_ACA)) {
23853+ PRINT_ERROR("Unsupported queue type %d", cmd->queue_type);
23854+ scst_set_cmd_error(cmd,
23855+ SCST_LOAD_SENSE(scst_sense_invalid_message));
23856+ goto active;
23857+ }
23858+
23859+ /*
23860+ * Cmd must be inited here to preserve the order. In case if cmd
23861+ * already preliminary completed by target driver we need to init
23862+ * cmd anyway to find out in which format we should return sense.
23863+ */
23864+ cmd->state = SCST_CMD_STATE_INIT;
23865+ rc = scst_init_cmd(cmd, &pref_context);
23866+ if (unlikely(rc < 0))
23867+ goto out;
23868+
23869+active:
23870+ /* Here cmd must not be in any cmd list, no locks */
23871+ switch (pref_context) {
23872+ case SCST_CONTEXT_TASKLET:
23873+ scst_schedule_tasklet(cmd);
23874+ break;
23875+
23876+ case SCST_CONTEXT_DIRECT:
23877+ scst_process_active_cmd(cmd, false);
23878+ break;
23879+
23880+ case SCST_CONTEXT_DIRECT_ATOMIC:
23881+ scst_process_active_cmd(cmd, true);
23882+ break;
23883+
23884+ default:
23885+ PRINT_ERROR("Context %x is undefined, using the thread one",
23886+ pref_context);
23887+ /* go through */
23888+ case SCST_CONTEXT_THREAD:
23889+ spin_lock_irqsave(&cmd->cmd_threads->cmd_list_lock, flags);
23890+ TRACE_DBG("Adding cmd %p to active cmd list", cmd);
23891+ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
23892+ list_add(&cmd->cmd_list_entry,
23893+ &cmd->cmd_threads->active_cmd_list);
23894+ else
23895+ list_add_tail(&cmd->cmd_list_entry,
23896+ &cmd->cmd_threads->active_cmd_list);
23897+ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
23898+ spin_unlock_irqrestore(&cmd->cmd_threads->cmd_list_lock, flags);
23899+ break;
23900+ }
23901+
23902+out:
23903+ TRACE_EXIT();
23904+ return;
23905+}
23906+EXPORT_SYMBOL(scst_cmd_init_done);
23907+
23908+static int scst_pre_parse(struct scst_cmd *cmd)
23909+{
23910+ int res;
23911+ struct scst_device *dev = cmd->dev;
23912+ int rc;
23913+
23914+ TRACE_ENTRY();
23915+
23916+ /*
23917+ * Expected transfer data supplied by the SCSI transport via the
23918+ * target driver are untrusted, so we prefer to fetch them from CDB.
23919+ * Additionally, not all transports support supplying the expected
23920+ * transfer data.
23921+ */
23922+
23923+ rc = scst_get_cdb_info(cmd);
23924+ if (unlikely(rc != 0)) {
23925+ if (rc > 0) {
23926+ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
23927+ goto out_err;
23928+ }
23929+
23930+ EXTRACHECKS_BUG_ON(cmd->op_flags & SCST_INFO_VALID);
23931+
23932+ TRACE(TRACE_MINOR, "Unknown opcode 0x%02x for %s. "
23933+ "Should you update scst_scsi_op_table?",
23934+ cmd->cdb[0], dev->handler->name);
23935+ PRINT_BUFF_FLAG(TRACE_MINOR, "Failed CDB", cmd->cdb,
23936+ cmd->cdb_len);
23937+ } else
23938+ EXTRACHECKS_BUG_ON(!(cmd->op_flags & SCST_INFO_VALID));
23939+
23940+#ifdef CONFIG_SCST_STRICT_SERIALIZING
23941+ cmd->inc_expected_sn_on_done = 1;
23942+#else
23943+ cmd->inc_expected_sn_on_done = dev->handler->exec_sync ||
23944+ (!dev->has_own_order_mgmt &&
23945+ (dev->queue_alg == SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER ||
23946+ cmd->queue_type == SCST_CMD_QUEUE_ORDERED));
23947+#endif
23948+
23949+ TRACE_DBG("op_name <%s> (cmd %p), direction=%d "
23950+ "(expected %d, set %s), bufflen=%d, out_bufflen=%d (expected "
23951+ "len %d, out expected len %d), flags=%d", cmd->op_name, cmd,
23952+ cmd->data_direction, cmd->expected_data_direction,
23953+ scst_cmd_is_expected_set(cmd) ? "yes" : "no",
23954+ cmd->bufflen, cmd->out_bufflen, cmd->expected_transfer_len,
23955+ cmd->expected_out_transfer_len, cmd->op_flags);
23956+
23957+ res = 0;
23958+
23959+out:
23960+ TRACE_EXIT_RES(res);
23961+ return res;
23962+
23963+out_err:
23964+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
23965+ scst_set_cmd_abnormal_done_state(cmd);
23966+ res = -1;
23967+ goto out;
23968+}
23969+
23970+#ifndef CONFIG_SCST_USE_EXPECTED_VALUES
23971+static bool scst_is_allowed_to_mismatch_cmd(struct scst_cmd *cmd)
23972+{
23973+ bool res = false;
23974+
23975+ /* VERIFY commands with BYTCHK unset shouldn't fail here */
23976+ if ((cmd->op_flags & SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED) &&
23977+ (cmd->cdb[1] & BYTCHK) == 0) {
23978+ res = true;
23979+ goto out;
23980+ }
23981+
23982+ switch (cmd->cdb[0]) {
23983+ case TEST_UNIT_READY:
23984+ /* Crazy VMware people sometimes do TUR with READ direction */
23985+ if ((cmd->expected_data_direction == SCST_DATA_READ) ||
23986+ (cmd->expected_data_direction == SCST_DATA_NONE))
23987+ res = true;
23988+ break;
23989+ }
23990+
23991+out:
23992+ return res;
23993+}
23994+#endif
23995+
23996+static int scst_parse_cmd(struct scst_cmd *cmd)
23997+{
23998+ int res = SCST_CMD_STATE_RES_CONT_SAME;
23999+ int state;
24000+ struct scst_device *dev = cmd->dev;
24001+ int orig_bufflen = cmd->bufflen;
24002+
24003+ TRACE_ENTRY();
24004+
24005+ if (likely(!scst_is_cmd_fully_local(cmd))) {
24006+ if (unlikely(!dev->handler->parse_atomic &&
24007+ scst_cmd_atomic(cmd))) {
24008+ /*
24009+ * It shouldn't be because of the SCST_TGT_DEV_AFTER_*
24010+ * optimization.
24011+ */
24012+ TRACE_DBG("Dev handler %s parse() needs thread "
24013+ "context, rescheduling", dev->handler->name);
24014+ res = SCST_CMD_STATE_RES_NEED_THREAD;
24015+ goto out;
24016+ }
24017+
24018+ TRACE_DBG("Calling dev handler %s parse(%p)",
24019+ dev->handler->name, cmd);
24020+ TRACE_BUFF_FLAG(TRACE_SND_BOT, "Parsing: ",
24021+ cmd->cdb, cmd->cdb_len);
24022+ scst_set_cur_start(cmd);
24023+ state = dev->handler->parse(cmd);
24024+ /* Caution: cmd can be already dead here */
24025+ TRACE_DBG("Dev handler %s parse() returned %d",
24026+ dev->handler->name, state);
24027+
24028+ switch (state) {
24029+ case SCST_CMD_STATE_NEED_THREAD_CTX:
24030+ scst_set_parse_time(cmd);
24031+ TRACE_DBG("Dev handler %s parse() requested thread "
24032+ "context, rescheduling", dev->handler->name);
24033+ res = SCST_CMD_STATE_RES_NEED_THREAD;
24034+ goto out;
24035+
24036+ case SCST_CMD_STATE_STOP:
24037+ TRACE_DBG("Dev handler %s parse() requested stop "
24038+ "processing", dev->handler->name);
24039+ res = SCST_CMD_STATE_RES_CONT_NEXT;
24040+ goto out;
24041+ }
24042+
24043+ scst_set_parse_time(cmd);
24044+
24045+ if (state == SCST_CMD_STATE_DEFAULT)
24046+ state = SCST_CMD_STATE_PREPARE_SPACE;
24047+ } else
24048+ state = SCST_CMD_STATE_PREPARE_SPACE;
24049+
24050+ if (unlikely(state == SCST_CMD_STATE_PRE_XMIT_RESP))
24051+ goto set_res;
24052+
24053+ if (unlikely(!(cmd->op_flags & SCST_INFO_VALID))) {
24054+#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
24055+ if (scst_cmd_is_expected_set(cmd)) {
24056+ TRACE(TRACE_MINOR, "Using initiator supplied values: "
24057+ "direction %d, transfer_len %d/%d",
24058+ cmd->expected_data_direction,
24059+ cmd->expected_transfer_len,
24060+ cmd->expected_out_transfer_len);
24061+ cmd->data_direction = cmd->expected_data_direction;
24062+ cmd->bufflen = cmd->expected_transfer_len;
24063+ cmd->out_bufflen = cmd->expected_out_transfer_len;
24064+ } else {
24065+ PRINT_ERROR("Unknown opcode 0x%02x for %s and "
24066+ "target %s not supplied expected values",
24067+ cmd->cdb[0], dev->handler->name, cmd->tgtt->name);
24068+ scst_set_cmd_error(cmd,
24069+ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
24070+ goto out_done;
24071+ }
24072+#else
24073+ /*
24074+ * Let's ignore reporting T10/04-262r7 16-byte and 12-byte ATA
24075+ * pass-thru commands to not pollute logs (udev(?) checks them
24076+ * for some reason). If somebody has their description, please,
24077+ * update scst_scsi_op_table.
24078+ */
24079+ if ((cmd->cdb[0] != 0x85) && (cmd->cdb[0] != 0xa1))
24080+ PRINT_ERROR("Refusing unknown opcode %x", cmd->cdb[0]);
24081+ else
24082+ TRACE(TRACE_MINOR, "Refusing unknown opcode %x",
24083+ cmd->cdb[0]);
24084+ scst_set_cmd_error(cmd,
24085+ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
24086+ goto out_done;
24087+#endif
24088+ }
24089+
24090+ if (unlikely(cmd->cdb_len == 0)) {
24091+ PRINT_ERROR("Unable to get CDB length for "
24092+ "opcode 0x%02x. Returning INVALID "
24093+ "OPCODE", cmd->cdb[0]);
24094+ scst_set_cmd_error(cmd,
24095+ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
24096+ goto out_done;
24097+ }
24098+
24099+ EXTRACHECKS_BUG_ON(cmd->cdb_len == 0);
24100+
24101+ TRACE(TRACE_SCSI, "op_name <%s> (cmd %p), direction=%d "
24102+ "(expected %d, set %s), bufflen=%d, out_bufflen=%d, (expected "
24103+ "len %d, out expected len %d), flags=%x", cmd->op_name, cmd,
24104+ cmd->data_direction, cmd->expected_data_direction,
24105+ scst_cmd_is_expected_set(cmd) ? "yes" : "no",
24106+ cmd->bufflen, cmd->out_bufflen, cmd->expected_transfer_len,
24107+ cmd->expected_out_transfer_len, cmd->op_flags);
24108+
24109+ if (unlikely((cmd->op_flags & SCST_UNKNOWN_LENGTH) != 0)) {
24110+ if (scst_cmd_is_expected_set(cmd)) {
24111+ /*
24112+ * Command data length can't be easily
24113+ * determined from the CDB. ToDo, all such
24114+ * commands processing should be fixed. Until
24115+ * it's done, get the length from the supplied
24116+ * expected value, but limit it to some
24117+ * reasonable value (15MB).
24118+ */
24119+ cmd->bufflen = min(cmd->expected_transfer_len,
24120+ 15*1024*1024);
24121+ if (cmd->data_direction == SCST_DATA_BIDI)
24122+ cmd->out_bufflen = min(cmd->expected_out_transfer_len,
24123+ 15*1024*1024);
24124+ cmd->op_flags &= ~SCST_UNKNOWN_LENGTH;
24125+ } else {
24126+ PRINT_ERROR("Unknown data transfer length for opcode "
24127+ "0x%x (handler %s, target %s)", cmd->cdb[0],
24128+ dev->handler->name, cmd->tgtt->name);
24129+ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
24130+ scst_set_cmd_error(cmd,
24131+ SCST_LOAD_SENSE(scst_sense_invalid_message));
24132+ goto out_done;
24133+ }
24134+ }
24135+
24136+ if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_NACA_BIT)) {
24137+ PRINT_ERROR("NACA bit in control byte CDB is not supported "
24138+ "(opcode 0x%02x)", cmd->cdb[0]);
24139+ scst_set_cmd_error(cmd,
24140+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
24141+ goto out_done;
24142+ }
24143+
24144+ if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_LINK_BIT)) {
24145+ PRINT_ERROR("Linked commands are not supported "
24146+ "(opcode 0x%02x)", cmd->cdb[0]);
24147+ scst_set_cmd_error(cmd,
24148+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
24149+ goto out_done;
24150+ }
24151+
24152+ if (cmd->dh_data_buf_alloced &&
24153+ unlikely((orig_bufflen > cmd->bufflen))) {
24154+ PRINT_ERROR("Dev handler supplied data buffer (size %d), "
24155+ "is less, than required (size %d)", cmd->bufflen,
24156+ orig_bufflen);
24157+ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
24158+ goto out_hw_error;
24159+ }
24160+
24161+#ifdef CONFIG_SCST_EXTRACHECKS
24162+ if ((cmd->bufflen != 0) &&
24163+ ((cmd->data_direction == SCST_DATA_NONE) ||
24164+ ((cmd->sg == NULL) && (state > SCST_CMD_STATE_PREPARE_SPACE)))) {
24165+ PRINT_ERROR("Dev handler %s parse() returned "
24166+ "invalid cmd data_direction %d, bufflen %d, state %d "
24167+ "or sg %p (opcode 0x%x)", dev->handler->name,
24168+ cmd->data_direction, cmd->bufflen, state, cmd->sg,
24169+ cmd->cdb[0]);
24170+ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
24171+ goto out_hw_error;
24172+ }
24173+#endif
24174+
24175+ if (scst_cmd_is_expected_set(cmd)) {
24176+#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
24177+ if (unlikely((cmd->data_direction != cmd->expected_data_direction) ||
24178+ (cmd->bufflen != cmd->expected_transfer_len) ||
24179+ (cmd->out_bufflen != cmd->expected_out_transfer_len))) {
24180+ TRACE(TRACE_MINOR, "Expected values don't match "
24181+ "decoded ones: data_direction %d, "
24182+ "expected_data_direction %d, "
24183+ "bufflen %d, expected_transfer_len %d, "
24184+ "out_bufflen %d, expected_out_transfer_len %d",
24185+ cmd->data_direction,
24186+ cmd->expected_data_direction,
24187+ cmd->bufflen, cmd->expected_transfer_len,
24188+ cmd->out_bufflen, cmd->expected_out_transfer_len);
24189+ PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
24190+ cmd->cdb, cmd->cdb_len);
24191+ cmd->data_direction = cmd->expected_data_direction;
24192+ cmd->bufflen = cmd->expected_transfer_len;
24193+ cmd->out_bufflen = cmd->expected_out_transfer_len;
24194+ cmd->resid_possible = 1;
24195+ }
24196+#else
24197+ if (unlikely(cmd->data_direction !=
24198+ cmd->expected_data_direction)) {
24199+ if (((cmd->expected_data_direction != SCST_DATA_NONE) ||
24200+ (cmd->bufflen != 0)) &&
24201+ !scst_is_allowed_to_mismatch_cmd(cmd)) {
24202+ PRINT_ERROR("Expected data direction %d for "
24203+ "opcode 0x%02x (handler %s, target %s) "
24204+ "doesn't match decoded value %d",
24205+ cmd->expected_data_direction,
24206+ cmd->cdb[0], dev->handler->name,
24207+ cmd->tgtt->name, cmd->data_direction);
24208+ PRINT_BUFFER("Failed CDB", cmd->cdb,
24209+ cmd->cdb_len);
24210+ scst_set_cmd_error(cmd,
24211+ SCST_LOAD_SENSE(scst_sense_invalid_message));
24212+ goto out_done;
24213+ }
24214+ }
24215+ if (unlikely(cmd->bufflen != cmd->expected_transfer_len)) {
24216+ TRACE(TRACE_MINOR, "Warning: expected "
24217+ "transfer length %d for opcode 0x%02x "
24218+ "(handler %s, target %s) doesn't match "
24219+ "decoded value %d",
24220+ cmd->expected_transfer_len, cmd->cdb[0],
24221+ dev->handler->name, cmd->tgtt->name,
24222+ cmd->bufflen);
24223+ PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
24224+ cmd->cdb, cmd->cdb_len);
24225+ if ((cmd->data_direction & SCST_DATA_READ) ||
24226+ (cmd->data_direction & SCST_DATA_WRITE))
24227+ cmd->resid_possible = 1;
24228+ }
24229+ if (unlikely(cmd->out_bufflen != cmd->expected_out_transfer_len)) {
24230+ TRACE(TRACE_MINOR, "Warning: expected bidirectional OUT "
24231+ "transfer length %d for opcode 0x%02x "
24232+ "(handler %s, target %s) doesn't match "
24233+ "decoded value %d",
24234+ cmd->expected_out_transfer_len, cmd->cdb[0],
24235+ dev->handler->name, cmd->tgtt->name,
24236+ cmd->out_bufflen);
24237+ PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
24238+ cmd->cdb, cmd->cdb_len);
24239+ cmd->resid_possible = 1;
24240+ }
24241+#endif
24242+ }
24243+
24244+ if (unlikely(cmd->data_direction == SCST_DATA_UNKNOWN)) {
24245+ PRINT_ERROR("Unknown data direction. Opcode 0x%x, handler %s, "
24246+ "target %s", cmd->cdb[0], dev->handler->name,
24247+ cmd->tgtt->name);
24248+ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
24249+ goto out_hw_error;
24250+ }
24251+
24252+set_res:
24253+ if (cmd->data_len == -1)
24254+ cmd->data_len = cmd->bufflen;
24255+
24256+ if (cmd->bufflen == 0) {
24257+ /*
24258+ * According to SPC bufflen 0 for data transfer commands isn't
24259+ * an error, so we need to fix the transfer direction.
24260+ */
24261+ cmd->data_direction = SCST_DATA_NONE;
24262+ }
24263+
24264+#ifdef CONFIG_SCST_EXTRACHECKS
24265+ switch (state) {
24266+ case SCST_CMD_STATE_PREPARE_SPACE:
24267+ case SCST_CMD_STATE_PARSE:
24268+ case SCST_CMD_STATE_RDY_TO_XFER:
24269+ case SCST_CMD_STATE_TGT_PRE_EXEC:
24270+ case SCST_CMD_STATE_SEND_FOR_EXEC:
24271+ case SCST_CMD_STATE_LOCAL_EXEC:
24272+ case SCST_CMD_STATE_REAL_EXEC:
24273+ case SCST_CMD_STATE_PRE_DEV_DONE:
24274+ case SCST_CMD_STATE_DEV_DONE:
24275+ case SCST_CMD_STATE_PRE_XMIT_RESP:
24276+ case SCST_CMD_STATE_XMIT_RESP:
24277+ case SCST_CMD_STATE_FINISHED:
24278+ case SCST_CMD_STATE_FINISHED_INTERNAL:
24279+#endif
24280+ cmd->state = state;
24281+ res = SCST_CMD_STATE_RES_CONT_SAME;
24282+#ifdef CONFIG_SCST_EXTRACHECKS
24283+ break;
24284+
24285+ default:
24286+ if (state >= 0) {
24287+ PRINT_ERROR("Dev handler %s parse() returned "
24288+ "invalid cmd state %d (opcode %d)",
24289+ dev->handler->name, state, cmd->cdb[0]);
24290+ } else {
24291+ PRINT_ERROR("Dev handler %s parse() returned "
24292+ "error %d (opcode %d)", dev->handler->name,
24293+ state, cmd->cdb[0]);
24294+ }
24295+ goto out_hw_error;
24296+ }
24297+#endif
24298+
24299+ if (cmd->resp_data_len == -1) {
24300+ if (cmd->data_direction & SCST_DATA_READ)
24301+ cmd->resp_data_len = cmd->bufflen;
24302+ else
24303+ cmd->resp_data_len = 0;
24304+ }
24305+
24306+ /* We already completed (with an error) */
24307+ if (unlikely(cmd->completed))
24308+ goto out_done;
24309+
24310+out:
24311+ TRACE_EXIT_HRES(res);
24312+ return res;
24313+
24314+out_hw_error:
24315+ /* dev_done() will be called as part of the regular cmd's finish */
24316+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
24317+
24318+out_done:
24319+ scst_set_cmd_abnormal_done_state(cmd);
24320+ res = SCST_CMD_STATE_RES_CONT_SAME;
24321+ goto out;
24322+}
24323+
24324+static void scst_set_write_len(struct scst_cmd *cmd)
24325+{
24326+ TRACE_ENTRY();
24327+
24328+ EXTRACHECKS_BUG_ON(!(cmd->data_direction & SCST_DATA_WRITE));
24329+
24330+ if (cmd->data_direction & SCST_DATA_READ) {
24331+ cmd->write_len = cmd->out_bufflen;
24332+ cmd->write_sg = &cmd->out_sg;
24333+ cmd->write_sg_cnt = &cmd->out_sg_cnt;
24334+ } else {
24335+ cmd->write_len = cmd->bufflen;
24336+ /* write_sg and write_sg_cnt already initialized correctly */
24337+ }
24338+
24339+ TRACE_MEM("cmd %p, write_len %d, write_sg %p, write_sg_cnt %d, "
24340+ "resid_possible %d", cmd, cmd->write_len, *cmd->write_sg,
24341+ *cmd->write_sg_cnt, cmd->resid_possible);
24342+
24343+ if (unlikely(cmd->resid_possible)) {
24344+ if (cmd->data_direction & SCST_DATA_READ) {
24345+ cmd->write_len = min(cmd->out_bufflen,
24346+ cmd->expected_out_transfer_len);
24347+ if (cmd->write_len == cmd->out_bufflen)
24348+ goto out;
24349+ } else {
24350+ cmd->write_len = min(cmd->bufflen,
24351+ cmd->expected_transfer_len);
24352+ if (cmd->write_len == cmd->bufflen)
24353+ goto out;
24354+ }
24355+ scst_limit_sg_write_len(cmd);
24356+ }
24357+
24358+out:
24359+ TRACE_EXIT();
24360+ return;
24361+}
24362+
24363+static int scst_prepare_space(struct scst_cmd *cmd)
24364+{
24365+ int r = 0, res = SCST_CMD_STATE_RES_CONT_SAME;
24366+ struct scst_device *dev = cmd->dev;
24367+
24368+ TRACE_ENTRY();
24369+
24370+ if (cmd->data_direction == SCST_DATA_NONE)
24371+ goto done;
24372+
24373+ if (likely(!scst_is_cmd_fully_local(cmd)) &&
24374+ (dev->handler->alloc_data_buf != NULL)) {
24375+ int state;
24376+
24377+ if (unlikely(!dev->handler->alloc_data_buf_atomic &&
24378+ scst_cmd_atomic(cmd))) {
24379+ /*
24380+ * It shouldn't be because of the SCST_TGT_DEV_AFTER_*
24381+ * optimization.
24382+ */
24383+ TRACE_DBG("Dev handler %s alloc_data_buf() needs "
24384+ "thread context, rescheduling",
24385+ dev->handler->name);
24386+ res = SCST_CMD_STATE_RES_NEED_THREAD;
24387+ goto out;
24388+ }
24389+
24390+ TRACE_DBG("Calling dev handler %s alloc_data_buf(%p)",
24391+ dev->handler->name, cmd);
24392+ scst_set_cur_start(cmd);
24393+ state = dev->handler->alloc_data_buf(cmd);
24394+ /* Caution: cmd can be already dead here */
24395+ TRACE_DBG("Dev handler %s alloc_data_buf() returned %d",
24396+ dev->handler->name, state);
24397+
24398+ switch (state) {
24399+ case SCST_CMD_STATE_NEED_THREAD_CTX:
24400+ scst_set_alloc_buf_time(cmd);
24401+ TRACE_DBG("Dev handler %s alloc_data_buf() requested "
24402+ "thread context, rescheduling",
24403+ dev->handler->name);
24404+ res = SCST_CMD_STATE_RES_NEED_THREAD;
24405+ goto out;
24406+
24407+ case SCST_CMD_STATE_STOP:
24408+ TRACE_DBG("Dev handler %s alloc_data_buf() requested "
24409+ "stop processing", dev->handler->name);
24410+ res = SCST_CMD_STATE_RES_CONT_NEXT;
24411+ goto out;
24412+ }
24413+
24414+ scst_set_alloc_buf_time(cmd);
24415+
24416+ if (unlikely(state != SCST_CMD_STATE_DEFAULT)) {
24417+ cmd->state = state;
24418+ goto out;
24419+ }
24420+ }
24421+
24422+ if (cmd->tgt_need_alloc_data_buf) {
24423+ int orig_bufflen = cmd->bufflen;
24424+
24425+ TRACE_MEM("Custom tgt data buf allocation requested (cmd %p)",
24426+ cmd);
24427+
24428+ scst_set_cur_start(cmd);
24429+ r = cmd->tgtt->alloc_data_buf(cmd);
24430+ scst_set_alloc_buf_time(cmd);
24431+
24432+ if (r > 0)
24433+ goto alloc;
24434+ else if (r == 0) {
24435+ if (unlikely(cmd->bufflen == 0)) {
24436+ /* See comment in scst_alloc_space() */
24437+ if (cmd->sg == NULL)
24438+ goto alloc;
24439+ }
24440+
24441+ cmd->tgt_data_buf_alloced = 1;
24442+
24443+ if (unlikely(orig_bufflen < cmd->bufflen)) {
24444+ PRINT_ERROR("Target driver allocated data "
24445+ "buffer (size %d), is less, than "
24446+ "required (size %d)", orig_bufflen,
24447+ cmd->bufflen);
24448+ goto out_error;
24449+ }
24450+ TRACE_MEM("tgt_data_buf_alloced (cmd %p)", cmd);
24451+ } else
24452+ goto check;
24453+ }
24454+
24455+alloc:
24456+ if (!cmd->tgt_data_buf_alloced && !cmd->dh_data_buf_alloced) {
24457+ r = scst_alloc_space(cmd);
24458+ } else if (cmd->dh_data_buf_alloced && !cmd->tgt_data_buf_alloced) {
24459+ TRACE_MEM("dh_data_buf_alloced set (cmd %p)", cmd);
24460+ r = 0;
24461+ } else if (cmd->tgt_data_buf_alloced && !cmd->dh_data_buf_alloced) {
24462+ TRACE_MEM("tgt_data_buf_alloced set (cmd %p)", cmd);
24463+ cmd->sg = cmd->tgt_sg;
24464+ cmd->sg_cnt = cmd->tgt_sg_cnt;
24465+ cmd->out_sg = cmd->tgt_out_sg;
24466+ cmd->out_sg_cnt = cmd->tgt_out_sg_cnt;
24467+ r = 0;
24468+ } else {
24469+ TRACE_MEM("Both *_data_buf_alloced set (cmd %p, sg %p, "
24470+ "sg_cnt %d, tgt_sg %p, tgt_sg_cnt %d)", cmd, cmd->sg,
24471+ cmd->sg_cnt, cmd->tgt_sg, cmd->tgt_sg_cnt);
24472+ r = 0;
24473+ }
24474+
24475+check:
24476+ if (r != 0) {
24477+ if (scst_cmd_atomic(cmd)) {
24478+ TRACE_MEM("%s", "Atomic memory allocation failed, "
24479+ "rescheduling to the thread");
24480+ res = SCST_CMD_STATE_RES_NEED_THREAD;
24481+ goto out;
24482+ } else
24483+ goto out_no_space;
24484+ }
24485+
24486+done:
24487+ if (cmd->preprocessing_only) {
24488+ cmd->state = SCST_CMD_STATE_PREPROCESSING_DONE;
24489+ if (cmd->data_direction & SCST_DATA_WRITE)
24490+ scst_set_write_len(cmd);
24491+ } else if (cmd->data_direction & SCST_DATA_WRITE) {
24492+ cmd->state = SCST_CMD_STATE_RDY_TO_XFER;
24493+ scst_set_write_len(cmd);
24494+ } else
24495+ cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC;
24496+
24497+out:
24498+ TRACE_EXIT_HRES(res);
24499+ return res;
24500+
24501+out_no_space:
24502+ TRACE(TRACE_OUT_OF_MEM, "Unable to allocate or build requested buffer "
24503+ "(size %d), sending BUSY or QUEUE FULL status", cmd->bufflen);
24504+ scst_set_busy(cmd);
24505+ scst_set_cmd_abnormal_done_state(cmd);
24506+ res = SCST_CMD_STATE_RES_CONT_SAME;
24507+ goto out;
24508+
24509+out_error:
24510+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
24511+ scst_set_cmd_abnormal_done_state(cmd);
24512+ res = SCST_CMD_STATE_RES_CONT_SAME;
24513+ goto out;
24514+}
24515+
24516+static int scst_preprocessing_done(struct scst_cmd *cmd)
24517+{
24518+ int res;
24519+
24520+ TRACE_ENTRY();
24521+
24522+ EXTRACHECKS_BUG_ON(!cmd->preprocessing_only);
24523+
24524+ cmd->preprocessing_only = 0;
24525+
24526+ res = SCST_CMD_STATE_RES_CONT_NEXT;
24527+ cmd->state = SCST_CMD_STATE_PREPROCESSING_DONE_CALLED;
24528+
24529+ TRACE_DBG("Calling preprocessing_done(cmd %p)", cmd);
24530+ scst_set_cur_start(cmd);
24531+ cmd->tgtt->preprocessing_done(cmd);
24532+ TRACE_DBG("%s", "preprocessing_done() returned");
24533+
24534+ TRACE_EXIT_HRES(res);
24535+ return res;
24536+}
24537+
24538+/**
24539+ * scst_restart_cmd() - restart execution of the command
24540+ * @cmd: SCST commands
24541+ * @status: completion status
24542+ * @pref_context: preferred command execition context
24543+ *
24544+ * Description:
24545+ * Notifies SCST that the driver finished its part of the command's
24546+ * preprocessing and it is ready for further processing.
24547+ *
24548+ * The second argument sets completion status
24549+ * (see SCST_PREPROCESS_STATUS_* constants for details)
24550+ *
24551+ * See also comment for scst_cmd_init_done() for the serialization
24552+ * requirements.
24553+ */
24554+void scst_restart_cmd(struct scst_cmd *cmd, int status,
24555+ enum scst_exec_context pref_context)
24556+{
24557+ TRACE_ENTRY();
24558+
24559+ scst_set_restart_waiting_time(cmd);
24560+
24561+ TRACE_DBG("Preferred context: %d", pref_context);
24562+ TRACE_DBG("tag=%llu, status=%#x",
24563+ (long long unsigned int)scst_cmd_get_tag(cmd),
24564+ status);
24565+
24566+#ifdef CONFIG_SCST_EXTRACHECKS
24567+ if ((in_irq() || irqs_disabled()) &&
24568+ ((pref_context == SCST_CONTEXT_DIRECT) ||
24569+ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC))) {
24570+ PRINT_ERROR("Wrong context %d in IRQ from target %s, use "
24571+ "SCST_CONTEXT_THREAD instead", pref_context,
24572+ cmd->tgtt->name);
24573+ pref_context = SCST_CONTEXT_THREAD;
24574+ }
24575+#endif
24576+
24577+ switch (status) {
24578+ case SCST_PREPROCESS_STATUS_SUCCESS:
24579+ if (cmd->data_direction & SCST_DATA_WRITE)
24580+ cmd->state = SCST_CMD_STATE_RDY_TO_XFER;
24581+ else
24582+ cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC;
24583+ if (cmd->set_sn_on_restart_cmd)
24584+ scst_cmd_set_sn(cmd);
24585+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
24586+ if (cmd->op_flags & SCST_TEST_IO_IN_SIRQ_ALLOWED)
24587+ break;
24588+#endif
24589+ /* Small context optimization */
24590+ if ((pref_context == SCST_CONTEXT_TASKLET) ||
24591+ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC) ||
24592+ ((pref_context == SCST_CONTEXT_SAME) &&
24593+ scst_cmd_atomic(cmd)))
24594+ pref_context = SCST_CONTEXT_THREAD;
24595+ break;
24596+
24597+ case SCST_PREPROCESS_STATUS_ERROR_SENSE_SET:
24598+ scst_set_cmd_abnormal_done_state(cmd);
24599+ break;
24600+
24601+ case SCST_PREPROCESS_STATUS_ERROR_FATAL:
24602+ set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags);
24603+ /* go through */
24604+ case SCST_PREPROCESS_STATUS_ERROR:
24605+ if (cmd->sense != NULL)
24606+ scst_set_cmd_error(cmd,
24607+ SCST_LOAD_SENSE(scst_sense_hardw_error));
24608+ scst_set_cmd_abnormal_done_state(cmd);
24609+ break;
24610+
24611+ default:
24612+ PRINT_ERROR("%s() received unknown status %x", __func__,
24613+ status);
24614+ scst_set_cmd_abnormal_done_state(cmd);
24615+ break;
24616+ }
24617+
24618+ scst_process_redirect_cmd(cmd, pref_context, 1);
24619+
24620+ TRACE_EXIT();
24621+ return;
24622+}
24623+EXPORT_SYMBOL(scst_restart_cmd);
24624+
24625+static int scst_rdy_to_xfer(struct scst_cmd *cmd)
24626+{
24627+ int res, rc;
24628+ struct scst_tgt_template *tgtt = cmd->tgtt;
24629+
24630+ TRACE_ENTRY();
24631+
24632+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
24633+ TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd);
24634+ goto out_dev_done;
24635+ }
24636+
24637+ if ((tgtt->rdy_to_xfer == NULL) || unlikely(cmd->internal)) {
24638+ cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC;
24639+ res = SCST_CMD_STATE_RES_CONT_SAME;
24640+ goto out;
24641+ }
24642+
24643+ if (unlikely(!tgtt->rdy_to_xfer_atomic && scst_cmd_atomic(cmd))) {
24644+ /*
24645+ * It shouldn't be because of the SCST_TGT_DEV_AFTER_*
24646+ * optimization.
24647+ */
24648+ TRACE_DBG("Target driver %s rdy_to_xfer() needs thread "
24649+ "context, rescheduling", tgtt->name);
24650+ res = SCST_CMD_STATE_RES_NEED_THREAD;
24651+ goto out;
24652+ }
24653+
24654+ while (1) {
24655+ int finished_cmds = atomic_read(&cmd->tgt->finished_cmds);
24656+
24657+ res = SCST_CMD_STATE_RES_CONT_NEXT;
24658+ cmd->state = SCST_CMD_STATE_DATA_WAIT;
24659+
24660+ if (tgtt->on_hw_pending_cmd_timeout != NULL) {
24661+ struct scst_session *sess = cmd->sess;
24662+ cmd->hw_pending_start = jiffies;
24663+ cmd->cmd_hw_pending = 1;
24664+ if (!test_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED, &sess->sess_aflags)) {
24665+ TRACE_DBG("Sched HW pending work for sess %p "
24666+ "(max time %d)", sess,
24667+ tgtt->max_hw_pending_time);
24668+ set_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED,
24669+ &sess->sess_aflags);
24670+ schedule_delayed_work(&sess->hw_pending_work,
24671+ tgtt->max_hw_pending_time * HZ);
24672+ }
24673+ }
24674+
24675+ scst_set_cur_start(cmd);
24676+
24677+ TRACE_DBG("Calling rdy_to_xfer(%p)", cmd);
24678+#ifdef CONFIG_SCST_DEBUG_RETRY
24679+ if (((scst_random() % 100) == 75))
24680+ rc = SCST_TGT_RES_QUEUE_FULL;
24681+ else
24682+#endif
24683+ rc = tgtt->rdy_to_xfer(cmd);
24684+ TRACE_DBG("rdy_to_xfer() returned %d", rc);
24685+
24686+ if (likely(rc == SCST_TGT_RES_SUCCESS))
24687+ goto out;
24688+
24689+ scst_set_rdy_to_xfer_time(cmd);
24690+
24691+ cmd->cmd_hw_pending = 0;
24692+
24693+ /* Restore the previous state */
24694+ cmd->state = SCST_CMD_STATE_RDY_TO_XFER;
24695+
24696+ switch (rc) {
24697+ case SCST_TGT_RES_QUEUE_FULL:
24698+ if (scst_queue_retry_cmd(cmd, finished_cmds) == 0)
24699+ break;
24700+ else
24701+ continue;
24702+
24703+ case SCST_TGT_RES_NEED_THREAD_CTX:
24704+ TRACE_DBG("Target driver %s "
24705+ "rdy_to_xfer() requested thread "
24706+ "context, rescheduling", tgtt->name);
24707+ res = SCST_CMD_STATE_RES_NEED_THREAD;
24708+ break;
24709+
24710+ default:
24711+ goto out_error_rc;
24712+ }
24713+ break;
24714+ }
24715+
24716+out:
24717+ TRACE_EXIT_HRES(res);
24718+ return res;
24719+
24720+out_error_rc:
24721+ if (rc == SCST_TGT_RES_FATAL_ERROR) {
24722+ PRINT_ERROR("Target driver %s rdy_to_xfer() returned "
24723+ "fatal error", tgtt->name);
24724+ } else {
24725+ PRINT_ERROR("Target driver %s rdy_to_xfer() returned invalid "
24726+ "value %d", tgtt->name, rc);
24727+ }
24728+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
24729+
24730+out_dev_done:
24731+ scst_set_cmd_abnormal_done_state(cmd);
24732+ res = SCST_CMD_STATE_RES_CONT_SAME;
24733+ goto out;
24734+}
24735+
24736+/* No locks, but might be in IRQ */
24737+static void scst_process_redirect_cmd(struct scst_cmd *cmd,
24738+ enum scst_exec_context context, int check_retries)
24739+{
24740+ struct scst_tgt *tgt = cmd->tgt;
24741+ unsigned long flags;
24742+
24743+ TRACE_ENTRY();
24744+
24745+ TRACE_DBG("Context: %x", context);
24746+
24747+ if (context == SCST_CONTEXT_SAME)
24748+ context = scst_cmd_atomic(cmd) ? SCST_CONTEXT_DIRECT_ATOMIC :
24749+ SCST_CONTEXT_DIRECT;
24750+
24751+ switch (context) {
24752+ case SCST_CONTEXT_DIRECT_ATOMIC:
24753+ scst_process_active_cmd(cmd, true);
24754+ break;
24755+
24756+ case SCST_CONTEXT_DIRECT:
24757+ if (check_retries)
24758+ scst_check_retries(tgt);
24759+ scst_process_active_cmd(cmd, false);
24760+ break;
24761+
24762+ default:
24763+ PRINT_ERROR("Context %x is unknown, using the thread one",
24764+ context);
24765+ /* go through */
24766+ case SCST_CONTEXT_THREAD:
24767+ if (check_retries)
24768+ scst_check_retries(tgt);
24769+ spin_lock_irqsave(&cmd->cmd_threads->cmd_list_lock, flags);
24770+ TRACE_DBG("Adding cmd %p to active cmd list", cmd);
24771+ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
24772+ list_add(&cmd->cmd_list_entry,
24773+ &cmd->cmd_threads->active_cmd_list);
24774+ else
24775+ list_add_tail(&cmd->cmd_list_entry,
24776+ &cmd->cmd_threads->active_cmd_list);
24777+ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
24778+ spin_unlock_irqrestore(&cmd->cmd_threads->cmd_list_lock, flags);
24779+ break;
24780+
24781+ case SCST_CONTEXT_TASKLET:
24782+ if (check_retries)
24783+ scst_check_retries(tgt);
24784+ scst_schedule_tasklet(cmd);
24785+ break;
24786+ }
24787+
24788+ TRACE_EXIT();
24789+ return;
24790+}
24791+
24792+/**
24793+ * scst_rx_data() - the command's data received
24794+ * @cmd: SCST commands
24795+ * @status: data receiving completion status
24796+ * @pref_context: preferred command execution context
24797+ *
24798+ * Description:
24799+ * Notifies SCST that the driver received all the necessary data
24800+ * and the command is ready for further processing.
24801+ *
24802+ * The second argument sets data receiving completion status
24803+ * (see SCST_RX_STATUS_* constants for details)
24804+ */
24805+void scst_rx_data(struct scst_cmd *cmd, int status,
24806+ enum scst_exec_context pref_context)
24807+{
24808+ TRACE_ENTRY();
24809+
24810+ scst_set_rdy_to_xfer_time(cmd);
24811+
24812+ TRACE_DBG("Preferred context: %d", pref_context);
24813+ TRACE(TRACE_SCSI, "cmd %p, status %#x", cmd, status);
24814+
24815+ cmd->cmd_hw_pending = 0;
24816+
24817+#ifdef CONFIG_SCST_EXTRACHECKS
24818+ if ((in_irq() || irqs_disabled()) &&
24819+ ((pref_context == SCST_CONTEXT_DIRECT) ||
24820+ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC))) {
24821+ PRINT_ERROR("Wrong context %d in IRQ from target %s, use "
24822+ "SCST_CONTEXT_THREAD instead", pref_context,
24823+ cmd->tgtt->name);
24824+ pref_context = SCST_CONTEXT_THREAD;
24825+ }
24826+#endif
24827+
24828+ switch (status) {
24829+ case SCST_RX_STATUS_SUCCESS:
24830+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
24831+ if (trace_flag & TRACE_RCV_BOT) {
24832+ int i;
24833+ struct scatterlist *sg;
24834+ if (cmd->out_sg != NULL)
24835+ sg = cmd->out_sg;
24836+ else if (cmd->tgt_out_sg != NULL)
24837+ sg = cmd->tgt_out_sg;
24838+ else if (cmd->tgt_sg != NULL)
24839+ sg = cmd->tgt_sg;
24840+ else
24841+ sg = cmd->sg;
24842+ if (sg != NULL) {
24843+ TRACE_RECV_BOT("RX data for cmd %p "
24844+ "(sg_cnt %d, sg %p, sg[0].page %p)",
24845+ cmd, cmd->tgt_sg_cnt, sg,
24846+ (void *)sg_page(&sg[0]));
24847+ for (i = 0; i < cmd->tgt_sg_cnt; ++i) {
24848+ PRINT_BUFF_FLAG(TRACE_RCV_BOT, "RX sg",
24849+ sg_virt(&sg[i]), sg[i].length);
24850+ }
24851+ }
24852+ }
24853+#endif
24854+ cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC;
24855+
24856+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
24857+ if (cmd->op_flags & SCST_TEST_IO_IN_SIRQ_ALLOWED)
24858+ break;
24859+#endif
24860+
24861+ /* Small context optimization */
24862+ if ((pref_context == SCST_CONTEXT_TASKLET) ||
24863+ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC) ||
24864+ ((pref_context == SCST_CONTEXT_SAME) &&
24865+ scst_cmd_atomic(cmd)))
24866+ pref_context = SCST_CONTEXT_THREAD;
24867+ break;
24868+
24869+ case SCST_RX_STATUS_ERROR_SENSE_SET:
24870+ scst_set_cmd_abnormal_done_state(cmd);
24871+ break;
24872+
24873+ case SCST_RX_STATUS_ERROR_FATAL:
24874+ set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags);
24875+ /* go through */
24876+ case SCST_RX_STATUS_ERROR:
24877+ scst_set_cmd_error(cmd,
24878+ SCST_LOAD_SENSE(scst_sense_hardw_error));
24879+ scst_set_cmd_abnormal_done_state(cmd);
24880+ break;
24881+
24882+ default:
24883+ PRINT_ERROR("scst_rx_data() received unknown status %x",
24884+ status);
24885+ scst_set_cmd_abnormal_done_state(cmd);
24886+ break;
24887+ }
24888+
24889+ scst_process_redirect_cmd(cmd, pref_context, 1);
24890+
24891+ TRACE_EXIT();
24892+ return;
24893+}
24894+EXPORT_SYMBOL(scst_rx_data);
24895+
24896+static int scst_tgt_pre_exec(struct scst_cmd *cmd)
24897+{
24898+ int res = SCST_CMD_STATE_RES_CONT_SAME, rc;
24899+
24900+ TRACE_ENTRY();
24901+
24902+ if (unlikely(cmd->resid_possible)) {
24903+ if (cmd->data_direction & SCST_DATA_WRITE) {
24904+ bool do_zero = false;
24905+ if (cmd->data_direction & SCST_DATA_READ) {
24906+ if (cmd->write_len != cmd->out_bufflen)
24907+ do_zero = true;
24908+ } else {
24909+ if (cmd->write_len != cmd->bufflen)
24910+ do_zero = true;
24911+ }
24912+ if (do_zero) {
24913+ scst_check_restore_sg_buff(cmd);
24914+ scst_zero_write_rest(cmd);
24915+ }
24916+ }
24917+ }
24918+
24919+ cmd->state = SCST_CMD_STATE_SEND_FOR_EXEC;
24920+
24921+ if ((cmd->tgtt->pre_exec == NULL) || unlikely(cmd->internal))
24922+ goto out;
24923+
24924+ TRACE_DBG("Calling pre_exec(%p)", cmd);
24925+ scst_set_cur_start(cmd);
24926+ rc = cmd->tgtt->pre_exec(cmd);
24927+ scst_set_pre_exec_time(cmd);
24928+ TRACE_DBG("pre_exec() returned %d", rc);
24929+
24930+ if (unlikely(rc != SCST_PREPROCESS_STATUS_SUCCESS)) {
24931+ switch (rc) {
24932+ case SCST_PREPROCESS_STATUS_ERROR_SENSE_SET:
24933+ scst_set_cmd_abnormal_done_state(cmd);
24934+ break;
24935+ case SCST_PREPROCESS_STATUS_ERROR_FATAL:
24936+ set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags);
24937+ /* go through */
24938+ case SCST_PREPROCESS_STATUS_ERROR:
24939+ scst_set_cmd_error(cmd,
24940+ SCST_LOAD_SENSE(scst_sense_hardw_error));
24941+ scst_set_cmd_abnormal_done_state(cmd);
24942+ break;
24943+ default:
24944+ BUG();
24945+ break;
24946+ }
24947+ }
24948+
24949+out:
24950+ TRACE_EXIT_RES(res);
24951+ return res;
24952+}
24953+
24954+static void scst_do_cmd_done(struct scst_cmd *cmd, int result,
24955+ const uint8_t *rq_sense, int rq_sense_len, int resid)
24956+{
24957+ TRACE_ENTRY();
24958+
24959+ scst_set_exec_time(cmd);
24960+
24961+ cmd->status = result & 0xff;
24962+ cmd->msg_status = msg_byte(result);
24963+ cmd->host_status = host_byte(result);
24964+ cmd->driver_status = driver_byte(result);
24965+ if (unlikely(resid != 0)) {
24966+ if ((cmd->data_direction & SCST_DATA_READ) &&
24967+ (resid > 0) && (resid < cmd->resp_data_len))
24968+ scst_set_resp_data_len(cmd, cmd->resp_data_len - resid);
24969+ /*
24970+ * We ignore write direction residue, because from the
24971+ * initiator's POV we already transferred all the data.
24972+ */
24973+ }
24974+
24975+ if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION)) {
24976+ /* We might have double reset UA here */
24977+ cmd->dbl_ua_orig_resp_data_len = cmd->resp_data_len;
24978+ cmd->dbl_ua_orig_data_direction = cmd->data_direction;
24979+
24980+ scst_alloc_set_sense(cmd, 1, rq_sense, rq_sense_len);
24981+ }
24982+
24983+ TRACE(TRACE_SCSI, "cmd %p, result %x, cmd->status %x, resid %d, "
24984+ "cmd->msg_status %x, cmd->host_status %x, "
24985+ "cmd->driver_status %x", cmd, result, cmd->status, resid,
24986+ cmd->msg_status, cmd->host_status, cmd->driver_status);
24987+
24988+ cmd->completed = 1;
24989+
24990+ TRACE_EXIT();
24991+ return;
24992+}
24993+
24994+/* For small context optimization */
24995+static inline enum scst_exec_context scst_optimize_post_exec_context(
24996+ struct scst_cmd *cmd, enum scst_exec_context context)
24997+{
24998+ if (((context == SCST_CONTEXT_SAME) && scst_cmd_atomic(cmd)) ||
24999+ (context == SCST_CONTEXT_TASKLET) ||
25000+ (context == SCST_CONTEXT_DIRECT_ATOMIC)) {
25001+ if (!test_bit(SCST_TGT_DEV_AFTER_EXEC_ATOMIC,
25002+ &cmd->tgt_dev->tgt_dev_flags))
25003+ context = SCST_CONTEXT_THREAD;
25004+ }
25005+ return context;
25006+}
25007+
25008+static void scst_cmd_done(void *data, char *sense, int result, int resid)
25009+{
25010+ struct scst_cmd *cmd;
25011+
25012+ TRACE_ENTRY();
25013+
25014+ cmd = (struct scst_cmd *)data;
25015+ if (cmd == NULL)
25016+ goto out;
25017+
25018+ scst_do_cmd_done(cmd, result, sense, SCSI_SENSE_BUFFERSIZE, resid);
25019+
25020+ cmd->state = SCST_CMD_STATE_PRE_DEV_DONE;
25021+
25022+ scst_process_redirect_cmd(cmd,
25023+ scst_optimize_post_exec_context(cmd, scst_estimate_context()), 0);
25024+
25025+out:
25026+ TRACE_EXIT();
25027+ return;
25028+}
25029+
25030+static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state,
25031+ enum scst_exec_context pref_context)
25032+{
25033+ TRACE_ENTRY();
25034+
25035+ EXTRACHECKS_BUG_ON(cmd->pr_abort_counter != NULL);
25036+
25037+ scst_set_exec_time(cmd);
25038+
25039+ TRACE(TRACE_SCSI, "cmd %p, status %x, msg_status %x, host_status %x, "
25040+ "driver_status %x, resp_data_len %d", cmd, cmd->status,
25041+ cmd->msg_status, cmd->host_status, cmd->driver_status,
25042+ cmd->resp_data_len);
25043+
25044+ if (next_state == SCST_CMD_STATE_DEFAULT)
25045+ next_state = SCST_CMD_STATE_PRE_DEV_DONE;
25046+
25047+#if defined(CONFIG_SCST_DEBUG)
25048+ if (next_state == SCST_CMD_STATE_PRE_DEV_DONE) {
25049+ if ((trace_flag & TRACE_RCV_TOP) && (cmd->sg != NULL)) {
25050+ int i;
25051+ struct scatterlist *sg = cmd->sg;
25052+ TRACE_RECV_TOP("Exec'd %d S/G(s) at %p sg[0].page at "
25053+ "%p", cmd->sg_cnt, sg, (void *)sg_page(&sg[0]));
25054+ for (i = 0; i < cmd->sg_cnt; ++i) {
25055+ TRACE_BUFF_FLAG(TRACE_RCV_TOP,
25056+ "Exec'd sg", sg_virt(&sg[i]),
25057+ sg[i].length);
25058+ }
25059+ }
25060+ }
25061+#endif
25062+
25063+ cmd->state = next_state;
25064+
25065+#ifdef CONFIG_SCST_EXTRACHECKS
25066+ if ((next_state != SCST_CMD_STATE_PRE_DEV_DONE) &&
25067+ (next_state != SCST_CMD_STATE_PRE_XMIT_RESP) &&
25068+ (next_state != SCST_CMD_STATE_FINISHED) &&
25069+ (next_state != SCST_CMD_STATE_FINISHED_INTERNAL)) {
25070+ PRINT_ERROR("%s() received invalid cmd state %d (opcode %d)",
25071+ __func__, next_state, cmd->cdb[0]);
25072+ scst_set_cmd_error(cmd,
25073+ SCST_LOAD_SENSE(scst_sense_hardw_error));
25074+ scst_set_cmd_abnormal_done_state(cmd);
25075+ }
25076+#endif
25077+ pref_context = scst_optimize_post_exec_context(cmd, pref_context);
25078+ scst_process_redirect_cmd(cmd, pref_context, 0);
25079+
25080+ TRACE_EXIT();
25081+ return;
25082+}
25083+
25084+static int scst_report_luns_local(struct scst_cmd *cmd)
25085+{
25086+ int res = SCST_EXEC_COMPLETED, rc;
25087+ int dev_cnt = 0;
25088+ int buffer_size;
25089+ int i;
25090+ struct scst_tgt_dev *tgt_dev = NULL;
25091+ uint8_t *buffer;
25092+ int offs, overflow = 0;
25093+
25094+ TRACE_ENTRY();
25095+
25096+ rc = scst_check_local_events(cmd);
25097+ if (unlikely(rc != 0))
25098+ goto out_done;
25099+
25100+ cmd->status = 0;
25101+ cmd->msg_status = 0;
25102+ cmd->host_status = DID_OK;
25103+ cmd->driver_status = 0;
25104+
25105+ if ((cmd->cdb[2] != 0) && (cmd->cdb[2] != 2)) {
25106+ PRINT_ERROR("Unsupported SELECT REPORT value %x in REPORT "
25107+ "LUNS command", cmd->cdb[2]);
25108+ goto out_err;
25109+ }
25110+
25111+ buffer_size = scst_get_buf_first(cmd, &buffer);
25112+ if (unlikely(buffer_size == 0))
25113+ goto out_compl;
25114+ else if (unlikely(buffer_size < 0))
25115+ goto out_hw_err;
25116+
25117+ if (buffer_size < 16)
25118+ goto out_put_err;
25119+
25120+ memset(buffer, 0, buffer_size);
25121+ offs = 8;
25122+
25123+ /*
25124+ * cmd won't allow to suspend activities, so we can access
25125+ * sess->sess_tgt_dev_list_hash without any additional protection.
25126+ */
25127+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
25128+ struct list_head *sess_tgt_dev_list_head =
25129+ &cmd->sess->sess_tgt_dev_list_hash[i];
25130+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
25131+ sess_tgt_dev_list_entry) {
25132+ if (!overflow) {
25133+ if (offs >= buffer_size) {
25134+ scst_put_buf(cmd, buffer);
25135+ buffer_size = scst_get_buf_next(cmd,
25136+ &buffer);
25137+ if (buffer_size > 0) {
25138+ memset(buffer, 0, buffer_size);
25139+ offs = 0;
25140+ } else {
25141+ overflow = 1;
25142+ goto inc_dev_cnt;
25143+ }
25144+ }
25145+ if ((buffer_size - offs) < 8) {
25146+ PRINT_ERROR("Buffer allocated for "
25147+ "REPORT LUNS command doesn't "
25148+ "allow to fit 8 byte entry "
25149+ "(buffer_size=%d)",
25150+ buffer_size);
25151+ goto out_put_hw_err;
25152+ }
25153+ if ((cmd->sess->acg->addr_method == SCST_LUN_ADDR_METHOD_FLAT) &&
25154+ (tgt_dev->lun != 0)) {
25155+ buffer[offs] = (tgt_dev->lun >> 8) & 0x3f;
25156+ buffer[offs] = buffer[offs] | 0x40;
25157+ buffer[offs+1] = tgt_dev->lun & 0xff;
25158+ } else {
25159+ buffer[offs] = (tgt_dev->lun >> 8) & 0xff;
25160+ buffer[offs+1] = tgt_dev->lun & 0xff;
25161+ }
25162+ offs += 8;
25163+ }
25164+inc_dev_cnt:
25165+ dev_cnt++;
25166+ }
25167+ }
25168+ if (!overflow)
25169+ scst_put_buf(cmd, buffer);
25170+
25171+ /* Set the response header */
25172+ buffer_size = scst_get_buf_first(cmd, &buffer);
25173+ if (unlikely(buffer_size == 0))
25174+ goto out_compl;
25175+ else if (unlikely(buffer_size < 0))
25176+ goto out_hw_err;
25177+
25178+ dev_cnt *= 8;
25179+ buffer[0] = (dev_cnt >> 24) & 0xff;
25180+ buffer[1] = (dev_cnt >> 16) & 0xff;
25181+ buffer[2] = (dev_cnt >> 8) & 0xff;
25182+ buffer[3] = dev_cnt & 0xff;
25183+
25184+ scst_put_buf(cmd, buffer);
25185+
25186+ dev_cnt += 8;
25187+ if (dev_cnt < cmd->resp_data_len)
25188+ scst_set_resp_data_len(cmd, dev_cnt);
25189+
25190+out_compl:
25191+ cmd->completed = 1;
25192+
25193+ /* Clear left sense_reported_luns_data_changed UA, if any. */
25194+
25195+ /*
25196+ * cmd won't allow to suspend activities, so we can access
25197+ * sess->sess_tgt_dev_list_hash without any additional protection.
25198+ */
25199+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
25200+ struct list_head *sess_tgt_dev_list_head =
25201+ &cmd->sess->sess_tgt_dev_list_hash[i];
25202+
25203+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
25204+ sess_tgt_dev_list_entry) {
25205+ struct scst_tgt_dev_UA *ua;
25206+
25207+ spin_lock_bh(&tgt_dev->tgt_dev_lock);
25208+ list_for_each_entry(ua, &tgt_dev->UA_list,
25209+ UA_list_entry) {
25210+ if (scst_analyze_sense(ua->UA_sense_buffer,
25211+ ua->UA_valid_sense_len,
25212+ SCST_SENSE_ALL_VALID,
25213+ SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed))) {
25214+ TRACE_MGMT_DBG("Freeing not needed "
25215+ "REPORTED LUNS DATA CHANGED UA "
25216+ "%p", ua);
25217+ list_del(&ua->UA_list_entry);
25218+ mempool_free(ua, scst_ua_mempool);
25219+ break;
25220+ }
25221+ }
25222+ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
25223+ }
25224+ }
25225+
25226+out_done:
25227+ /* Report the result */
25228+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
25229+
25230+ TRACE_EXIT_RES(res);
25231+ return res;
25232+
25233+out_put_err:
25234+ scst_put_buf(cmd, buffer);
25235+
25236+out_err:
25237+ scst_set_cmd_error(cmd,
25238+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
25239+ goto out_compl;
25240+
25241+out_put_hw_err:
25242+ scst_put_buf(cmd, buffer);
25243+
25244+out_hw_err:
25245+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
25246+ goto out_compl;
25247+}
25248+
25249+static int scst_request_sense_local(struct scst_cmd *cmd)
25250+{
25251+ int res = SCST_EXEC_COMPLETED, rc;
25252+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
25253+ uint8_t *buffer;
25254+ int buffer_size = 0, sl = 0;
25255+
25256+ TRACE_ENTRY();
25257+
25258+ rc = scst_check_local_events(cmd);
25259+ if (unlikely(rc != 0))
25260+ goto out_done;
25261+
25262+ cmd->status = 0;
25263+ cmd->msg_status = 0;
25264+ cmd->host_status = DID_OK;
25265+ cmd->driver_status = 0;
25266+
25267+ spin_lock_bh(&tgt_dev->tgt_dev_lock);
25268+
25269+ if (tgt_dev->tgt_dev_valid_sense_len == 0)
25270+ goto out_unlock_not_completed;
25271+
25272+ TRACE(TRACE_SCSI, "%s: Returning stored sense", cmd->op_name);
25273+
25274+ buffer_size = scst_get_buf_first(cmd, &buffer);
25275+ if (unlikely(buffer_size == 0))
25276+ goto out_unlock_compl;
25277+ else if (unlikely(buffer_size < 0))
25278+ goto out_unlock_hw_err;
25279+
25280+ memset(buffer, 0, buffer_size);
25281+
25282+ if (((tgt_dev->tgt_dev_sense[0] == 0x70) ||
25283+ (tgt_dev->tgt_dev_sense[0] == 0x71)) && (cmd->cdb[1] & 1)) {
25284+ PRINT_WARNING("%s: Fixed format of the saved sense, but "
25285+ "descriptor format requested. Convertion will "
25286+ "truncated data", cmd->op_name);
25287+ PRINT_BUFFER("Original sense", tgt_dev->tgt_dev_sense,
25288+ tgt_dev->tgt_dev_valid_sense_len);
25289+
25290+ buffer_size = min(SCST_STANDARD_SENSE_LEN, buffer_size);
25291+ sl = scst_set_sense(buffer, buffer_size, true,
25292+ tgt_dev->tgt_dev_sense[2], tgt_dev->tgt_dev_sense[12],
25293+ tgt_dev->tgt_dev_sense[13]);
25294+ } else if (((tgt_dev->tgt_dev_sense[0] == 0x72) ||
25295+ (tgt_dev->tgt_dev_sense[0] == 0x73)) && !(cmd->cdb[1] & 1)) {
25296+ PRINT_WARNING("%s: Descriptor format of the "
25297+ "saved sense, but fixed format requested. Convertion "
25298+ "will truncated data", cmd->op_name);
25299+ PRINT_BUFFER("Original sense", tgt_dev->tgt_dev_sense,
25300+ tgt_dev->tgt_dev_valid_sense_len);
25301+
25302+ buffer_size = min(SCST_STANDARD_SENSE_LEN, buffer_size);
25303+ sl = scst_set_sense(buffer, buffer_size, false,
25304+ tgt_dev->tgt_dev_sense[1], tgt_dev->tgt_dev_sense[2],
25305+ tgt_dev->tgt_dev_sense[3]);
25306+ } else {
25307+ if (buffer_size >= tgt_dev->tgt_dev_valid_sense_len)
25308+ sl = tgt_dev->tgt_dev_valid_sense_len;
25309+ else {
25310+ sl = buffer_size;
25311+ TRACE(TRACE_MINOR, "%s: Being returned sense truncated "
25312+ "to size %d (needed %d)", cmd->op_name,
25313+ buffer_size, tgt_dev->tgt_dev_valid_sense_len);
25314+ }
25315+ memcpy(buffer, tgt_dev->tgt_dev_sense, sl);
25316+ }
25317+
25318+ scst_put_buf(cmd, buffer);
25319+
25320+ tgt_dev->tgt_dev_valid_sense_len = 0;
25321+
25322+ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
25323+
25324+ scst_set_resp_data_len(cmd, sl);
25325+
25326+out_compl:
25327+ cmd->completed = 1;
25328+
25329+out_done:
25330+ /* Report the result */
25331+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
25332+
25333+out:
25334+ TRACE_EXIT_RES(res);
25335+ return res;
25336+
25337+out_unlock_hw_err:
25338+ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
25339+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
25340+ goto out_compl;
25341+
25342+out_unlock_not_completed:
25343+ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
25344+ res = SCST_EXEC_NOT_COMPLETED;
25345+ goto out;
25346+
25347+out_unlock_compl:
25348+ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
25349+ goto out_compl;
25350+}
25351+
25352+static int scst_reserve_local(struct scst_cmd *cmd)
25353+{
25354+ int res = SCST_EXEC_NOT_COMPLETED, rc;
25355+ struct scst_device *dev;
25356+ struct scst_tgt_dev *tgt_dev_tmp;
25357+
25358+ TRACE_ENTRY();
25359+
25360+ if ((cmd->cdb[0] == RESERVE_10) && (cmd->cdb[2] & SCST_RES_3RDPTY)) {
25361+ PRINT_ERROR("RESERVE_10: 3rdPty RESERVE not implemented "
25362+ "(lun=%lld)", (long long unsigned int)cmd->lun);
25363+ scst_set_cmd_error(cmd,
25364+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
25365+ goto out_done;
25366+ }
25367+
25368+ dev = cmd->dev;
25369+
25370+ /*
25371+ * There's no need to block this device, even for
25372+ * SCST_CONTR_MODE_ONE_TASK_SET, or anyhow else protect reservations
25373+ * changes, because:
25374+ *
25375+ * 1. The reservation changes are (rather) atomic, i.e., in contrast
25376+ * to persistent reservations, don't have any invalid intermediate
25377+ * states during being changed.
25378+ *
25379+ * 2. It's a duty of initiators to ensure order of regular commands
25380+ * around the reservation command either by ORDERED attribute, or by
25381+ * queue draining, or etc. For case of SCST_CONTR_MODE_ONE_TASK_SET
25382+ * there are no target drivers which can ensure even for ORDERED
25383+ * comamnds order of their delivery, so, because initiators know
25384+ * it, also there's no point to do any extra protection actions.
25385+ */
25386+
25387+ rc = scst_check_local_events(cmd);
25388+ if (unlikely(rc != 0))
25389+ goto out_done;
25390+
25391+ if (!list_empty(&dev->dev_registrants_list)) {
25392+ if (scst_pr_crh_case(cmd))
25393+ goto out_completed;
25394+ else {
25395+ scst_set_cmd_error_status(cmd,
25396+ SAM_STAT_RESERVATION_CONFLICT);
25397+ goto out_done;
25398+ }
25399+ }
25400+
25401+ spin_lock_bh(&dev->dev_lock);
25402+
25403+ if (test_bit(SCST_TGT_DEV_RESERVED, &cmd->tgt_dev->tgt_dev_flags)) {
25404+ spin_unlock_bh(&dev->dev_lock);
25405+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
25406+ goto out_done;
25407+ }
25408+
25409+ list_for_each_entry(tgt_dev_tmp, &dev->dev_tgt_dev_list,
25410+ dev_tgt_dev_list_entry) {
25411+ if (cmd->tgt_dev != tgt_dev_tmp)
25412+ set_bit(SCST_TGT_DEV_RESERVED,
25413+ &tgt_dev_tmp->tgt_dev_flags);
25414+ }
25415+ dev->dev_reserved = 1;
25416+
25417+ spin_unlock_bh(&dev->dev_lock);
25418+
25419+out:
25420+ TRACE_EXIT_RES(res);
25421+ return res;
25422+
25423+out_completed:
25424+ cmd->completed = 1;
25425+
25426+out_done:
25427+ /* Report the result */
25428+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
25429+ res = SCST_EXEC_COMPLETED;
25430+ goto out;
25431+}
25432+
25433+static int scst_release_local(struct scst_cmd *cmd)
25434+{
25435+ int res = SCST_EXEC_NOT_COMPLETED, rc;
25436+ struct scst_tgt_dev *tgt_dev_tmp;
25437+ struct scst_device *dev;
25438+
25439+ TRACE_ENTRY();
25440+
25441+ dev = cmd->dev;
25442+
25443+ /*
25444+ * See comment in scst_reserve_local() why no dev blocking or any
25445+ * other protection is needed here.
25446+ */
25447+
25448+ rc = scst_check_local_events(cmd);
25449+ if (unlikely(rc != 0))
25450+ goto out_done;
25451+
25452+ if (!list_empty(&dev->dev_registrants_list)) {
25453+ if (scst_pr_crh_case(cmd))
25454+ goto out_completed;
25455+ else {
25456+ scst_set_cmd_error_status(cmd,
25457+ SAM_STAT_RESERVATION_CONFLICT);
25458+ goto out_done;
25459+ }
25460+ }
25461+
25462+ spin_lock_bh(&dev->dev_lock);
25463+
25464+ /*
25465+ * The device could be RELEASED behind us, if RESERVING session
25466+ * is closed (see scst_free_tgt_dev()), but this actually doesn't
25467+ * matter, so use lock and no retest for DEV_RESERVED bits again
25468+ */
25469+ if (test_bit(SCST_TGT_DEV_RESERVED, &cmd->tgt_dev->tgt_dev_flags)) {
25470+ res = SCST_EXEC_COMPLETED;
25471+ cmd->status = 0;
25472+ cmd->msg_status = 0;
25473+ cmd->host_status = DID_OK;
25474+ cmd->driver_status = 0;
25475+ cmd->completed = 1;
25476+ } else {
25477+ list_for_each_entry(tgt_dev_tmp,
25478+ &dev->dev_tgt_dev_list,
25479+ dev_tgt_dev_list_entry) {
25480+ clear_bit(SCST_TGT_DEV_RESERVED,
25481+ &tgt_dev_tmp->tgt_dev_flags);
25482+ }
25483+ dev->dev_reserved = 0;
25484+ }
25485+
25486+ spin_unlock_bh(&dev->dev_lock);
25487+
25488+ if (res == SCST_EXEC_COMPLETED)
25489+ goto out_done;
25490+
25491+out:
25492+ TRACE_EXIT_RES(res);
25493+ return res;
25494+
25495+out_completed:
25496+ cmd->completed = 1;
25497+
25498+out_done:
25499+ res = SCST_EXEC_COMPLETED;
25500+ /* Report the result */
25501+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
25502+ goto out;
25503+}
25504+
25505+/**
25506+ * scst_check_local_events() - check if there are any local SCSI events
25507+ *
25508+ * Description:
25509+ * Checks if the command can be executed or there are local events,
25510+ * like reservatons, pending UAs, etc. Returns < 0 if command must be
25511+ * aborted, > 0 if there is an event and command should be immediately
25512+ * completed, or 0 otherwise.
25513+ *
25514+ * !! Dev handlers implementing exec() callback must call this function there
25515+ * !! just before the actual command's execution!
25516+ *
25517+ * On call no locks, no IRQ or IRQ-disabled context allowed.
25518+ */
25519+static int scst_persistent_reserve_in_local(struct scst_cmd *cmd)
25520+{
25521+ int rc;
25522+ struct scst_device *dev;
25523+ struct scst_tgt_dev *tgt_dev;
25524+ struct scst_session *session;
25525+ int action;
25526+ uint8_t *buffer;
25527+ int buffer_size;
25528+
25529+ TRACE_ENTRY();
25530+
25531+ EXTRACHECKS_BUG_ON(scst_cmd_atomic(cmd));
25532+
25533+ dev = cmd->dev;
25534+ tgt_dev = cmd->tgt_dev;
25535+ session = cmd->sess;
25536+
25537+ rc = scst_check_local_events(cmd);
25538+ if (unlikely(rc != 0))
25539+ goto out_done;
25540+
25541+ if (unlikely(dev->not_pr_supporting_tgt_devs_num != 0)) {
25542+ PRINT_WARNING("Persistent Reservation command %x refused for "
25543+ "device %s, because the device has not supporting PR "
25544+ "transports connected", cmd->cdb[0], dev->virt_name);
25545+ scst_set_cmd_error(cmd,
25546+ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
25547+ goto out_done;
25548+ }
25549+
25550+ if (dev->dev_reserved) {
25551+ TRACE_PR("PR command rejected, because device %s holds regular "
25552+ "reservation", dev->virt_name);
25553+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
25554+ goto out_done;
25555+ }
25556+
25557+ if (dev->scsi_dev != NULL) {
25558+ PRINT_WARNING("PR commands for pass-through devices not "
25559+ "supported (device %s)", dev->virt_name);
25560+ scst_set_cmd_error(cmd,
25561+ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
25562+ goto out_done;
25563+ }
25564+
25565+ buffer_size = scst_get_full_buf(cmd, &buffer);
25566+ if (unlikely(buffer_size <= 0)) {
25567+ if (buffer_size < 0)
25568+ scst_set_busy(cmd);
25569+ goto out_done;
25570+ }
25571+
25572+ scst_pr_write_lock(dev);
25573+
25574+ /* We can be aborted by another PR command while waiting for the lock */
25575+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
25576+ TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd);
25577+ goto out_unlock;
25578+ }
25579+
25580+ action = cmd->cdb[1] & 0x1f;
25581+
25582+ TRACE(TRACE_SCSI, "PR action %x for '%s' (LUN %llx) from '%s'", action,
25583+ dev->virt_name, tgt_dev->lun, session->initiator_name);
25584+
25585+ switch (action) {
25586+ case PR_READ_KEYS:
25587+ scst_pr_read_keys(cmd, buffer, buffer_size);
25588+ break;
25589+ case PR_READ_RESERVATION:
25590+ scst_pr_read_reservation(cmd, buffer, buffer_size);
25591+ break;
25592+ case PR_REPORT_CAPS:
25593+ scst_pr_report_caps(cmd, buffer, buffer_size);
25594+ break;
25595+ case PR_READ_FULL_STATUS:
25596+ scst_pr_read_full_status(cmd, buffer, buffer_size);
25597+ break;
25598+ default:
25599+ PRINT_ERROR("Unsupported action %x", action);
25600+ scst_pr_write_unlock(dev);
25601+ goto out_err;
25602+ }
25603+
25604+out_complete:
25605+ cmd->completed = 1;
25606+
25607+out_unlock:
25608+ scst_pr_write_unlock(dev);
25609+
25610+ scst_put_full_buf(cmd, buffer);
25611+
25612+out_done:
25613+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
25614+
25615+ TRACE_EXIT_RES(SCST_EXEC_COMPLETED);
25616+ return SCST_EXEC_COMPLETED;
25617+
25618+out_err:
25619+ scst_set_cmd_error(cmd,
25620+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
25621+ goto out_complete;
25622+}
25623+
25624+/* No locks, no IRQ or IRQ-disabled context allowed */
25625+static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
25626+{
25627+ int res = SCST_EXEC_COMPLETED;
25628+ int rc;
25629+ struct scst_device *dev;
25630+ struct scst_tgt_dev *tgt_dev;
25631+ struct scst_session *session;
25632+ int action;
25633+ uint8_t *buffer;
25634+ int buffer_size;
25635+ bool aborted = false;
25636+
25637+ TRACE_ENTRY();
25638+
25639+ EXTRACHECKS_BUG_ON(scst_cmd_atomic(cmd));
25640+
25641+ dev = cmd->dev;
25642+ tgt_dev = cmd->tgt_dev;
25643+ session = cmd->sess;
25644+
25645+ rc = scst_check_local_events(cmd);
25646+ if (unlikely(rc != 0))
25647+ goto out_done;
25648+
25649+ if (unlikely(dev->not_pr_supporting_tgt_devs_num != 0)) {
25650+ PRINT_WARNING("Persistent Reservation command %x refused for "
25651+ "device %s, because the device has not supporting PR "
25652+ "transports connected", cmd->cdb[0], dev->virt_name);
25653+ scst_set_cmd_error(cmd,
25654+ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
25655+ goto out_done;
25656+ }
25657+
25658+ action = cmd->cdb[1] & 0x1f;
25659+
25660+ TRACE(TRACE_SCSI, "PR action %x for '%s' (LUN %llx) from '%s'", action,
25661+ dev->virt_name, tgt_dev->lun, session->initiator_name);
25662+
25663+ if (dev->dev_reserved) {
25664+ TRACE_PR("PR command rejected, because device %s holds regular "
25665+ "reservation", dev->virt_name);
25666+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
25667+ goto out_done;
25668+ }
25669+
25670+ /*
25671+ * Check if tgt_dev already registered. Also by this check we make
25672+ * sure that table "PERSISTENT RESERVE OUT service actions that are
25673+ * allowed in the presence of various reservations" is honored.
25674+ * REGISTER AND MOVE and RESERVE will be additionally checked for
25675+ * conflicts later.
25676+ */
25677+ if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_IGNORE) &&
25678+ (tgt_dev->registrant == NULL)) {
25679+ TRACE_PR("'%s' not registered", cmd->sess->initiator_name);
25680+ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
25681+ goto out_done;
25682+ }
25683+
25684+ buffer_size = scst_get_full_buf(cmd, &buffer);
25685+ if (unlikely(buffer_size <= 0)) {
25686+ if (buffer_size < 0)
25687+ scst_set_busy(cmd);
25688+ goto out_done;
25689+ }
25690+
25691+ /* Check scope */
25692+ if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_IGNORE) &&
25693+ (action != PR_CLEAR) && ((cmd->cdb[2] & 0x0f) >> 4) != SCOPE_LU) {
25694+ TRACE_PR("Scope must be SCOPE_LU for action %x", action);
25695+ scst_set_cmd_error(cmd,
25696+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
25697+ goto out_put_full_buf;
25698+ }
25699+
25700+ /* Check SPEC_I_PT (PR_REGISTER_AND_MOVE has another format) */
25701+ if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_MOVE) &&
25702+ ((buffer[20] >> 3) & 0x01)) {
25703+ TRACE_PR("SPEC_I_PT must be zero for action %x", action);
25704+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
25705+ scst_sense_invalid_field_in_cdb));
25706+ goto out_put_full_buf;
25707+ }
25708+
25709+ /* Check ALL_TG_PT (PR_REGISTER_AND_MOVE has another format) */
25710+ if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_IGNORE) &&
25711+ (action != PR_REGISTER_AND_MOVE) && ((buffer[20] >> 2) & 0x01)) {
25712+ TRACE_PR("ALL_TG_PT must be zero for action %x", action);
25713+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
25714+ scst_sense_invalid_field_in_cdb));
25715+ goto out_put_full_buf;
25716+ }
25717+
25718+ scst_pr_write_lock(dev);
25719+
25720+ /* We can be aborted by another PR command while waiting for the lock */
25721+ aborted = test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags);
25722+ if (unlikely(aborted)) {
25723+ TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd);
25724+ goto out_unlock;
25725+ }
25726+
25727+ switch (action) {
25728+ case PR_REGISTER:
25729+ scst_pr_register(cmd, buffer, buffer_size);
25730+ break;
25731+ case PR_RESERVE:
25732+ scst_pr_reserve(cmd, buffer, buffer_size);
25733+ break;
25734+ case PR_RELEASE:
25735+ scst_pr_release(cmd, buffer, buffer_size);
25736+ break;
25737+ case PR_CLEAR:
25738+ scst_pr_clear(cmd, buffer, buffer_size);
25739+ break;
25740+ case PR_PREEMPT:
25741+ scst_pr_preempt(cmd, buffer, buffer_size);
25742+ break;
25743+ case PR_PREEMPT_AND_ABORT:
25744+ scst_pr_preempt_and_abort(cmd, buffer, buffer_size);
25745+ break;
25746+ case PR_REGISTER_AND_IGNORE:
25747+ scst_pr_register_and_ignore(cmd, buffer, buffer_size);
25748+ break;
25749+ case PR_REGISTER_AND_MOVE:
25750+ scst_pr_register_and_move(cmd, buffer, buffer_size);
25751+ break;
25752+ default:
25753+ scst_set_cmd_error(cmd,
25754+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
25755+ goto out_unlock;
25756+ }
25757+
25758+ if (cmd->status == SAM_STAT_GOOD)
25759+ scst_pr_sync_device_file(tgt_dev, cmd);
25760+
25761+ if ((dev->handler->pr_cmds_notifications) &&
25762+ (cmd->status == SAM_STAT_GOOD)) /* sync file may change status */
25763+ res = SCST_EXEC_NOT_COMPLETED;
25764+
25765+out_unlock:
25766+ scst_pr_write_unlock(dev);
25767+
25768+out_put_full_buf:
25769+ scst_put_full_buf(cmd, buffer);
25770+
25771+out_done:
25772+ if (SCST_EXEC_COMPLETED == res) {
25773+ if (!aborted)
25774+ cmd->completed = 1;
25775+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT,
25776+ SCST_CONTEXT_SAME);
25777+ }
25778+
25779+ TRACE_EXIT_RES(res);
25780+ return res;
25781+}
25782+
25783+/* No locks, no IRQ or IRQ-disabled context allowed */
25784+int scst_check_local_events(struct scst_cmd *cmd)
25785+{
25786+ int res, rc;
25787+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
25788+ struct scst_device *dev = cmd->dev;
25789+
25790+ TRACE_ENTRY();
25791+
25792+ /*
25793+ * There's no race here, because we need to trace commands sent
25794+ * *after* dev_double_ua_possible flag was set.
25795+ */
25796+ if (unlikely(dev->dev_double_ua_possible))
25797+ cmd->double_ua_possible = 1;
25798+
25799+ /* Reserve check before Unit Attention */
25800+ if (unlikely(test_bit(SCST_TGT_DEV_RESERVED,
25801+ &tgt_dev->tgt_dev_flags))) {
25802+ if ((cmd->op_flags & SCST_REG_RESERVE_ALLOWED) == 0) {
25803+ scst_set_cmd_error_status(cmd,
25804+ SAM_STAT_RESERVATION_CONFLICT);
25805+ goto out_complete;
25806+ }
25807+ }
25808+
25809+ if (dev->pr_is_set) {
25810+ if (unlikely(!scst_pr_is_cmd_allowed(cmd))) {
25811+ scst_set_cmd_error_status(cmd,
25812+ SAM_STAT_RESERVATION_CONFLICT);
25813+ goto out_complete;
25814+ }
25815+ }
25816+
25817+ /*
25818+ * Let's check for ABORTED after scst_pr_is_cmd_allowed(), because
25819+ * we might sleep for a while there.
25820+ */
25821+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
25822+ TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd);
25823+ goto out_uncomplete;
25824+ }
25825+
25826+ /* If we had internal bus reset, set the command error unit attention */
25827+ if ((dev->scsi_dev != NULL) &&
25828+ unlikely(dev->scsi_dev->was_reset)) {
25829+ if (scst_is_ua_command(cmd)) {
25830+ int done = 0;
25831+ /*
25832+ * Prevent more than 1 cmd to be triggered by
25833+ * was_reset.
25834+ */
25835+ spin_lock_bh(&dev->dev_lock);
25836+ if (dev->scsi_dev->was_reset) {
25837+ TRACE(TRACE_MGMT, "was_reset is %d", 1);
25838+ scst_set_cmd_error(cmd,
25839+ SCST_LOAD_SENSE(scst_sense_reset_UA));
25840+ /*
25841+ * It looks like it is safe to clear was_reset
25842+ * here.
25843+ */
25844+ dev->scsi_dev->was_reset = 0;
25845+ done = 1;
25846+ }
25847+ spin_unlock_bh(&dev->dev_lock);
25848+
25849+ if (done)
25850+ goto out_complete;
25851+ }
25852+ }
25853+
25854+ if (unlikely(test_bit(SCST_TGT_DEV_UA_PENDING,
25855+ &cmd->tgt_dev->tgt_dev_flags))) {
25856+ if (scst_is_ua_command(cmd)) {
25857+ rc = scst_set_pending_UA(cmd);
25858+ if (rc == 0)
25859+ goto out_complete;
25860+ }
25861+ }
25862+
25863+ res = 0;
25864+
25865+out:
25866+ TRACE_EXIT_RES(res);
25867+ return res;
25868+
25869+out_complete:
25870+ res = 1;
25871+ BUG_ON(!cmd->completed);
25872+ goto out;
25873+
25874+out_uncomplete:
25875+ res = -1;
25876+ goto out;
25877+}
25878+EXPORT_SYMBOL_GPL(scst_check_local_events);
25879+
25880+/* No locks */
25881+void scst_inc_expected_sn(struct scst_tgt_dev *tgt_dev, atomic_t *slot)
25882+{
25883+ if (slot == NULL)
25884+ goto inc;
25885+
25886+ /* Optimized for lockless fast path */
25887+
25888+ TRACE_SN("Slot %zd, *cur_sn_slot %d", slot - tgt_dev->sn_slots,
25889+ atomic_read(slot));
25890+
25891+ if (!atomic_dec_and_test(slot))
25892+ goto out;
25893+
25894+ TRACE_SN("Slot is 0 (num_free_sn_slots=%d)",
25895+ tgt_dev->num_free_sn_slots);
25896+ if (tgt_dev->num_free_sn_slots < (int)ARRAY_SIZE(tgt_dev->sn_slots)-1) {
25897+ spin_lock_irq(&tgt_dev->sn_lock);
25898+ if (likely(tgt_dev->num_free_sn_slots < (int)ARRAY_SIZE(tgt_dev->sn_slots)-1)) {
25899+ if (tgt_dev->num_free_sn_slots < 0)
25900+ tgt_dev->cur_sn_slot = slot;
25901+ /*
25902+ * To be in-sync with SIMPLE case in scst_cmd_set_sn()
25903+ */
25904+ smp_mb();
25905+ tgt_dev->num_free_sn_slots++;
25906+ TRACE_SN("Incremented num_free_sn_slots (%d)",
25907+ tgt_dev->num_free_sn_slots);
25908+
25909+ }
25910+ spin_unlock_irq(&tgt_dev->sn_lock);
25911+ }
25912+
25913+inc:
25914+ /*
25915+ * No protection of expected_sn is needed, because only one thread
25916+ * at time can be here (serialized by sn). Also it is supposed that
25917+ * there could not be half-incremented halves.
25918+ */
25919+ tgt_dev->expected_sn++;
25920+ /*
25921+ * Write must be before def_cmd_count read to be in sync. with
25922+ * scst_post_exec_sn(). See comment in scst_send_for_exec().
25923+ */
25924+ smp_mb();
25925+ TRACE_SN("Next expected_sn: %d", tgt_dev->expected_sn);
25926+
25927+out:
25928+ return;
25929+}
25930+
25931+/* No locks */
25932+static struct scst_cmd *scst_post_exec_sn(struct scst_cmd *cmd,
25933+ bool make_active)
25934+{
25935+ /* For HQ commands SN is not set */
25936+ bool inc_expected_sn = !cmd->inc_expected_sn_on_done &&
25937+ cmd->sn_set && !cmd->retry;
25938+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
25939+ struct scst_cmd *res;
25940+
25941+ TRACE_ENTRY();
25942+
25943+ if (inc_expected_sn)
25944+ scst_inc_expected_sn(tgt_dev, cmd->sn_slot);
25945+
25946+ if (make_active) {
25947+ scst_make_deferred_commands_active(tgt_dev);
25948+ res = NULL;
25949+ } else
25950+ res = scst_check_deferred_commands(tgt_dev);
25951+
25952+ TRACE_EXIT_HRES(res);
25953+ return res;
25954+}
25955+
25956+/* cmd must be additionally referenced to not die inside */
25957+static int scst_do_real_exec(struct scst_cmd *cmd)
25958+{
25959+ int res = SCST_EXEC_NOT_COMPLETED;
25960+ int rc;
25961+ struct scst_device *dev = cmd->dev;
25962+ struct scst_dev_type *handler = dev->handler;
25963+ struct io_context *old_ctx = NULL;
25964+ bool ctx_changed = false;
25965+
25966+ TRACE_ENTRY();
25967+
25968+ ctx_changed = scst_set_io_context(cmd, &old_ctx);
25969+
25970+ cmd->state = SCST_CMD_STATE_REAL_EXECUTING;
25971+
25972+ if (handler->exec) {
25973+ TRACE_DBG("Calling dev handler %s exec(%p)",
25974+ handler->name, cmd);
25975+ TRACE_BUFF_FLAG(TRACE_SND_TOP, "Execing: ", cmd->cdb,
25976+ cmd->cdb_len);
25977+ scst_set_cur_start(cmd);
25978+ res = handler->exec(cmd);
25979+ TRACE_DBG("Dev handler %s exec() returned %d",
25980+ handler->name, res);
25981+
25982+ if (res == SCST_EXEC_COMPLETED)
25983+ goto out_complete;
25984+
25985+ scst_set_exec_time(cmd);
25986+
25987+ BUG_ON(res != SCST_EXEC_NOT_COMPLETED);
25988+ }
25989+
25990+ TRACE_DBG("Sending cmd %p to SCSI mid-level", cmd);
25991+
25992+ if (unlikely(dev->scsi_dev == NULL)) {
25993+ PRINT_ERROR("Command for virtual device must be "
25994+ "processed by device handler (LUN %lld)!",
25995+ (long long unsigned int)cmd->lun);
25996+ goto out_error;
25997+ }
25998+
25999+ res = scst_check_local_events(cmd);
26000+ if (unlikely(res != 0))
26001+ goto out_done;
26002+
26003+ scst_set_cur_start(cmd);
26004+
26005+ rc = scst_scsi_exec_async(cmd, scst_cmd_done);
26006+ if (unlikely(rc != 0)) {
26007+ PRINT_ERROR("scst pass-through exec failed: %x", rc);
26008+ if ((int)rc == -EINVAL)
26009+ PRINT_ERROR("Do you have too low max_sectors on your "
26010+ "backend hardware? For success max_sectors must "
26011+ "be >= bufflen in sectors (max_sectors %d, "
26012+ "bufflen %db, CDB %x). See README for more "
26013+ "details.", dev->scsi_dev->host->max_sectors,
26014+ cmd->bufflen, cmd->cdb[0]);
26015+ goto out_error;
26016+ }
26017+
26018+out_complete:
26019+ res = SCST_EXEC_COMPLETED;
26020+
26021+ if (ctx_changed)
26022+ scst_reset_io_context(cmd->tgt_dev, old_ctx);
26023+
26024+ TRACE_EXIT();
26025+ return res;
26026+
26027+out_error:
26028+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
26029+ goto out_done;
26030+
26031+out_done:
26032+ res = SCST_EXEC_COMPLETED;
26033+ /* Report the result */
26034+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
26035+ goto out_complete;
26036+}
26037+
26038+static inline int scst_real_exec(struct scst_cmd *cmd)
26039+{
26040+ int res;
26041+
26042+ TRACE_ENTRY();
26043+
26044+ BUILD_BUG_ON(SCST_CMD_STATE_RES_CONT_SAME != SCST_EXEC_NOT_COMPLETED);
26045+ BUILD_BUG_ON(SCST_CMD_STATE_RES_CONT_NEXT != SCST_EXEC_COMPLETED);
26046+
26047+ __scst_cmd_get(cmd);
26048+
26049+ res = scst_do_real_exec(cmd);
26050+
26051+ if (likely(res == SCST_EXEC_COMPLETED)) {
26052+ scst_post_exec_sn(cmd, true);
26053+ if (cmd->dev->scsi_dev != NULL)
26054+ generic_unplug_device(
26055+ cmd->dev->scsi_dev->request_queue);
26056+ } else
26057+ BUG();
26058+
26059+ __scst_cmd_put(cmd);
26060+
26061+ /* SCST_EXEC_* match SCST_CMD_STATE_RES_* */
26062+
26063+ TRACE_EXIT_RES(res);
26064+ return res;
26065+}
26066+
26067+static int scst_do_local_exec(struct scst_cmd *cmd)
26068+{
26069+ int res;
26070+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
26071+
26072+ TRACE_ENTRY();
26073+
26074+ /* Check READ_ONLY device status */
26075+ if ((cmd->op_flags & SCST_WRITE_MEDIUM) &&
26076+ (tgt_dev->acg_dev->rd_only || cmd->dev->swp ||
26077+ cmd->dev->rd_only)) {
26078+ PRINT_WARNING("Attempt of write access to read-only device: "
26079+ "initiator %s, LUN %lld, op %x",
26080+ cmd->sess->initiator_name, cmd->lun, cmd->cdb[0]);
26081+ scst_set_cmd_error(cmd,
26082+ SCST_LOAD_SENSE(scst_sense_data_protect));
26083+ goto out_done;
26084+ }
26085+
26086+ if (!scst_is_cmd_local(cmd)) {
26087+ res = SCST_EXEC_NOT_COMPLETED;
26088+ goto out;
26089+ }
26090+
26091+ switch (cmd->cdb[0]) {
26092+ case RESERVE:
26093+ case RESERVE_10:
26094+ res = scst_reserve_local(cmd);
26095+ break;
26096+ case RELEASE:
26097+ case RELEASE_10:
26098+ res = scst_release_local(cmd);
26099+ break;
26100+ case PERSISTENT_RESERVE_IN:
26101+ res = scst_persistent_reserve_in_local(cmd);
26102+ break;
26103+ case PERSISTENT_RESERVE_OUT:
26104+ res = scst_persistent_reserve_out_local(cmd);
26105+ break;
26106+ case REPORT_LUNS:
26107+ res = scst_report_luns_local(cmd);
26108+ break;
26109+ case REQUEST_SENSE:
26110+ res = scst_request_sense_local(cmd);
26111+ break;
26112+ default:
26113+ res = SCST_EXEC_NOT_COMPLETED;
26114+ break;
26115+ }
26116+
26117+out:
26118+ TRACE_EXIT_RES(res);
26119+ return res;
26120+
26121+out_done:
26122+ /* Report the result */
26123+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
26124+ res = SCST_EXEC_COMPLETED;
26125+ goto out;
26126+}
26127+
26128+static int scst_local_exec(struct scst_cmd *cmd)
26129+{
26130+ int res;
26131+
26132+ TRACE_ENTRY();
26133+
26134+ BUILD_BUG_ON(SCST_CMD_STATE_RES_CONT_SAME != SCST_EXEC_NOT_COMPLETED);
26135+ BUILD_BUG_ON(SCST_CMD_STATE_RES_CONT_NEXT != SCST_EXEC_COMPLETED);
26136+
26137+ __scst_cmd_get(cmd);
26138+
26139+ res = scst_do_local_exec(cmd);
26140+ if (likely(res == SCST_EXEC_NOT_COMPLETED))
26141+ cmd->state = SCST_CMD_STATE_REAL_EXEC;
26142+ else if (res == SCST_EXEC_COMPLETED)
26143+ scst_post_exec_sn(cmd, true);
26144+ else
26145+ BUG();
26146+
26147+ __scst_cmd_put(cmd);
26148+
26149+ /* SCST_EXEC_* match SCST_CMD_STATE_RES_* */
26150+ TRACE_EXIT_RES(res);
26151+ return res;
26152+}
26153+
26154+static int scst_exec(struct scst_cmd **active_cmd)
26155+{
26156+ struct scst_cmd *cmd = *active_cmd;
26157+ struct scst_cmd *ref_cmd;
26158+ struct scst_device *dev = cmd->dev;
26159+ int res = SCST_CMD_STATE_RES_CONT_NEXT, count;
26160+
26161+ TRACE_ENTRY();
26162+
26163+ if (unlikely(scst_check_blocked_dev(cmd)))
26164+ goto out;
26165+
26166+ /* To protect tgt_dev */
26167+ ref_cmd = cmd;
26168+ __scst_cmd_get(ref_cmd);
26169+
26170+ count = 0;
26171+ while (1) {
26172+ int rc;
26173+
26174+ cmd->sent_for_exec = 1;
26175+ /*
26176+ * To sync with scst_abort_cmd(). The above assignment must
26177+ * be before SCST_CMD_ABORTED test, done later in
26178+ * scst_check_local_events(). It's far from here, so the order
26179+ * is virtually guaranteed, but let's have it just in case.
26180+ */
26181+ smp_mb();
26182+
26183+ cmd->scst_cmd_done = scst_cmd_done_local;
26184+ cmd->state = SCST_CMD_STATE_LOCAL_EXEC;
26185+
26186+ rc = scst_do_local_exec(cmd);
26187+ if (likely(rc == SCST_EXEC_NOT_COMPLETED))
26188+ /* Nothing to do */;
26189+ else {
26190+ BUG_ON(rc != SCST_EXEC_COMPLETED);
26191+ goto done;
26192+ }
26193+
26194+ cmd->state = SCST_CMD_STATE_REAL_EXEC;
26195+
26196+ rc = scst_do_real_exec(cmd);
26197+ BUG_ON(rc != SCST_EXEC_COMPLETED);
26198+
26199+done:
26200+ count++;
26201+
26202+ cmd = scst_post_exec_sn(cmd, false);
26203+ if (cmd == NULL)
26204+ break;
26205+
26206+ if (unlikely(scst_check_blocked_dev(cmd)))
26207+ break;
26208+
26209+ __scst_cmd_put(ref_cmd);
26210+ ref_cmd = cmd;
26211+ __scst_cmd_get(ref_cmd);
26212+ }
26213+
26214+ *active_cmd = cmd;
26215+
26216+ if (count == 0)
26217+ goto out_put;
26218+
26219+ if (dev->scsi_dev != NULL)
26220+ generic_unplug_device(dev->scsi_dev->request_queue);
26221+
26222+out_put:
26223+ __scst_cmd_put(ref_cmd);
26224+ /* !! At this point sess, dev and tgt_dev can be already freed !! */
26225+
26226+out:
26227+ TRACE_EXIT_RES(res);
26228+ return res;
26229+}
26230+
26231+static int scst_send_for_exec(struct scst_cmd **active_cmd)
26232+{
26233+ int res;
26234+ struct scst_cmd *cmd = *active_cmd;
26235+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
26236+ typeof(tgt_dev->expected_sn) expected_sn;
26237+
26238+ TRACE_ENTRY();
26239+
26240+ if (unlikely(cmd->internal))
26241+ goto exec;
26242+
26243+ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
26244+ goto exec;
26245+
26246+ BUG_ON(!cmd->sn_set);
26247+
26248+ expected_sn = tgt_dev->expected_sn;
26249+ /* Optimized for lockless fast path */
26250+ if ((cmd->sn != expected_sn) || (tgt_dev->hq_cmd_count > 0)) {
26251+ spin_lock_irq(&tgt_dev->sn_lock);
26252+
26253+ tgt_dev->def_cmd_count++;
26254+ /*
26255+ * Memory barrier is needed here to implement lockless fast
26256+ * path. We need the exact order of read and write between
26257+ * def_cmd_count and expected_sn. Otherwise, we can miss case,
26258+ * when expected_sn was changed to be equal to cmd->sn while
26259+ * we are queuing cmd the deferred list after the expected_sn
26260+ * below. It will lead to a forever stuck command. But with
26261+ * the barrier in such case __scst_check_deferred_commands()
26262+ * will be called and it will take sn_lock, so we will be
26263+ * synchronized.
26264+ */
26265+ smp_mb();
26266+
26267+ expected_sn = tgt_dev->expected_sn;
26268+ if ((cmd->sn != expected_sn) || (tgt_dev->hq_cmd_count > 0)) {
26269+ if (unlikely(test_bit(SCST_CMD_ABORTED,
26270+ &cmd->cmd_flags))) {
26271+ /* Necessary to allow aborting out of sn cmds */
26272+ TRACE_MGMT_DBG("Aborting out of sn cmd %p "
26273+ "(tag %llu, sn %u)", cmd,
26274+ (long long unsigned)cmd->tag, cmd->sn);
26275+ tgt_dev->def_cmd_count--;
26276+ scst_set_cmd_abnormal_done_state(cmd);
26277+ res = SCST_CMD_STATE_RES_CONT_SAME;
26278+ } else {
26279+ TRACE_SN("Deferring cmd %p (sn=%d, set %d, "
26280+ "expected_sn=%d)", cmd, cmd->sn,
26281+ cmd->sn_set, expected_sn);
26282+ list_add_tail(&cmd->sn_cmd_list_entry,
26283+ &tgt_dev->deferred_cmd_list);
26284+ res = SCST_CMD_STATE_RES_CONT_NEXT;
26285+ }
26286+ spin_unlock_irq(&tgt_dev->sn_lock);
26287+ goto out;
26288+ } else {
26289+ TRACE_SN("Somebody incremented expected_sn %d, "
26290+ "continuing", expected_sn);
26291+ tgt_dev->def_cmd_count--;
26292+ spin_unlock_irq(&tgt_dev->sn_lock);
26293+ }
26294+ }
26295+
26296+exec:
26297+ res = scst_exec(active_cmd);
26298+
26299+out:
26300+ TRACE_EXIT_HRES(res);
26301+ return res;
26302+}
26303+
26304+/* No locks supposed to be held */
26305+static int scst_check_sense(struct scst_cmd *cmd)
26306+{
26307+ int res = 0;
26308+ struct scst_device *dev = cmd->dev;
26309+
26310+ TRACE_ENTRY();
26311+
26312+ if (unlikely(cmd->ua_ignore))
26313+ goto out;
26314+
26315+ /* If we had internal bus reset behind us, set the command error UA */
26316+ if ((dev->scsi_dev != NULL) &&
26317+ unlikely(cmd->host_status == DID_RESET) &&
26318+ scst_is_ua_command(cmd)) {
26319+ TRACE(TRACE_MGMT, "DID_RESET: was_reset=%d host_status=%x",
26320+ dev->scsi_dev->was_reset, cmd->host_status);
26321+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_reset_UA));
26322+ /* It looks like it is safe to clear was_reset here */
26323+ dev->scsi_dev->was_reset = 0;
26324+ }
26325+
26326+ if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION) &&
26327+ SCST_SENSE_VALID(cmd->sense)) {
26328+ PRINT_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense,
26329+ cmd->sense_valid_len);
26330+
26331+ /* Check Unit Attention Sense Key */
26332+ if (scst_is_ua_sense(cmd->sense, cmd->sense_valid_len)) {
26333+ if (scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
26334+ SCST_SENSE_ASC_VALID,
26335+ 0, SCST_SENSE_ASC_UA_RESET, 0)) {
26336+ if (cmd->double_ua_possible) {
26337+ TRACE_MGMT_DBG("Double UA "
26338+ "detected for device %p", dev);
26339+ TRACE_MGMT_DBG("Retrying cmd"
26340+ " %p (tag %llu)", cmd,
26341+ (long long unsigned)cmd->tag);
26342+
26343+ cmd->status = 0;
26344+ cmd->msg_status = 0;
26345+ cmd->host_status = DID_OK;
26346+ cmd->driver_status = 0;
26347+ cmd->completed = 0;
26348+
26349+ mempool_free(cmd->sense,
26350+ scst_sense_mempool);
26351+ cmd->sense = NULL;
26352+
26353+ scst_check_restore_sg_buff(cmd);
26354+
26355+ BUG_ON(cmd->dbl_ua_orig_resp_data_len < 0);
26356+ cmd->data_direction =
26357+ cmd->dbl_ua_orig_data_direction;
26358+ cmd->resp_data_len =
26359+ cmd->dbl_ua_orig_resp_data_len;
26360+
26361+ cmd->state = SCST_CMD_STATE_REAL_EXEC;
26362+ cmd->retry = 1;
26363+ res = 1;
26364+ goto out;
26365+ }
26366+ }
26367+ scst_dev_check_set_UA(dev, cmd, cmd->sense,
26368+ cmd->sense_valid_len);
26369+ }
26370+ }
26371+
26372+ if (unlikely(cmd->double_ua_possible)) {
26373+ if (scst_is_ua_command(cmd)) {
26374+ TRACE_MGMT_DBG("Clearing dbl_ua_possible flag (dev %p, "
26375+ "cmd %p)", dev, cmd);
26376+ /*
26377+ * Lock used to protect other flags in the bitfield
26378+ * (just in case, actually). Those flags can't be
26379+ * changed in parallel, because the device is
26380+ * serialized.
26381+ */
26382+ spin_lock_bh(&dev->dev_lock);
26383+ dev->dev_double_ua_possible = 0;
26384+ spin_unlock_bh(&dev->dev_lock);
26385+ }
26386+ }
26387+
26388+out:
26389+ TRACE_EXIT_RES(res);
26390+ return res;
26391+}
26392+
26393+static int scst_check_auto_sense(struct scst_cmd *cmd)
26394+{
26395+ int res = 0;
26396+
26397+ TRACE_ENTRY();
26398+
26399+ if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION) &&
26400+ (!SCST_SENSE_VALID(cmd->sense) ||
26401+ SCST_NO_SENSE(cmd->sense))) {
26402+ TRACE(TRACE_SCSI|TRACE_MINOR_AND_MGMT_DBG, "CHECK_CONDITION, "
26403+ "but no sense: cmd->status=%x, cmd->msg_status=%x, "
26404+ "cmd->host_status=%x, cmd->driver_status=%x (cmd %p)",
26405+ cmd->status, cmd->msg_status, cmd->host_status,
26406+ cmd->driver_status, cmd);
26407+ res = 1;
26408+ } else if (unlikely(cmd->host_status)) {
26409+ if ((cmd->host_status == DID_REQUEUE) ||
26410+ (cmd->host_status == DID_IMM_RETRY) ||
26411+ (cmd->host_status == DID_SOFT_ERROR) ||
26412+ (cmd->host_status == DID_ABORT)) {
26413+ scst_set_busy(cmd);
26414+ } else {
26415+ TRACE(TRACE_SCSI|TRACE_MINOR_AND_MGMT_DBG, "Host "
26416+ "status %x received, returning HARDWARE ERROR "
26417+ "instead (cmd %p)", cmd->host_status, cmd);
26418+ scst_set_cmd_error(cmd,
26419+ SCST_LOAD_SENSE(scst_sense_hardw_error));
26420+ }
26421+ }
26422+
26423+ TRACE_EXIT_RES(res);
26424+ return res;
26425+}
26426+
26427+static int scst_pre_dev_done(struct scst_cmd *cmd)
26428+{
26429+ int res = SCST_CMD_STATE_RES_CONT_SAME, rc;
26430+
26431+ TRACE_ENTRY();
26432+
26433+ if (unlikely(scst_check_auto_sense(cmd))) {
26434+ PRINT_INFO("Command finished with CHECK CONDITION, but "
26435+ "without sense data (opcode 0x%x), issuing "
26436+ "REQUEST SENSE", cmd->cdb[0]);
26437+ rc = scst_prepare_request_sense(cmd);
26438+ if (rc == 0)
26439+ res = SCST_CMD_STATE_RES_CONT_NEXT;
26440+ else {
26441+ PRINT_ERROR("%s", "Unable to issue REQUEST SENSE, "
26442+ "returning HARDWARE ERROR");
26443+ scst_set_cmd_error(cmd,
26444+ SCST_LOAD_SENSE(scst_sense_hardw_error));
26445+ }
26446+ goto out;
26447+ } else if (unlikely(scst_check_sense(cmd)))
26448+ goto out;
26449+
26450+ if (likely(scsi_status_is_good(cmd->status))) {
26451+ unsigned char type = cmd->dev->type;
26452+ if (unlikely((cmd->cdb[0] == MODE_SENSE ||
26453+ cmd->cdb[0] == MODE_SENSE_10)) &&
26454+ (cmd->tgt_dev->acg_dev->rd_only || cmd->dev->swp ||
26455+ cmd->dev->rd_only) &&
26456+ (type == TYPE_DISK ||
26457+ type == TYPE_WORM ||
26458+ type == TYPE_MOD ||
26459+ type == TYPE_TAPE)) {
26460+ int32_t length;
26461+ uint8_t *address;
26462+ bool err = false;
26463+
26464+ length = scst_get_buf_first(cmd, &address);
26465+ if (length < 0) {
26466+ PRINT_ERROR("%s", "Unable to get "
26467+ "MODE_SENSE buffer");
26468+ scst_set_cmd_error(cmd,
26469+ SCST_LOAD_SENSE(
26470+ scst_sense_hardw_error));
26471+ err = true;
26472+ } else if (length > 2 && cmd->cdb[0] == MODE_SENSE)
26473+ address[2] |= 0x80; /* Write Protect*/
26474+ else if (length > 3 && cmd->cdb[0] == MODE_SENSE_10)
26475+ address[3] |= 0x80; /* Write Protect*/
26476+ scst_put_buf(cmd, address);
26477+
26478+ if (err)
26479+ goto out;
26480+ }
26481+
26482+ /*
26483+ * Check and clear NormACA option for the device, if necessary,
26484+ * since we don't support ACA
26485+ */
26486+ if (unlikely((cmd->cdb[0] == INQUIRY)) &&
26487+ /* Std INQUIRY data (no EVPD) */
26488+ !(cmd->cdb[1] & SCST_INQ_EVPD) &&
26489+ (cmd->resp_data_len > SCST_INQ_BYTE3)) {
26490+ uint8_t *buffer;
26491+ int buflen;
26492+ bool err = false;
26493+
26494+ /* ToDo: all pages ?? */
26495+ buflen = scst_get_buf_first(cmd, &buffer);
26496+ if (buflen > SCST_INQ_BYTE3) {
26497+#ifdef CONFIG_SCST_EXTRACHECKS
26498+ if (buffer[SCST_INQ_BYTE3] & SCST_INQ_NORMACA_BIT) {
26499+ PRINT_INFO("NormACA set for device: "
26500+ "lun=%lld, type 0x%02x. Clear it, "
26501+ "since it's unsupported.",
26502+ (long long unsigned int)cmd->lun,
26503+ buffer[0]);
26504+ }
26505+#endif
26506+ buffer[SCST_INQ_BYTE3] &= ~SCST_INQ_NORMACA_BIT;
26507+ } else if (buflen != 0) {
26508+ PRINT_ERROR("%s", "Unable to get INQUIRY "
26509+ "buffer");
26510+ scst_set_cmd_error(cmd,
26511+ SCST_LOAD_SENSE(scst_sense_hardw_error));
26512+ err = true;
26513+ }
26514+ if (buflen > 0)
26515+ scst_put_buf(cmd, buffer);
26516+
26517+ if (err)
26518+ goto out;
26519+ }
26520+
26521+ if (unlikely((cmd->cdb[0] == MODE_SELECT) ||
26522+ (cmd->cdb[0] == MODE_SELECT_10) ||
26523+ (cmd->cdb[0] == LOG_SELECT))) {
26524+ TRACE(TRACE_SCSI,
26525+ "MODE/LOG SELECT succeeded (LUN %lld)",
26526+ (long long unsigned int)cmd->lun);
26527+ cmd->state = SCST_CMD_STATE_MODE_SELECT_CHECKS;
26528+ goto out;
26529+ }
26530+ } else {
26531+ TRACE(TRACE_SCSI, "cmd %p not succeeded with status %x",
26532+ cmd, cmd->status);
26533+
26534+ if ((cmd->cdb[0] == RESERVE) || (cmd->cdb[0] == RESERVE_10)) {
26535+ if (!test_bit(SCST_TGT_DEV_RESERVED,
26536+ &cmd->tgt_dev->tgt_dev_flags)) {
26537+ struct scst_tgt_dev *tgt_dev_tmp;
26538+ struct scst_device *dev = cmd->dev;
26539+
26540+ TRACE(TRACE_SCSI, "RESERVE failed lun=%lld, "
26541+ "status=%x",
26542+ (long long unsigned int)cmd->lun,
26543+ cmd->status);
26544+ PRINT_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense,
26545+ cmd->sense_valid_len);
26546+
26547+ /* Clearing the reservation */
26548+ spin_lock_bh(&dev->dev_lock);
26549+ list_for_each_entry(tgt_dev_tmp,
26550+ &dev->dev_tgt_dev_list,
26551+ dev_tgt_dev_list_entry) {
26552+ clear_bit(SCST_TGT_DEV_RESERVED,
26553+ &tgt_dev_tmp->tgt_dev_flags);
26554+ }
26555+ dev->dev_reserved = 0;
26556+ spin_unlock_bh(&dev->dev_lock);
26557+ }
26558+ }
26559+
26560+ /* Check for MODE PARAMETERS CHANGED UA */
26561+ if ((cmd->dev->scsi_dev != NULL) &&
26562+ (cmd->status == SAM_STAT_CHECK_CONDITION) &&
26563+ scst_is_ua_sense(cmd->sense, cmd->sense_valid_len) &&
26564+ scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
26565+ SCST_SENSE_ASCx_VALID,
26566+ 0, 0x2a, 0x01)) {
26567+ TRACE(TRACE_SCSI, "MODE PARAMETERS CHANGED UA (lun "
26568+ "%lld)", (long long unsigned int)cmd->lun);
26569+ cmd->state = SCST_CMD_STATE_MODE_SELECT_CHECKS;
26570+ goto out;
26571+ }
26572+ }
26573+
26574+ cmd->state = SCST_CMD_STATE_DEV_DONE;
26575+
26576+out:
26577+ TRACE_EXIT_RES(res);
26578+ return res;
26579+}
26580+
26581+static int scst_mode_select_checks(struct scst_cmd *cmd)
26582+{
26583+ int res = SCST_CMD_STATE_RES_CONT_SAME;
26584+
26585+ TRACE_ENTRY();
26586+
26587+ if (likely(scsi_status_is_good(cmd->status))) {
26588+ int atomic = scst_cmd_atomic(cmd);
26589+ if (unlikely((cmd->cdb[0] == MODE_SELECT) ||
26590+ (cmd->cdb[0] == MODE_SELECT_10) ||
26591+ (cmd->cdb[0] == LOG_SELECT))) {
26592+ struct scst_device *dev = cmd->dev;
26593+ int sl;
26594+ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
26595+
26596+ if (atomic && (dev->scsi_dev != NULL)) {
26597+ TRACE_DBG("%s", "MODE/LOG SELECT: thread "
26598+ "context required");
26599+ res = SCST_CMD_STATE_RES_NEED_THREAD;
26600+ goto out;
26601+ }
26602+
26603+ TRACE(TRACE_SCSI, "MODE/LOG SELECT succeeded, "
26604+ "setting the SELECT UA (lun=%lld)",
26605+ (long long unsigned int)cmd->lun);
26606+
26607+ spin_lock_bh(&dev->dev_lock);
26608+ if (cmd->cdb[0] == LOG_SELECT) {
26609+ sl = scst_set_sense(sense_buffer,
26610+ sizeof(sense_buffer),
26611+ dev->d_sense,
26612+ UNIT_ATTENTION, 0x2a, 0x02);
26613+ } else {
26614+ sl = scst_set_sense(sense_buffer,
26615+ sizeof(sense_buffer),
26616+ dev->d_sense,
26617+ UNIT_ATTENTION, 0x2a, 0x01);
26618+ }
26619+ scst_dev_check_set_local_UA(dev, cmd, sense_buffer, sl);
26620+ spin_unlock_bh(&dev->dev_lock);
26621+
26622+ if (dev->scsi_dev != NULL)
26623+ scst_obtain_device_parameters(dev);
26624+ }
26625+ } else if ((cmd->status == SAM_STAT_CHECK_CONDITION) &&
26626+ scst_is_ua_sense(cmd->sense, cmd->sense_valid_len) &&
26627+ /* mode parameters changed */
26628+ (scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
26629+ SCST_SENSE_ASCx_VALID,
26630+ 0, 0x2a, 0x01) ||
26631+ scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
26632+ SCST_SENSE_ASC_VALID,
26633+ 0, 0x29, 0) /* reset */ ||
26634+ scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
26635+ SCST_SENSE_ASC_VALID,
26636+ 0, 0x28, 0) /* medium changed */ ||
26637+ /* cleared by another ini (just in case) */
26638+ scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
26639+ SCST_SENSE_ASC_VALID,
26640+ 0, 0x2F, 0))) {
26641+ int atomic = scst_cmd_atomic(cmd);
26642+ if (atomic) {
26643+ TRACE_DBG("Possible parameters changed UA %x: "
26644+ "thread context required", cmd->sense[12]);
26645+ res = SCST_CMD_STATE_RES_NEED_THREAD;
26646+ goto out;
26647+ }
26648+
26649+ TRACE(TRACE_SCSI, "Possible parameters changed UA %x "
26650+ "(LUN %lld): getting new parameters", cmd->sense[12],
26651+ (long long unsigned int)cmd->lun);
26652+
26653+ scst_obtain_device_parameters(cmd->dev);
26654+ } else
26655+ BUG();
26656+
26657+ cmd->state = SCST_CMD_STATE_DEV_DONE;
26658+
26659+out:
26660+ TRACE_EXIT_HRES(res);
26661+ return res;
26662+}
26663+
26664+static void scst_inc_check_expected_sn(struct scst_cmd *cmd)
26665+{
26666+ if (likely(cmd->sn_set))
26667+ scst_inc_expected_sn(cmd->tgt_dev, cmd->sn_slot);
26668+
26669+ scst_make_deferred_commands_active(cmd->tgt_dev);
26670+}
26671+
26672+static int scst_dev_done(struct scst_cmd *cmd)
26673+{
26674+ int res = SCST_CMD_STATE_RES_CONT_SAME;
26675+ int state;
26676+ struct scst_device *dev = cmd->dev;
26677+
26678+ TRACE_ENTRY();
26679+
26680+ state = SCST_CMD_STATE_PRE_XMIT_RESP;
26681+
26682+ if (likely(!scst_is_cmd_fully_local(cmd)) &&
26683+ likely(dev->handler->dev_done != NULL)) {
26684+ int rc;
26685+
26686+ if (unlikely(!dev->handler->dev_done_atomic &&
26687+ scst_cmd_atomic(cmd))) {
26688+ /*
26689+ * It shouldn't be because of the SCST_TGT_DEV_AFTER_*
26690+ * optimization.
26691+ */
26692+ TRACE_DBG("Dev handler %s dev_done() needs thread "
26693+ "context, rescheduling", dev->handler->name);
26694+ res = SCST_CMD_STATE_RES_NEED_THREAD;
26695+ goto out;
26696+ }
26697+
26698+ TRACE_DBG("Calling dev handler %s dev_done(%p)",
26699+ dev->handler->name, cmd);
26700+ scst_set_cur_start(cmd);
26701+ rc = dev->handler->dev_done(cmd);
26702+ scst_set_dev_done_time(cmd);
26703+ TRACE_DBG("Dev handler %s dev_done() returned %d",
26704+ dev->handler->name, rc);
26705+ if (rc != SCST_CMD_STATE_DEFAULT)
26706+ state = rc;
26707+ }
26708+
26709+ switch (state) {
26710+#ifdef CONFIG_SCST_EXTRACHECKS
26711+ case SCST_CMD_STATE_PRE_XMIT_RESP:
26712+ case SCST_CMD_STATE_PARSE:
26713+ case SCST_CMD_STATE_PREPARE_SPACE:
26714+ case SCST_CMD_STATE_RDY_TO_XFER:
26715+ case SCST_CMD_STATE_TGT_PRE_EXEC:
26716+ case SCST_CMD_STATE_SEND_FOR_EXEC:
26717+ case SCST_CMD_STATE_LOCAL_EXEC:
26718+ case SCST_CMD_STATE_REAL_EXEC:
26719+ case SCST_CMD_STATE_PRE_DEV_DONE:
26720+ case SCST_CMD_STATE_MODE_SELECT_CHECKS:
26721+ case SCST_CMD_STATE_DEV_DONE:
26722+ case SCST_CMD_STATE_XMIT_RESP:
26723+ case SCST_CMD_STATE_FINISHED:
26724+ case SCST_CMD_STATE_FINISHED_INTERNAL:
26725+#else
26726+ default:
26727+#endif
26728+ cmd->state = state;
26729+ break;
26730+ case SCST_CMD_STATE_NEED_THREAD_CTX:
26731+ TRACE_DBG("Dev handler %s dev_done() requested "
26732+ "thread context, rescheduling",
26733+ dev->handler->name);
26734+ res = SCST_CMD_STATE_RES_NEED_THREAD;
26735+ break;
26736+#ifdef CONFIG_SCST_EXTRACHECKS
26737+ default:
26738+ if (state >= 0) {
26739+ PRINT_ERROR("Dev handler %s dev_done() returned "
26740+ "invalid cmd state %d",
26741+ dev->handler->name, state);
26742+ } else {
26743+ PRINT_ERROR("Dev handler %s dev_done() returned "
26744+ "error %d", dev->handler->name,
26745+ state);
26746+ }
26747+ scst_set_cmd_error(cmd,
26748+ SCST_LOAD_SENSE(scst_sense_hardw_error));
26749+ scst_set_cmd_abnormal_done_state(cmd);
26750+ break;
26751+#endif
26752+ }
26753+
26754+ scst_check_unblock_dev(cmd);
26755+
26756+ if (cmd->inc_expected_sn_on_done && cmd->sent_for_exec)
26757+ scst_inc_check_expected_sn(cmd);
26758+
26759+ if (unlikely(cmd->internal))
26760+ cmd->state = SCST_CMD_STATE_FINISHED_INTERNAL;
26761+
26762+out:
26763+ TRACE_EXIT_HRES(res);
26764+ return res;
26765+}
26766+
26767+static int scst_pre_xmit_response(struct scst_cmd *cmd)
26768+{
26769+ int res;
26770+
26771+ TRACE_ENTRY();
26772+
26773+ EXTRACHECKS_BUG_ON(cmd->internal);
26774+
26775+#ifdef CONFIG_SCST_DEBUG_TM
26776+ if (cmd->tm_dbg_delayed &&
26777+ !test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
26778+ if (scst_cmd_atomic(cmd)) {
26779+ TRACE_MGMT_DBG("%s",
26780+ "DEBUG_TM delayed cmd needs a thread");
26781+ res = SCST_CMD_STATE_RES_NEED_THREAD;
26782+ return res;
26783+ }
26784+ TRACE_MGMT_DBG("Delaying cmd %p (tag %llu) for 1 second",
26785+ cmd, cmd->tag);
26786+ schedule_timeout_uninterruptible(HZ);
26787+ }
26788+#endif
26789+
26790+ if (likely(cmd->tgt_dev != NULL)) {
26791+ /*
26792+ * Those counters protect from not getting too long processing
26793+ * latency, so we should decrement them after cmd completed.
26794+ */
26795+ atomic_dec(&cmd->tgt_dev->tgt_dev_cmd_count);
26796+#ifdef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT
26797+ atomic_dec(&cmd->dev->dev_cmd_count);
26798+#endif
26799+#ifdef CONFIG_SCST_ORDERED_READS
26800+ /* If expected values not set, expected direction is UNKNOWN */
26801+ if (cmd->expected_data_direction & SCST_DATA_WRITE)
26802+ atomic_dec(&cmd->dev->write_cmd_count);
26803+#endif
26804+ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
26805+ scst_on_hq_cmd_response(cmd);
26806+
26807+ if (unlikely(!cmd->sent_for_exec)) {
26808+ TRACE_SN("cmd %p was not sent to mid-lev"
26809+ " (sn %d, set %d)",
26810+ cmd, cmd->sn, cmd->sn_set);
26811+ scst_unblock_deferred(cmd->tgt_dev, cmd);
26812+ cmd->sent_for_exec = 1;
26813+ }
26814+ }
26815+
26816+ cmd->done = 1;
26817+ smp_mb(); /* to sync with scst_abort_cmd() */
26818+
26819+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)))
26820+ scst_xmit_process_aborted_cmd(cmd);
26821+ else if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION))
26822+ scst_store_sense(cmd);
26823+
26824+ if (unlikely(test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags))) {
26825+ TRACE_MGMT_DBG("Flag NO_RESP set for cmd %p (tag %llu), "
26826+ "skipping", cmd, (long long unsigned int)cmd->tag);
26827+ cmd->state = SCST_CMD_STATE_FINISHED;
26828+ res = SCST_CMD_STATE_RES_CONT_SAME;
26829+ goto out;
26830+ }
26831+
26832+ if (unlikely(cmd->resid_possible))
26833+ scst_adjust_resp_data_len(cmd);
26834+ else
26835+ cmd->adjusted_resp_data_len = cmd->resp_data_len;
26836+
26837+ cmd->state = SCST_CMD_STATE_XMIT_RESP;
26838+ res = SCST_CMD_STATE_RES_CONT_SAME;
26839+
26840+out:
26841+ TRACE_EXIT_HRES(res);
26842+ return res;
26843+}
26844+
26845+static int scst_xmit_response(struct scst_cmd *cmd)
26846+{
26847+ struct scst_tgt_template *tgtt = cmd->tgtt;
26848+ int res, rc;
26849+
26850+ TRACE_ENTRY();
26851+
26852+ EXTRACHECKS_BUG_ON(cmd->internal);
26853+
26854+ if (unlikely(!tgtt->xmit_response_atomic &&
26855+ scst_cmd_atomic(cmd))) {
26856+ /*
26857+ * It shouldn't be because of the SCST_TGT_DEV_AFTER_*
26858+ * optimization.
26859+ */
26860+ TRACE_DBG("Target driver %s xmit_response() needs thread "
26861+ "context, rescheduling", tgtt->name);
26862+ res = SCST_CMD_STATE_RES_NEED_THREAD;
26863+ goto out;
26864+ }
26865+
26866+ while (1) {
26867+ int finished_cmds = atomic_read(&cmd->tgt->finished_cmds);
26868+
26869+ res = SCST_CMD_STATE_RES_CONT_NEXT;
26870+ cmd->state = SCST_CMD_STATE_XMIT_WAIT;
26871+
26872+ TRACE_DBG("Calling xmit_response(%p)", cmd);
26873+
26874+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
26875+ if (trace_flag & TRACE_SND_BOT) {
26876+ int i;
26877+ struct scatterlist *sg;
26878+ if (cmd->tgt_sg != NULL)
26879+ sg = cmd->tgt_sg;
26880+ else
26881+ sg = cmd->sg;
26882+ if (sg != NULL) {
26883+ TRACE(TRACE_SND_BOT, "Xmitting data for cmd %p "
26884+ "(sg_cnt %d, sg %p, sg[0].page %p)",
26885+ cmd, cmd->tgt_sg_cnt, sg,
26886+ (void *)sg_page(&sg[0]));
26887+ for (i = 0; i < cmd->tgt_sg_cnt; ++i) {
26888+ PRINT_BUFF_FLAG(TRACE_SND_BOT,
26889+ "Xmitting sg", sg_virt(&sg[i]),
26890+ sg[i].length);
26891+ }
26892+ }
26893+ }
26894+#endif
26895+
26896+ if (tgtt->on_hw_pending_cmd_timeout != NULL) {
26897+ struct scst_session *sess = cmd->sess;
26898+ cmd->hw_pending_start = jiffies;
26899+ cmd->cmd_hw_pending = 1;
26900+ if (!test_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED, &sess->sess_aflags)) {
26901+ TRACE_DBG("Sched HW pending work for sess %p "
26902+ "(max time %d)", sess,
26903+ tgtt->max_hw_pending_time);
26904+ set_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED,
26905+ &sess->sess_aflags);
26906+ schedule_delayed_work(&sess->hw_pending_work,
26907+ tgtt->max_hw_pending_time * HZ);
26908+ }
26909+ }
26910+
26911+ scst_set_cur_start(cmd);
26912+
26913+#ifdef CONFIG_SCST_DEBUG_RETRY
26914+ if (((scst_random() % 100) == 77))
26915+ rc = SCST_TGT_RES_QUEUE_FULL;
26916+ else
26917+#endif
26918+ rc = tgtt->xmit_response(cmd);
26919+ TRACE_DBG("xmit_response() returned %d", rc);
26920+
26921+ if (likely(rc == SCST_TGT_RES_SUCCESS))
26922+ goto out;
26923+
26924+ scst_set_xmit_time(cmd);
26925+
26926+ cmd->cmd_hw_pending = 0;
26927+
26928+ /* Restore the previous state */
26929+ cmd->state = SCST_CMD_STATE_XMIT_RESP;
26930+
26931+ switch (rc) {
26932+ case SCST_TGT_RES_QUEUE_FULL:
26933+ if (scst_queue_retry_cmd(cmd, finished_cmds) == 0)
26934+ break;
26935+ else
26936+ continue;
26937+
26938+ case SCST_TGT_RES_NEED_THREAD_CTX:
26939+ TRACE_DBG("Target driver %s xmit_response() "
26940+ "requested thread context, rescheduling",
26941+ tgtt->name);
26942+ res = SCST_CMD_STATE_RES_NEED_THREAD;
26943+ break;
26944+
26945+ default:
26946+ goto out_error;
26947+ }
26948+ break;
26949+ }
26950+
26951+out:
26952+ /* Caution: cmd can be already dead here */
26953+ TRACE_EXIT_HRES(res);
26954+ return res;
26955+
26956+out_error:
26957+ if (rc == SCST_TGT_RES_FATAL_ERROR) {
26958+ PRINT_ERROR("Target driver %s xmit_response() returned "
26959+ "fatal error", tgtt->name);
26960+ } else {
26961+ PRINT_ERROR("Target driver %s xmit_response() returned "
26962+ "invalid value %d", tgtt->name, rc);
26963+ }
26964+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
26965+ cmd->state = SCST_CMD_STATE_FINISHED;
26966+ res = SCST_CMD_STATE_RES_CONT_SAME;
26967+ goto out;
26968+}
26969+
26970+/**
26971+ * scst_tgt_cmd_done() - the command's processing done
26972+ * @cmd: SCST command
26973+ * @pref_context: preferred command execution context
26974+ *
26975+ * Description:
26976+ * Notifies SCST that the driver sent the response and the command
26977+ * can be freed now. Don't forget to set the delivery status, if it
26978+ * isn't success, using scst_set_delivery_status() before calling
26979+ * this function. The third argument sets preferred command execition
26980+ * context (see SCST_CONTEXT_* constants for details)
26981+ */
26982+void scst_tgt_cmd_done(struct scst_cmd *cmd,
26983+ enum scst_exec_context pref_context)
26984+{
26985+ TRACE_ENTRY();
26986+
26987+ BUG_ON(cmd->state != SCST_CMD_STATE_XMIT_WAIT);
26988+
26989+ scst_set_xmit_time(cmd);
26990+
26991+ cmd->cmd_hw_pending = 0;
26992+
26993+ cmd->state = SCST_CMD_STATE_FINISHED;
26994+ scst_process_redirect_cmd(cmd, pref_context, 1);
26995+
26996+ TRACE_EXIT();
26997+ return;
26998+}
26999+EXPORT_SYMBOL(scst_tgt_cmd_done);
27000+
27001+static int scst_finish_cmd(struct scst_cmd *cmd)
27002+{
27003+ int res;
27004+ struct scst_session *sess = cmd->sess;
27005+
27006+ TRACE_ENTRY();
27007+
27008+ scst_update_lat_stats(cmd);
27009+
27010+ if (unlikely(cmd->delivery_status != SCST_CMD_DELIVERY_SUCCESS)) {
27011+ if ((cmd->tgt_dev != NULL) &&
27012+ scst_is_ua_sense(cmd->sense, cmd->sense_valid_len)) {
27013+ /* This UA delivery failed, so we need to requeue it */
27014+ if (scst_cmd_atomic(cmd) &&
27015+ scst_is_ua_global(cmd->sense, cmd->sense_valid_len)) {
27016+ TRACE_MGMT_DBG("Requeuing of global UA for "
27017+ "failed cmd %p needs a thread", cmd);
27018+ res = SCST_CMD_STATE_RES_NEED_THREAD;
27019+ goto out;
27020+ }
27021+ scst_requeue_ua(cmd);
27022+ }
27023+ }
27024+
27025+ atomic_dec(&sess->sess_cmd_count);
27026+
27027+ spin_lock_irq(&sess->sess_list_lock);
27028+ list_del(&cmd->sess_cmd_list_entry);
27029+ spin_unlock_irq(&sess->sess_list_lock);
27030+
27031+ cmd->finished = 1;
27032+ smp_mb(); /* to sync with scst_abort_cmd() */
27033+
27034+ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
27035+ TRACE_MGMT_DBG("Aborted cmd %p finished (cmd_ref %d, "
27036+ "scst_cmd_count %d)", cmd, atomic_read(&cmd->cmd_ref),
27037+ atomic_read(&scst_cmd_count));
27038+
27039+ scst_finish_cmd_mgmt(cmd);
27040+ }
27041+
27042+ __scst_cmd_put(cmd);
27043+
27044+ res = SCST_CMD_STATE_RES_CONT_NEXT;
27045+
27046+out:
27047+ TRACE_EXIT_HRES(res);
27048+ return res;
27049+}
27050+
27051+/*
27052+ * No locks, but it must be externally serialized (see comment for
27053+ * scst_cmd_init_done() in scst.h)
27054+ */
27055+static void scst_cmd_set_sn(struct scst_cmd *cmd)
27056+{
27057+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
27058+ unsigned long flags;
27059+
27060+ TRACE_ENTRY();
27061+
27062+ if (scst_is_implicit_hq(cmd) &&
27063+ likely(cmd->queue_type == SCST_CMD_QUEUE_SIMPLE)) {
27064+ TRACE_SN("Implicit HQ cmd %p", cmd);
27065+ cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
27066+ }
27067+
27068+ EXTRACHECKS_BUG_ON(cmd->sn_set || cmd->hq_cmd_inced);
27069+
27070+ /* Optimized for lockless fast path */
27071+
27072+ scst_check_debug_sn(cmd);
27073+
27074+#ifdef CONFIG_SCST_STRICT_SERIALIZING
27075+ cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
27076+#endif
27077+
27078+ if (cmd->dev->queue_alg == SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER) {
27079+ /*
27080+ * Not the best way, but good enough until there is a
27081+ * possibility to specify queue type during pass-through
27082+ * commands submission.
27083+ */
27084+ cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
27085+ }
27086+
27087+ switch (cmd->queue_type) {
27088+ case SCST_CMD_QUEUE_SIMPLE:
27089+ case SCST_CMD_QUEUE_UNTAGGED:
27090+#ifdef CONFIG_SCST_ORDERED_READS
27091+ if (scst_cmd_is_expected_set(cmd)) {
27092+ if ((cmd->expected_data_direction == SCST_DATA_READ) &&
27093+ (atomic_read(&cmd->dev->write_cmd_count) == 0))
27094+ goto ordered;
27095+ } else
27096+ goto ordered;
27097+#endif
27098+ if (likely(tgt_dev->num_free_sn_slots >= 0)) {
27099+ /*
27100+ * atomic_inc_return() implies memory barrier to sync
27101+ * with scst_inc_expected_sn()
27102+ */
27103+ if (atomic_inc_return(tgt_dev->cur_sn_slot) == 1) {
27104+ tgt_dev->curr_sn++;
27105+ TRACE_SN("Incremented curr_sn %d",
27106+ tgt_dev->curr_sn);
27107+ }
27108+ cmd->sn_slot = tgt_dev->cur_sn_slot;
27109+ cmd->sn = tgt_dev->curr_sn;
27110+
27111+ tgt_dev->prev_cmd_ordered = 0;
27112+ } else {
27113+ TRACE(TRACE_MINOR, "***WARNING*** Not enough SN slots "
27114+ "%zd", ARRAY_SIZE(tgt_dev->sn_slots));
27115+ goto ordered;
27116+ }
27117+ break;
27118+
27119+ case SCST_CMD_QUEUE_ORDERED:
27120+ TRACE_SN("ORDERED cmd %p (op %x)", cmd, cmd->cdb[0]);
27121+ordered:
27122+ if (!tgt_dev->prev_cmd_ordered) {
27123+ spin_lock_irqsave(&tgt_dev->sn_lock, flags);
27124+ if (tgt_dev->num_free_sn_slots >= 0) {
27125+ tgt_dev->num_free_sn_slots--;
27126+ if (tgt_dev->num_free_sn_slots >= 0) {
27127+ int i = 0;
27128+ /* Commands can finish in any order, so
27129+ * we don't know which slot is empty.
27130+ */
27131+ while (1) {
27132+ tgt_dev->cur_sn_slot++;
27133+ if (tgt_dev->cur_sn_slot ==
27134+ tgt_dev->sn_slots + ARRAY_SIZE(tgt_dev->sn_slots))
27135+ tgt_dev->cur_sn_slot = tgt_dev->sn_slots;
27136+
27137+ if (atomic_read(tgt_dev->cur_sn_slot) == 0)
27138+ break;
27139+
27140+ i++;
27141+ BUG_ON(i == ARRAY_SIZE(tgt_dev->sn_slots));
27142+ }
27143+ TRACE_SN("New cur SN slot %zd",
27144+ tgt_dev->cur_sn_slot -
27145+ tgt_dev->sn_slots);
27146+ }
27147+ }
27148+ spin_unlock_irqrestore(&tgt_dev->sn_lock, flags);
27149+ }
27150+ tgt_dev->prev_cmd_ordered = 1;
27151+ tgt_dev->curr_sn++;
27152+ cmd->sn = tgt_dev->curr_sn;
27153+ break;
27154+
27155+ case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
27156+ TRACE_SN("HQ cmd %p (op %x)", cmd, cmd->cdb[0]);
27157+ spin_lock_irqsave(&tgt_dev->sn_lock, flags);
27158+ tgt_dev->hq_cmd_count++;
27159+ spin_unlock_irqrestore(&tgt_dev->sn_lock, flags);
27160+ cmd->hq_cmd_inced = 1;
27161+ goto out;
27162+
27163+ default:
27164+ BUG();
27165+ }
27166+
27167+ TRACE_SN("cmd(%p)->sn: %d (tgt_dev %p, *cur_sn_slot %d, "
27168+ "num_free_sn_slots %d, prev_cmd_ordered %ld, "
27169+ "cur_sn_slot %zd)", cmd, cmd->sn, tgt_dev,
27170+ atomic_read(tgt_dev->cur_sn_slot),
27171+ tgt_dev->num_free_sn_slots, tgt_dev->prev_cmd_ordered,
27172+ tgt_dev->cur_sn_slot-tgt_dev->sn_slots);
27173+
27174+ cmd->sn_set = 1;
27175+
27176+out:
27177+ TRACE_EXIT();
27178+ return;
27179+}
27180+
27181+/*
27182+ * Returns 0 on success, > 0 when we need to wait for unblock,
27183+ * < 0 if there is no device (lun) or device type handler.
27184+ *
27185+ * No locks, but might be on IRQ, protection is done by the
27186+ * suspended activity.
27187+ */
27188+static int scst_translate_lun(struct scst_cmd *cmd)
27189+{
27190+ struct scst_tgt_dev *tgt_dev = NULL;
27191+ int res;
27192+
27193+ TRACE_ENTRY();
27194+
27195+ /* See comment about smp_mb() in scst_suspend_activity() */
27196+ __scst_get();
27197+
27198+ if (likely(!test_bit(SCST_FLAG_SUSPENDED, &scst_flags))) {
27199+ struct list_head *sess_tgt_dev_list_head =
27200+ &cmd->sess->sess_tgt_dev_list_hash[HASH_VAL(cmd->lun)];
27201+ TRACE_DBG("Finding tgt_dev for cmd %p (lun %lld)", cmd,
27202+ (long long unsigned int)cmd->lun);
27203+ res = -1;
27204+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
27205+ sess_tgt_dev_list_entry) {
27206+ if (tgt_dev->lun == cmd->lun) {
27207+ TRACE_DBG("tgt_dev %p found", tgt_dev);
27208+
27209+ if (unlikely(tgt_dev->dev->handler ==
27210+ &scst_null_devtype)) {
27211+ PRINT_INFO("Dev handler for device "
27212+ "%lld is NULL, the device will not "
27213+ "be visible remotely",
27214+ (long long unsigned int)cmd->lun);
27215+ break;
27216+ }
27217+
27218+ cmd->cmd_threads = tgt_dev->active_cmd_threads;
27219+ cmd->tgt_dev = tgt_dev;
27220+ cmd->dev = tgt_dev->dev;
27221+
27222+ res = 0;
27223+ break;
27224+ }
27225+ }
27226+ if (res != 0) {
27227+ TRACE(TRACE_MINOR,
27228+ "tgt_dev for LUN %lld not found, command to "
27229+ "unexisting LU?",
27230+ (long long unsigned int)cmd->lun);
27231+ __scst_put();
27232+ }
27233+ } else {
27234+ TRACE_MGMT_DBG("%s", "FLAG SUSPENDED set, skipping");
27235+ __scst_put();
27236+ res = 1;
27237+ }
27238+
27239+ TRACE_EXIT_RES(res);
27240+ return res;
27241+}
27242+
27243+/*
27244+ * No locks, but might be on IRQ.
27245+ *
27246+ * Returns 0 on success, > 0 when we need to wait for unblock,
27247+ * < 0 if there is no device (lun) or device type handler.
27248+ */
27249+static int __scst_init_cmd(struct scst_cmd *cmd)
27250+{
27251+ int res = 0;
27252+
27253+ TRACE_ENTRY();
27254+
27255+ res = scst_translate_lun(cmd);
27256+ if (likely(res == 0)) {
27257+ int cnt;
27258+ bool failure = false;
27259+
27260+ cmd->state = SCST_CMD_STATE_PARSE;
27261+
27262+ cnt = atomic_inc_return(&cmd->tgt_dev->tgt_dev_cmd_count);
27263+ if (unlikely(cnt > SCST_MAX_TGT_DEV_COMMANDS)) {
27264+ TRACE(TRACE_FLOW_CONTROL,
27265+ "Too many pending commands (%d) in "
27266+ "session, returning BUSY to initiator \"%s\"",
27267+ cnt, (cmd->sess->initiator_name[0] == '\0') ?
27268+ "Anonymous" : cmd->sess->initiator_name);
27269+ failure = true;
27270+ }
27271+
27272+#ifdef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT
27273+ cnt = atomic_inc_return(&cmd->dev->dev_cmd_count);
27274+ if (unlikely(cnt > SCST_MAX_DEV_COMMANDS)) {
27275+ if (!failure) {
27276+ TRACE(TRACE_FLOW_CONTROL,
27277+ "Too many pending device "
27278+ "commands (%d), returning BUSY to "
27279+ "initiator \"%s\"", cnt,
27280+ (cmd->sess->initiator_name[0] == '\0') ?
27281+ "Anonymous" :
27282+ cmd->sess->initiator_name);
27283+ failure = true;
27284+ }
27285+ }
27286+#endif
27287+
27288+#ifdef CONFIG_SCST_ORDERED_READS
27289+ /* If expected values not set, expected direction is UNKNOWN */
27290+ if (cmd->expected_data_direction & SCST_DATA_WRITE)
27291+ atomic_inc(&cmd->dev->write_cmd_count);
27292+#endif
27293+
27294+ if (unlikely(failure))
27295+ goto out_busy;
27296+
27297+ if (unlikely(scst_pre_parse(cmd) != 0))
27298+ goto out;
27299+
27300+ if (!cmd->set_sn_on_restart_cmd)
27301+ scst_cmd_set_sn(cmd);
27302+ } else if (res < 0) {
27303+ TRACE_DBG("Finishing cmd %p", cmd);
27304+ scst_set_cmd_error(cmd,
27305+ SCST_LOAD_SENSE(scst_sense_lun_not_supported));
27306+ scst_set_cmd_abnormal_done_state(cmd);
27307+ } else
27308+ goto out;
27309+
27310+out:
27311+ TRACE_EXIT_RES(res);
27312+ return res;
27313+
27314+out_busy:
27315+ scst_set_busy(cmd);
27316+ scst_set_cmd_abnormal_done_state(cmd);
27317+ goto out;
27318+}
27319+
27320+/* Called under scst_init_lock and IRQs disabled */
27321+static void scst_do_job_init(void)
27322+ __releases(&scst_init_lock)
27323+ __acquires(&scst_init_lock)
27324+{
27325+ struct scst_cmd *cmd;
27326+ int susp;
27327+
27328+ TRACE_ENTRY();
27329+
27330+restart:
27331+ /*
27332+ * There is no need for read barrier here, because we don't care where
27333+ * this check will be done.
27334+ */
27335+ susp = test_bit(SCST_FLAG_SUSPENDED, &scst_flags);
27336+ if (scst_init_poll_cnt > 0)
27337+ scst_init_poll_cnt--;
27338+
27339+ list_for_each_entry(cmd, &scst_init_cmd_list, cmd_list_entry) {
27340+ int rc;
27341+ if (susp && !test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))
27342+ continue;
27343+ if (!test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
27344+ spin_unlock_irq(&scst_init_lock);
27345+ rc = __scst_init_cmd(cmd);
27346+ spin_lock_irq(&scst_init_lock);
27347+ if (rc > 0) {
27348+ TRACE_MGMT_DBG("%s",
27349+ "FLAG SUSPENDED set, restarting");
27350+ goto restart;
27351+ }
27352+ } else {
27353+ TRACE_MGMT_DBG("Aborting not inited cmd %p (tag %llu)",
27354+ cmd, (long long unsigned int)cmd->tag);
27355+ scst_set_cmd_abnormal_done_state(cmd);
27356+ }
27357+
27358+ /*
27359+ * Deleting cmd from init cmd list after __scst_init_cmd()
27360+ * is necessary to keep the check in scst_init_cmd() correct
27361+ * to preserve the commands order.
27362+ *
27363+ * We don't care about the race, when init cmd list is empty
27364+ * and one command detected that it just was not empty, so
27365+ * it's inserting to it, but another command at the same time
27366+ * seeing init cmd list empty and goes directly, because it
27367+ * could affect only commands from the same initiator to the
27368+ * same tgt_dev, but scst_cmd_init_done*() doesn't guarantee
27369+ * the order in case of simultaneous such calls anyway.
27370+ */
27371+ TRACE_MGMT_DBG("Deleting cmd %p from init cmd list", cmd);
27372+ smp_wmb(); /* enforce the required order */
27373+ list_del(&cmd->cmd_list_entry);
27374+ spin_unlock(&scst_init_lock);
27375+
27376+ spin_lock(&cmd->cmd_threads->cmd_list_lock);
27377+ TRACE_MGMT_DBG("Adding cmd %p to active cmd list", cmd);
27378+ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
27379+ list_add(&cmd->cmd_list_entry,
27380+ &cmd->cmd_threads->active_cmd_list);
27381+ else
27382+ list_add_tail(&cmd->cmd_list_entry,
27383+ &cmd->cmd_threads->active_cmd_list);
27384+ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
27385+ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
27386+
27387+ spin_lock(&scst_init_lock);
27388+ goto restart;
27389+ }
27390+
27391+ /* It isn't really needed, but let's keep it */
27392+ if (susp != test_bit(SCST_FLAG_SUSPENDED, &scst_flags))
27393+ goto restart;
27394+
27395+ TRACE_EXIT();
27396+ return;
27397+}
27398+
27399+static inline int test_init_cmd_list(void)
27400+{
27401+ int res = (!list_empty(&scst_init_cmd_list) &&
27402+ !test_bit(SCST_FLAG_SUSPENDED, &scst_flags)) ||
27403+ unlikely(kthread_should_stop()) ||
27404+ (scst_init_poll_cnt > 0);
27405+ return res;
27406+}
27407+
27408+int scst_init_thread(void *arg)
27409+{
27410+ TRACE_ENTRY();
27411+
27412+ PRINT_INFO("Init thread started, PID %d", current->pid);
27413+
27414+ current->flags |= PF_NOFREEZE;
27415+
27416+ set_user_nice(current, -10);
27417+
27418+ spin_lock_irq(&scst_init_lock);
27419+ while (!kthread_should_stop()) {
27420+ wait_queue_t wait;
27421+ init_waitqueue_entry(&wait, current);
27422+
27423+ if (!test_init_cmd_list()) {
27424+ add_wait_queue_exclusive(&scst_init_cmd_list_waitQ,
27425+ &wait);
27426+ for (;;) {
27427+ set_current_state(TASK_INTERRUPTIBLE);
27428+ if (test_init_cmd_list())
27429+ break;
27430+ spin_unlock_irq(&scst_init_lock);
27431+ schedule();
27432+ spin_lock_irq(&scst_init_lock);
27433+ }
27434+ set_current_state(TASK_RUNNING);
27435+ remove_wait_queue(&scst_init_cmd_list_waitQ, &wait);
27436+ }
27437+ scst_do_job_init();
27438+ }
27439+ spin_unlock_irq(&scst_init_lock);
27440+
27441+ /*
27442+ * If kthread_should_stop() is true, we are guaranteed to be
27443+ * on the module unload, so scst_init_cmd_list must be empty.
27444+ */
27445+ BUG_ON(!list_empty(&scst_init_cmd_list));
27446+
27447+ PRINT_INFO("Init thread PID %d finished", current->pid);
27448+
27449+ TRACE_EXIT();
27450+ return 0;
27451+}
27452+
27453+/**
27454+ * scst_process_active_cmd() - process active command
27455+ *
27456+ * Description:
27457+ * Main SCST commands processing routing. Must be used only by dev handlers.
27458+ *
27459+ * Argument atomic is true, if function called in atomic context.
27460+ *
27461+ * Must be called with no locks held.
27462+ */
27463+void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic)
27464+{
27465+ int res;
27466+
27467+ TRACE_ENTRY();
27468+
27469+ /*
27470+ * Checkpatch will complain on the use of in_atomic() below. You
27471+ * can safely ignore this warning since in_atomic() is used here only
27472+ * for debugging purposes.
27473+ */
27474+ EXTRACHECKS_BUG_ON(in_irq() || irqs_disabled());
27475+ EXTRACHECKS_WARN_ON((in_atomic() || in_interrupt() || irqs_disabled()) &&
27476+ !atomic);
27477+
27478+ cmd->atomic = atomic;
27479+
27480+ TRACE_DBG("cmd %p, atomic %d", cmd, atomic);
27481+
27482+ do {
27483+ switch (cmd->state) {
27484+ case SCST_CMD_STATE_PARSE:
27485+ res = scst_parse_cmd(cmd);
27486+ break;
27487+
27488+ case SCST_CMD_STATE_PREPARE_SPACE:
27489+ res = scst_prepare_space(cmd);
27490+ break;
27491+
27492+ case SCST_CMD_STATE_PREPROCESSING_DONE:
27493+ res = scst_preprocessing_done(cmd);
27494+ break;
27495+
27496+ case SCST_CMD_STATE_RDY_TO_XFER:
27497+ res = scst_rdy_to_xfer(cmd);
27498+ break;
27499+
27500+ case SCST_CMD_STATE_TGT_PRE_EXEC:
27501+ res = scst_tgt_pre_exec(cmd);
27502+ break;
27503+
27504+ case SCST_CMD_STATE_SEND_FOR_EXEC:
27505+ if (tm_dbg_check_cmd(cmd) != 0) {
27506+ res = SCST_CMD_STATE_RES_CONT_NEXT;
27507+ TRACE_MGMT_DBG("Skipping cmd %p (tag %llu), "
27508+ "because of TM DBG delay", cmd,
27509+ (long long unsigned int)cmd->tag);
27510+ break;
27511+ }
27512+ res = scst_send_for_exec(&cmd);
27513+ /*
27514+ * !! At this point cmd, sess & tgt_dev can already be
27515+ * freed !!
27516+ */
27517+ break;
27518+
27519+ case SCST_CMD_STATE_LOCAL_EXEC:
27520+ res = scst_local_exec(cmd);
27521+ /*
27522+ * !! At this point cmd, sess & tgt_dev can already be
27523+ * freed !!
27524+ */
27525+ break;
27526+
27527+ case SCST_CMD_STATE_REAL_EXEC:
27528+ res = scst_real_exec(cmd);
27529+ /*
27530+ * !! At this point cmd, sess & tgt_dev can already be
27531+ * freed !!
27532+ */
27533+ break;
27534+
27535+ case SCST_CMD_STATE_PRE_DEV_DONE:
27536+ res = scst_pre_dev_done(cmd);
27537+ EXTRACHECKS_BUG_ON(res ==
27538+ SCST_CMD_STATE_RES_NEED_THREAD);
27539+ break;
27540+
27541+ case SCST_CMD_STATE_MODE_SELECT_CHECKS:
27542+ res = scst_mode_select_checks(cmd);
27543+ break;
27544+
27545+ case SCST_CMD_STATE_DEV_DONE:
27546+ res = scst_dev_done(cmd);
27547+ break;
27548+
27549+ case SCST_CMD_STATE_PRE_XMIT_RESP:
27550+ res = scst_pre_xmit_response(cmd);
27551+ EXTRACHECKS_BUG_ON(res ==
27552+ SCST_CMD_STATE_RES_NEED_THREAD);
27553+ break;
27554+
27555+ case SCST_CMD_STATE_XMIT_RESP:
27556+ res = scst_xmit_response(cmd);
27557+ break;
27558+
27559+ case SCST_CMD_STATE_FINISHED:
27560+ res = scst_finish_cmd(cmd);
27561+ break;
27562+
27563+ case SCST_CMD_STATE_FINISHED_INTERNAL:
27564+ res = scst_finish_internal_cmd(cmd);
27565+ EXTRACHECKS_BUG_ON(res ==
27566+ SCST_CMD_STATE_RES_NEED_THREAD);
27567+ break;
27568+
27569+ default:
27570+ PRINT_CRIT_ERROR("cmd (%p) in state %d, but shouldn't "
27571+ "be", cmd, cmd->state);
27572+ BUG();
27573+ res = SCST_CMD_STATE_RES_CONT_NEXT;
27574+ break;
27575+ }
27576+ } while (res == SCST_CMD_STATE_RES_CONT_SAME);
27577+
27578+ if (res == SCST_CMD_STATE_RES_CONT_NEXT) {
27579+ /* None */
27580+ } else if (res == SCST_CMD_STATE_RES_NEED_THREAD) {
27581+ spin_lock_irq(&cmd->cmd_threads->cmd_list_lock);
27582+#ifdef CONFIG_SCST_EXTRACHECKS
27583+ switch (cmd->state) {
27584+ case SCST_CMD_STATE_PARSE:
27585+ case SCST_CMD_STATE_PREPARE_SPACE:
27586+ case SCST_CMD_STATE_RDY_TO_XFER:
27587+ case SCST_CMD_STATE_TGT_PRE_EXEC:
27588+ case SCST_CMD_STATE_SEND_FOR_EXEC:
27589+ case SCST_CMD_STATE_LOCAL_EXEC:
27590+ case SCST_CMD_STATE_REAL_EXEC:
27591+ case SCST_CMD_STATE_DEV_DONE:
27592+ case SCST_CMD_STATE_XMIT_RESP:
27593+#endif
27594+ TRACE_DBG("Adding cmd %p to head of active cmd list",
27595+ cmd);
27596+ list_add(&cmd->cmd_list_entry,
27597+ &cmd->cmd_threads->active_cmd_list);
27598+#ifdef CONFIG_SCST_EXTRACHECKS
27599+ break;
27600+ default:
27601+ PRINT_CRIT_ERROR("cmd %p is in invalid state %d)", cmd,
27602+ cmd->state);
27603+ spin_unlock_irq(&cmd->cmd_threads->cmd_list_lock);
27604+ BUG();
27605+ spin_lock_irq(&cmd->cmd_threads->cmd_list_lock);
27606+ break;
27607+ }
27608+#endif
27609+ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
27610+ spin_unlock_irq(&cmd->cmd_threads->cmd_list_lock);
27611+ } else
27612+ BUG();
27613+
27614+ TRACE_EXIT();
27615+ return;
27616+}
27617+EXPORT_SYMBOL_GPL(scst_process_active_cmd);
27618+
27619+/* Called under cmd_list_lock and IRQs disabled */
27620+static void scst_do_job_active(struct list_head *cmd_list,
27621+ spinlock_t *cmd_list_lock, bool atomic)
27622+ __releases(cmd_list_lock)
27623+ __acquires(cmd_list_lock)
27624+{
27625+ TRACE_ENTRY();
27626+
27627+ while (!list_empty(cmd_list)) {
27628+ struct scst_cmd *cmd = list_entry(cmd_list->next, typeof(*cmd),
27629+ cmd_list_entry);
27630+ TRACE_DBG("Deleting cmd %p from active cmd list", cmd);
27631+ list_del(&cmd->cmd_list_entry);
27632+ spin_unlock_irq(cmd_list_lock);
27633+ scst_process_active_cmd(cmd, atomic);
27634+ spin_lock_irq(cmd_list_lock);
27635+ }
27636+
27637+ TRACE_EXIT();
27638+ return;
27639+}
27640+
27641+static inline int test_cmd_threads(struct scst_cmd_threads *p_cmd_threads)
27642+{
27643+ int res = !list_empty(&p_cmd_threads->active_cmd_list) ||
27644+ unlikely(kthread_should_stop()) ||
27645+ tm_dbg_is_release();
27646+ return res;
27647+}
27648+
27649+int scst_cmd_thread(void *arg)
27650+{
27651+ struct scst_cmd_threads *p_cmd_threads = arg;
27652+
27653+ TRACE_ENTRY();
27654+
27655+ PRINT_INFO("Processing thread %s (PID %d) started", current->comm,
27656+ current->pid);
27657+
27658+#if 0
27659+ set_user_nice(current, 10);
27660+#endif
27661+ current->flags |= PF_NOFREEZE;
27662+
27663+ mutex_lock(&p_cmd_threads->io_context_mutex);
27664+
27665+ WARN_ON(current->io_context);
27666+
27667+ if (p_cmd_threads != &scst_main_cmd_threads) {
27668+ /*
27669+ * For linked IO contexts io_context might be not NULL while
27670+ * io_context 0.
27671+ */
27672+ if (p_cmd_threads->io_context == NULL) {
27673+ p_cmd_threads->io_context = get_io_context(GFP_KERNEL, -1);
27674+ TRACE_MGMT_DBG("Alloced new IO context %p "
27675+ "(p_cmd_threads %p)",
27676+ p_cmd_threads->io_context,
27677+ p_cmd_threads);
27678+ /*
27679+ * Put the extra reference created by get_io_context()
27680+ * because we don't need it.
27681+ */
27682+ put_io_context(p_cmd_threads->io_context);
27683+ } else {
27684+ current->io_context = ioc_task_link(p_cmd_threads->io_context);
27685+ TRACE_MGMT_DBG("Linked IO context %p "
27686+ "(p_cmd_threads %p)", p_cmd_threads->io_context,
27687+ p_cmd_threads);
27688+ }
27689+ p_cmd_threads->io_context_refcnt++;
27690+ }
27691+
27692+ mutex_unlock(&p_cmd_threads->io_context_mutex);
27693+
27694+ p_cmd_threads->io_context_ready = true;
27695+
27696+ spin_lock_irq(&p_cmd_threads->cmd_list_lock);
27697+ while (!kthread_should_stop()) {
27698+ wait_queue_t wait;
27699+ init_waitqueue_entry(&wait, current);
27700+
27701+ if (!test_cmd_threads(p_cmd_threads)) {
27702+ add_wait_queue_exclusive_head(
27703+ &p_cmd_threads->cmd_list_waitQ,
27704+ &wait);
27705+ for (;;) {
27706+ set_current_state(TASK_INTERRUPTIBLE);
27707+ if (test_cmd_threads(p_cmd_threads))
27708+ break;
27709+ spin_unlock_irq(&p_cmd_threads->cmd_list_lock);
27710+ schedule();
27711+ spin_lock_irq(&p_cmd_threads->cmd_list_lock);
27712+ }
27713+ set_current_state(TASK_RUNNING);
27714+ remove_wait_queue(&p_cmd_threads->cmd_list_waitQ, &wait);
27715+ }
27716+
27717+ if (tm_dbg_is_release()) {
27718+ spin_unlock_irq(&p_cmd_threads->cmd_list_lock);
27719+ tm_dbg_check_released_cmds();
27720+ spin_lock_irq(&p_cmd_threads->cmd_list_lock);
27721+ }
27722+
27723+ scst_do_job_active(&p_cmd_threads->active_cmd_list,
27724+ &p_cmd_threads->cmd_list_lock, false);
27725+ }
27726+ spin_unlock_irq(&p_cmd_threads->cmd_list_lock);
27727+
27728+ if (p_cmd_threads != &scst_main_cmd_threads) {
27729+ mutex_lock(&p_cmd_threads->io_context_mutex);
27730+ if (--p_cmd_threads->io_context_refcnt == 0)
27731+ p_cmd_threads->io_context = NULL;
27732+ mutex_unlock(&p_cmd_threads->io_context_mutex);
27733+ }
27734+
27735+ PRINT_INFO("Processing thread %s (PID %d) finished", current->comm,
27736+ current->pid);
27737+
27738+ TRACE_EXIT();
27739+ return 0;
27740+}
27741+
27742+void scst_cmd_tasklet(long p)
27743+{
27744+ struct scst_tasklet *t = (struct scst_tasklet *)p;
27745+
27746+ TRACE_ENTRY();
27747+
27748+ spin_lock_irq(&t->tasklet_lock);
27749+ scst_do_job_active(&t->tasklet_cmd_list, &t->tasklet_lock, true);
27750+ spin_unlock_irq(&t->tasklet_lock);
27751+
27752+ TRACE_EXIT();
27753+ return;
27754+}
27755+
27756+/*
27757+ * Returns 0 on success, < 0 if there is no device handler or
27758+ * > 0 if SCST_FLAG_SUSPENDED set and SCST_FLAG_SUSPENDING - not.
27759+ * No locks, protection is done by the suspended activity.
27760+ */
27761+static int scst_mgmt_translate_lun(struct scst_mgmt_cmd *mcmd)
27762+{
27763+ struct scst_tgt_dev *tgt_dev = NULL;
27764+ struct list_head *sess_tgt_dev_list_head;
27765+ int res = -1;
27766+
27767+ TRACE_ENTRY();
27768+
27769+ TRACE_DBG("Finding tgt_dev for mgmt cmd %p (lun %lld)", mcmd,
27770+ (long long unsigned int)mcmd->lun);
27771+
27772+ /* See comment about smp_mb() in scst_suspend_activity() */
27773+ __scst_get();
27774+
27775+ if (unlikely(test_bit(SCST_FLAG_SUSPENDED, &scst_flags) &&
27776+ !test_bit(SCST_FLAG_SUSPENDING, &scst_flags))) {
27777+ TRACE_MGMT_DBG("%s", "FLAG SUSPENDED set, skipping");
27778+ __scst_put();
27779+ res = 1;
27780+ goto out;
27781+ }
27782+
27783+ sess_tgt_dev_list_head =
27784+ &mcmd->sess->sess_tgt_dev_list_hash[HASH_VAL(mcmd->lun)];
27785+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
27786+ sess_tgt_dev_list_entry) {
27787+ if (tgt_dev->lun == mcmd->lun) {
27788+ TRACE_DBG("tgt_dev %p found", tgt_dev);
27789+ mcmd->mcmd_tgt_dev = tgt_dev;
27790+ res = 0;
27791+ break;
27792+ }
27793+ }
27794+ if (mcmd->mcmd_tgt_dev == NULL)
27795+ __scst_put();
27796+
27797+out:
27798+ TRACE_EXIT_HRES(res);
27799+ return res;
27800+}
27801+
27802+/* No locks */
27803+void scst_done_cmd_mgmt(struct scst_cmd *cmd)
27804+{
27805+ struct scst_mgmt_cmd_stub *mstb, *t;
27806+ bool wake = 0;
27807+ unsigned long flags;
27808+
27809+ TRACE_ENTRY();
27810+
27811+ TRACE_MGMT_DBG("cmd %p done (tag %llu)",
27812+ cmd, (long long unsigned int)cmd->tag);
27813+
27814+ spin_lock_irqsave(&scst_mcmd_lock, flags);
27815+
27816+ list_for_each_entry_safe(mstb, t, &cmd->mgmt_cmd_list,
27817+ cmd_mgmt_cmd_list_entry) {
27818+ struct scst_mgmt_cmd *mcmd;
27819+
27820+ if (!mstb->done_counted)
27821+ continue;
27822+
27823+ mcmd = mstb->mcmd;
27824+ TRACE_MGMT_DBG("mcmd %p, mcmd->cmd_done_wait_count %d",
27825+ mcmd, mcmd->cmd_done_wait_count);
27826+
27827+ mcmd->cmd_done_wait_count--;
27828+
27829+ BUG_ON(mcmd->cmd_done_wait_count < 0);
27830+
27831+ if (mcmd->cmd_done_wait_count > 0) {
27832+ TRACE_MGMT_DBG("cmd_done_wait_count(%d) not 0, "
27833+ "skipping", mcmd->cmd_done_wait_count);
27834+ goto check_free;
27835+ }
27836+
27837+ if (mcmd->state == SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_DONE) {
27838+ mcmd->state = SCST_MCMD_STATE_AFFECTED_CMDS_DONE;
27839+ TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd "
27840+ "list", mcmd);
27841+ list_add_tail(&mcmd->mgmt_cmd_list_entry,
27842+ &scst_active_mgmt_cmd_list);
27843+ wake = 1;
27844+ }
27845+
27846+check_free:
27847+ if (!mstb->finish_counted) {
27848+ TRACE_DBG("Releasing mstb %p", mstb);
27849+ list_del(&mstb->cmd_mgmt_cmd_list_entry);
27850+ mempool_free(mstb, scst_mgmt_stub_mempool);
27851+ }
27852+ }
27853+
27854+ spin_unlock_irqrestore(&scst_mcmd_lock, flags);
27855+
27856+ if (wake)
27857+ wake_up(&scst_mgmt_cmd_list_waitQ);
27858+
27859+ TRACE_EXIT();
27860+ return;
27861+}
27862+
27863+/* Called under scst_mcmd_lock and IRQs disabled */
27864+static void __scst_dec_finish_wait_count(struct scst_mgmt_cmd *mcmd, bool *wake)
27865+{
27866+ TRACE_ENTRY();
27867+
27868+ mcmd->cmd_finish_wait_count--;
27869+
27870+ BUG_ON(mcmd->cmd_finish_wait_count < 0);
27871+
27872+ if (mcmd->cmd_finish_wait_count > 0) {
27873+ TRACE_MGMT_DBG("cmd_finish_wait_count(%d) not 0, "
27874+ "skipping", mcmd->cmd_finish_wait_count);
27875+ goto out;
27876+ }
27877+
27878+ if (mcmd->cmd_done_wait_count > 0) {
27879+ TRACE_MGMT_DBG("cmd_done_wait_count(%d) not 0, "
27880+ "skipping", mcmd->cmd_done_wait_count);
27881+ goto out;
27882+ }
27883+
27884+ if (mcmd->state == SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_FINISHED) {
27885+ mcmd->state = SCST_MCMD_STATE_DONE;
27886+ TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd "
27887+ "list", mcmd);
27888+ list_add_tail(&mcmd->mgmt_cmd_list_entry,
27889+ &scst_active_mgmt_cmd_list);
27890+ *wake = true;
27891+ }
27892+
27893+out:
27894+ TRACE_EXIT();
27895+ return;
27896+}
27897+
27898+/**
27899+ * scst_prepare_async_mcmd() - prepare async management command
27900+ *
27901+ * Notifies SCST that management command is going to be async, i.e.
27902+ * will be completed in another context.
27903+ *
27904+ * No SCST locks supposed to be held on entrance.
27905+ */
27906+void scst_prepare_async_mcmd(struct scst_mgmt_cmd *mcmd)
27907+{
27908+ unsigned long flags;
27909+
27910+ TRACE_ENTRY();
27911+
27912+ TRACE_MGMT_DBG("Preparing mcmd %p for async execution "
27913+ "(cmd_finish_wait_count %d)", mcmd,
27914+ mcmd->cmd_finish_wait_count);
27915+
27916+ spin_lock_irqsave(&scst_mcmd_lock, flags);
27917+ mcmd->cmd_finish_wait_count++;
27918+ spin_unlock_irqrestore(&scst_mcmd_lock, flags);
27919+
27920+ TRACE_EXIT();
27921+ return;
27922+}
27923+EXPORT_SYMBOL_GPL(scst_prepare_async_mcmd);
27924+
27925+/**
27926+ * scst_async_mcmd_completed() - async management command completed
27927+ *
27928+ * Notifies SCST that async management command, prepared by
27929+ * scst_prepare_async_mcmd(), completed.
27930+ *
27931+ * No SCST locks supposed to be held on entrance.
27932+ */
27933+void scst_async_mcmd_completed(struct scst_mgmt_cmd *mcmd, int status)
27934+{
27935+ unsigned long flags;
27936+ bool wake = false;
27937+
27938+ TRACE_ENTRY();
27939+
27940+ TRACE_MGMT_DBG("Async mcmd %p completed (status %d)", mcmd, status);
27941+
27942+ spin_lock_irqsave(&scst_mcmd_lock, flags);
27943+
27944+ if (status != SCST_MGMT_STATUS_SUCCESS)
27945+ mcmd->status = status;
27946+
27947+ __scst_dec_finish_wait_count(mcmd, &wake);
27948+
27949+ spin_unlock_irqrestore(&scst_mcmd_lock, flags);
27950+
27951+ if (wake)
27952+ wake_up(&scst_mgmt_cmd_list_waitQ);
27953+
27954+ TRACE_EXIT();
27955+ return;
27956+}
27957+EXPORT_SYMBOL_GPL(scst_async_mcmd_completed);
27958+
27959+/* No locks */
27960+static void scst_finish_cmd_mgmt(struct scst_cmd *cmd)
27961+{
27962+ struct scst_mgmt_cmd_stub *mstb, *t;
27963+ bool wake = false;
27964+ unsigned long flags;
27965+
27966+ TRACE_ENTRY();
27967+
27968+ TRACE_MGMT_DBG("cmd %p finished (tag %llu)",
27969+ cmd, (long long unsigned int)cmd->tag);
27970+
27971+ spin_lock_irqsave(&scst_mcmd_lock, flags);
27972+
27973+ list_for_each_entry_safe(mstb, t, &cmd->mgmt_cmd_list,
27974+ cmd_mgmt_cmd_list_entry) {
27975+ struct scst_mgmt_cmd *mcmd = mstb->mcmd;
27976+
27977+ TRACE_MGMT_DBG("mcmd %p, mcmd->cmd_finish_wait_count %d", mcmd,
27978+ mcmd->cmd_finish_wait_count);
27979+
27980+ BUG_ON(!mstb->finish_counted);
27981+
27982+ if (cmd->completed)
27983+ mcmd->completed_cmd_count++;
27984+
27985+ __scst_dec_finish_wait_count(mcmd, &wake);
27986+
27987+ TRACE_DBG("Releasing mstb %p", mstb);
27988+ list_del(&mstb->cmd_mgmt_cmd_list_entry);
27989+ mempool_free(mstb, scst_mgmt_stub_mempool);
27990+ }
27991+
27992+ spin_unlock_irqrestore(&scst_mcmd_lock, flags);
27993+
27994+ if (wake)
27995+ wake_up(&scst_mgmt_cmd_list_waitQ);
27996+
27997+ TRACE_EXIT();
27998+ return;
27999+}
28000+
28001+static int scst_call_dev_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
28002+ struct scst_tgt_dev *tgt_dev, int set_status)
28003+{
28004+ int res = SCST_DEV_TM_NOT_COMPLETED;
28005+ struct scst_dev_type *h = tgt_dev->dev->handler;
28006+
28007+ if (h->task_mgmt_fn) {
28008+ TRACE_MGMT_DBG("Calling dev handler %s task_mgmt_fn(fn=%d)",
28009+ h->name, mcmd->fn);
28010+ EXTRACHECKS_BUG_ON(in_irq() || irqs_disabled());
28011+ res = h->task_mgmt_fn(mcmd, tgt_dev);
28012+ TRACE_MGMT_DBG("Dev handler %s task_mgmt_fn() returned %d",
28013+ h->name, res);
28014+ if (set_status && (res != SCST_DEV_TM_NOT_COMPLETED))
28015+ mcmd->status = res;
28016+ }
28017+ return res;
28018+}
28019+
28020+static inline int scst_is_strict_mgmt_fn(int mgmt_fn)
28021+{
28022+ switch (mgmt_fn) {
28023+#ifdef CONFIG_SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING
28024+ case SCST_ABORT_TASK:
28025+#endif
28026+#if 0
28027+ case SCST_ABORT_TASK_SET:
28028+ case SCST_CLEAR_TASK_SET:
28029+#endif
28030+ return 1;
28031+ default:
28032+ return 0;
28033+ }
28034+}
28035+
28036+/* Might be called under sess_list_lock and IRQ off + BHs also off */
28037+void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
28038+ bool other_ini, bool call_dev_task_mgmt_fn)
28039+{
28040+ unsigned long flags;
28041+ static DEFINE_SPINLOCK(other_ini_lock);
28042+
28043+ TRACE_ENTRY();
28044+
28045+ TRACE(TRACE_SCSI|TRACE_MGMT_DEBUG, "Aborting cmd %p (tag %llu, op %x)",
28046+ cmd, (long long unsigned int)cmd->tag, cmd->cdb[0]);
28047+
28048+ /* To protect from concurrent aborts */
28049+ spin_lock_irqsave(&other_ini_lock, flags);
28050+
28051+ if (other_ini) {
28052+ struct scst_device *dev = NULL;
28053+
28054+ /* Might be necessary if command aborted several times */
28055+ if (!test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))
28056+ set_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags);
28057+
28058+ /* Necessary for scst_xmit_process_aborted_cmd */
28059+ if (cmd->dev != NULL)
28060+ dev = cmd->dev;
28061+ else if ((mcmd != NULL) && (mcmd->mcmd_tgt_dev != NULL))
28062+ dev = mcmd->mcmd_tgt_dev->dev;
28063+
28064+ if (dev != NULL) {
28065+ if (dev->tas)
28066+ set_bit(SCST_CMD_DEVICE_TAS, &cmd->cmd_flags);
28067+ } else
28068+ PRINT_WARNING("Abort cmd %p from other initiator, but "
28069+ "neither cmd, nor mcmd %p have tgt_dev set, so "
28070+ "TAS information can be lost", cmd, mcmd);
28071+ } else {
28072+ /* Might be necessary if command aborted several times */
28073+ clear_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags);
28074+ }
28075+
28076+ set_bit(SCST_CMD_ABORTED, &cmd->cmd_flags);
28077+
28078+ spin_unlock_irqrestore(&other_ini_lock, flags);
28079+
28080+ /*
28081+ * To sync with cmd->finished/done set in
28082+ * scst_finish_cmd()/scst_pre_xmit_response() and with setting UA for
28083+ * aborted cmd in scst_set_pending_UA().
28084+ */
28085+ smp_mb__after_set_bit();
28086+
28087+ if (cmd->tgt_dev == NULL) {
28088+ spin_lock_irqsave(&scst_init_lock, flags);
28089+ scst_init_poll_cnt++;
28090+ spin_unlock_irqrestore(&scst_init_lock, flags);
28091+ wake_up(&scst_init_cmd_list_waitQ);
28092+ }
28093+
28094+ if (call_dev_task_mgmt_fn && (cmd->tgt_dev != NULL)) {
28095+ EXTRACHECKS_BUG_ON(irqs_disabled());
28096+ scst_call_dev_task_mgmt_fn(mcmd, cmd->tgt_dev, 1);
28097+ }
28098+
28099+ spin_lock_irqsave(&scst_mcmd_lock, flags);
28100+ if ((mcmd != NULL) && !cmd->finished) {
28101+ struct scst_mgmt_cmd_stub *mstb;
28102+
28103+ mstb = mempool_alloc(scst_mgmt_stub_mempool, GFP_ATOMIC);
28104+ if (mstb == NULL) {
28105+ PRINT_CRIT_ERROR("Allocation of management command "
28106+ "stub failed (mcmd %p, cmd %p)", mcmd, cmd);
28107+ goto unlock;
28108+ }
28109+ memset(mstb, 0, sizeof(*mstb));
28110+
28111+ TRACE_DBG("mstb %p, mcmd %p", mstb, mcmd);
28112+
28113+ mstb->mcmd = mcmd;
28114+
28115+ /*
28116+ * Delay the response until the command's finish in order to
28117+ * guarantee that "no further responses from the task are sent
28118+ * to the SCSI initiator port" after response from the TM
28119+ * function is sent (SAM). Plus, we must wait here to be sure
28120+ * that we won't receive double commands with the same tag.
28121+ * Moreover, if we don't wait here, we might have a possibility
28122+ * for data corruption, when aborted and reported as completed
28123+ * command actually gets executed *after* new commands sent
28124+ * after this TM command completed.
28125+ */
28126+
28127+ if (cmd->sent_for_exec && !cmd->done) {
28128+ TRACE_MGMT_DBG("cmd %p (tag %llu) is being executed",
28129+ cmd, (long long unsigned int)cmd->tag);
28130+ mstb->done_counted = 1;
28131+ mcmd->cmd_done_wait_count++;
28132+ }
28133+
28134+ /*
28135+ * We don't have to wait the command's status delivery finish
28136+ * to other initiators + it can affect MPIO failover.
28137+ */
28138+ if (!other_ini) {
28139+ mstb->finish_counted = 1;
28140+ mcmd->cmd_finish_wait_count++;
28141+ }
28142+
28143+ if (mstb->done_counted || mstb->finish_counted) {
28144+ TRACE_MGMT_DBG("cmd %p (tag %llu, sn %u) being "
28145+ "executed/xmitted (state %d, op %x, proc time "
28146+ "%ld sec., timeout %d sec.), deferring ABORT "
28147+ "(cmd_done_wait_count %d, cmd_finish_wait_count "
28148+ "%d)", cmd, (long long unsigned int)cmd->tag,
28149+ cmd->sn, cmd->state, cmd->cdb[0],
28150+ (long)(jiffies - cmd->start_time) / HZ,
28151+ cmd->timeout / HZ, mcmd->cmd_done_wait_count,
28152+ mcmd->cmd_finish_wait_count);
28153+ /*
28154+ * cmd can't die here or sess_list_lock already taken
28155+ * and cmd is in the sess list
28156+ */
28157+ list_add_tail(&mstb->cmd_mgmt_cmd_list_entry,
28158+ &cmd->mgmt_cmd_list);
28159+ } else {
28160+ /* We don't need to wait for this cmd */
28161+ mempool_free(mstb, scst_mgmt_stub_mempool);
28162+ }
28163+ }
28164+
28165+unlock:
28166+ spin_unlock_irqrestore(&scst_mcmd_lock, flags);
28167+
28168+ tm_dbg_release_cmd(cmd);
28169+
28170+ TRACE_EXIT();
28171+ return;
28172+}
28173+
28174+/* No locks. Returns 0, if mcmd should be processed further. */
28175+static int scst_set_mcmd_next_state(struct scst_mgmt_cmd *mcmd)
28176+{
28177+ int res;
28178+
28179+ spin_lock_irq(&scst_mcmd_lock);
28180+
28181+ switch (mcmd->state) {
28182+ case SCST_MCMD_STATE_INIT:
28183+ case SCST_MCMD_STATE_EXEC:
28184+ if (mcmd->cmd_done_wait_count == 0) {
28185+ mcmd->state = SCST_MCMD_STATE_AFFECTED_CMDS_DONE;
28186+ res = 0;
28187+ } else {
28188+ TRACE_MGMT_DBG("cmd_done_wait_count(%d) not 0, "
28189+ "preparing to wait", mcmd->cmd_done_wait_count);
28190+ mcmd->state = SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_DONE;
28191+ res = -1;
28192+ }
28193+ break;
28194+
28195+ case SCST_MCMD_STATE_AFFECTED_CMDS_DONE:
28196+ if (mcmd->cmd_finish_wait_count == 0) {
28197+ mcmd->state = SCST_MCMD_STATE_DONE;
28198+ res = 0;
28199+ } else {
28200+ TRACE_MGMT_DBG("cmd_finish_wait_count(%d) not 0, "
28201+ "preparing to wait",
28202+ mcmd->cmd_finish_wait_count);
28203+ mcmd->state = SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_FINISHED;
28204+ res = -1;
28205+ }
28206+ break;
28207+
28208+ case SCST_MCMD_STATE_DONE:
28209+ mcmd->state = SCST_MCMD_STATE_FINISHED;
28210+ res = 0;
28211+ break;
28212+
28213+ default:
28214+ PRINT_CRIT_ERROR("Wrong mcmd %p state %d (fn %d, "
28215+ "cmd_finish_wait_count %d, cmd_done_wait_count %d)",
28216+ mcmd, mcmd->state, mcmd->fn,
28217+ mcmd->cmd_finish_wait_count, mcmd->cmd_done_wait_count);
28218+ spin_unlock_irq(&scst_mcmd_lock);
28219+ BUG();
28220+ goto out;
28221+ }
28222+
28223+ spin_unlock_irq(&scst_mcmd_lock);
28224+
28225+out:
28226+ return res;
28227+}
28228+
28229+/* IRQs supposed to be disabled */
28230+static bool __scst_check_unblock_aborted_cmd(struct scst_cmd *cmd,
28231+ struct list_head *list_entry)
28232+{
28233+ bool res;
28234+ if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
28235+ list_del(list_entry);
28236+ spin_lock(&cmd->cmd_threads->cmd_list_lock);
28237+ list_add_tail(&cmd->cmd_list_entry,
28238+ &cmd->cmd_threads->active_cmd_list);
28239+ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
28240+ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
28241+ res = 1;
28242+ } else
28243+ res = 0;
28244+ return res;
28245+}
28246+
28247+static void scst_unblock_aborted_cmds(int scst_mutex_held)
28248+{
28249+ struct scst_device *dev;
28250+
28251+ TRACE_ENTRY();
28252+
28253+ if (!scst_mutex_held)
28254+ mutex_lock(&scst_mutex);
28255+
28256+ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
28257+ struct scst_cmd *cmd, *tcmd;
28258+ struct scst_tgt_dev *tgt_dev;
28259+ spin_lock_bh(&dev->dev_lock);
28260+ local_irq_disable();
28261+ list_for_each_entry_safe(cmd, tcmd, &dev->blocked_cmd_list,
28262+ blocked_cmd_list_entry) {
28263+ if (__scst_check_unblock_aborted_cmd(cmd,
28264+ &cmd->blocked_cmd_list_entry)) {
28265+ TRACE_MGMT_DBG("Unblock aborted blocked cmd %p",
28266+ cmd);
28267+ }
28268+ }
28269+ local_irq_enable();
28270+ spin_unlock_bh(&dev->dev_lock);
28271+
28272+ local_irq_disable();
28273+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
28274+ dev_tgt_dev_list_entry) {
28275+ spin_lock(&tgt_dev->sn_lock);
28276+ list_for_each_entry_safe(cmd, tcmd,
28277+ &tgt_dev->deferred_cmd_list,
28278+ sn_cmd_list_entry) {
28279+ if (__scst_check_unblock_aborted_cmd(cmd,
28280+ &cmd->sn_cmd_list_entry)) {
28281+ TRACE_MGMT_DBG("Unblocked aborted SN "
28282+ "cmd %p (sn %u)",
28283+ cmd, cmd->sn);
28284+ tgt_dev->def_cmd_count--;
28285+ }
28286+ }
28287+ spin_unlock(&tgt_dev->sn_lock);
28288+ }
28289+ local_irq_enable();
28290+ }
28291+
28292+ if (!scst_mutex_held)
28293+ mutex_unlock(&scst_mutex);
28294+
28295+ TRACE_EXIT();
28296+ return;
28297+}
28298+
28299+static void __scst_abort_task_set(struct scst_mgmt_cmd *mcmd,
28300+ struct scst_tgt_dev *tgt_dev)
28301+{
28302+ struct scst_cmd *cmd;
28303+ struct scst_session *sess = tgt_dev->sess;
28304+ bool other_ini;
28305+
28306+ TRACE_ENTRY();
28307+
28308+ if ((mcmd->fn == SCST_PR_ABORT_ALL) &&
28309+ (mcmd->origin_pr_cmd->sess != sess))
28310+ other_ini = true;
28311+ else
28312+ other_ini = false;
28313+
28314+ spin_lock_irq(&sess->sess_list_lock);
28315+
28316+ TRACE_DBG("Searching in sess cmd list (sess=%p)", sess);
28317+ list_for_each_entry(cmd, &sess->sess_cmd_list,
28318+ sess_cmd_list_entry) {
28319+ if ((mcmd->fn == SCST_PR_ABORT_ALL) &&
28320+ (mcmd->origin_pr_cmd == cmd))
28321+ continue;
28322+ if ((cmd->tgt_dev == tgt_dev) ||
28323+ ((cmd->tgt_dev == NULL) &&
28324+ (cmd->lun == tgt_dev->lun))) {
28325+ if (mcmd->cmd_sn_set) {
28326+ BUG_ON(!cmd->tgt_sn_set);
28327+ if (scst_sn_before(mcmd->cmd_sn, cmd->tgt_sn) ||
28328+ (mcmd->cmd_sn == cmd->tgt_sn))
28329+ continue;
28330+ }
28331+ scst_abort_cmd(cmd, mcmd, other_ini, 0);
28332+ }
28333+ }
28334+ spin_unlock_irq(&sess->sess_list_lock);
28335+
28336+ TRACE_EXIT();
28337+ return;
28338+}
28339+
28340+/* Returns 0 if the command processing should be continued, <0 otherwise */
28341+static int scst_abort_task_set(struct scst_mgmt_cmd *mcmd)
28342+{
28343+ int res;
28344+ struct scst_tgt_dev *tgt_dev = mcmd->mcmd_tgt_dev;
28345+
28346+ TRACE(TRACE_MGMT, "Aborting task set (lun=%lld, mcmd=%p)",
28347+ (long long unsigned int)tgt_dev->lun, mcmd);
28348+
28349+ __scst_abort_task_set(mcmd, tgt_dev);
28350+
28351+ if (mcmd->fn == SCST_PR_ABORT_ALL) {
28352+ struct scst_pr_abort_all_pending_mgmt_cmds_counter *pr_cnt =
28353+ mcmd->origin_pr_cmd->pr_abort_counter;
28354+ if (atomic_dec_and_test(&pr_cnt->pr_aborting_cnt))
28355+ complete_all(&pr_cnt->pr_aborting_cmpl);
28356+ }
28357+
28358+ tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "ABORT TASK SET/PR ABORT", 0);
28359+
28360+ scst_unblock_aborted_cmds(0);
28361+
28362+ scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 0);
28363+
28364+ res = scst_set_mcmd_next_state(mcmd);
28365+
28366+ TRACE_EXIT_RES(res);
28367+ return res;
28368+}
28369+
28370+static int scst_is_cmd_belongs_to_dev(struct scst_cmd *cmd,
28371+ struct scst_device *dev)
28372+{
28373+ struct scst_tgt_dev *tgt_dev = NULL;
28374+ struct list_head *sess_tgt_dev_list_head;
28375+ int res = 0;
28376+
28377+ TRACE_ENTRY();
28378+
28379+ TRACE_DBG("Finding match for dev %p and cmd %p (lun %lld)", dev, cmd,
28380+ (long long unsigned int)cmd->lun);
28381+
28382+ sess_tgt_dev_list_head =
28383+ &cmd->sess->sess_tgt_dev_list_hash[HASH_VAL(cmd->lun)];
28384+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
28385+ sess_tgt_dev_list_entry) {
28386+ if (tgt_dev->lun == cmd->lun) {
28387+ TRACE_DBG("dev %p found", tgt_dev->dev);
28388+ res = (tgt_dev->dev == dev);
28389+ goto out;
28390+ }
28391+ }
28392+
28393+out:
28394+ TRACE_EXIT_HRES(res);
28395+ return res;
28396+}
28397+
28398+/* Returns 0 if the command processing should be continued, <0 otherwise */
28399+static int scst_clear_task_set(struct scst_mgmt_cmd *mcmd)
28400+{
28401+ int res;
28402+ struct scst_device *dev = mcmd->mcmd_tgt_dev->dev;
28403+ struct scst_tgt_dev *tgt_dev;
28404+ LIST_HEAD(UA_tgt_devs);
28405+
28406+ TRACE_ENTRY();
28407+
28408+ TRACE(TRACE_MGMT, "Clearing task set (lun=%lld, mcmd=%p)",
28409+ (long long unsigned int)mcmd->lun, mcmd);
28410+
28411+#if 0 /* we are SAM-3 */
28412+ /*
28413+ * When a logical unit is aborting one or more tasks from a SCSI
28414+ * initiator port with the TASK ABORTED status it should complete all
28415+ * of those tasks before entering additional tasks from that SCSI
28416+ * initiator port into the task set - SAM2
28417+ */
28418+ mcmd->needs_unblocking = 1;
28419+ spin_lock_bh(&dev->dev_lock);
28420+ scst_block_dev(dev);
28421+ spin_unlock_bh(&dev->dev_lock);
28422+#endif
28423+
28424+ __scst_abort_task_set(mcmd, mcmd->mcmd_tgt_dev);
28425+
28426+ mutex_lock(&scst_mutex);
28427+
28428+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
28429+ dev_tgt_dev_list_entry) {
28430+ struct scst_session *sess = tgt_dev->sess;
28431+ struct scst_cmd *cmd;
28432+ int aborted = 0;
28433+
28434+ if (tgt_dev == mcmd->mcmd_tgt_dev)
28435+ continue;
28436+
28437+ spin_lock_irq(&sess->sess_list_lock);
28438+
28439+ TRACE_DBG("Searching in sess cmd list (sess=%p)", sess);
28440+ list_for_each_entry(cmd, &sess->sess_cmd_list,
28441+ sess_cmd_list_entry) {
28442+ if ((cmd->dev == dev) ||
28443+ ((cmd->dev == NULL) &&
28444+ scst_is_cmd_belongs_to_dev(cmd, dev))) {
28445+ scst_abort_cmd(cmd, mcmd, 1, 0);
28446+ aborted = 1;
28447+ }
28448+ }
28449+ spin_unlock_irq(&sess->sess_list_lock);
28450+
28451+ if (aborted)
28452+ list_add_tail(&tgt_dev->extra_tgt_dev_list_entry,
28453+ &UA_tgt_devs);
28454+ }
28455+
28456+ tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "CLEAR TASK SET", 0);
28457+
28458+ scst_unblock_aborted_cmds(1);
28459+
28460+ mutex_unlock(&scst_mutex);
28461+
28462+ if (!dev->tas) {
28463+ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
28464+ int sl;
28465+
28466+ sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
28467+ dev->d_sense,
28468+ SCST_LOAD_SENSE(scst_sense_cleared_by_another_ini_UA));
28469+
28470+ list_for_each_entry(tgt_dev, &UA_tgt_devs,
28471+ extra_tgt_dev_list_entry) {
28472+ scst_check_set_UA(tgt_dev, sense_buffer, sl, 0);
28473+ }
28474+ }
28475+
28476+ scst_call_dev_task_mgmt_fn(mcmd, mcmd->mcmd_tgt_dev, 0);
28477+
28478+ res = scst_set_mcmd_next_state(mcmd);
28479+
28480+ TRACE_EXIT_RES(res);
28481+ return res;
28482+}
28483+
28484+/* Returns 0 if the command processing should be continued,
28485+ * >0, if it should be requeued, <0 otherwise */
28486+static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
28487+{
28488+ int res = 0, rc;
28489+
28490+ TRACE_ENTRY();
28491+
28492+ switch (mcmd->fn) {
28493+ case SCST_ABORT_TASK:
28494+ {
28495+ struct scst_session *sess = mcmd->sess;
28496+ struct scst_cmd *cmd;
28497+
28498+ spin_lock_irq(&sess->sess_list_lock);
28499+ cmd = __scst_find_cmd_by_tag(sess, mcmd->tag, true);
28500+ if (cmd == NULL) {
28501+ TRACE_MGMT_DBG("ABORT TASK: command "
28502+ "for tag %llu not found",
28503+ (long long unsigned int)mcmd->tag);
28504+ mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST;
28505+ spin_unlock_irq(&sess->sess_list_lock);
28506+ res = scst_set_mcmd_next_state(mcmd);
28507+ goto out;
28508+ }
28509+ __scst_cmd_get(cmd);
28510+ spin_unlock_irq(&sess->sess_list_lock);
28511+ TRACE_DBG("Cmd to abort %p for tag %llu found",
28512+ cmd, (long long unsigned int)mcmd->tag);
28513+ mcmd->cmd_to_abort = cmd;
28514+ mcmd->state = SCST_MCMD_STATE_EXEC;
28515+ break;
28516+ }
28517+
28518+ case SCST_TARGET_RESET:
28519+ case SCST_NEXUS_LOSS_SESS:
28520+ case SCST_ABORT_ALL_TASKS_SESS:
28521+ case SCST_NEXUS_LOSS:
28522+ case SCST_ABORT_ALL_TASKS:
28523+ case SCST_UNREG_SESS_TM:
28524+ mcmd->state = SCST_MCMD_STATE_EXEC;
28525+ break;
28526+
28527+ case SCST_ABORT_TASK_SET:
28528+ case SCST_CLEAR_ACA:
28529+ case SCST_CLEAR_TASK_SET:
28530+ case SCST_LUN_RESET:
28531+ case SCST_PR_ABORT_ALL:
28532+ rc = scst_mgmt_translate_lun(mcmd);
28533+ if (rc == 0)
28534+ mcmd->state = SCST_MCMD_STATE_EXEC;
28535+ else if (rc < 0) {
28536+ PRINT_ERROR("Corresponding device for LUN %lld not "
28537+ "found", (long long unsigned int)mcmd->lun);
28538+ mcmd->status = SCST_MGMT_STATUS_LUN_NOT_EXIST;
28539+ res = scst_set_mcmd_next_state(mcmd);
28540+ } else
28541+ res = rc;
28542+ break;
28543+
28544+ default:
28545+ BUG();
28546+ }
28547+
28548+out:
28549+ TRACE_EXIT_RES(res);
28550+ return res;
28551+}
28552+
28553+/* Returns 0 if the command processing should be continued, <0 otherwise */
28554+static int scst_target_reset(struct scst_mgmt_cmd *mcmd)
28555+{
28556+ int res, rc;
28557+ struct scst_device *dev;
28558+ struct scst_acg *acg = mcmd->sess->acg;
28559+ struct scst_acg_dev *acg_dev;
28560+ int cont, c;
28561+ LIST_HEAD(host_devs);
28562+
28563+ TRACE_ENTRY();
28564+
28565+ TRACE(TRACE_MGMT, "Target reset (mcmd %p, cmd count %d)",
28566+ mcmd, atomic_read(&mcmd->sess->sess_cmd_count));
28567+
28568+ mcmd->needs_unblocking = 1;
28569+
28570+ mutex_lock(&scst_mutex);
28571+
28572+ list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
28573+ struct scst_device *d;
28574+ struct scst_tgt_dev *tgt_dev;
28575+ int found = 0;
28576+
28577+ dev = acg_dev->dev;
28578+
28579+ spin_lock_bh(&dev->dev_lock);
28580+ scst_block_dev(dev);
28581+ scst_process_reset(dev, mcmd->sess, NULL, mcmd, true);
28582+ spin_unlock_bh(&dev->dev_lock);
28583+
28584+ cont = 0;
28585+ c = 0;
28586+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
28587+ dev_tgt_dev_list_entry) {
28588+ cont = 1;
28589+ if (mcmd->sess == tgt_dev->sess) {
28590+ rc = scst_call_dev_task_mgmt_fn(mcmd,
28591+ tgt_dev, 0);
28592+ if (rc == SCST_DEV_TM_NOT_COMPLETED)
28593+ c = 1;
28594+ else if ((rc < 0) &&
28595+ (mcmd->status == SCST_MGMT_STATUS_SUCCESS))
28596+ mcmd->status = rc;
28597+ break;
28598+ }
28599+ }
28600+ if (cont && !c)
28601+ continue;
28602+
28603+ if (dev->scsi_dev == NULL)
28604+ continue;
28605+
28606+ list_for_each_entry(d, &host_devs, tm_dev_list_entry) {
28607+ if (dev->scsi_dev->host->host_no ==
28608+ d->scsi_dev->host->host_no) {
28609+ found = 1;
28610+ break;
28611+ }
28612+ }
28613+ if (!found)
28614+ list_add_tail(&dev->tm_dev_list_entry, &host_devs);
28615+
28616+ tm_dbg_task_mgmt(dev, "TARGET RESET", 0);
28617+ }
28618+
28619+ scst_unblock_aborted_cmds(1);
28620+
28621+ /*
28622+ * We suppose here that for all commands that already on devices
28623+ * on/after scsi_reset_provider() completion callbacks will be called.
28624+ */
28625+
28626+ list_for_each_entry(dev, &host_devs, tm_dev_list_entry) {
28627+ /* dev->scsi_dev must be non-NULL here */
28628+ TRACE(TRACE_MGMT, "Resetting host %d bus ",
28629+ dev->scsi_dev->host->host_no);
28630+ rc = scsi_reset_provider(dev->scsi_dev, SCSI_TRY_RESET_TARGET);
28631+ TRACE(TRACE_MGMT, "Result of host %d target reset: %s",
28632+ dev->scsi_dev->host->host_no,
28633+ (rc == SUCCESS) ? "SUCCESS" : "FAILED");
28634+#if 0
28635+ if ((rc != SUCCESS) &&
28636+ (mcmd->status == SCST_MGMT_STATUS_SUCCESS)) {
28637+ /*
28638+ * SCSI_TRY_RESET_BUS is also done by
28639+ * scsi_reset_provider()
28640+ */
28641+ mcmd->status = SCST_MGMT_STATUS_FAILED;
28642+ }
28643+#else
28644+ /*
28645+ * scsi_reset_provider() returns very weird status, so let's
28646+ * always succeed
28647+ */
28648+#endif
28649+ }
28650+
28651+ list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
28652+ dev = acg_dev->dev;
28653+ if (dev->scsi_dev != NULL)
28654+ dev->scsi_dev->was_reset = 0;
28655+ }
28656+
28657+ mutex_unlock(&scst_mutex);
28658+
28659+ res = scst_set_mcmd_next_state(mcmd);
28660+
28661+ TRACE_EXIT_RES(res);
28662+ return res;
28663+}
28664+
28665+/* Returns 0 if the command processing should be continued, <0 otherwise */
28666+static int scst_lun_reset(struct scst_mgmt_cmd *mcmd)
28667+{
28668+ int res, rc;
28669+ struct scst_tgt_dev *tgt_dev = mcmd->mcmd_tgt_dev;
28670+ struct scst_device *dev = tgt_dev->dev;
28671+
28672+ TRACE_ENTRY();
28673+
28674+ TRACE(TRACE_MGMT, "Resetting LUN %lld (mcmd %p)",
28675+ (long long unsigned int)tgt_dev->lun, mcmd);
28676+
28677+ mcmd->needs_unblocking = 1;
28678+
28679+ spin_lock_bh(&dev->dev_lock);
28680+ scst_block_dev(dev);
28681+ scst_process_reset(dev, mcmd->sess, NULL, mcmd, true);
28682+ spin_unlock_bh(&dev->dev_lock);
28683+
28684+ rc = scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 1);
28685+ if (rc != SCST_DEV_TM_NOT_COMPLETED)
28686+ goto out_tm_dbg;
28687+
28688+ if (dev->scsi_dev != NULL) {
28689+ TRACE(TRACE_MGMT, "Resetting host %d bus ",
28690+ dev->scsi_dev->host->host_no);
28691+ rc = scsi_reset_provider(dev->scsi_dev, SCSI_TRY_RESET_DEVICE);
28692+#if 0
28693+ if (rc != SUCCESS && mcmd->status == SCST_MGMT_STATUS_SUCCESS)
28694+ mcmd->status = SCST_MGMT_STATUS_FAILED;
28695+#else
28696+ /*
28697+ * scsi_reset_provider() returns very weird status, so let's
28698+ * always succeed
28699+ */
28700+#endif
28701+ dev->scsi_dev->was_reset = 0;
28702+ }
28703+
28704+ scst_unblock_aborted_cmds(0);
28705+
28706+out_tm_dbg:
28707+ tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "LUN RESET", 0);
28708+
28709+ res = scst_set_mcmd_next_state(mcmd);
28710+
28711+ TRACE_EXIT_RES(res);
28712+ return res;
28713+}
28714+
28715+/* scst_mutex supposed to be held */
28716+static void scst_do_nexus_loss_sess(struct scst_mgmt_cmd *mcmd)
28717+{
28718+ int i;
28719+ struct scst_session *sess = mcmd->sess;
28720+ struct scst_tgt_dev *tgt_dev;
28721+
28722+ TRACE_ENTRY();
28723+
28724+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
28725+ struct list_head *sess_tgt_dev_list_head =
28726+ &sess->sess_tgt_dev_list_hash[i];
28727+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
28728+ sess_tgt_dev_list_entry) {
28729+ scst_nexus_loss(tgt_dev,
28730+ (mcmd->fn != SCST_UNREG_SESS_TM));
28731+ }
28732+ }
28733+
28734+ TRACE_EXIT();
28735+ return;
28736+}
28737+
28738+/* Returns 0 if the command processing should be continued, <0 otherwise */
28739+static int scst_abort_all_nexus_loss_sess(struct scst_mgmt_cmd *mcmd,
28740+ int nexus_loss)
28741+{
28742+ int res;
28743+ int i;
28744+ struct scst_session *sess = mcmd->sess;
28745+ struct scst_tgt_dev *tgt_dev;
28746+
28747+ TRACE_ENTRY();
28748+
28749+ if (nexus_loss) {
28750+ TRACE_MGMT_DBG("Nexus loss for sess %p (mcmd %p)",
28751+ sess, mcmd);
28752+ } else {
28753+ TRACE_MGMT_DBG("Aborting all from sess %p (mcmd %p)",
28754+ sess, mcmd);
28755+ }
28756+
28757+ mutex_lock(&scst_mutex);
28758+
28759+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
28760+ struct list_head *sess_tgt_dev_list_head =
28761+ &sess->sess_tgt_dev_list_hash[i];
28762+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
28763+ sess_tgt_dev_list_entry) {
28764+ int rc;
28765+
28766+ __scst_abort_task_set(mcmd, tgt_dev);
28767+
28768+ rc = scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 0);
28769+ if (rc < 0 && mcmd->status == SCST_MGMT_STATUS_SUCCESS)
28770+ mcmd->status = rc;
28771+
28772+ tm_dbg_task_mgmt(tgt_dev->dev, "NEXUS LOSS SESS or "
28773+ "ABORT ALL SESS or UNREG SESS",
28774+ (mcmd->fn == SCST_UNREG_SESS_TM));
28775+ }
28776+ }
28777+
28778+ scst_unblock_aborted_cmds(1);
28779+
28780+ mutex_unlock(&scst_mutex);
28781+
28782+ res = scst_set_mcmd_next_state(mcmd);
28783+
28784+ TRACE_EXIT_RES(res);
28785+ return res;
28786+}
28787+
28788+/* scst_mutex supposed to be held */
28789+static void scst_do_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd)
28790+{
28791+ int i;
28792+ struct scst_tgt *tgt = mcmd->sess->tgt;
28793+ struct scst_session *sess;
28794+
28795+ TRACE_ENTRY();
28796+
28797+ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
28798+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
28799+ struct list_head *sess_tgt_dev_list_head =
28800+ &sess->sess_tgt_dev_list_hash[i];
28801+ struct scst_tgt_dev *tgt_dev;
28802+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
28803+ sess_tgt_dev_list_entry) {
28804+ scst_nexus_loss(tgt_dev, true);
28805+ }
28806+ }
28807+ }
28808+
28809+ TRACE_EXIT();
28810+ return;
28811+}
28812+
28813+static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd,
28814+ int nexus_loss)
28815+{
28816+ int res;
28817+ int i;
28818+ struct scst_tgt *tgt = mcmd->sess->tgt;
28819+ struct scst_session *sess;
28820+
28821+ TRACE_ENTRY();
28822+
28823+ if (nexus_loss) {
28824+ TRACE_MGMT_DBG("I_T Nexus loss (tgt %p, mcmd %p)",
28825+ tgt, mcmd);
28826+ } else {
28827+ TRACE_MGMT_DBG("Aborting all from tgt %p (mcmd %p)",
28828+ tgt, mcmd);
28829+ }
28830+
28831+ mutex_lock(&scst_mutex);
28832+
28833+ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
28834+ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
28835+ struct list_head *sess_tgt_dev_list_head =
28836+ &sess->sess_tgt_dev_list_hash[i];
28837+ struct scst_tgt_dev *tgt_dev;
28838+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
28839+ sess_tgt_dev_list_entry) {
28840+ int rc;
28841+
28842+ __scst_abort_task_set(mcmd, tgt_dev);
28843+
28844+ if (nexus_loss)
28845+ scst_nexus_loss(tgt_dev, true);
28846+
28847+ if (mcmd->sess == tgt_dev->sess) {
28848+ rc = scst_call_dev_task_mgmt_fn(
28849+ mcmd, tgt_dev, 0);
28850+ if ((rc < 0) &&
28851+ (mcmd->status == SCST_MGMT_STATUS_SUCCESS))
28852+ mcmd->status = rc;
28853+ }
28854+
28855+ tm_dbg_task_mgmt(tgt_dev->dev, "NEXUS LOSS or "
28856+ "ABORT ALL", 0);
28857+ }
28858+ }
28859+ }
28860+
28861+ scst_unblock_aborted_cmds(1);
28862+
28863+ mutex_unlock(&scst_mutex);
28864+
28865+ res = scst_set_mcmd_next_state(mcmd);
28866+
28867+ TRACE_EXIT_RES(res);
28868+ return res;
28869+}
28870+
28871+static int scst_abort_task(struct scst_mgmt_cmd *mcmd)
28872+{
28873+ int res;
28874+ struct scst_cmd *cmd = mcmd->cmd_to_abort;
28875+
28876+ TRACE_ENTRY();
28877+
28878+ TRACE_MGMT_DBG("Abortind task (cmd %p, sn %d, set %d, tag %llu, "
28879+ "queue_type %x)", cmd, cmd->sn, cmd->sn_set,
28880+ (long long unsigned int)mcmd->tag, cmd->queue_type);
28881+
28882+ if (mcmd->lun_set && (mcmd->lun != cmd->lun)) {
28883+ PRINT_ERROR("ABORT TASK: LUN mismatch: mcmd LUN %llx, "
28884+ "cmd LUN %llx, cmd tag %llu",
28885+ (long long unsigned int)mcmd->lun,
28886+ (long long unsigned int)cmd->lun,
28887+ (long long unsigned int)mcmd->tag);
28888+ mcmd->status = SCST_MGMT_STATUS_REJECTED;
28889+ } else if (mcmd->cmd_sn_set &&
28890+ (scst_sn_before(mcmd->cmd_sn, cmd->tgt_sn) ||
28891+ (mcmd->cmd_sn == cmd->tgt_sn))) {
28892+ PRINT_ERROR("ABORT TASK: SN mismatch: mcmd SN %x, "
28893+ "cmd SN %x, cmd tag %llu", mcmd->cmd_sn,
28894+ cmd->tgt_sn, (long long unsigned int)mcmd->tag);
28895+ mcmd->status = SCST_MGMT_STATUS_REJECTED;
28896+ } else {
28897+ scst_abort_cmd(cmd, mcmd, 0, 1);
28898+ scst_unblock_aborted_cmds(0);
28899+ }
28900+
28901+ res = scst_set_mcmd_next_state(mcmd);
28902+
28903+ mcmd->cmd_to_abort = NULL; /* just in case */
28904+
28905+ __scst_cmd_put(cmd);
28906+
28907+ TRACE_EXIT_RES(res);
28908+ return res;
28909+}
28910+
28911+/* Returns 0 if the command processing should be continued, <0 otherwise */
28912+static int scst_mgmt_cmd_exec(struct scst_mgmt_cmd *mcmd)
28913+{
28914+ int res = 0;
28915+
28916+ TRACE_ENTRY();
28917+
28918+ mcmd->status = SCST_MGMT_STATUS_SUCCESS;
28919+
28920+ switch (mcmd->fn) {
28921+ case SCST_ABORT_TASK:
28922+ res = scst_abort_task(mcmd);
28923+ break;
28924+
28925+ case SCST_ABORT_TASK_SET:
28926+ case SCST_PR_ABORT_ALL:
28927+ res = scst_abort_task_set(mcmd);
28928+ break;
28929+
28930+ case SCST_CLEAR_TASK_SET:
28931+ if (mcmd->mcmd_tgt_dev->dev->tst ==
28932+ SCST_CONTR_MODE_SEP_TASK_SETS)
28933+ res = scst_abort_task_set(mcmd);
28934+ else
28935+ res = scst_clear_task_set(mcmd);
28936+ break;
28937+
28938+ case SCST_LUN_RESET:
28939+ res = scst_lun_reset(mcmd);
28940+ break;
28941+
28942+ case SCST_TARGET_RESET:
28943+ res = scst_target_reset(mcmd);
28944+ break;
28945+
28946+ case SCST_ABORT_ALL_TASKS_SESS:
28947+ res = scst_abort_all_nexus_loss_sess(mcmd, 0);
28948+ break;
28949+
28950+ case SCST_NEXUS_LOSS_SESS:
28951+ case SCST_UNREG_SESS_TM:
28952+ res = scst_abort_all_nexus_loss_sess(mcmd, 1);
28953+ break;
28954+
28955+ case SCST_ABORT_ALL_TASKS:
28956+ res = scst_abort_all_nexus_loss_tgt(mcmd, 0);
28957+ break;
28958+
28959+ case SCST_NEXUS_LOSS:
28960+ res = scst_abort_all_nexus_loss_tgt(mcmd, 1);
28961+ break;
28962+
28963+ case SCST_CLEAR_ACA:
28964+ if (scst_call_dev_task_mgmt_fn(mcmd, mcmd->mcmd_tgt_dev, 1) ==
28965+ SCST_DEV_TM_NOT_COMPLETED) {
28966+ mcmd->status = SCST_MGMT_STATUS_FN_NOT_SUPPORTED;
28967+ /* Nothing to do (yet) */
28968+ }
28969+ goto out_done;
28970+
28971+ default:
28972+ PRINT_ERROR("Unknown task management function %d", mcmd->fn);
28973+ mcmd->status = SCST_MGMT_STATUS_REJECTED;
28974+ goto out_done;
28975+ }
28976+
28977+out:
28978+ TRACE_EXIT_RES(res);
28979+ return res;
28980+
28981+out_done:
28982+ res = scst_set_mcmd_next_state(mcmd);
28983+ goto out;
28984+}
28985+
28986+static void scst_call_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *mcmd)
28987+{
28988+ struct scst_session *sess = mcmd->sess;
28989+
28990+ if ((sess->tgt->tgtt->task_mgmt_affected_cmds_done != NULL) &&
28991+ (mcmd->fn != SCST_UNREG_SESS_TM) &&
28992+ (mcmd->fn != SCST_PR_ABORT_ALL)) {
28993+ TRACE_DBG("Calling target %s task_mgmt_affected_cmds_done(%p)",
28994+ sess->tgt->tgtt->name, sess);
28995+ sess->tgt->tgtt->task_mgmt_affected_cmds_done(mcmd);
28996+ TRACE_MGMT_DBG("Target's %s task_mgmt_affected_cmds_done() "
28997+ "returned", sess->tgt->tgtt->name);
28998+ }
28999+ return;
29000+}
29001+
29002+static int scst_mgmt_affected_cmds_done(struct scst_mgmt_cmd *mcmd)
29003+{
29004+ int res;
29005+
29006+ TRACE_ENTRY();
29007+
29008+ mutex_lock(&scst_mutex);
29009+
29010+ switch (mcmd->fn) {
29011+ case SCST_NEXUS_LOSS_SESS:
29012+ case SCST_UNREG_SESS_TM:
29013+ scst_do_nexus_loss_sess(mcmd);
29014+ break;
29015+
29016+ case SCST_NEXUS_LOSS:
29017+ scst_do_nexus_loss_tgt(mcmd);
29018+ break;
29019+ }
29020+
29021+ mutex_unlock(&scst_mutex);
29022+
29023+ scst_call_task_mgmt_affected_cmds_done(mcmd);
29024+
29025+ res = scst_set_mcmd_next_state(mcmd);
29026+
29027+ TRACE_EXIT_RES(res);
29028+ return res;
29029+}
29030+
29031+static void scst_mgmt_cmd_send_done(struct scst_mgmt_cmd *mcmd)
29032+{
29033+ struct scst_device *dev;
29034+ struct scst_session *sess = mcmd->sess;
29035+
29036+ TRACE_ENTRY();
29037+
29038+ mcmd->state = SCST_MCMD_STATE_FINISHED;
29039+ if (scst_is_strict_mgmt_fn(mcmd->fn) && (mcmd->completed_cmd_count > 0))
29040+ mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST;
29041+
29042+ if (mcmd->fn < SCST_UNREG_SESS_TM)
29043+ TRACE(TRACE_MGMT, "TM fn %d finished, "
29044+ "status %x", mcmd->fn, mcmd->status);
29045+ else
29046+ TRACE_MGMT_DBG("TM fn %d finished, "
29047+ "status %x", mcmd->fn, mcmd->status);
29048+
29049+ if (mcmd->fn == SCST_PR_ABORT_ALL) {
29050+ mcmd->origin_pr_cmd->scst_cmd_done(mcmd->origin_pr_cmd,
29051+ SCST_CMD_STATE_DEFAULT,
29052+ SCST_CONTEXT_THREAD);
29053+ } else if ((sess->tgt->tgtt->task_mgmt_fn_done != NULL) &&
29054+ (mcmd->fn != SCST_UNREG_SESS_TM)) {
29055+ TRACE_DBG("Calling target %s task_mgmt_fn_done(%p)",
29056+ sess->tgt->tgtt->name, sess);
29057+ sess->tgt->tgtt->task_mgmt_fn_done(mcmd);
29058+ TRACE_MGMT_DBG("Target's %s task_mgmt_fn_done() "
29059+ "returned", sess->tgt->tgtt->name);
29060+ }
29061+
29062+ if (mcmd->needs_unblocking) {
29063+ switch (mcmd->fn) {
29064+ case SCST_LUN_RESET:
29065+ case SCST_CLEAR_TASK_SET:
29066+ scst_unblock_dev(mcmd->mcmd_tgt_dev->dev);
29067+ break;
29068+
29069+ case SCST_TARGET_RESET:
29070+ {
29071+ struct scst_acg *acg = mcmd->sess->acg;
29072+ struct scst_acg_dev *acg_dev;
29073+
29074+ mutex_lock(&scst_mutex);
29075+ list_for_each_entry(acg_dev, &acg->acg_dev_list,
29076+ acg_dev_list_entry) {
29077+ dev = acg_dev->dev;
29078+ scst_unblock_dev(dev);
29079+ }
29080+ mutex_unlock(&scst_mutex);
29081+ break;
29082+ }
29083+
29084+ default:
29085+ BUG();
29086+ break;
29087+ }
29088+ }
29089+
29090+ mcmd->tgt_priv = NULL;
29091+
29092+ TRACE_EXIT();
29093+ return;
29094+}
29095+
29096+/* Returns >0, if cmd should be requeued */
29097+static int scst_process_mgmt_cmd(struct scst_mgmt_cmd *mcmd)
29098+{
29099+ int res = 0;
29100+
29101+ TRACE_ENTRY();
29102+
29103+ /*
29104+ * We are in the TM thread and mcmd->state guaranteed to not be
29105+ * changed behind us.
29106+ */
29107+
29108+ TRACE_DBG("mcmd %p, state %d", mcmd, mcmd->state);
29109+
29110+ while (1) {
29111+ switch (mcmd->state) {
29112+ case SCST_MCMD_STATE_INIT:
29113+ res = scst_mgmt_cmd_init(mcmd);
29114+ if (res)
29115+ goto out;
29116+ break;
29117+
29118+ case SCST_MCMD_STATE_EXEC:
29119+ if (scst_mgmt_cmd_exec(mcmd))
29120+ goto out;
29121+ break;
29122+
29123+ case SCST_MCMD_STATE_AFFECTED_CMDS_DONE:
29124+ if (scst_mgmt_affected_cmds_done(mcmd))
29125+ goto out;
29126+ break;
29127+
29128+ case SCST_MCMD_STATE_DONE:
29129+ scst_mgmt_cmd_send_done(mcmd);
29130+ break;
29131+
29132+ case SCST_MCMD_STATE_FINISHED:
29133+ scst_free_mgmt_cmd(mcmd);
29134+ /* mcmd is dead */
29135+ goto out;
29136+
29137+ default:
29138+ PRINT_CRIT_ERROR("Wrong mcmd %p state %d (fn %d, "
29139+ "cmd_finish_wait_count %d, cmd_done_wait_count "
29140+ "%d)", mcmd, mcmd->state, mcmd->fn,
29141+ mcmd->cmd_finish_wait_count,
29142+ mcmd->cmd_done_wait_count);
29143+ BUG();
29144+ res = -1;
29145+ goto out;
29146+ }
29147+ }
29148+
29149+out:
29150+ TRACE_EXIT_RES(res);
29151+ return res;
29152+}
29153+
29154+static inline int test_mgmt_cmd_list(void)
29155+{
29156+ int res = !list_empty(&scst_active_mgmt_cmd_list) ||
29157+ unlikely(kthread_should_stop());
29158+ return res;
29159+}
29160+
29161+int scst_tm_thread(void *arg)
29162+{
29163+ TRACE_ENTRY();
29164+
29165+ PRINT_INFO("Task management thread started, PID %d", current->pid);
29166+
29167+ current->flags |= PF_NOFREEZE;
29168+
29169+ set_user_nice(current, -10);
29170+
29171+ spin_lock_irq(&scst_mcmd_lock);
29172+ while (!kthread_should_stop()) {
29173+ wait_queue_t wait;
29174+ init_waitqueue_entry(&wait, current);
29175+
29176+ if (!test_mgmt_cmd_list()) {
29177+ add_wait_queue_exclusive(&scst_mgmt_cmd_list_waitQ,
29178+ &wait);
29179+ for (;;) {
29180+ set_current_state(TASK_INTERRUPTIBLE);
29181+ if (test_mgmt_cmd_list())
29182+ break;
29183+ spin_unlock_irq(&scst_mcmd_lock);
29184+ schedule();
29185+ spin_lock_irq(&scst_mcmd_lock);
29186+ }
29187+ set_current_state(TASK_RUNNING);
29188+ remove_wait_queue(&scst_mgmt_cmd_list_waitQ, &wait);
29189+ }
29190+
29191+ while (!list_empty(&scst_active_mgmt_cmd_list)) {
29192+ int rc;
29193+ struct scst_mgmt_cmd *mcmd;
29194+ mcmd = list_entry(scst_active_mgmt_cmd_list.next,
29195+ typeof(*mcmd), mgmt_cmd_list_entry);
29196+ TRACE_MGMT_DBG("Deleting mgmt cmd %p from active cmd "
29197+ "list", mcmd);
29198+ list_del(&mcmd->mgmt_cmd_list_entry);
29199+ spin_unlock_irq(&scst_mcmd_lock);
29200+ rc = scst_process_mgmt_cmd(mcmd);
29201+ spin_lock_irq(&scst_mcmd_lock);
29202+ if (rc > 0) {
29203+ if (test_bit(SCST_FLAG_SUSPENDED, &scst_flags) &&
29204+ !test_bit(SCST_FLAG_SUSPENDING,
29205+ &scst_flags)) {
29206+ TRACE_MGMT_DBG("Adding mgmt cmd %p to "
29207+ "head of delayed mgmt cmd list",
29208+ mcmd);
29209+ list_add(&mcmd->mgmt_cmd_list_entry,
29210+ &scst_delayed_mgmt_cmd_list);
29211+ } else {
29212+ TRACE_MGMT_DBG("Adding mgmt cmd %p to "
29213+ "head of active mgmt cmd list",
29214+ mcmd);
29215+ list_add(&mcmd->mgmt_cmd_list_entry,
29216+ &scst_active_mgmt_cmd_list);
29217+ }
29218+ }
29219+ }
29220+ }
29221+ spin_unlock_irq(&scst_mcmd_lock);
29222+
29223+ /*
29224+ * If kthread_should_stop() is true, we are guaranteed to be
29225+ * on the module unload, so scst_active_mgmt_cmd_list must be empty.
29226+ */
29227+ BUG_ON(!list_empty(&scst_active_mgmt_cmd_list));
29228+
29229+ PRINT_INFO("Task management thread PID %d finished", current->pid);
29230+
29231+ TRACE_EXIT();
29232+ return 0;
29233+}
29234+
29235+static struct scst_mgmt_cmd *scst_pre_rx_mgmt_cmd(struct scst_session
29236+ *sess, int fn, int atomic, void *tgt_priv)
29237+{
29238+ struct scst_mgmt_cmd *mcmd = NULL;
29239+
29240+ TRACE_ENTRY();
29241+
29242+ if (unlikely(sess->tgt->tgtt->task_mgmt_fn_done == NULL)) {
29243+ PRINT_ERROR("New mgmt cmd, but task_mgmt_fn_done() is NULL "
29244+ "(target %s)", sess->tgt->tgtt->name);
29245+ goto out;
29246+ }
29247+
29248+ mcmd = scst_alloc_mgmt_cmd(atomic ? GFP_ATOMIC : GFP_KERNEL);
29249+ if (mcmd == NULL) {
29250+ PRINT_CRIT_ERROR("Lost TM fn %d, initiator %s", fn,
29251+ sess->initiator_name);
29252+ goto out;
29253+ }
29254+
29255+ mcmd->sess = sess;
29256+ mcmd->fn = fn;
29257+ mcmd->state = SCST_MCMD_STATE_INIT;
29258+ mcmd->tgt_priv = tgt_priv;
29259+
29260+ if (fn == SCST_PR_ABORT_ALL) {
29261+ atomic_inc(&mcmd->origin_pr_cmd->pr_abort_counter->pr_abort_pending_cnt);
29262+ atomic_inc(&mcmd->origin_pr_cmd->pr_abort_counter->pr_aborting_cnt);
29263+ }
29264+
29265+out:
29266+ TRACE_EXIT();
29267+ return mcmd;
29268+}
29269+
29270+static int scst_post_rx_mgmt_cmd(struct scst_session *sess,
29271+ struct scst_mgmt_cmd *mcmd)
29272+{
29273+ unsigned long flags;
29274+ int res = 0;
29275+
29276+ TRACE_ENTRY();
29277+
29278+ scst_sess_get(sess);
29279+
29280+ if (unlikely(sess->shut_phase != SCST_SESS_SPH_READY)) {
29281+ PRINT_CRIT_ERROR("New mgmt cmd while shutting down the "
29282+ "session %p shut_phase %ld", sess, sess->shut_phase);
29283+ BUG();
29284+ }
29285+
29286+ local_irq_save(flags);
29287+
29288+ spin_lock(&sess->sess_list_lock);
29289+ atomic_inc(&sess->sess_cmd_count);
29290+
29291+ if (unlikely(sess->init_phase != SCST_SESS_IPH_READY)) {
29292+ switch (sess->init_phase) {
29293+ case SCST_SESS_IPH_INITING:
29294+ TRACE_DBG("Adding mcmd %p to init deferred mcmd list",
29295+ mcmd);
29296+ list_add_tail(&mcmd->mgmt_cmd_list_entry,
29297+ &sess->init_deferred_mcmd_list);
29298+ goto out_unlock;
29299+ case SCST_SESS_IPH_SUCCESS:
29300+ break;
29301+ case SCST_SESS_IPH_FAILED:
29302+ res = -1;
29303+ goto out_unlock;
29304+ default:
29305+ BUG();
29306+ }
29307+ }
29308+
29309+ spin_unlock(&sess->sess_list_lock);
29310+
29311+ TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd list", mcmd);
29312+ spin_lock(&scst_mcmd_lock);
29313+ list_add_tail(&mcmd->mgmt_cmd_list_entry, &scst_active_mgmt_cmd_list);
29314+ spin_unlock(&scst_mcmd_lock);
29315+
29316+ local_irq_restore(flags);
29317+
29318+ wake_up(&scst_mgmt_cmd_list_waitQ);
29319+
29320+out:
29321+ TRACE_EXIT();
29322+ return res;
29323+
29324+out_unlock:
29325+ spin_unlock(&sess->sess_list_lock);
29326+ local_irq_restore(flags);
29327+ goto out;
29328+}
29329+
29330+/**
29331+ * scst_rx_mgmt_fn() - create new management command and send it for execution
29332+ *
29333+ * Description:
29334+ * Creates new management command and sends it for execution.
29335+ *
29336+ * Returns 0 for success, error code otherwise.
29337+ *
29338+ * Must not be called in parallel with scst_unregister_session() for the
29339+ * same sess.
29340+ */
29341+int scst_rx_mgmt_fn(struct scst_session *sess,
29342+ const struct scst_rx_mgmt_params *params)
29343+{
29344+ int res = -EFAULT;
29345+ struct scst_mgmt_cmd *mcmd = NULL;
29346+
29347+ TRACE_ENTRY();
29348+
29349+ switch (params->fn) {
29350+ case SCST_ABORT_TASK:
29351+ BUG_ON(!params->tag_set);
29352+ break;
29353+ case SCST_TARGET_RESET:
29354+ case SCST_ABORT_ALL_TASKS:
29355+ case SCST_NEXUS_LOSS:
29356+ break;
29357+ default:
29358+ BUG_ON(!params->lun_set);
29359+ }
29360+
29361+ mcmd = scst_pre_rx_mgmt_cmd(sess, params->fn, params->atomic,
29362+ params->tgt_priv);
29363+ if (mcmd == NULL)
29364+ goto out;
29365+
29366+ if (params->lun_set) {
29367+ mcmd->lun = scst_unpack_lun(params->lun, params->lun_len);
29368+ if (mcmd->lun == NO_SUCH_LUN)
29369+ goto out_free;
29370+ mcmd->lun_set = 1;
29371+ }
29372+
29373+ if (params->tag_set)
29374+ mcmd->tag = params->tag;
29375+
29376+ mcmd->cmd_sn_set = params->cmd_sn_set;
29377+ mcmd->cmd_sn = params->cmd_sn;
29378+
29379+ if (params->fn < SCST_UNREG_SESS_TM)
29380+ TRACE(TRACE_MGMT, "TM fn %d", params->fn);
29381+ else
29382+ TRACE_MGMT_DBG("TM fn %d", params->fn);
29383+
29384+ TRACE_MGMT_DBG("sess=%p, tag_set %d, tag %lld, lun_set %d, "
29385+ "lun=%lld, cmd_sn_set %d, cmd_sn %d, priv %p", sess,
29386+ params->tag_set,
29387+ (long long unsigned int)params->tag,
29388+ params->lun_set,
29389+ (long long unsigned int)mcmd->lun,
29390+ params->cmd_sn_set,
29391+ params->cmd_sn,
29392+ params->tgt_priv);
29393+
29394+ if (scst_post_rx_mgmt_cmd(sess, mcmd) != 0)
29395+ goto out_free;
29396+
29397+ res = 0;
29398+
29399+out:
29400+ TRACE_EXIT_RES(res);
29401+ return res;
29402+
29403+out_free:
29404+ scst_free_mgmt_cmd(mcmd);
29405+ mcmd = NULL;
29406+ goto out;
29407+}
29408+EXPORT_SYMBOL(scst_rx_mgmt_fn);
29409+
29410+/*
29411+ * Written by Jack Handy - jakkhandy@hotmail.com
29412+ * Taken by Gennadiy Nerubayev <parakie@gmail.com> from
29413+ * http://www.codeproject.com/KB/string/wildcmp.aspx. No license attached
29414+ * to it, and it's posted on a free site; assumed to be free for use.
29415+ *
29416+ * Added the negative sign support - VLNB
29417+ *
29418+ * Also see comment for wildcmp().
29419+ *
29420+ * User space part of iSCSI-SCST also has a copy of this code, so fixing a bug
29421+ * here, don't forget to fix the copy too!
29422+ */
29423+static bool __wildcmp(const char *wild, const char *string, int recursion_level)
29424+{
29425+ const char *cp = NULL, *mp = NULL;
29426+
29427+ while ((*string) && (*wild != '*')) {
29428+ if ((*wild == '!') && (recursion_level == 0))
29429+ return !__wildcmp(++wild, string, ++recursion_level);
29430+
29431+ if ((*wild != *string) && (*wild != '?'))
29432+ return false;
29433+
29434+ wild++;
29435+ string++;
29436+ }
29437+
29438+ while (*string) {
29439+ if ((*wild == '!') && (recursion_level == 0))
29440+ return !__wildcmp(++wild, string, ++recursion_level);
29441+
29442+ if (*wild == '*') {
29443+ if (!*++wild)
29444+ return true;
29445+
29446+ mp = wild;
29447+ cp = string+1;
29448+ } else if ((*wild == *string) || (*wild == '?')) {
29449+ wild++;
29450+ string++;
29451+ } else {
29452+ wild = mp;
29453+ string = cp++;
29454+ }
29455+ }
29456+
29457+ while (*wild == '*')
29458+ wild++;
29459+
29460+ return !*wild;
29461+}
29462+
29463+/*
29464+ * Returns true if string "string" matches pattern "wild", false otherwise.
29465+ * Pattern is a regular DOS-type pattern, containing '*' and '?' symbols.
29466+ * '*' means match all any symbols, '?' means match only any single symbol.
29467+ *
29468+ * For instance:
29469+ * if (wildcmp("bl?h.*", "blah.jpg")) {
29470+ * // match
29471+ * } else {
29472+ * // no match
29473+ * }
29474+ *
29475+ * Also it supports boolean inversion sign '!', which does boolean inversion of
29476+ * the value of the rest of the string. Only one '!' allowed in the pattern,
29477+ * other '!' are treated as regular symbols. For instance:
29478+ * if (wildcmp("bl!?h.*", "blah.jpg")) {
29479+ * // no match
29480+ * } else {
29481+ * // match
29482+ * }
29483+ *
29484+ * Also see comment for __wildcmp().
29485+ */
29486+static bool wildcmp(const char *wild, const char *string)
29487+{
29488+ return __wildcmp(wild, string, 0);
29489+}
29490+
29491+/* scst_mutex supposed to be held */
29492+static struct scst_acg *scst_find_tgt_acg_by_name_wild(struct scst_tgt *tgt,
29493+ const char *initiator_name)
29494+{
29495+ struct scst_acg *acg, *res = NULL;
29496+ struct scst_acn *n;
29497+
29498+ TRACE_ENTRY();
29499+
29500+ if (initiator_name == NULL)
29501+ goto out;
29502+
29503+ list_for_each_entry(acg, &tgt->tgt_acg_list, acg_list_entry) {
29504+ list_for_each_entry(n, &acg->acn_list, acn_list_entry) {
29505+ if (wildcmp(n->name, initiator_name)) {
29506+ TRACE_DBG("Access control group %s found",
29507+ acg->acg_name);
29508+ res = acg;
29509+ goto out;
29510+ }
29511+ }
29512+ }
29513+
29514+out:
29515+ TRACE_EXIT_HRES(res);
29516+ return res;
29517+}
29518+
29519+/* Must be called under scst_mutex */
29520+static struct scst_acg *__scst_find_acg(struct scst_tgt *tgt,
29521+ const char *initiator_name)
29522+{
29523+ struct scst_acg *acg = NULL;
29524+
29525+ TRACE_ENTRY();
29526+
29527+ acg = scst_find_tgt_acg_by_name_wild(tgt, initiator_name);
29528+ if (acg == NULL)
29529+ acg = tgt->default_acg;
29530+
29531+ TRACE_EXIT_HRES((unsigned long)acg);
29532+ return acg;
29533+}
29534+
29535+/* Must be called under scst_mutex */
29536+struct scst_acg *scst_find_acg(const struct scst_session *sess)
29537+{
29538+ return __scst_find_acg(sess->tgt, sess->initiator_name);
29539+}
29540+
29541+/**
29542+ * scst_initiator_has_luns() - check if this initiator will see any LUNs
29543+ *
29544+ * Checks if this initiator will see any LUNs upon connect to this target.
29545+ * Returns true if yes and false otherwise.
29546+ */
29547+bool scst_initiator_has_luns(struct scst_tgt *tgt, const char *initiator_name)
29548+{
29549+ bool res;
29550+ struct scst_acg *acg;
29551+
29552+ TRACE_ENTRY();
29553+
29554+ mutex_lock(&scst_mutex);
29555+
29556+ acg = __scst_find_acg(tgt, initiator_name);
29557+
29558+ res = !list_empty(&acg->acg_dev_list);
29559+
29560+ mutex_unlock(&scst_mutex);
29561+
29562+ TRACE_EXIT_RES(res);
29563+ return res;
29564+}
29565+EXPORT_SYMBOL_GPL(scst_initiator_has_luns);
29566+
29567+static int scst_init_session(struct scst_session *sess)
29568+{
29569+ int res = 0;
29570+ struct scst_cmd *cmd;
29571+ struct scst_mgmt_cmd *mcmd, *tm;
29572+ int mwake = 0;
29573+
29574+ TRACE_ENTRY();
29575+
29576+ mutex_lock(&scst_mutex);
29577+
29578+ sess->acg = scst_find_acg(sess);
29579+
29580+ PRINT_INFO("Using security group \"%s\" for initiator \"%s\"",
29581+ sess->acg->acg_name, sess->initiator_name);
29582+
29583+ list_add_tail(&sess->acg_sess_list_entry, &sess->acg->acg_sess_list);
29584+
29585+ TRACE_DBG("Adding sess %p to tgt->sess_list", sess);
29586+ list_add_tail(&sess->sess_list_entry, &sess->tgt->sess_list);
29587+
29588+ if (sess->tgt->tgtt->get_initiator_port_transport_id != NULL) {
29589+ res = sess->tgt->tgtt->get_initiator_port_transport_id(sess,
29590+ &sess->transport_id);
29591+ if (res != 0) {
29592+ PRINT_ERROR("Unable to make initiator %s port "
29593+ "transport id", sess->initiator_name);
29594+ goto failed;
29595+ }
29596+ TRACE_PR("sess %p (ini %s), transport id %s/%d", sess,
29597+ sess->initiator_name,
29598+ debug_transport_id_to_initiator_name(
29599+ sess->transport_id), sess->tgt->rel_tgt_id);
29600+ }
29601+
29602+ res = scst_sess_sysfs_create(sess);
29603+ if (res != 0)
29604+ goto failed;
29605+
29606+ /*
29607+ * scst_sess_alloc_tgt_devs() must be called after session added in the
29608+ * sess_list to not race with scst_check_reassign_sess()!
29609+ */
29610+ res = scst_sess_alloc_tgt_devs(sess);
29611+
29612+failed:
29613+ mutex_unlock(&scst_mutex);
29614+
29615+ if (sess->init_result_fn) {
29616+ TRACE_DBG("Calling init_result_fn(%p)", sess);
29617+ sess->init_result_fn(sess, sess->reg_sess_data, res);
29618+ TRACE_DBG("%s", "init_result_fn() returned");
29619+ }
29620+
29621+ spin_lock_irq(&sess->sess_list_lock);
29622+
29623+ if (res == 0)
29624+ sess->init_phase = SCST_SESS_IPH_SUCCESS;
29625+ else
29626+ sess->init_phase = SCST_SESS_IPH_FAILED;
29627+
29628+restart:
29629+ list_for_each_entry(cmd, &sess->init_deferred_cmd_list,
29630+ cmd_list_entry) {
29631+ TRACE_DBG("Deleting cmd %p from init deferred cmd list", cmd);
29632+ list_del(&cmd->cmd_list_entry);
29633+ atomic_dec(&sess->sess_cmd_count);
29634+ spin_unlock_irq(&sess->sess_list_lock);
29635+ scst_cmd_init_done(cmd, SCST_CONTEXT_THREAD);
29636+ spin_lock_irq(&sess->sess_list_lock);
29637+ goto restart;
29638+ }
29639+
29640+ spin_lock(&scst_mcmd_lock);
29641+ list_for_each_entry_safe(mcmd, tm, &sess->init_deferred_mcmd_list,
29642+ mgmt_cmd_list_entry) {
29643+ TRACE_DBG("Moving mgmt command %p from init deferred mcmd list",
29644+ mcmd);
29645+ list_move_tail(&mcmd->mgmt_cmd_list_entry,
29646+ &scst_active_mgmt_cmd_list);
29647+ mwake = 1;
29648+ }
29649+
29650+ spin_unlock(&scst_mcmd_lock);
29651+ /*
29652+ * In case of an error at this point the caller target driver supposed
29653+ * to already call this sess's unregistration.
29654+ */
29655+ sess->init_phase = SCST_SESS_IPH_READY;
29656+ spin_unlock_irq(&sess->sess_list_lock);
29657+
29658+ if (mwake)
29659+ wake_up(&scst_mgmt_cmd_list_waitQ);
29660+
29661+ scst_sess_put(sess);
29662+
29663+ TRACE_EXIT();
29664+ return res;
29665+}
29666+
29667+/**
29668+ * scst_register_session() - register session
29669+ * @tgt: target
29670+ * @atomic: true, if the function called in the atomic context. If false,
29671+ * this function will block until the session registration is
29672+ * completed.
29673+ * @initiator_name: remote initiator's name, any NULL-terminated string,
29674+ * e.g. iSCSI name, which used as the key to found appropriate
29675+ * access control group. Could be NULL, then the default
29676+ * target's LUNs are used.
29677+ * @tgt_priv: pointer to target driver's private data
29678+ * @result_fn_data: any target driver supplied data
29679+ * @result_fn: pointer to the function that will be asynchronously called
29680+ * when session initialization finishes.
29681+ * Can be NULL. Parameters:
29682+ * - sess - session
29683+ * - data - target driver supplied to scst_register_session()
29684+ * data
29685+ * - result - session initialization result, 0 on success or
29686+ * appropriate error code otherwise
29687+ *
29688+ * Description:
29689+ * Registers new session. Returns new session on success or NULL otherwise.
29690+ *
29691+ * Note: A session creation and initialization is a complex task,
29692+ * which requires sleeping state, so it can't be fully done
29693+ * in interrupt context. Therefore the "bottom half" of it, if
29694+ * scst_register_session() is called from atomic context, will be
29695+ * done in SCST thread context. In this case scst_register_session()
29696+ * will return not completely initialized session, but the target
29697+ * driver can supply commands to this session via scst_rx_cmd().
29698+ * Those commands processing will be delayed inside SCST until
29699+ * the session initialization is finished, then their processing
29700+ * will be restarted. The target driver will be notified about
29701+ * finish of the session initialization by function result_fn().
29702+ * On success the target driver could do nothing, but if the
29703+ * initialization fails, the target driver must ensure that
29704+ * no more new commands being sent or will be sent to SCST after
29705+ * result_fn() returns. All already sent to SCST commands for
29706+ * failed session will be returned in xmit_response() with BUSY status.
29707+ * In case of failure the driver shall call scst_unregister_session()
29708+ * inside result_fn(), it will NOT be called automatically.
29709+ */
29710+struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
29711+ const char *initiator_name, void *tgt_priv, void *result_fn_data,
29712+ void (*result_fn) (struct scst_session *sess, void *data, int result))
29713+{
29714+ struct scst_session *sess;
29715+ int res;
29716+ unsigned long flags;
29717+
29718+ TRACE_ENTRY();
29719+
29720+ sess = scst_alloc_session(tgt, atomic ? GFP_ATOMIC : GFP_KERNEL,
29721+ initiator_name);
29722+ if (sess == NULL)
29723+ goto out;
29724+
29725+ scst_sess_set_tgt_priv(sess, tgt_priv);
29726+
29727+ scst_sess_get(sess); /* one for registered session */
29728+ scst_sess_get(sess); /* one held until sess is inited */
29729+
29730+ if (atomic) {
29731+ sess->reg_sess_data = result_fn_data;
29732+ sess->init_result_fn = result_fn;
29733+ spin_lock_irqsave(&scst_mgmt_lock, flags);
29734+ TRACE_DBG("Adding sess %p to scst_sess_init_list", sess);
29735+ list_add_tail(&sess->sess_init_list_entry,
29736+ &scst_sess_init_list);
29737+ spin_unlock_irqrestore(&scst_mgmt_lock, flags);
29738+ wake_up(&scst_mgmt_waitQ);
29739+ } else {
29740+ res = scst_init_session(sess);
29741+ if (res != 0)
29742+ goto out_free;
29743+ }
29744+
29745+out:
29746+ TRACE_EXIT();
29747+ return sess;
29748+
29749+out_free:
29750+ scst_free_session(sess);
29751+ sess = NULL;
29752+ goto out;
29753+}
29754+EXPORT_SYMBOL_GPL(scst_register_session);
29755+
29756+/**
29757+ * scst_register_session_non_gpl() - register session (non-GPL version)
29758+ * @tgt: target
29759+ * @initiator_name: remote initiator's name, any NULL-terminated string,
29760+ * e.g. iSCSI name, which used as the key to found appropriate
29761+ * access control group. Could be NULL, then the default
29762+ * target's LUNs are used.
29763+ * @tgt_priv: pointer to target driver's private data
29764+ *
29765+ * Description:
29766+ * Registers new session. Returns new session on success or NULL otherwise.
29767+ */
29768+struct scst_session *scst_register_session_non_gpl(struct scst_tgt *tgt,
29769+ const char *initiator_name, void *tgt_priv)
29770+{
29771+ return scst_register_session(tgt, 0, initiator_name, tgt_priv,
29772+ NULL, NULL);
29773+}
29774+EXPORT_SYMBOL(scst_register_session_non_gpl);
29775+
29776+/**
29777+ * scst_unregister_session() - unregister session
29778+ * @sess: session to be unregistered
29779+ * @wait: if true, instructs to wait until all commands, which
29780+ * currently is being executed and belonged to the session,
29781+ * finished. Otherwise, target driver should be prepared to
29782+ * receive xmit_response() for the session's command after
29783+ * scst_unregister_session() returns.
29784+ * @unreg_done_fn: pointer to the function that will be asynchronously called
29785+ * when the last session's command finishes and
29786+ * the session is about to be completely freed. Can be NULL.
29787+ * Parameter:
29788+ * - sess - session
29789+ *
29790+ * Unregisters session.
29791+ *
29792+ * Notes:
29793+ * - All outstanding commands will be finished regularly. After
29794+ * scst_unregister_session() returned, no new commands must be sent to
29795+ * SCST via scst_rx_cmd().
29796+ *
29797+ * - The caller must ensure that no scst_rx_cmd() or scst_rx_mgmt_fn_*() is
29798+ * called in paralell with scst_unregister_session().
29799+ *
29800+ * - Can be called before result_fn() of scst_register_session() called,
29801+ * i.e. during the session registration/initialization.
29802+ *
29803+ * - It is highly recommended to call scst_unregister_session() as soon as it
29804+ * gets clear that session will be unregistered and not to wait until all
29805+ * related commands finished. This function provides the wait functionality,
29806+ * but it also starts recovering stuck commands, if there are any.
29807+ * Otherwise, your target driver could wait for those commands forever.
29808+ */
29809+void scst_unregister_session(struct scst_session *sess, int wait,
29810+ void (*unreg_done_fn) (struct scst_session *sess))
29811+{
29812+ unsigned long flags;
29813+ DECLARE_COMPLETION_ONSTACK(c);
29814+ int rc, lun;
29815+
29816+ TRACE_ENTRY();
29817+
29818+ TRACE_MGMT_DBG("Unregistering session %p (wait %d)", sess, wait);
29819+
29820+ sess->unreg_done_fn = unreg_done_fn;
29821+
29822+ /* Abort all outstanding commands and clear reservation, if necessary */
29823+ lun = 0;
29824+ rc = scst_rx_mgmt_fn_lun(sess, SCST_UNREG_SESS_TM,
29825+ (uint8_t *)&lun, sizeof(lun), SCST_ATOMIC, NULL);
29826+ if (rc != 0) {
29827+ PRINT_ERROR("SCST_UNREG_SESS_TM failed %d (sess %p)",
29828+ rc, sess);
29829+ }
29830+
29831+ sess->shut_phase = SCST_SESS_SPH_SHUTDOWN;
29832+
29833+ spin_lock_irqsave(&scst_mgmt_lock, flags);
29834+
29835+ if (wait)
29836+ sess->shutdown_compl = &c;
29837+
29838+ spin_unlock_irqrestore(&scst_mgmt_lock, flags);
29839+
29840+ scst_sess_put(sess);
29841+
29842+ if (wait) {
29843+ TRACE_DBG("Waiting for session %p to complete", sess);
29844+ wait_for_completion(&c);
29845+ }
29846+
29847+ TRACE_EXIT();
29848+ return;
29849+}
29850+EXPORT_SYMBOL_GPL(scst_unregister_session);
29851+
29852+/**
29853+ * scst_unregister_session_non_gpl() - unregister session, non-GPL version
29854+ * @sess: session to be unregistered
29855+ *
29856+ * Unregisters session.
29857+ *
29858+ * See notes for scst_unregister_session() above.
29859+ */
29860+void scst_unregister_session_non_gpl(struct scst_session *sess)
29861+{
29862+ TRACE_ENTRY();
29863+
29864+ scst_unregister_session(sess, 1, NULL);
29865+
29866+ TRACE_EXIT();
29867+ return;
29868+}
29869+EXPORT_SYMBOL(scst_unregister_session_non_gpl);
29870+
29871+static inline int test_mgmt_list(void)
29872+{
29873+ int res = !list_empty(&scst_sess_init_list) ||
29874+ !list_empty(&scst_sess_shut_list) ||
29875+ unlikely(kthread_should_stop());
29876+ return res;
29877+}
29878+
29879+int scst_global_mgmt_thread(void *arg)
29880+{
29881+ struct scst_session *sess;
29882+
29883+ TRACE_ENTRY();
29884+
29885+ PRINT_INFO("Management thread started, PID %d", current->pid);
29886+
29887+ current->flags |= PF_NOFREEZE;
29888+
29889+ set_user_nice(current, -10);
29890+
29891+ spin_lock_irq(&scst_mgmt_lock);
29892+ while (!kthread_should_stop()) {
29893+ wait_queue_t wait;
29894+ init_waitqueue_entry(&wait, current);
29895+
29896+ if (!test_mgmt_list()) {
29897+ add_wait_queue_exclusive(&scst_mgmt_waitQ, &wait);
29898+ for (;;) {
29899+ set_current_state(TASK_INTERRUPTIBLE);
29900+ if (test_mgmt_list())
29901+ break;
29902+ spin_unlock_irq(&scst_mgmt_lock);
29903+ schedule();
29904+ spin_lock_irq(&scst_mgmt_lock);
29905+ }
29906+ set_current_state(TASK_RUNNING);
29907+ remove_wait_queue(&scst_mgmt_waitQ, &wait);
29908+ }
29909+
29910+ while (!list_empty(&scst_sess_init_list)) {
29911+ sess = list_entry(scst_sess_init_list.next,
29912+ typeof(*sess), sess_init_list_entry);
29913+ TRACE_DBG("Removing sess %p from scst_sess_init_list",
29914+ sess);
29915+ list_del(&sess->sess_init_list_entry);
29916+ spin_unlock_irq(&scst_mgmt_lock);
29917+
29918+ if (sess->init_phase == SCST_SESS_IPH_INITING)
29919+ scst_init_session(sess);
29920+ else {
29921+ PRINT_CRIT_ERROR("session %p is in "
29922+ "scst_sess_init_list, but in unknown "
29923+ "init phase %x", sess,
29924+ sess->init_phase);
29925+ BUG();
29926+ }
29927+
29928+ spin_lock_irq(&scst_mgmt_lock);
29929+ }
29930+
29931+ while (!list_empty(&scst_sess_shut_list)) {
29932+ sess = list_entry(scst_sess_shut_list.next,
29933+ typeof(*sess), sess_shut_list_entry);
29934+ TRACE_DBG("Removing sess %p from scst_sess_shut_list",
29935+ sess);
29936+ list_del(&sess->sess_shut_list_entry);
29937+ spin_unlock_irq(&scst_mgmt_lock);
29938+
29939+ switch (sess->shut_phase) {
29940+ case SCST_SESS_SPH_SHUTDOWN:
29941+ BUG_ON(atomic_read(&sess->refcnt) != 0);
29942+ scst_free_session_callback(sess);
29943+ break;
29944+ default:
29945+ PRINT_CRIT_ERROR("session %p is in "
29946+ "scst_sess_shut_list, but in unknown "
29947+ "shut phase %lx", sess,
29948+ sess->shut_phase);
29949+ BUG();
29950+ break;
29951+ }
29952+
29953+ spin_lock_irq(&scst_mgmt_lock);
29954+ }
29955+ }
29956+ spin_unlock_irq(&scst_mgmt_lock);
29957+
29958+ /*
29959+ * If kthread_should_stop() is true, we are guaranteed to be
29960+ * on the module unload, so both lists must be empty.
29961+ */
29962+ BUG_ON(!list_empty(&scst_sess_init_list));
29963+ BUG_ON(!list_empty(&scst_sess_shut_list));
29964+
29965+ PRINT_INFO("Management thread PID %d finished", current->pid);
29966+
29967+ TRACE_EXIT();
29968+ return 0;
29969+}
29970+
29971+/* Called under sess->sess_list_lock */
29972+static struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess,
29973+ uint64_t tag, bool to_abort)
29974+{
29975+ struct scst_cmd *cmd, *res = NULL;
29976+
29977+ TRACE_ENTRY();
29978+
29979+ /* ToDo: hash list */
29980+
29981+ TRACE_DBG("%s (sess=%p, tag=%llu)", "Searching in sess cmd list",
29982+ sess, (long long unsigned int)tag);
29983+
29984+ list_for_each_entry(cmd, &sess->sess_cmd_list,
29985+ sess_cmd_list_entry) {
29986+ if (cmd->tag == tag) {
29987+ /*
29988+ * We must not count done commands, because
29989+ * they were submitted for transmittion.
29990+ * Otherwise we can have a race, when for
29991+ * some reason cmd's release delayed
29992+ * after transmittion and initiator sends
29993+ * cmd with the same tag => it can be possible
29994+ * that a wrong cmd will be returned.
29995+ */
29996+ if (cmd->done) {
29997+ if (to_abort) {
29998+ /*
29999+ * We should return the latest not
30000+ * aborted cmd with this tag.
30001+ */
30002+ if (res == NULL)
30003+ res = cmd;
30004+ else {
30005+ if (test_bit(SCST_CMD_ABORTED,
30006+ &res->cmd_flags)) {
30007+ res = cmd;
30008+ } else if (!test_bit(SCST_CMD_ABORTED,
30009+ &cmd->cmd_flags))
30010+ res = cmd;
30011+ }
30012+ }
30013+ continue;
30014+ } else {
30015+ res = cmd;
30016+ break;
30017+ }
30018+ }
30019+ }
30020+
30021+ TRACE_EXIT();
30022+ return res;
30023+}
30024+
30025+/**
30026+ * scst_find_cmd() - find command by custom comparison function
30027+ *
30028+ * Finds a command based on user supplied data and comparision
30029+ * callback function, that should return true, if the command is found.
30030+ * Returns the command on success or NULL otherwise.
30031+ */
30032+struct scst_cmd *scst_find_cmd(struct scst_session *sess, void *data,
30033+ int (*cmp_fn) (struct scst_cmd *cmd,
30034+ void *data))
30035+{
30036+ struct scst_cmd *cmd = NULL;
30037+ unsigned long flags = 0;
30038+
30039+ TRACE_ENTRY();
30040+
30041+ if (cmp_fn == NULL)
30042+ goto out;
30043+
30044+ spin_lock_irqsave(&sess->sess_list_lock, flags);
30045+
30046+ TRACE_DBG("Searching in sess cmd list (sess=%p)", sess);
30047+ list_for_each_entry(cmd, &sess->sess_cmd_list, sess_cmd_list_entry) {
30048+ /*
30049+ * We must not count done commands, because they were
30050+ * submitted for transmittion. Otherwise we can have a race,
30051+ * when for some reason cmd's release delayed after
30052+ * transmittion and initiator sends cmd with the same tag =>
30053+ * it can be possible that a wrong cmd will be returned.
30054+ */
30055+ if (cmd->done)
30056+ continue;
30057+ if (cmp_fn(cmd, data))
30058+ goto out_unlock;
30059+ }
30060+
30061+ cmd = NULL;
30062+
30063+out_unlock:
30064+ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
30065+
30066+out:
30067+ TRACE_EXIT();
30068+ return cmd;
30069+}
30070+EXPORT_SYMBOL(scst_find_cmd);
30071+
30072+/**
30073+ * scst_find_cmd_by_tag() - find command by tag
30074+ *
30075+ * Finds a command based on the supplied tag comparing it with one
30076+ * that previously set by scst_cmd_set_tag(). Returns the found command on
30077+ * success or NULL otherwise.
30078+ */
30079+struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess,
30080+ uint64_t tag)
30081+{
30082+ unsigned long flags;
30083+ struct scst_cmd *cmd;
30084+ spin_lock_irqsave(&sess->sess_list_lock, flags);
30085+ cmd = __scst_find_cmd_by_tag(sess, tag, false);
30086+ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
30087+ return cmd;
30088+}
30089+EXPORT_SYMBOL(scst_find_cmd_by_tag);
30090diff -uprN orig/linux-2.6.35/include/scst/scst_debug.h linux-2.6.35/include/scst/scst_debug.h
30091--- orig/linux-2.6.35/include/scst/scst_debug.h
30092+++ linux-2.6.35/include/scst/scst_debug.h
30093@@ -0,0 +1,350 @@
30094+/*
30095+ * include/scst_debug.h
30096+ *
30097+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
30098+ * Copyright (C) 2004 - 2005 Leonid Stoljar
30099+ * Copyright (C) 2007 - 2010 ID7 Ltd.
30100+ *
30101+ * Contains macroses for execution tracing and error reporting
30102+ *
30103+ * This program is free software; you can redistribute it and/or
30104+ * modify it under the terms of the GNU General Public License
30105+ * as published by the Free Software Foundation, version 2
30106+ * of the License.
30107+ *
30108+ * This program is distributed in the hope that it will be useful,
30109+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30110+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30111+ * GNU General Public License for more details.
30112+ */
30113+
30114+#ifndef __SCST_DEBUG_H
30115+#define __SCST_DEBUG_H
30116+
30117+#include <generated/autoconf.h> /* for CONFIG_* */
30118+
30119+#include <linux/bug.h> /* for WARN_ON_ONCE */
30120+
30121+#ifdef CONFIG_SCST_EXTRACHECKS
30122+#define EXTRACHECKS_BUG_ON(a) BUG_ON(a)
30123+#define EXTRACHECKS_WARN_ON(a) WARN_ON(a)
30124+#define EXTRACHECKS_WARN_ON_ONCE(a) WARN_ON_ONCE(a)
30125+#else
30126+#define EXTRACHECKS_BUG_ON(a) do { } while (0)
30127+#define EXTRACHECKS_WARN_ON(a) do { } while (0)
30128+#define EXTRACHECKS_WARN_ON_ONCE(a) do { } while (0)
30129+#endif
30130+
30131+#define TRACE_NULL 0x00000000
30132+#define TRACE_DEBUG 0x00000001
30133+#define TRACE_FUNCTION 0x00000002
30134+#define TRACE_LINE 0x00000004
30135+#define TRACE_PID 0x00000008
30136+#ifndef GENERATING_UPSTREAM_PATCH
30137+#define TRACE_ENTRYEXIT 0x00000010
30138+#endif
30139+#define TRACE_BUFF 0x00000020
30140+#define TRACE_MEMORY 0x00000040
30141+#define TRACE_SG_OP 0x00000080
30142+#define TRACE_OUT_OF_MEM 0x00000100
30143+#define TRACE_MINOR 0x00000200 /* less important events */
30144+#define TRACE_MGMT 0x00000400
30145+#define TRACE_MGMT_DEBUG 0x00000800
30146+#define TRACE_SCSI 0x00001000
30147+#define TRACE_SPECIAL 0x00002000 /* filtering debug, etc */
30148+#define TRACE_FLOW_CONTROL 0x00004000 /* flow control in action */
30149+#define TRACE_PRES 0x00008000
30150+#define TRACE_ALL 0xffffffff
30151+/* Flags 0xXXXX0000 are local for users */
30152+
30153+#define TRACE_MINOR_AND_MGMT_DBG (TRACE_MINOR|TRACE_MGMT_DEBUG)
30154+
30155+#ifndef KERN_CONT
30156+#define KERN_CONT ""
30157+#endif
30158+
30159+/*
30160+ * Note: in the next two printk() statements the KERN_CONT macro is only
30161+ * present to suppress a checkpatch warning (KERN_CONT is defined as "").
30162+ */
30163+#define PRINT(log_flag, format, args...) \
30164+ printk(log_flag format "\n", ## args)
30165+#define PRINTN(log_flag, format, args...) \
30166+ printk(log_flag format, ## args)
30167+
30168+#ifdef LOG_PREFIX
30169+#define __LOG_PREFIX LOG_PREFIX
30170+#else
30171+#define __LOG_PREFIX NULL
30172+#endif
30173+
30174+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
30175+
30176+#ifndef CONFIG_SCST_DEBUG
30177+#define ___unlikely(a) (a)
30178+#else
30179+#define ___unlikely(a) unlikely(a)
30180+#endif
30181+
30182+/*
30183+ * We don't print prefix for debug traces to not put additional preasure
30184+ * on the logging system in case of a lot of logging.
30185+ */
30186+
30187+int debug_print_prefix(unsigned long trace_flag,
30188+ const char *prefix, const char *func, int line);
30189+void debug_print_buffer(const void *data, int len);
30190+const char *debug_transport_id_to_initiator_name(const uint8_t *transport_id);
30191+
30192+#define TRACING_MINOR() (trace_flag & TRACE_MINOR)
30193+
30194+#define TRACE(trace, format, args...) \
30195+do { \
30196+ if (___unlikely(trace_flag & (trace))) { \
30197+ debug_print_prefix(trace_flag, __LOG_PREFIX, \
30198+ __func__, __LINE__); \
30199+ PRINT(KERN_CONT, format, args); \
30200+ } \
30201+} while (0)
30202+
30203+#ifdef CONFIG_SCST_DEBUG
30204+
30205+#define PRINT_BUFFER(message, buff, len) \
30206+do { \
30207+ PRINT(KERN_INFO, "%s:%s:", __func__, message); \
30208+ debug_print_buffer(buff, len); \
30209+} while (0)
30210+
30211+#else
30212+
30213+#define PRINT_BUFFER(message, buff, len) \
30214+do { \
30215+ PRINT(KERN_INFO, "%s:", message); \
30216+ debug_print_buffer(buff, len); \
30217+} while (0)
30218+
30219+#endif
30220+
30221+#define PRINT_BUFF_FLAG(flag, message, buff, len) \
30222+do { \
30223+ if (___unlikely(trace_flag & (flag))) { \
30224+ debug_print_prefix(trace_flag, NULL, __func__, __LINE__);\
30225+ PRINT(KERN_CONT, "%s:", message); \
30226+ debug_print_buffer(buff, len); \
30227+ } \
30228+} while (0)
30229+
30230+#else /* CONFIG_SCST_DEBUG || CONFIG_SCST_TRACING */
30231+
30232+#define TRACING_MINOR() (false)
30233+
30234+#define TRACE(trace, args...) do {} while (0)
30235+#define PRINT_BUFFER(message, buff, len) do {} while (0)
30236+#define PRINT_BUFF_FLAG(flag, message, buff, len) do {} while (0)
30237+
30238+#endif /* CONFIG_SCST_DEBUG || CONFIG_SCST_TRACING */
30239+
30240+#ifdef CONFIG_SCST_DEBUG
30241+
30242+#define TRACE_DBG_FLAG(trace, format, args...) \
30243+do { \
30244+ if (trace_flag & (trace)) { \
30245+ debug_print_prefix(trace_flag, NULL, __func__, __LINE__);\
30246+ PRINT(KERN_CONT, format, args); \
30247+ } \
30248+} while (0)
30249+
30250+#define TRACE_MEM(args...) TRACE_DBG_FLAG(TRACE_MEMORY, args)
30251+#define TRACE_SG(args...) TRACE_DBG_FLAG(TRACE_SG_OP, args)
30252+#define TRACE_DBG(args...) TRACE_DBG_FLAG(TRACE_DEBUG, args)
30253+#define TRACE_DBG_SPECIAL(args...) TRACE_DBG_FLAG(TRACE_DEBUG|TRACE_SPECIAL, args)
30254+#define TRACE_MGMT_DBG(args...) TRACE_DBG_FLAG(TRACE_MGMT_DEBUG, args)
30255+#define TRACE_MGMT_DBG_SPECIAL(args...) \
30256+ TRACE_DBG_FLAG(TRACE_MGMT_DEBUG|TRACE_SPECIAL, args)
30257+#define TRACE_PR(args...) TRACE_DBG_FLAG(TRACE_PRES, args)
30258+
30259+#define TRACE_BUFFER(message, buff, len) \
30260+do { \
30261+ if (trace_flag & TRACE_BUFF) { \
30262+ debug_print_prefix(trace_flag, NULL, __func__, __LINE__);\
30263+ PRINT(KERN_CONT, "%s:", message); \
30264+ debug_print_buffer(buff, len); \
30265+ } \
30266+} while (0)
30267+
30268+#define TRACE_BUFF_FLAG(flag, message, buff, len) \
30269+do { \
30270+ if (trace_flag & (flag)) { \
30271+ debug_print_prefix(trace_flag, NULL, __func__, __LINE__);\
30272+ PRINT(KERN_CONT, "%s:", message); \
30273+ debug_print_buffer(buff, len); \
30274+ } \
30275+} while (0)
30276+
30277+#define PRINT_LOG_FLAG(log_flag, format, args...) \
30278+do { \
30279+ debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\
30280+ PRINT(KERN_CONT, format, args); \
30281+} while (0)
30282+
30283+#define PRINT_WARNING(format, args...) \
30284+do { \
30285+ debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\
30286+ PRINT(KERN_CONT, "***WARNING***: " format, args); \
30287+} while (0)
30288+
30289+#define PRINT_ERROR(format, args...) \
30290+do { \
30291+ debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\
30292+ PRINT(KERN_CONT, "***ERROR***: " format, args); \
30293+} while (0)
30294+
30295+#define PRINT_CRIT_ERROR(format, args...) \
30296+do { \
30297+ debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\
30298+ PRINT(KERN_CONT, "***CRITICAL ERROR***: " format, args); \
30299+} while (0)
30300+
30301+#define PRINT_INFO(format, args...) \
30302+do { \
30303+ debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\
30304+ PRINT(KERN_CONT, format, args); \
30305+} while (0)
30306+
30307+#ifndef GENERATING_UPSTREAM_PATCH
30308+#define TRACE_ENTRY() \
30309+do { \
30310+ if (trace_flag & TRACE_ENTRYEXIT) { \
30311+ if (trace_flag & TRACE_PID) { \
30312+ PRINT(KERN_INFO, "[%d]: ENTRY %s", current->pid, \
30313+ __func__); \
30314+ } \
30315+ else { \
30316+ PRINT(KERN_INFO, "ENTRY %s", __func__); \
30317+ } \
30318+ } \
30319+} while (0)
30320+
30321+#define TRACE_EXIT() \
30322+do { \
30323+ if (trace_flag & TRACE_ENTRYEXIT) { \
30324+ if (trace_flag & TRACE_PID) { \
30325+ PRINT(KERN_INFO, "[%d]: EXIT %s", current->pid, \
30326+ __func__); \
30327+ } \
30328+ else { \
30329+ PRINT(KERN_INFO, "EXIT %s", __func__); \
30330+ } \
30331+ } \
30332+} while (0)
30333+
30334+#define TRACE_EXIT_RES(res) \
30335+do { \
30336+ if (trace_flag & TRACE_ENTRYEXIT) { \
30337+ if (trace_flag & TRACE_PID) { \
30338+ PRINT(KERN_INFO, "[%d]: EXIT %s: %ld", current->pid, \
30339+ __func__, (long)(res)); \
30340+ } \
30341+ else { \
30342+ PRINT(KERN_INFO, "EXIT %s: %ld", \
30343+ __func__, (long)(res)); \
30344+ } \
30345+ } \
30346+} while (0)
30347+
30348+#define TRACE_EXIT_HRES(res) \
30349+do { \
30350+ if (trace_flag & TRACE_ENTRYEXIT) { \
30351+ if (trace_flag & TRACE_PID) { \
30352+ PRINT(KERN_INFO, "[%d]: EXIT %s: 0x%lx", current->pid, \
30353+ __func__, (long)(res)); \
30354+ } \
30355+ else { \
30356+ PRINT(KERN_INFO, "EXIT %s: %lx", \
30357+ __func__, (long)(res)); \
30358+ } \
30359+ } \
30360+} while (0)
30361+#endif
30362+
30363+#else /* CONFIG_SCST_DEBUG */
30364+
30365+#define TRACE_MEM(format, args...) do {} while (0)
30366+#define TRACE_SG(format, args...) do {} while (0)
30367+#define TRACE_DBG(format, args...) do {} while (0)
30368+#define TRACE_DBG_FLAG(format, args...) do {} while (0)
30369+#define TRACE_DBG_SPECIAL(format, args...) do {} while (0)
30370+#define TRACE_MGMT_DBG(format, args...) do {} while (0)
30371+#define TRACE_MGMT_DBG_SPECIAL(format, args...) do {} while (0)
30372+#define TRACE_PR(format, args...) do {} while (0)
30373+#define TRACE_BUFFER(message, buff, len) do {} while (0)
30374+#define TRACE_BUFF_FLAG(flag, message, buff, len) do {} while (0)
30375+
30376+#ifndef GENERATING_UPSTREAM_PATCH
30377+#define TRACE_ENTRY() do {} while (0)
30378+#define TRACE_EXIT() do {} while (0)
30379+#define TRACE_EXIT_RES(res) do {} while (0)
30380+#define TRACE_EXIT_HRES(res) do {} while (0)
30381+#endif
30382+
30383+#ifdef LOG_PREFIX
30384+
30385+#define PRINT_INFO(format, args...) \
30386+do { \
30387+ PRINT(KERN_INFO, "%s: " format, LOG_PREFIX, args); \
30388+} while (0)
30389+
30390+#define PRINT_WARNING(format, args...) \
30391+do { \
30392+ PRINT(KERN_INFO, "%s: ***WARNING***: " \
30393+ format, LOG_PREFIX, args); \
30394+} while (0)
30395+
30396+#define PRINT_ERROR(format, args...) \
30397+do { \
30398+ PRINT(KERN_INFO, "%s: ***ERROR***: " \
30399+ format, LOG_PREFIX, args); \
30400+} while (0)
30401+
30402+#define PRINT_CRIT_ERROR(format, args...) \
30403+do { \
30404+ PRINT(KERN_INFO, "%s: ***CRITICAL ERROR***: " \
30405+ format, LOG_PREFIX, args); \
30406+} while (0)
30407+
30408+#else
30409+
30410+#define PRINT_INFO(format, args...) \
30411+do { \
30412+ PRINT(KERN_INFO, format, args); \
30413+} while (0)
30414+
30415+#define PRINT_WARNING(format, args...) \
30416+do { \
30417+ PRINT(KERN_INFO, "***WARNING***: " \
30418+ format, args); \
30419+} while (0)
30420+
30421+#define PRINT_ERROR(format, args...) \
30422+do { \
30423+ PRINT(KERN_ERR, "***ERROR***: " \
30424+ format, args); \
30425+} while (0)
30426+
30427+#define PRINT_CRIT_ERROR(format, args...) \
30428+do { \
30429+ PRINT(KERN_CRIT, "***CRITICAL ERROR***: " \
30430+ format, args); \
30431+} while (0)
30432+
30433+#endif /* LOG_PREFIX */
30434+
30435+#endif /* CONFIG_SCST_DEBUG */
30436+
30437+#if defined(CONFIG_SCST_DEBUG) && defined(CONFIG_DEBUG_SLAB)
30438+#define SCST_SLAB_FLAGS (SLAB_RED_ZONE | SLAB_POISON)
30439+#else
30440+#define SCST_SLAB_FLAGS 0L
30441+#endif
30442+
30443+#endif /* __SCST_DEBUG_H */
30444diff -uprN orig/linux-2.6.35/drivers/scst/scst_debug.c linux-2.6.35/drivers/scst/scst_debug.c
30445--- orig/linux-2.6.35/drivers/scst/scst_debug.c
30446+++ linux-2.6.35/drivers/scst/scst_debug.c
30447@@ -0,0 +1,223 @@
30448+/*
30449+ * scst_debug.c
30450+ *
30451+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
30452+ * Copyright (C) 2004 - 2005 Leonid Stoljar
30453+ * Copyright (C) 2007 - 2010 ID7 Ltd.
30454+ *
30455+ * Contains helper functions for execution tracing and error reporting.
30456+ * Intended to be included in main .c file.
30457+ *
30458+ * This program is free software; you can redistribute it and/or
30459+ * modify it under the terms of the GNU General Public License
30460+ * as published by the Free Software Foundation, version 2
30461+ * of the License.
30462+ *
30463+ * This program is distributed in the hope that it will be useful,
30464+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30465+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30466+ * GNU General Public License for more details.
30467+ */
30468+
30469+#include <scst/scst.h>
30470+#include <scst/scst_debug.h>
30471+
30472+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
30473+
30474+#define TRACE_BUF_SIZE 512
30475+
30476+static char trace_buf[TRACE_BUF_SIZE];
30477+static DEFINE_SPINLOCK(trace_buf_lock);
30478+
30479+static inline int get_current_tid(void)
30480+{
30481+ /* Code should be the same as in sys_gettid() */
30482+ if (in_interrupt()) {
30483+ /*
30484+ * Unfortunately, task_pid_vnr() isn't IRQ-safe, so otherwise
30485+ * it can oops. ToDo.
30486+ */
30487+ return 0;
30488+ }
30489+ return task_pid_vnr(current);
30490+}
30491+
30492+/**
30493+ * debug_print_prefix() - print debug prefix for a log line
30494+ *
30495+ * Prints, if requested by trace_flag, debug prefix for each log line
30496+ */
30497+int debug_print_prefix(unsigned long trace_flag,
30498+ const char *prefix, const char *func, int line)
30499+{
30500+ int i = 0;
30501+ unsigned long flags;
30502+ int pid = get_current_tid();
30503+
30504+ spin_lock_irqsave(&trace_buf_lock, flags);
30505+
30506+ trace_buf[0] = '\0';
30507+
30508+ if (trace_flag & TRACE_PID)
30509+ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE, "[%d]: ", pid);
30510+ if (prefix != NULL)
30511+ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%s: ",
30512+ prefix);
30513+ if (trace_flag & TRACE_FUNCTION)
30514+ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%s:", func);
30515+ if (trace_flag & TRACE_LINE)
30516+ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%i:", line);
30517+
30518+ PRINTN(KERN_INFO, "%s", trace_buf);
30519+
30520+ spin_unlock_irqrestore(&trace_buf_lock, flags);
30521+
30522+ return i;
30523+}
30524+EXPORT_SYMBOL(debug_print_prefix);
30525+
30526+/**
30527+ * debug_print_buffer() - print a buffer
30528+ *
30529+ * Prints in the log data from the buffer
30530+ */
30531+void debug_print_buffer(const void *data, int len)
30532+{
30533+ int z, z1, i;
30534+ const unsigned char *buf = (const unsigned char *) data;
30535+ unsigned long flags;
30536+
30537+ if (buf == NULL)
30538+ return;
30539+
30540+ spin_lock_irqsave(&trace_buf_lock, flags);
30541+
30542+ PRINT(KERN_INFO, " (h)___0__1__2__3__4__5__6__7__8__9__A__B__C__D__E__F");
30543+ for (z = 0, z1 = 0, i = 0; z < len; z++) {
30544+ if (z % 16 == 0) {
30545+ if (z != 0) {
30546+ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i,
30547+ " ");
30548+ for (; (z1 < z) && (i < TRACE_BUF_SIZE - 1);
30549+ z1++) {
30550+ if ((buf[z1] >= 0x20) &&
30551+ (buf[z1] < 0x80))
30552+ trace_buf[i++] = buf[z1];
30553+ else
30554+ trace_buf[i++] = '.';
30555+ }
30556+ trace_buf[i] = '\0';
30557+ PRINT(KERN_INFO, "%s", trace_buf);
30558+ i = 0;
30559+ }
30560+ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i,
30561+ "%4x: ", z);
30562+ }
30563+ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%02x ",
30564+ buf[z]);
30565+ }
30566+
30567+ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, " ");
30568+ for (; (z1 < z) && (i < TRACE_BUF_SIZE - 1); z1++) {
30569+ if ((buf[z1] > 0x20) && (buf[z1] < 0x80))
30570+ trace_buf[i++] = buf[z1];
30571+ else
30572+ trace_buf[i++] = '.';
30573+ }
30574+ trace_buf[i] = '\0';
30575+
30576+ PRINT(KERN_INFO, "%s", trace_buf);
30577+
30578+ spin_unlock_irqrestore(&trace_buf_lock, flags);
30579+ return;
30580+}
30581+EXPORT_SYMBOL(debug_print_buffer);
30582+
30583+/*
30584+ * This function converts transport_id in a string form into internal per-CPU
30585+ * static buffer. This buffer isn't anyhow protected, because it's acceptable
30586+ * if the name corrupted in the debug logs because of the race for this buffer.
30587+ *
30588+ * Note! You can't call this function 2 or more times in a single logging
30589+ * (printk) statement, because then each new call of this functon will override
30590+ * data written in this buffer by the previous call. You should instead split
30591+ * that logging statement on smaller statements each calling
30592+ * debug_transport_id_to_initiator_name() only once.
30593+ */
30594+const char *debug_transport_id_to_initiator_name(const uint8_t *transport_id)
30595+{
30596+ /*
30597+ * No external protection, because it's acceptable if the name
30598+ * corrupted in the debug logs because of the race for this
30599+ * buffer.
30600+ */
30601+#define SIZEOF_NAME_BUF 256
30602+ static char name_bufs[NR_CPUS][SIZEOF_NAME_BUF];
30603+ char *name_buf;
30604+ unsigned long flags;
30605+
30606+ BUG_ON(transport_id == NULL); /* better to catch it not under lock */
30607+
30608+ spin_lock_irqsave(&trace_buf_lock, flags);
30609+
30610+ name_buf = name_bufs[smp_processor_id()];
30611+
30612+ /*
30613+ * To prevent external racing with us users from accidentally
30614+ * missing their NULL terminator.
30615+ */
30616+ memset(name_buf, 0, SIZEOF_NAME_BUF);
30617+ smp_mb();
30618+
30619+ switch (transport_id[0] & 0x0f) {
30620+ case SCSI_TRANSPORTID_PROTOCOLID_ISCSI:
30621+ scnprintf(name_buf, SIZEOF_NAME_BUF, "%s",
30622+ &transport_id[4]);
30623+ break;
30624+ case SCSI_TRANSPORTID_PROTOCOLID_FCP2:
30625+ scnprintf(name_buf, SIZEOF_NAME_BUF,
30626+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
30627+ transport_id[8], transport_id[9],
30628+ transport_id[10], transport_id[11],
30629+ transport_id[12], transport_id[13],
30630+ transport_id[14], transport_id[15]);
30631+ break;
30632+ case SCSI_TRANSPORTID_PROTOCOLID_SPI5:
30633+ scnprintf(name_buf, SIZEOF_NAME_BUF,
30634+ "%x:%x", be16_to_cpu((__force __be16)transport_id[2]),
30635+ be16_to_cpu((__force __be16)transport_id[6]));
30636+ break;
30637+ case SCSI_TRANSPORTID_PROTOCOLID_SRP:
30638+ scnprintf(name_buf, SIZEOF_NAME_BUF,
30639+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
30640+ ":%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
30641+ transport_id[8], transport_id[9],
30642+ transport_id[10], transport_id[11],
30643+ transport_id[12], transport_id[13],
30644+ transport_id[14], transport_id[15],
30645+ transport_id[16], transport_id[17],
30646+ transport_id[18], transport_id[19],
30647+ transport_id[20], transport_id[21],
30648+ transport_id[22], transport_id[23]);
30649+ break;
30650+ case SCSI_TRANSPORTID_PROTOCOLID_SAS:
30651+ scnprintf(name_buf, SIZEOF_NAME_BUF,
30652+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
30653+ transport_id[4], transport_id[5],
30654+ transport_id[6], transport_id[7],
30655+ transport_id[8], transport_id[9],
30656+ transport_id[10], transport_id[11]);
30657+ break;
30658+ default:
30659+ scnprintf(name_buf, SIZEOF_NAME_BUF,
30660+ "(Not known protocol ID %x)", transport_id[0] & 0x0f);
30661+ break;
30662+ }
30663+
30664+ spin_unlock_irqrestore(&trace_buf_lock, flags);
30665+
30666+ return name_buf;
30667+#undef SIZEOF_NAME_BUF
30668+}
30669+
30670+#endif /* CONFIG_SCST_DEBUG || CONFIG_SCST_TRACING */
30671diff -uprN orig/linux-2.6.35/drivers/scst/scst_proc.c linux-2.6.35/drivers/scst/scst_proc.c
30672--- orig/linux-2.6.35/drivers/scst/scst_proc.c
30673+++ linux-2.6.35/drivers/scst/scst_proc.c
30674@@ -0,0 +1,2703 @@
30675+/*
30676+ * scst_proc.c
30677+ *
30678+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
30679+ * Copyright (C) 2004 - 2005 Leonid Stoljar
30680+ * Copyright (C) 2007 - 2010 ID7 Ltd.
30681+ *
30682+ * This program is free software; you can redistribute it and/or
30683+ * modify it under the terms of the GNU General Public License
30684+ * as published by the Free Software Foundation, version 2
30685+ * of the License.
30686+ *
30687+ * This program is distributed in the hope that it will be useful,
30688+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30689+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30690+ * GNU General Public License for more details.
30691+ */
30692+
30693+#include <linux/module.h>
30694+
30695+#include <linux/init.h>
30696+#include <linux/kernel.h>
30697+#include <linux/errno.h>
30698+#include <linux/list.h>
30699+#include <linux/spinlock.h>
30700+#include <linux/slab.h>
30701+#include <linux/sched.h>
30702+#include <linux/unistd.h>
30703+#include <linux/string.h>
30704+#include <linux/proc_fs.h>
30705+#include <linux/seq_file.h>
30706+
30707+#include <scst/scst.h>
30708+#include "scst_priv.h"
30709+#include "scst_mem.h"
30710+#include "scst_pres.h"
30711+
30712+static int scst_proc_init_groups(void);
30713+static void scst_proc_cleanup_groups(void);
30714+static int scst_proc_assign_handler(char *buf);
30715+static int scst_proc_group_add(const char *p, unsigned int addr_method);
30716+static int scst_proc_del_free_acg(struct scst_acg *acg, int remove_proc);
30717+
30718+static struct scst_proc_data scst_version_proc_data;
30719+static struct scst_proc_data scst_help_proc_data;
30720+static struct scst_proc_data scst_sgv_proc_data;
30721+static struct scst_proc_data scst_groups_names_proc_data;
30722+static struct scst_proc_data scst_groups_devices_proc_data;
30723+static struct scst_proc_data scst_groups_addr_method_proc_data;
30724+static struct scst_proc_data scst_sessions_proc_data;
30725+static struct scst_proc_data scst_dev_handler_type_proc_data;
30726+static struct scst_proc_data scst_tgt_proc_data;
30727+static struct scst_proc_data scst_threads_proc_data;
30728+static struct scst_proc_data scst_scsi_tgt_proc_data;
30729+static struct scst_proc_data scst_dev_handler_proc_data;
30730+
30731+/*
30732+ * Must be less than 4K page size, since our output routines
30733+ * use some slack for overruns
30734+ */
30735+#define SCST_PROC_BLOCK_SIZE (PAGE_SIZE - 512)
30736+
30737+#define SCST_PROC_LOG_ENTRY_NAME "trace_level"
30738+#define SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME "type"
30739+#define SCST_PROC_VERSION_NAME "version"
30740+#define SCST_PROC_SESSIONS_NAME "sessions"
30741+#define SCST_PROC_HELP_NAME "help"
30742+#define SCST_PROC_THREADS_NAME "threads"
30743+#define SCST_PROC_GROUPS_ENTRY_NAME "groups"
30744+#define SCST_PROC_GROUPS_DEVICES_ENTRY_NAME "devices"
30745+#define SCST_PROC_GROUPS_USERS_ENTRY_NAME "names"
30746+#define SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME "addr_method"
30747+
30748+#ifdef CONFIG_SCST_MEASURE_LATENCY
30749+#define SCST_PROC_LAT_ENTRY_NAME "latency"
30750+#endif
30751+
30752+#define SCST_PROC_ACTION_ALL 1
30753+#define SCST_PROC_ACTION_NONE 2
30754+#define SCST_PROC_ACTION_DEFAULT 3
30755+#define SCST_PROC_ACTION_ADD 4
30756+#define SCST_PROC_ACTION_CLEAR 5
30757+#define SCST_PROC_ACTION_MOVE 6
30758+#define SCST_PROC_ACTION_DEL 7
30759+#define SCST_PROC_ACTION_REPLACE 8
30760+#define SCST_PROC_ACTION_VALUE 9
30761+#define SCST_PROC_ACTION_ASSIGN 10
30762+#define SCST_PROC_ACTION_ADD_GROUP 11
30763+#define SCST_PROC_ACTION_DEL_GROUP 12
30764+#define SCST_PROC_ACTION_RENAME_GROUP 13
30765+#define SCST_PROC_ACTION_DUMP_PRS 14
30766+
30767+static struct proc_dir_entry *scst_proc_scsi_tgt;
30768+static struct proc_dir_entry *scst_proc_groups_root;
30769+
30770+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
30771+static struct scst_proc_data scst_log_proc_data;
30772+
30773+static struct scst_trace_log scst_proc_trace_tbl[] = {
30774+ { TRACE_OUT_OF_MEM, "out_of_mem" },
30775+ { TRACE_MINOR, "minor" },
30776+ { TRACE_SG_OP, "sg" },
30777+ { TRACE_MEMORY, "mem" },
30778+ { TRACE_BUFF, "buff" },
30779+#ifndef GENERATING_UPSTREAM_PATCH
30780+ { TRACE_ENTRYEXIT, "entryexit" },
30781+#endif
30782+ { TRACE_PID, "pid" },
30783+ { TRACE_LINE, "line" },
30784+ { TRACE_FUNCTION, "function" },
30785+ { TRACE_DEBUG, "debug" },
30786+ { TRACE_SPECIAL, "special" },
30787+ { TRACE_SCSI, "scsi" },
30788+ { TRACE_MGMT, "mgmt" },
30789+ { TRACE_MGMT_DEBUG, "mgmt_dbg" },
30790+ { TRACE_FLOW_CONTROL, "flow_control" },
30791+ { TRACE_PRES, "pr" },
30792+ { 0, NULL }
30793+};
30794+
30795+static struct scst_trace_log scst_proc_local_trace_tbl[] = {
30796+ { TRACE_RTRY, "retry" },
30797+ { TRACE_SCSI_SERIALIZING, "scsi_serializing" },
30798+ { TRACE_RCV_BOT, "recv_bot" },
30799+ { TRACE_SND_BOT, "send_bot" },
30800+ { TRACE_RCV_TOP, "recv_top" },
30801+ { TRACE_SND_TOP, "send_top" },
30802+ { 0, NULL }
30803+};
30804+#endif
30805+
30806+static char *scst_proc_help_string =
30807+" echo \"assign H:C:I:L HANDLER_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
30808+"\n"
30809+" echo \"add_group GROUP_NAME [FLAT]\" >/proc/scsi_tgt/scsi_tgt\n"
30810+" echo \"del_group GROUP_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
30811+" echo \"rename_group OLD_NAME NEW_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
30812+"\n"
30813+" echo \"add|del H:C:I:L lun [READ_ONLY]\""
30814+" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
30815+" echo \"replace H:C:I:L lun [READ_ONLY]\""
30816+" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
30817+" echo \"add|del V_NAME lun [READ_ONLY]\""
30818+" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
30819+" echo \"replace V_NAME lun [READ_ONLY]\""
30820+" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
30821+" echo \"clear\" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
30822+"\n"
30823+" echo \"add|del NAME\" >/proc/scsi_tgt/groups/GROUP_NAME/names\n"
30824+" echo \"move NAME NEW_GROUP_NAME\" >/proc/scsi_tgt/groups/OLD_GROUP_NAME/names\n"
30825+" echo \"clear\" >/proc/scsi_tgt/groups/GROUP_NAME/names\n"
30826+"\n"
30827+" echo \"DEC|0xHEX|0OCT\" >/proc/scsi_tgt/threads\n"
30828+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
30829+"\n"
30830+" echo \"all|none|default\" >/proc/scsi_tgt/[DEV_HANDLER_NAME/]trace_level\n"
30831+" echo \"value DEC|0xHEX|0OCT\""
30832+" >/proc/scsi_tgt/[DEV_HANDLER_NAME/]trace_level\n"
30833+" echo \"set|add|del TOKEN\""
30834+" >/proc/scsi_tgt/[DEV_HANDLER_NAME/]trace_level\n"
30835+" where TOKEN is one of [debug, function, line, pid, entryexit,\n"
30836+" buff, mem, sg, out_of_mem, special, scsi,\n"
30837+" mgmt, minor, mgmt_dbg]\n"
30838+" Additionally for /proc/scsi_tgt/trace_level there are these TOKENs\n"
30839+" [scsi_serializing, retry, recv_bot, send_bot, recv_top, send_top]\n"
30840+" echo \"dump_prs dev_name\" >/proc/scsi_tgt/trace_level\n"
30841+#endif
30842+;
30843+
30844+static char *scst_proc_dev_handler_type[] = {
30845+ "Direct-access device (e.g., magnetic disk)",
30846+ "Sequential-access device (e.g., magnetic tape)",
30847+ "Printer device",
30848+ "Processor device",
30849+ "Write-once device (e.g., some optical disks)",
30850+ "CD-ROM device",
30851+ "Scanner device (obsolete)",
30852+ "Optical memory device (e.g., some optical disks)",
30853+ "Medium changer device (e.g., jukeboxes)",
30854+ "Communications device (obsolete)",
30855+ "Defined by ASC IT8 (Graphic arts pre-press devices)",
30856+ "Defined by ASC IT8 (Graphic arts pre-press devices)",
30857+ "Storage array controller device (e.g., RAID)",
30858+ "Enclosure services device",
30859+ "Simplified direct-access device (e.g., magnetic disk)",
30860+ "Optical card reader/writer device"
30861+};
30862+
30863+static DEFINE_MUTEX(scst_proc_mutex);
30864+
30865+#include <linux/ctype.h>
30866+
30867+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
30868+
30869+static DEFINE_MUTEX(scst_log_mutex);
30870+
30871+int scst_proc_log_entry_write(struct file *file, const char __user *buf,
30872+ unsigned long length, unsigned long *log_level,
30873+ unsigned long default_level, const struct scst_trace_log *tbl)
30874+{
30875+ int res = length;
30876+ int action;
30877+ unsigned long level = 0, oldlevel;
30878+ char *buffer, *p, *e;
30879+ const struct scst_trace_log *t;
30880+ char *data = (char *)PDE(file->f_dentry->d_inode)->data;
30881+
30882+ TRACE_ENTRY();
30883+
30884+ if (length > SCST_PROC_BLOCK_SIZE) {
30885+ res = -EOVERFLOW;
30886+ goto out;
30887+ }
30888+ if (!buf) {
30889+ res = -EINVAL;
30890+ goto out;
30891+ }
30892+ buffer = (char *)__get_free_page(GFP_KERNEL);
30893+ if (!buffer) {
30894+ res = -ENOMEM;
30895+ goto out;
30896+ }
30897+ if (copy_from_user(buffer, buf, length)) {
30898+ res = -EFAULT;
30899+ goto out_free;
30900+ }
30901+ if (length < PAGE_SIZE) {
30902+ buffer[length] = '\0';
30903+ } else if (buffer[PAGE_SIZE-1]) {
30904+ res = -EINVAL;
30905+ goto out_free;
30906+ }
30907+
30908+ /*
30909+ * Usage:
30910+ * echo "all|none|default" >/proc/scsi_tgt/trace_level
30911+ * echo "value DEC|0xHEX|0OCT" >/proc/scsi_tgt/trace_level
30912+ * echo "add|del TOKEN" >/proc/scsi_tgt/trace_level
30913+ */
30914+ p = buffer;
30915+ if (!strncasecmp("all", p, 3)) {
30916+ action = SCST_PROC_ACTION_ALL;
30917+ } else if (!strncasecmp("none", p, 4) || !strncasecmp("null", p, 4)) {
30918+ action = SCST_PROC_ACTION_NONE;
30919+ } else if (!strncasecmp("default", p, 7)) {
30920+ action = SCST_PROC_ACTION_DEFAULT;
30921+ } else if (!strncasecmp("add ", p, 4)) {
30922+ p += 4;
30923+ action = SCST_PROC_ACTION_ADD;
30924+ } else if (!strncasecmp("del ", p, 4)) {
30925+ p += 4;
30926+ action = SCST_PROC_ACTION_DEL;
30927+ } else if (!strncasecmp("value ", p, 6)) {
30928+ p += 6;
30929+ action = SCST_PROC_ACTION_VALUE;
30930+ } else if (!strncasecmp("dump_prs ", p, 9)) {
30931+ p += 9;
30932+ action = SCST_PROC_ACTION_DUMP_PRS;
30933+ } else {
30934+ if (p[strlen(p) - 1] == '\n')
30935+ p[strlen(p) - 1] = '\0';
30936+ PRINT_ERROR("Unknown action \"%s\"", p);
30937+ res = -EINVAL;
30938+ goto out_free;
30939+ }
30940+
30941+ switch (action) {
30942+ case SCST_PROC_ACTION_ALL:
30943+ level = TRACE_ALL;
30944+ break;
30945+ case SCST_PROC_ACTION_DEFAULT:
30946+ level = default_level;
30947+ break;
30948+ case SCST_PROC_ACTION_NONE:
30949+ level = TRACE_NULL;
30950+ break;
30951+ case SCST_PROC_ACTION_ADD:
30952+ case SCST_PROC_ACTION_DEL:
30953+ while (isspace(*p) && *p != '\0')
30954+ p++;
30955+ e = p;
30956+ while (!isspace(*e) && *e != '\0')
30957+ e++;
30958+ *e = 0;
30959+ if (tbl) {
30960+ t = tbl;
30961+ while (t->token) {
30962+ if (!strcasecmp(p, t->token)) {
30963+ level = t->val;
30964+ break;
30965+ }
30966+ t++;
30967+ }
30968+ }
30969+ if (level == 0) {
30970+ t = scst_proc_trace_tbl;
30971+ while (t->token) {
30972+ if (!strcasecmp(p, t->token)) {
30973+ level = t->val;
30974+ break;
30975+ }
30976+ t++;
30977+ }
30978+ }
30979+ if (level == 0) {
30980+ PRINT_ERROR("Unknown token \"%s\"", p);
30981+ res = -EINVAL;
30982+ goto out_free;
30983+ }
30984+ break;
30985+ case SCST_PROC_ACTION_VALUE:
30986+ while (isspace(*p) && *p != '\0')
30987+ p++;
30988+ level = simple_strtoul(p, NULL, 0);
30989+ break;
30990+ case SCST_PROC_ACTION_DUMP_PRS:
30991+ {
30992+ struct scst_device *dev;
30993+
30994+ while (isspace(*p) && *p != '\0')
30995+ p++;
30996+ e = p;
30997+ while (!isspace(*e) && *e != '\0')
30998+ e++;
30999+ *e = '\0';
31000+
31001+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
31002+ res = -EINTR;
31003+ goto out_free;
31004+ }
31005+
31006+ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
31007+ if (strcmp(dev->virt_name, p) == 0) {
31008+ scst_pr_dump_prs(dev, true);
31009+ goto out_up;
31010+ }
31011+ }
31012+
31013+ PRINT_ERROR("Device %s not found", p);
31014+ res = -ENOENT;
31015+out_up:
31016+ mutex_unlock(&scst_mutex);
31017+ goto out_free;
31018+ }
31019+ }
31020+
31021+ oldlevel = *log_level;
31022+
31023+ switch (action) {
31024+ case SCST_PROC_ACTION_ADD:
31025+ *log_level |= level;
31026+ break;
31027+ case SCST_PROC_ACTION_DEL:
31028+ *log_level &= ~level;
31029+ break;
31030+ default:
31031+ *log_level = level;
31032+ break;
31033+ }
31034+
31035+ PRINT_INFO("Changed trace level for \"%s\": "
31036+ "old 0x%08lx, new 0x%08lx",
31037+ (char *)data, oldlevel, *log_level);
31038+
31039+out_free:
31040+ free_page((unsigned long)buffer);
31041+out:
31042+ TRACE_EXIT_RES(res);
31043+ return res;
31044+}
31045+EXPORT_SYMBOL_GPL(scst_proc_log_entry_write);
31046+
31047+static ssize_t scst_proc_scsi_tgt_gen_write_log(struct file *file,
31048+ const char __user *buf,
31049+ size_t length, loff_t *off)
31050+{
31051+ int res;
31052+
31053+ TRACE_ENTRY();
31054+
31055+ if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
31056+ res = -EINTR;
31057+ goto out;
31058+ }
31059+
31060+ res = scst_proc_log_entry_write(file, buf, length,
31061+ &trace_flag, SCST_DEFAULT_LOG_FLAGS,
31062+ scst_proc_local_trace_tbl);
31063+
31064+ mutex_unlock(&scst_log_mutex);
31065+
31066+out:
31067+ TRACE_EXIT_RES(res);
31068+ return res;
31069+}
31070+
31071+#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
31072+
31073+#ifdef CONFIG_SCST_MEASURE_LATENCY
31074+
31075+static char *scst_io_size_names[] = {
31076+ "<=8K ",
31077+ "<=32K ",
31078+ "<=128K",
31079+ "<=512K",
31080+ ">512K "
31081+};
31082+
31083+static int lat_info_show(struct seq_file *seq, void *v)
31084+{
31085+ int res = 0;
31086+ struct scst_acg *acg;
31087+ struct scst_session *sess;
31088+ char buf[50];
31089+
31090+ TRACE_ENTRY();
31091+
31092+ BUILD_BUG_ON(SCST_LATENCY_STATS_NUM != ARRAY_SIZE(scst_io_size_names));
31093+ BUILD_BUG_ON(SCST_LATENCY_STATS_NUM != ARRAY_SIZE(sess->sess_latency_stat));
31094+
31095+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
31096+ res = -EINTR;
31097+ goto out;
31098+ }
31099+
31100+ list_for_each_entry(acg, &scst_acg_list, acg_list_entry) {
31101+ bool header_printed = false;
31102+
31103+ list_for_each_entry(sess, &acg->acg_sess_list,
31104+ acg_sess_list_entry) {
31105+ unsigned int i;
31106+ int t;
31107+ uint64_t scst_time, tgt_time, dev_time;
31108+ unsigned int processed_cmds;
31109+
31110+ if (!header_printed) {
31111+ seq_printf(seq, "%-15s %-15s %-46s %-46s %-46s\n",
31112+ "T-L names", "Total commands", "SCST latency",
31113+ "Target latency", "Dev latency (min/avg/max/all ns)");
31114+ header_printed = true;
31115+ }
31116+
31117+ seq_printf(seq, "Target name: %s\nInitiator name: %s\n",
31118+ sess->tgt->tgtt->name,
31119+ sess->initiator_name);
31120+
31121+ spin_lock_bh(&sess->lat_lock);
31122+
31123+ for (i = 0; i < SCST_LATENCY_STATS_NUM ; i++) {
31124+ uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
31125+ unsigned int processed_cmds_wr;
31126+ uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
31127+ unsigned int processed_cmds_rd;
31128+ struct scst_ext_latency_stat *latency_stat;
31129+
31130+ latency_stat = &sess->sess_latency_stat[i];
31131+ scst_time_wr = latency_stat->scst_time_wr;
31132+ scst_time_rd = latency_stat->scst_time_rd;
31133+ tgt_time_wr = latency_stat->tgt_time_wr;
31134+ tgt_time_rd = latency_stat->tgt_time_rd;
31135+ dev_time_wr = latency_stat->dev_time_wr;
31136+ dev_time_rd = latency_stat->dev_time_rd;
31137+ processed_cmds_wr = latency_stat->processed_cmds_wr;
31138+ processed_cmds_rd = latency_stat->processed_cmds_rd;
31139+
31140+ seq_printf(seq, "%-5s %-9s %-15lu ",
31141+ "Write", scst_io_size_names[i],
31142+ (unsigned long)processed_cmds_wr);
31143+ if (processed_cmds_wr == 0)
31144+ processed_cmds_wr = 1;
31145+
31146+ do_div(scst_time_wr, processed_cmds_wr);
31147+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31148+ (unsigned long)latency_stat->min_scst_time_wr,
31149+ (unsigned long)scst_time_wr,
31150+ (unsigned long)latency_stat->max_scst_time_wr,
31151+ (unsigned long)latency_stat->scst_time_wr);
31152+ seq_printf(seq, "%-47s", buf);
31153+
31154+ do_div(tgt_time_wr, processed_cmds_wr);
31155+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31156+ (unsigned long)latency_stat->min_tgt_time_wr,
31157+ (unsigned long)tgt_time_wr,
31158+ (unsigned long)latency_stat->max_tgt_time_wr,
31159+ (unsigned long)latency_stat->tgt_time_wr);
31160+ seq_printf(seq, "%-47s", buf);
31161+
31162+ do_div(dev_time_wr, processed_cmds_wr);
31163+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31164+ (unsigned long)latency_stat->min_dev_time_wr,
31165+ (unsigned long)dev_time_wr,
31166+ (unsigned long)latency_stat->max_dev_time_wr,
31167+ (unsigned long)latency_stat->dev_time_wr);
31168+ seq_printf(seq, "%-47s\n", buf);
31169+
31170+ seq_printf(seq, "%-5s %-9s %-15lu ",
31171+ "Read", scst_io_size_names[i],
31172+ (unsigned long)processed_cmds_rd);
31173+ if (processed_cmds_rd == 0)
31174+ processed_cmds_rd = 1;
31175+
31176+ do_div(scst_time_rd, processed_cmds_rd);
31177+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31178+ (unsigned long)latency_stat->min_scst_time_rd,
31179+ (unsigned long)scst_time_rd,
31180+ (unsigned long)latency_stat->max_scst_time_rd,
31181+ (unsigned long)latency_stat->scst_time_rd);
31182+ seq_printf(seq, "%-47s", buf);
31183+
31184+ do_div(tgt_time_rd, processed_cmds_rd);
31185+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31186+ (unsigned long)latency_stat->min_tgt_time_rd,
31187+ (unsigned long)tgt_time_rd,
31188+ (unsigned long)latency_stat->max_tgt_time_rd,
31189+ (unsigned long)latency_stat->tgt_time_rd);
31190+ seq_printf(seq, "%-47s", buf);
31191+
31192+ do_div(dev_time_rd, processed_cmds_rd);
31193+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31194+ (unsigned long)latency_stat->min_dev_time_rd,
31195+ (unsigned long)dev_time_rd,
31196+ (unsigned long)latency_stat->max_dev_time_rd,
31197+ (unsigned long)latency_stat->dev_time_rd);
31198+ seq_printf(seq, "%-47s\n", buf);
31199+ }
31200+
31201+ for (t = TGT_DEV_HASH_SIZE-1; t >= 0; t--) {
31202+ struct list_head *sess_tgt_dev_list_head =
31203+ &sess->sess_tgt_dev_list_hash[t];
31204+ struct scst_tgt_dev *tgt_dev;
31205+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
31206+ sess_tgt_dev_list_entry) {
31207+
31208+ seq_printf(seq, "\nLUN: %llu\n", tgt_dev->lun);
31209+
31210+ for (i = 0; i < SCST_LATENCY_STATS_NUM ; i++) {
31211+ uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
31212+ unsigned int processed_cmds_wr;
31213+ uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
31214+ unsigned int processed_cmds_rd;
31215+ struct scst_ext_latency_stat *latency_stat;
31216+
31217+ latency_stat = &tgt_dev->dev_latency_stat[i];
31218+ scst_time_wr = latency_stat->scst_time_wr;
31219+ scst_time_rd = latency_stat->scst_time_rd;
31220+ tgt_time_wr = latency_stat->tgt_time_wr;
31221+ tgt_time_rd = latency_stat->tgt_time_rd;
31222+ dev_time_wr = latency_stat->dev_time_wr;
31223+ dev_time_rd = latency_stat->dev_time_rd;
31224+ processed_cmds_wr = latency_stat->processed_cmds_wr;
31225+ processed_cmds_rd = latency_stat->processed_cmds_rd;
31226+
31227+ seq_printf(seq, "%-5s %-9s %-15lu ",
31228+ "Write", scst_io_size_names[i],
31229+ (unsigned long)processed_cmds_wr);
31230+ if (processed_cmds_wr == 0)
31231+ processed_cmds_wr = 1;
31232+
31233+ do_div(scst_time_wr, processed_cmds_wr);
31234+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31235+ (unsigned long)latency_stat->min_scst_time_wr,
31236+ (unsigned long)scst_time_wr,
31237+ (unsigned long)latency_stat->max_scst_time_wr,
31238+ (unsigned long)latency_stat->scst_time_wr);
31239+ seq_printf(seq, "%-47s", buf);
31240+
31241+ do_div(tgt_time_wr, processed_cmds_wr);
31242+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31243+ (unsigned long)latency_stat->min_tgt_time_wr,
31244+ (unsigned long)tgt_time_wr,
31245+ (unsigned long)latency_stat->max_tgt_time_wr,
31246+ (unsigned long)latency_stat->tgt_time_wr);
31247+ seq_printf(seq, "%-47s", buf);
31248+
31249+ do_div(dev_time_wr, processed_cmds_wr);
31250+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31251+ (unsigned long)latency_stat->min_dev_time_wr,
31252+ (unsigned long)dev_time_wr,
31253+ (unsigned long)latency_stat->max_dev_time_wr,
31254+ (unsigned long)latency_stat->dev_time_wr);
31255+ seq_printf(seq, "%-47s\n", buf);
31256+
31257+ seq_printf(seq, "%-5s %-9s %-15lu ",
31258+ "Read", scst_io_size_names[i],
31259+ (unsigned long)processed_cmds_rd);
31260+ if (processed_cmds_rd == 0)
31261+ processed_cmds_rd = 1;
31262+
31263+ do_div(scst_time_rd, processed_cmds_rd);
31264+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31265+ (unsigned long)latency_stat->min_scst_time_rd,
31266+ (unsigned long)scst_time_rd,
31267+ (unsigned long)latency_stat->max_scst_time_rd,
31268+ (unsigned long)latency_stat->scst_time_rd);
31269+ seq_printf(seq, "%-47s", buf);
31270+
31271+ do_div(tgt_time_rd, processed_cmds_rd);
31272+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31273+ (unsigned long)latency_stat->min_tgt_time_rd,
31274+ (unsigned long)tgt_time_rd,
31275+ (unsigned long)latency_stat->max_tgt_time_rd,
31276+ (unsigned long)latency_stat->tgt_time_rd);
31277+ seq_printf(seq, "%-47s", buf);
31278+
31279+ do_div(dev_time_rd, processed_cmds_rd);
31280+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31281+ (unsigned long)latency_stat->min_dev_time_rd,
31282+ (unsigned long)dev_time_rd,
31283+ (unsigned long)latency_stat->max_dev_time_rd,
31284+ (unsigned long)latency_stat->dev_time_rd);
31285+ seq_printf(seq, "%-47s\n", buf);
31286+ }
31287+ }
31288+ }
31289+
31290+ scst_time = sess->scst_time;
31291+ tgt_time = sess->tgt_time;
31292+ dev_time = sess->dev_time;
31293+ processed_cmds = sess->processed_cmds;
31294+
31295+ seq_printf(seq, "\n%-15s %-16d", "Overall ",
31296+ processed_cmds);
31297+
31298+ if (processed_cmds == 0)
31299+ processed_cmds = 1;
31300+
31301+ do_div(scst_time, processed_cmds);
31302+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31303+ (unsigned long)sess->min_scst_time,
31304+ (unsigned long)scst_time,
31305+ (unsigned long)sess->max_scst_time,
31306+ (unsigned long)sess->scst_time);
31307+ seq_printf(seq, "%-47s", buf);
31308+
31309+ do_div(tgt_time, processed_cmds);
31310+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31311+ (unsigned long)sess->min_tgt_time,
31312+ (unsigned long)tgt_time,
31313+ (unsigned long)sess->max_tgt_time,
31314+ (unsigned long)sess->tgt_time);
31315+ seq_printf(seq, "%-47s", buf);
31316+
31317+ do_div(dev_time, processed_cmds);
31318+ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
31319+ (unsigned long)sess->min_dev_time,
31320+ (unsigned long)dev_time,
31321+ (unsigned long)sess->max_dev_time,
31322+ (unsigned long)sess->dev_time);
31323+ seq_printf(seq, "%-47s\n\n", buf);
31324+
31325+ spin_unlock_bh(&sess->lat_lock);
31326+ }
31327+ }
31328+
31329+ mutex_unlock(&scst_mutex);
31330+
31331+out:
31332+ TRACE_EXIT_RES(res);
31333+ return res;
31334+}
31335+
31336+static ssize_t scst_proc_scsi_tgt_gen_write_lat(struct file *file,
31337+ const char __user *buf,
31338+ size_t length, loff_t *off)
31339+{
31340+ int res = length, t;
31341+ struct scst_acg *acg;
31342+ struct scst_session *sess;
31343+
31344+ TRACE_ENTRY();
31345+
31346+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
31347+ res = -EINTR;
31348+ goto out;
31349+ }
31350+
31351+ list_for_each_entry(acg, &scst_acg_list, acg_list_entry) {
31352+ list_for_each_entry(sess, &acg->acg_sess_list,
31353+ acg_sess_list_entry) {
31354+ PRINT_INFO("Zeroing latency statistics for initiator "
31355+ "%s", sess->initiator_name);
31356+ spin_lock_bh(&sess->lat_lock);
31357+
31358+ sess->scst_time = 0;
31359+ sess->tgt_time = 0;
31360+ sess->dev_time = 0;
31361+ sess->min_scst_time = 0;
31362+ sess->min_tgt_time = 0;
31363+ sess->min_dev_time = 0;
31364+ sess->max_scst_time = 0;
31365+ sess->max_tgt_time = 0;
31366+ sess->max_dev_time = 0;
31367+ sess->processed_cmds = 0;
31368+ memset(sess->sess_latency_stat, 0,
31369+ sizeof(sess->sess_latency_stat));
31370+
31371+ for (t = TGT_DEV_HASH_SIZE-1; t >= 0; t--) {
31372+ struct list_head *sess_tgt_dev_list_head =
31373+ &sess->sess_tgt_dev_list_hash[t];
31374+ struct scst_tgt_dev *tgt_dev;
31375+ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
31376+ sess_tgt_dev_list_entry) {
31377+ tgt_dev->scst_time = 0;
31378+ tgt_dev->tgt_time = 0;
31379+ tgt_dev->dev_time = 0;
31380+ tgt_dev->processed_cmds = 0;
31381+ memset(tgt_dev->dev_latency_stat, 0,
31382+ sizeof(tgt_dev->dev_latency_stat));
31383+ }
31384+ }
31385+
31386+ spin_unlock_bh(&sess->lat_lock);
31387+ }
31388+ }
31389+
31390+ mutex_unlock(&scst_mutex);
31391+
31392+out:
31393+ TRACE_EXIT_RES(res);
31394+ return res;
31395+}
31396+
31397+static struct scst_proc_data scst_lat_proc_data = {
31398+ SCST_DEF_RW_SEQ_OP(scst_proc_scsi_tgt_gen_write_lat)
31399+ .show = lat_info_show,
31400+ .data = "scsi_tgt",
31401+};
31402+
31403+#endif /* CONFIG_SCST_MEASURE_LATENCY */
31404+
31405+static int __init scst_proc_init_module_log(void)
31406+{
31407+ int res = 0;
31408+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) || \
31409+ defined(CONFIG_SCST_MEASURE_LATENCY)
31410+ struct proc_dir_entry *generic;
31411+#endif
31412+
31413+ TRACE_ENTRY();
31414+
31415+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
31416+ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
31417+ SCST_PROC_LOG_ENTRY_NAME,
31418+ &scst_log_proc_data);
31419+ if (!generic) {
31420+ PRINT_ERROR("cannot init /proc/%s/%s",
31421+ SCST_PROC_ENTRY_NAME, SCST_PROC_LOG_ENTRY_NAME);
31422+ res = -ENOMEM;
31423+ }
31424+#endif
31425+
31426+#ifdef CONFIG_SCST_MEASURE_LATENCY
31427+ if (res == 0) {
31428+ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
31429+ SCST_PROC_LAT_ENTRY_NAME,
31430+ &scst_lat_proc_data);
31431+ if (!generic) {
31432+ PRINT_ERROR("cannot init /proc/%s/%s",
31433+ SCST_PROC_ENTRY_NAME,
31434+ SCST_PROC_LAT_ENTRY_NAME);
31435+ res = -ENOMEM;
31436+ }
31437+ }
31438+#endif
31439+
31440+ TRACE_EXIT_RES(res);
31441+ return res;
31442+}
31443+
31444+static void scst_proc_cleanup_module_log(void)
31445+{
31446+ TRACE_ENTRY();
31447+
31448+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
31449+ remove_proc_entry(SCST_PROC_LOG_ENTRY_NAME, scst_proc_scsi_tgt);
31450+#endif
31451+
31452+#ifdef CONFIG_SCST_MEASURE_LATENCY
31453+ remove_proc_entry(SCST_PROC_LAT_ENTRY_NAME, scst_proc_scsi_tgt);
31454+#endif
31455+
31456+ TRACE_EXIT();
31457+ return;
31458+}
31459+
31460+static int scst_proc_group_add_tree(struct scst_acg *acg, const char *name)
31461+{
31462+ int res = 0;
31463+ struct proc_dir_entry *generic;
31464+
31465+ TRACE_ENTRY();
31466+
31467+ acg->acg_proc_root = proc_mkdir(name, scst_proc_groups_root);
31468+ if (acg->acg_proc_root == NULL) {
31469+ PRINT_ERROR("Not enough memory to register %s entry in "
31470+ "/proc/%s/%s", name, SCST_PROC_ENTRY_NAME,
31471+ SCST_PROC_GROUPS_ENTRY_NAME);
31472+ goto out;
31473+ }
31474+
31475+ scst_groups_addr_method_proc_data.data = acg;
31476+ generic = scst_create_proc_entry(acg->acg_proc_root,
31477+ SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME,
31478+ &scst_groups_addr_method_proc_data);
31479+ if (!generic) {
31480+ PRINT_ERROR("Cannot init /proc/%s/%s/%s/%s",
31481+ SCST_PROC_ENTRY_NAME,
31482+ SCST_PROC_GROUPS_ENTRY_NAME,
31483+ name, SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME);
31484+ res = -ENOMEM;
31485+ goto out_remove;
31486+ }
31487+
31488+ scst_groups_devices_proc_data.data = acg;
31489+ generic = scst_create_proc_entry(acg->acg_proc_root,
31490+ SCST_PROC_GROUPS_DEVICES_ENTRY_NAME,
31491+ &scst_groups_devices_proc_data);
31492+ if (!generic) {
31493+ PRINT_ERROR("Cannot init /proc/%s/%s/%s/%s",
31494+ SCST_PROC_ENTRY_NAME,
31495+ SCST_PROC_GROUPS_ENTRY_NAME,
31496+ name, SCST_PROC_GROUPS_DEVICES_ENTRY_NAME);
31497+ res = -ENOMEM;
31498+ goto out_remove0;
31499+ }
31500+
31501+ scst_groups_names_proc_data.data = acg;
31502+ generic = scst_create_proc_entry(acg->acg_proc_root,
31503+ SCST_PROC_GROUPS_USERS_ENTRY_NAME,
31504+ &scst_groups_names_proc_data);
31505+ if (!generic) {
31506+ PRINT_ERROR("Cannot init /proc/%s/%s/%s/%s",
31507+ SCST_PROC_ENTRY_NAME,
31508+ SCST_PROC_GROUPS_ENTRY_NAME,
31509+ name, SCST_PROC_GROUPS_USERS_ENTRY_NAME);
31510+ res = -ENOMEM;
31511+ goto out_remove1;
31512+ }
31513+
31514+out:
31515+ TRACE_EXIT_RES(res);
31516+ return res;
31517+
31518+out_remove1:
31519+ remove_proc_entry(SCST_PROC_GROUPS_DEVICES_ENTRY_NAME,
31520+ acg->acg_proc_root);
31521+
31522+out_remove0:
31523+ remove_proc_entry(SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME,
31524+ acg->acg_proc_root);
31525+out_remove:
31526+ remove_proc_entry(name, scst_proc_groups_root);
31527+ goto out;
31528+}
31529+
31530+static void scst_proc_del_acg_tree(struct proc_dir_entry *acg_proc_root,
31531+ const char *name)
31532+{
31533+ TRACE_ENTRY();
31534+
31535+ remove_proc_entry(SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME, acg_proc_root);
31536+ remove_proc_entry(SCST_PROC_GROUPS_USERS_ENTRY_NAME, acg_proc_root);
31537+ remove_proc_entry(SCST_PROC_GROUPS_DEVICES_ENTRY_NAME, acg_proc_root);
31538+ remove_proc_entry(name, scst_proc_groups_root);
31539+
31540+ TRACE_EXIT();
31541+ return;
31542+}
31543+
31544+/* The activity supposed to be suspended and scst_mutex held */
31545+static int scst_proc_group_add(const char *p, unsigned int addr_method)
31546+{
31547+ int res = 0, len = strlen(p) + 1;
31548+ struct scst_acg *acg;
31549+ char *name = NULL;
31550+
31551+ TRACE_ENTRY();
31552+
31553+ name = kmalloc(len, GFP_KERNEL);
31554+ if (name == NULL) {
31555+ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of name failed");
31556+ goto out_nomem;
31557+ }
31558+ strlcpy(name, p, len);
31559+
31560+ acg = scst_alloc_add_acg(NULL, name, false);
31561+ if (acg == NULL) {
31562+ PRINT_ERROR("scst_alloc_add_acg() (name %s) failed", name);
31563+ goto out_free;
31564+ }
31565+
31566+ acg->addr_method = addr_method;
31567+
31568+ res = scst_proc_group_add_tree(acg, p);
31569+ if (res != 0)
31570+ goto out_free_acg;
31571+
31572+out:
31573+ TRACE_EXIT_RES(res);
31574+ return res;
31575+
31576+out_free_acg:
31577+ scst_proc_del_free_acg(acg, 0);
31578+
31579+out_free:
31580+ kfree(name);
31581+
31582+out_nomem:
31583+ res = -ENOMEM;
31584+ goto out;
31585+}
31586+
31587+/* The activity supposed to be suspended and scst_mutex held */
31588+static int scst_proc_del_free_acg(struct scst_acg *acg, int remove_proc)
31589+{
31590+ struct proc_dir_entry *acg_proc_root = acg->acg_proc_root;
31591+ int res = 0;
31592+
31593+ TRACE_ENTRY();
31594+
31595+ if (acg != scst_default_acg) {
31596+ if (!scst_acg_sess_is_empty(acg)) {
31597+ PRINT_ERROR("%s", "Session is not empty");
31598+ res = -EBUSY;
31599+ goto out;
31600+ }
31601+ if (remove_proc)
31602+ scst_proc_del_acg_tree(acg_proc_root, acg->acg_name);
31603+ scst_del_free_acg(acg);
31604+ }
31605+out:
31606+ TRACE_EXIT_RES(res);
31607+ return res;
31608+}
31609+
31610+/* The activity supposed to be suspended and scst_mutex held */
31611+static int scst_proc_rename_acg(struct scst_acg *acg, const char *new_name)
31612+{
31613+ int res = 0, len = strlen(new_name) + 1;
31614+ char *name;
31615+ struct proc_dir_entry *old_acg_proc_root = acg->acg_proc_root;
31616+
31617+ TRACE_ENTRY();
31618+
31619+ name = kmalloc(len, GFP_KERNEL);
31620+ if (name == NULL) {
31621+ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of new name failed");
31622+ goto out_nomem;
31623+ }
31624+ strlcpy(name, new_name, len);
31625+
31626+ res = scst_proc_group_add_tree(acg, new_name);
31627+ if (res != 0)
31628+ goto out_free;
31629+
31630+ scst_proc_del_acg_tree(old_acg_proc_root, acg->acg_name);
31631+
31632+ kfree(acg->acg_name);
31633+ acg->acg_name = name;
31634+
31635+ scst_check_reassign_sessions();
31636+
31637+out:
31638+ TRACE_EXIT_RES(res);
31639+ return res;
31640+
31641+out_free:
31642+ kfree(name);
31643+
31644+out_nomem:
31645+ res = -ENOMEM;
31646+ goto out;
31647+}
31648+
31649+static int __init scst_proc_init_groups(void)
31650+{
31651+ int res = 0;
31652+
31653+ TRACE_ENTRY();
31654+
31655+ /* create the proc directory entry for the device */
31656+ scst_proc_groups_root = proc_mkdir(SCST_PROC_GROUPS_ENTRY_NAME,
31657+ scst_proc_scsi_tgt);
31658+ if (scst_proc_groups_root == NULL) {
31659+ PRINT_ERROR("Not enough memory to register %s entry in "
31660+ "/proc/%s", SCST_PROC_GROUPS_ENTRY_NAME,
31661+ SCST_PROC_ENTRY_NAME);
31662+ goto out_nomem;
31663+ }
31664+
31665+ res = scst_proc_group_add_tree(scst_default_acg,
31666+ SCST_DEFAULT_ACG_NAME);
31667+ if (res != 0)
31668+ goto out_remove;
31669+
31670+out:
31671+ TRACE_EXIT_RES(res);
31672+ return res;
31673+
31674+out_remove:
31675+ remove_proc_entry(SCST_PROC_GROUPS_ENTRY_NAME, scst_proc_scsi_tgt);
31676+
31677+out_nomem:
31678+ res = -ENOMEM;
31679+ goto out;
31680+}
31681+
31682+static void scst_proc_cleanup_groups(void)
31683+{
31684+ struct scst_acg *acg_tmp, *acg;
31685+
31686+ TRACE_ENTRY();
31687+
31688+ /* remove all groups (dir & entries) */
31689+ list_for_each_entry_safe(acg, acg_tmp, &scst_acg_list,
31690+ acg_list_entry) {
31691+ scst_proc_del_free_acg(acg, 1);
31692+ }
31693+
31694+ scst_proc_del_acg_tree(scst_default_acg->acg_proc_root,
31695+ SCST_DEFAULT_ACG_NAME);
31696+ TRACE_DBG("remove_proc_entry(%s, %p)",
31697+ SCST_PROC_GROUPS_ENTRY_NAME, scst_proc_scsi_tgt);
31698+ remove_proc_entry(SCST_PROC_GROUPS_ENTRY_NAME, scst_proc_scsi_tgt);
31699+
31700+ TRACE_EXIT();
31701+}
31702+
31703+static int __init scst_proc_init_sgv(void)
31704+{
31705+ int res = 0;
31706+ struct proc_dir_entry *pr;
31707+
31708+ TRACE_ENTRY();
31709+
31710+ pr = scst_create_proc_entry(scst_proc_scsi_tgt, "sgv",
31711+ &scst_sgv_proc_data);
31712+ if (pr == NULL) {
31713+ PRINT_ERROR("%s", "cannot create sgv /proc entry");
31714+ res = -ENOMEM;
31715+ }
31716+
31717+ TRACE_EXIT_RES(res);
31718+ return res;
31719+}
31720+
31721+static void __exit scst_proc_cleanup_sgv(void)
31722+{
31723+ TRACE_ENTRY();
31724+ remove_proc_entry("sgv", scst_proc_scsi_tgt);
31725+ TRACE_EXIT();
31726+}
31727+
31728+int __init scst_proc_init_module(void)
31729+{
31730+ int res = 0;
31731+ struct proc_dir_entry *generic;
31732+
31733+ TRACE_ENTRY();
31734+
31735+ scst_proc_scsi_tgt = proc_mkdir(SCST_PROC_ENTRY_NAME, NULL);
31736+ if (!scst_proc_scsi_tgt) {
31737+ PRINT_ERROR("cannot init /proc/%s", SCST_PROC_ENTRY_NAME);
31738+ goto out_nomem;
31739+ }
31740+
31741+ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
31742+ SCST_PROC_ENTRY_NAME,
31743+ &scst_tgt_proc_data);
31744+ if (!generic) {
31745+ PRINT_ERROR("cannot init /proc/%s/%s",
31746+ SCST_PROC_ENTRY_NAME, SCST_PROC_ENTRY_NAME);
31747+ goto out_remove;
31748+ }
31749+
31750+ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
31751+ SCST_PROC_VERSION_NAME,
31752+ &scst_version_proc_data);
31753+ if (!generic) {
31754+ PRINT_ERROR("cannot init /proc/%s/%s",
31755+ SCST_PROC_ENTRY_NAME, SCST_PROC_VERSION_NAME);
31756+ goto out_remove1;
31757+ }
31758+
31759+ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
31760+ SCST_PROC_SESSIONS_NAME,
31761+ &scst_sessions_proc_data);
31762+ if (!generic) {
31763+ PRINT_ERROR("cannot init /proc/%s/%s",
31764+ SCST_PROC_ENTRY_NAME, SCST_PROC_SESSIONS_NAME);
31765+ goto out_remove2;
31766+ }
31767+
31768+ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
31769+ SCST_PROC_HELP_NAME,
31770+ &scst_help_proc_data);
31771+ if (!generic) {
31772+ PRINT_ERROR("cannot init /proc/%s/%s",
31773+ SCST_PROC_ENTRY_NAME, SCST_PROC_HELP_NAME);
31774+ goto out_remove3;
31775+ }
31776+
31777+ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
31778+ SCST_PROC_THREADS_NAME,
31779+ &scst_threads_proc_data);
31780+ if (!generic) {
31781+ PRINT_ERROR("cannot init /proc/%s/%s",
31782+ SCST_PROC_ENTRY_NAME, SCST_PROC_THREADS_NAME);
31783+ goto out_remove4;
31784+ }
31785+
31786+ if (scst_proc_init_module_log() < 0)
31787+ goto out_remove5;
31788+
31789+ if (scst_proc_init_groups() < 0)
31790+ goto out_remove6;
31791+
31792+ if (scst_proc_init_sgv() < 0)
31793+ goto out_remove7;
31794+
31795+out:
31796+ TRACE_EXIT_RES(res);
31797+ return res;
31798+
31799+out_remove7:
31800+ scst_proc_cleanup_groups();
31801+
31802+out_remove6:
31803+ scst_proc_cleanup_module_log();
31804+
31805+out_remove5:
31806+ remove_proc_entry(SCST_PROC_THREADS_NAME, scst_proc_scsi_tgt);
31807+
31808+out_remove4:
31809+ remove_proc_entry(SCST_PROC_HELP_NAME, scst_proc_scsi_tgt);
31810+
31811+out_remove3:
31812+ remove_proc_entry(SCST_PROC_SESSIONS_NAME, scst_proc_scsi_tgt);
31813+
31814+out_remove2:
31815+ remove_proc_entry(SCST_PROC_VERSION_NAME, scst_proc_scsi_tgt);
31816+
31817+out_remove1:
31818+ remove_proc_entry(SCST_PROC_ENTRY_NAME, scst_proc_scsi_tgt);
31819+
31820+out_remove:
31821+ remove_proc_entry(SCST_PROC_ENTRY_NAME, NULL);
31822+
31823+out_nomem:
31824+ res = -ENOMEM;
31825+ goto out;
31826+}
31827+
31828+void __exit scst_proc_cleanup_module(void)
31829+{
31830+ TRACE_ENTRY();
31831+
31832+ /* We may not bother about locks here */
31833+ scst_proc_cleanup_sgv();
31834+ scst_proc_cleanup_groups();
31835+ scst_proc_cleanup_module_log();
31836+ remove_proc_entry(SCST_PROC_THREADS_NAME, scst_proc_scsi_tgt);
31837+ remove_proc_entry(SCST_PROC_HELP_NAME, scst_proc_scsi_tgt);
31838+ remove_proc_entry(SCST_PROC_SESSIONS_NAME, scst_proc_scsi_tgt);
31839+ remove_proc_entry(SCST_PROC_VERSION_NAME, scst_proc_scsi_tgt);
31840+ remove_proc_entry(SCST_PROC_ENTRY_NAME, scst_proc_scsi_tgt);
31841+ remove_proc_entry(SCST_PROC_ENTRY_NAME, NULL);
31842+
31843+ TRACE_EXIT();
31844+}
31845+
31846+static ssize_t scst_proc_threads_write(struct file *file,
31847+ const char __user *buf,
31848+ size_t length, loff_t *off)
31849+{
31850+ int res = length;
31851+ int oldtn, newtn, delta;
31852+ char *buffer;
31853+
31854+ TRACE_ENTRY();
31855+
31856+ if (length > SCST_PROC_BLOCK_SIZE) {
31857+ res = -EOVERFLOW;
31858+ goto out;
31859+ }
31860+ if (!buf) {
31861+ res = -EINVAL;
31862+ goto out;
31863+ }
31864+ buffer = (char *)__get_free_page(GFP_KERNEL);
31865+ if (!buffer) {
31866+ res = -ENOMEM;
31867+ goto out;
31868+ }
31869+ if (copy_from_user(buffer, buf, length)) {
31870+ res = -EFAULT;
31871+ goto out_free;
31872+ }
31873+ if (length < PAGE_SIZE) {
31874+ buffer[length] = '\0';
31875+ } else if (buffer[PAGE_SIZE-1]) {
31876+ res = -EINVAL;
31877+ goto out_free;
31878+ }
31879+
31880+ if (mutex_lock_interruptible(&scst_proc_mutex) != 0) {
31881+ res = -EINTR;
31882+ goto out_free;
31883+ }
31884+
31885+ mutex_lock(&scst_mutex);
31886+
31887+ oldtn = scst_main_cmd_threads.nr_threads;
31888+ newtn = simple_strtoul(buffer, NULL, 0);
31889+ if (newtn <= 0) {
31890+ PRINT_ERROR("Illegal threads num value %d", newtn);
31891+ res = -EINVAL;
31892+ goto out_up_thr_free;
31893+ }
31894+ delta = newtn - oldtn;
31895+ if (delta < 0)
31896+ scst_del_threads(&scst_main_cmd_threads, -delta);
31897+ else {
31898+ int rc = scst_add_threads(&scst_main_cmd_threads, NULL, NULL,
31899+ delta);
31900+ if (rc != 0)
31901+ res = rc;
31902+ }
31903+
31904+ PRINT_INFO("Changed cmd threads num: old %d, new %d", oldtn, newtn);
31905+
31906+out_up_thr_free:
31907+ mutex_unlock(&scst_mutex);
31908+
31909+ mutex_unlock(&scst_proc_mutex);
31910+
31911+out_free:
31912+ free_page((unsigned long)buffer);
31913+out:
31914+ TRACE_EXIT_RES(res);
31915+ return res;
31916+}
31917+
31918+int scst_build_proc_target_dir_entries(struct scst_tgt_template *vtt)
31919+{
31920+ int res = 0;
31921+
31922+ TRACE_ENTRY();
31923+
31924+ /* create the proc directory entry for the device */
31925+ vtt->proc_tgt_root = proc_mkdir(vtt->name, scst_proc_scsi_tgt);
31926+ if (vtt->proc_tgt_root == NULL) {
31927+ PRINT_ERROR("Not enough memory to register SCSI target %s "
31928+ "in /proc/%s", vtt->name, SCST_PROC_ENTRY_NAME);
31929+ goto out_nomem;
31930+ }
31931+
31932+out:
31933+ TRACE_EXIT_RES(res);
31934+ return res;
31935+
31936+out_nomem:
31937+ res = -ENOMEM;
31938+ goto out;
31939+}
31940+
31941+void scst_cleanup_proc_target_dir_entries(struct scst_tgt_template *vtt)
31942+{
31943+ TRACE_ENTRY();
31944+
31945+ remove_proc_entry(vtt->name, scst_proc_scsi_tgt);
31946+
31947+ TRACE_EXIT();
31948+ return;
31949+}
31950+
31951+/* Called under scst_mutex */
31952+int scst_build_proc_target_entries(struct scst_tgt *vtt)
31953+{
31954+ int res = 0;
31955+ struct proc_dir_entry *p;
31956+ char name[20];
31957+
31958+ TRACE_ENTRY();
31959+
31960+ if (vtt->tgtt->read_proc || vtt->tgtt->write_proc) {
31961+ /* create the proc file entry for the device */
31962+ scnprintf(name, sizeof(name), "%d", vtt->tgtt->proc_dev_num);
31963+ scst_scsi_tgt_proc_data.data = (void *)vtt;
31964+ p = scst_create_proc_entry(vtt->tgtt->proc_tgt_root,
31965+ name,
31966+ &scst_scsi_tgt_proc_data);
31967+ if (p == NULL) {
31968+ PRINT_ERROR("Not enough memory to register SCSI "
31969+ "target entry %s in /proc/%s/%s", name,
31970+ SCST_PROC_ENTRY_NAME, vtt->tgtt->name);
31971+ res = -ENOMEM;
31972+ goto out;
31973+ }
31974+ vtt->proc_num = vtt->tgtt->proc_dev_num;
31975+ vtt->tgtt->proc_dev_num++;
31976+ }
31977+
31978+out:
31979+ TRACE_EXIT_RES(res);
31980+ return res;
31981+}
31982+
31983+void scst_cleanup_proc_target_entries(struct scst_tgt *vtt)
31984+{
31985+ char name[20];
31986+
31987+ TRACE_ENTRY();
31988+
31989+ if (vtt->tgtt->read_proc || vtt->tgtt->write_proc) {
31990+ scnprintf(name, sizeof(name), "%d", vtt->proc_num);
31991+ remove_proc_entry(name, vtt->tgtt->proc_tgt_root);
31992+ }
31993+
31994+ TRACE_EXIT();
31995+ return;
31996+}
31997+
31998+static ssize_t scst_proc_scsi_tgt_write(struct file *file,
31999+ const char __user *buf,
32000+ size_t length, loff_t *off)
32001+{
32002+ struct scst_tgt *vtt =
32003+ (struct scst_tgt *)PDE(file->f_dentry->d_inode)->data;
32004+ ssize_t res = 0;
32005+ char *buffer;
32006+ char *start;
32007+ int eof = 0;
32008+
32009+ TRACE_ENTRY();
32010+
32011+ if (vtt->tgtt->write_proc == NULL) {
32012+ res = -ENOSYS;
32013+ goto out;
32014+ }
32015+
32016+ if (length > SCST_PROC_BLOCK_SIZE) {
32017+ res = -EOVERFLOW;
32018+ goto out;
32019+ }
32020+ if (!buf) {
32021+ res = -EINVAL;
32022+ goto out;
32023+ }
32024+ buffer = (char *)__get_free_page(GFP_KERNEL);
32025+ if (!buffer) {
32026+ res = -ENOMEM;
32027+ goto out;
32028+ }
32029+ if (copy_from_user(buffer, buf, length)) {
32030+ res = -EFAULT;
32031+ goto out_free;
32032+ }
32033+ if (length < PAGE_SIZE) {
32034+ buffer[length] = '\0';
32035+ } else if (buffer[PAGE_SIZE-1]) {
32036+ res = -EINVAL;
32037+ goto out_free;
32038+ }
32039+
32040+ TRACE_BUFFER("Buffer", buffer, length);
32041+
32042+ if (mutex_lock_interruptible(&scst_proc_mutex) != 0) {
32043+ res = -EINTR;
32044+ goto out_free;
32045+ }
32046+
32047+ res = vtt->tgtt->write_proc(buffer, &start, 0, length, &eof, vtt);
32048+
32049+ mutex_unlock(&scst_proc_mutex);
32050+
32051+out_free:
32052+ free_page((unsigned long)buffer);
32053+out:
32054+ TRACE_EXIT_RES(res);
32055+ return res;
32056+}
32057+
32058+int scst_build_proc_dev_handler_dir_entries(struct scst_dev_type *dev_type)
32059+{
32060+ int res = 0;
32061+ struct proc_dir_entry *p;
32062+ const char *name; /* workaround to keep /proc ABI intact */
32063+
32064+ TRACE_ENTRY();
32065+
32066+ BUG_ON(dev_type->proc_dev_type_root);
32067+
32068+ if (strcmp(dev_type->name, "vdisk_fileio") == 0)
32069+ name = "vdisk";
32070+ else
32071+ name = dev_type->name;
32072+
32073+ /* create the proc directory entry for the dev type handler */
32074+ dev_type->proc_dev_type_root = proc_mkdir(name,
32075+ scst_proc_scsi_tgt);
32076+ if (dev_type->proc_dev_type_root == NULL) {
32077+ PRINT_ERROR("Not enough memory to register dev handler dir "
32078+ "%s in /proc/%s", name, SCST_PROC_ENTRY_NAME);
32079+ goto out_nomem;
32080+ }
32081+
32082+ scst_dev_handler_type_proc_data.data = dev_type;
32083+ if (dev_type->type >= 0) {
32084+ p = scst_create_proc_entry(dev_type->proc_dev_type_root,
32085+ SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME,
32086+ &scst_dev_handler_type_proc_data);
32087+ if (p == NULL) {
32088+ PRINT_ERROR("Not enough memory to register dev "
32089+ "handler entry %s in /proc/%s/%s",
32090+ SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME,
32091+ SCST_PROC_ENTRY_NAME, name);
32092+ goto out_remove;
32093+ }
32094+ }
32095+
32096+ if (dev_type->read_proc || dev_type->write_proc) {
32097+ /* create the proc file entry for the dev type handler */
32098+ scst_dev_handler_proc_data.data = (void *)dev_type;
32099+ p = scst_create_proc_entry(dev_type->proc_dev_type_root,
32100+ name,
32101+ &scst_dev_handler_proc_data);
32102+ if (p == NULL) {
32103+ PRINT_ERROR("Not enough memory to register dev "
32104+ "handler entry %s in /proc/%s/%s", name,
32105+ SCST_PROC_ENTRY_NAME, name);
32106+ goto out_remove1;
32107+ }
32108+ }
32109+
32110+out:
32111+ TRACE_EXIT_RES(res);
32112+ return res;
32113+
32114+out_remove1:
32115+ if (dev_type->type >= 0)
32116+ remove_proc_entry(SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME,
32117+ dev_type->proc_dev_type_root);
32118+
32119+out_remove:
32120+ remove_proc_entry(name, scst_proc_scsi_tgt);
32121+
32122+out_nomem:
32123+ res = -ENOMEM;
32124+ goto out;
32125+}
32126+
32127+void scst_cleanup_proc_dev_handler_dir_entries(struct scst_dev_type *dev_type)
32128+{
32129+ /* Workaround to keep /proc ABI intact */
32130+ const char *name;
32131+
32132+ TRACE_ENTRY();
32133+
32134+ BUG_ON(dev_type->proc_dev_type_root == NULL);
32135+
32136+ if (strcmp(dev_type->name, "vdisk_fileio") == 0)
32137+ name = "vdisk";
32138+ else
32139+ name = dev_type->name;
32140+
32141+ if (dev_type->type >= 0) {
32142+ remove_proc_entry(SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME,
32143+ dev_type->proc_dev_type_root);
32144+ }
32145+ if (dev_type->read_proc || dev_type->write_proc)
32146+ remove_proc_entry(name, dev_type->proc_dev_type_root);
32147+ remove_proc_entry(name, scst_proc_scsi_tgt);
32148+ dev_type->proc_dev_type_root = NULL;
32149+
32150+ TRACE_EXIT();
32151+ return;
32152+}
32153+
32154+static ssize_t scst_proc_scsi_dev_handler_write(struct file *file,
32155+ const char __user *buf,
32156+ size_t length, loff_t *off)
32157+{
32158+ struct scst_dev_type *dev_type =
32159+ (struct scst_dev_type *)PDE(file->f_dentry->d_inode)->data;
32160+ ssize_t res = 0;
32161+ char *buffer;
32162+ char *start;
32163+ int eof = 0;
32164+
32165+ TRACE_ENTRY();
32166+
32167+ if (dev_type->write_proc == NULL) {
32168+ res = -ENOSYS;
32169+ goto out;
32170+ }
32171+
32172+ if (length > SCST_PROC_BLOCK_SIZE) {
32173+ res = -EOVERFLOW;
32174+ goto out;
32175+ }
32176+ if (!buf) {
32177+ res = -EINVAL;
32178+ goto out;
32179+ }
32180+
32181+ buffer = (char *)__get_free_page(GFP_KERNEL);
32182+ if (!buffer) {
32183+ res = -ENOMEM;
32184+ goto out;
32185+ }
32186+
32187+ if (copy_from_user(buffer, buf, length)) {
32188+ res = -EFAULT;
32189+ goto out_free;
32190+ }
32191+ if (length < PAGE_SIZE) {
32192+ buffer[length] = '\0';
32193+ } else if (buffer[PAGE_SIZE-1]) {
32194+ res = -EINVAL;
32195+ goto out_free;
32196+ }
32197+
32198+ TRACE_BUFFER("Buffer", buffer, length);
32199+
32200+ if (mutex_lock_interruptible(&scst_proc_mutex) != 0) {
32201+ res = -EINTR;
32202+ goto out_free;
32203+ }
32204+
32205+ res = dev_type->write_proc(buffer, &start, 0, length, &eof, dev_type);
32206+
32207+ mutex_unlock(&scst_proc_mutex);
32208+
32209+out_free:
32210+ free_page((unsigned long)buffer);
32211+
32212+out:
32213+ TRACE_EXIT_RES(res);
32214+ return res;
32215+}
32216+
32217+static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
32218+ const char __user *buf,
32219+ size_t length, loff_t *off)
32220+{
32221+ int res, rc = 0, action;
32222+ char *buffer, *p, *pp, *ppp;
32223+ struct scst_acg *a, *acg = NULL;
32224+ unsigned int addr_method = SCST_LUN_ADDR_METHOD_PERIPHERAL;
32225+
32226+ TRACE_ENTRY();
32227+
32228+ if (length > SCST_PROC_BLOCK_SIZE) {
32229+ res = -EOVERFLOW;
32230+ goto out;
32231+ }
32232+ if (!buf) {
32233+ res = -EINVAL;
32234+ goto out;
32235+ }
32236+ buffer = (char *)__get_free_page(GFP_KERNEL);
32237+ if (!buffer) {
32238+ res = -ENOMEM;
32239+ goto out;
32240+ }
32241+ if (copy_from_user(buffer, buf, length)) {
32242+ res = -EFAULT;
32243+ goto out_free;
32244+ }
32245+ if (length < PAGE_SIZE) {
32246+ buffer[length] = '\0';
32247+ } else if (buffer[PAGE_SIZE-1]) {
32248+ res = -EINVAL;
32249+ goto out_free;
32250+ }
32251+
32252+ /*
32253+ * Usage: echo "add_group GROUP_NAME [FLAT]" >/proc/scsi_tgt/scsi_tgt
32254+ * or echo "del_group GROUP_NAME" >/proc/scsi_tgt/scsi_tgt
32255+ * or echo "rename_group OLD_NAME NEW_NAME" >/proc/scsi_tgt/scsi_tgt"
32256+ * or echo "assign H:C:I:L HANDLER_NAME" >/proc/scsi_tgt/scsi_tgt
32257+ */
32258+ p = buffer;
32259+ if (p[strlen(p) - 1] == '\n')
32260+ p[strlen(p) - 1] = '\0';
32261+ if (!strncasecmp("assign ", p, 7)) {
32262+ p += 7;
32263+ action = SCST_PROC_ACTION_ASSIGN;
32264+ } else if (!strncasecmp("add_group ", p, 10)) {
32265+ p += 10;
32266+ action = SCST_PROC_ACTION_ADD_GROUP;
32267+ } else if (!strncasecmp("del_group ", p, 10)) {
32268+ p += 10;
32269+ action = SCST_PROC_ACTION_DEL_GROUP;
32270+ } else if (!strncasecmp("rename_group ", p, 13)) {
32271+ p += 13;
32272+ action = SCST_PROC_ACTION_RENAME_GROUP;
32273+ } else {
32274+ PRINT_ERROR("Unknown action \"%s\"", p);
32275+ res = -EINVAL;
32276+ goto out_free;
32277+ }
32278+
32279+ res = scst_suspend_activity(true);
32280+ if (res != 0)
32281+ goto out_free;
32282+
32283+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
32284+ res = -EINTR;
32285+ goto out_free_resume;
32286+ }
32287+
32288+ res = length;
32289+
32290+ while (isspace(*p) && *p != '\0')
32291+ p++;
32292+
32293+ switch (action) {
32294+ case SCST_PROC_ACTION_ADD_GROUP:
32295+ case SCST_PROC_ACTION_DEL_GROUP:
32296+ case SCST_PROC_ACTION_RENAME_GROUP:
32297+ pp = p;
32298+ while (!isspace(*pp) && *pp != '\0')
32299+ pp++;
32300+ if (*pp != '\0') {
32301+ *pp = '\0';
32302+ pp++;
32303+ while (isspace(*pp) && *pp != '\0')
32304+ pp++;
32305+ if (*pp != '\0') {
32306+ switch (action) {
32307+ case SCST_PROC_ACTION_ADD_GROUP:
32308+ ppp = pp;
32309+ while (!isspace(*ppp) && *ppp != '\0')
32310+ ppp++;
32311+ if (*ppp != '\0') {
32312+ *ppp = '\0';
32313+ ppp++;
32314+ while (isspace(*ppp) && *ppp != '\0')
32315+ ppp++;
32316+ if (*ppp != '\0') {
32317+ PRINT_ERROR("%s", "Too many "
32318+ "arguments");
32319+ res = -EINVAL;
32320+ goto out_up_free;
32321+ }
32322+ }
32323+ if (strcasecmp(pp, "FLAT") != 0) {
32324+ PRINT_ERROR("Unexpected "
32325+ "argument %s", pp);
32326+ res = -EINVAL;
32327+ goto out_up_free;
32328+ } else
32329+ addr_method = SCST_LUN_ADDR_METHOD_FLAT;
32330+ break;
32331+ case SCST_PROC_ACTION_DEL_GROUP:
32332+ PRINT_ERROR("%s", "Too many "
32333+ "arguments");
32334+ res = -EINVAL;
32335+ goto out_up_free;
32336+ }
32337+ }
32338+ }
32339+
32340+ if (strcmp(p, SCST_DEFAULT_ACG_NAME) == 0) {
32341+ PRINT_ERROR("Attempt to add/delete/rename predefined "
32342+ "group \"%s\"", p);
32343+ res = -EINVAL;
32344+ goto out_up_free;
32345+ }
32346+
32347+ list_for_each_entry(a, &scst_acg_list, acg_list_entry) {
32348+ if (strcmp(a->acg_name, p) == 0) {
32349+ TRACE_DBG("group (acg) %p %s found",
32350+ a, a->acg_name);
32351+ acg = a;
32352+ break;
32353+ }
32354+ }
32355+
32356+ switch (action) {
32357+ case SCST_PROC_ACTION_ADD_GROUP:
32358+ if (acg) {
32359+ PRINT_ERROR("acg name %s exist", p);
32360+ res = -EINVAL;
32361+ goto out_up_free;
32362+ }
32363+ rc = scst_proc_group_add(p, addr_method);
32364+ break;
32365+ case SCST_PROC_ACTION_DEL_GROUP:
32366+ if (acg == NULL) {
32367+ PRINT_ERROR("acg name %s not found", p);
32368+ res = -EINVAL;
32369+ goto out_up_free;
32370+ }
32371+ rc = scst_proc_del_free_acg(acg, 1);
32372+ break;
32373+ case SCST_PROC_ACTION_RENAME_GROUP:
32374+ if (acg == NULL) {
32375+ PRINT_ERROR("acg name %s not found", p);
32376+ res = -EINVAL;
32377+ goto out_up_free;
32378+ }
32379+
32380+ p = pp;
32381+ while (!isspace(*pp) && *pp != '\0')
32382+ pp++;
32383+ if (*pp != '\0') {
32384+ *pp = '\0';
32385+ pp++;
32386+ while (isspace(*pp) && *pp != '\0')
32387+ pp++;
32388+ if (*pp != '\0') {
32389+ PRINT_ERROR("%s", "Too many arguments");
32390+ res = -EINVAL;
32391+ goto out_up_free;
32392+ }
32393+ }
32394+ rc = scst_proc_rename_acg(acg, p);
32395+ break;
32396+ }
32397+ break;
32398+ case SCST_PROC_ACTION_ASSIGN:
32399+ rc = scst_proc_assign_handler(p);
32400+ break;
32401+ }
32402+
32403+ if (rc != 0)
32404+ res = rc;
32405+
32406+out_up_free:
32407+ mutex_unlock(&scst_mutex);
32408+
32409+out_free_resume:
32410+ scst_resume_activity();
32411+
32412+out_free:
32413+ free_page((unsigned long)buffer);
32414+
32415+out:
32416+ TRACE_EXIT_RES(res);
32417+ return res;
32418+}
32419+
32420+/* The activity supposed to be suspended and scst_mutex held */
32421+static int scst_proc_assign_handler(char *buf)
32422+{
32423+ int res = 0;
32424+ char *p = buf, *e, *ee;
32425+ unsigned long host, channel = 0, id = 0, lun = 0;
32426+ struct scst_device *d, *dev = NULL;
32427+ struct scst_dev_type *dt, *handler = NULL;
32428+
32429+ TRACE_ENTRY();
32430+
32431+ while (isspace(*p) && *p != '\0')
32432+ p++;
32433+
32434+ host = simple_strtoul(p, &p, 0);
32435+ if ((host == ULONG_MAX) || (*p != ':'))
32436+ goto out_synt_err;
32437+ p++;
32438+ channel = simple_strtoul(p, &p, 0);
32439+ if ((channel == ULONG_MAX) || (*p != ':'))
32440+ goto out_synt_err;
32441+ p++;
32442+ id = simple_strtoul(p, &p, 0);
32443+ if ((channel == ULONG_MAX) || (*p != ':'))
32444+ goto out_synt_err;
32445+ p++;
32446+ lun = simple_strtoul(p, &p, 0);
32447+ if (lun == ULONG_MAX)
32448+ goto out_synt_err;
32449+
32450+ e = p;
32451+ e++;
32452+ while (isspace(*e) && *e != '\0')
32453+ e++;
32454+ ee = e;
32455+ while (!isspace(*ee) && *ee != '\0')
32456+ ee++;
32457+ *ee = '\0';
32458+
32459+ TRACE_DBG("Dev %ld:%ld:%ld:%ld, handler %s", host, channel, id, lun, e);
32460+
32461+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
32462+ if ((d->virt_id == 0) &&
32463+ d->scsi_dev->host->host_no == host &&
32464+ d->scsi_dev->channel == channel &&
32465+ d->scsi_dev->id == id &&
32466+ d->scsi_dev->lun == lun) {
32467+ dev = d;
32468+ TRACE_DBG("Dev %p (%ld:%ld:%ld:%ld) found",
32469+ dev, host, channel, id, lun);
32470+ break;
32471+ }
32472+ }
32473+
32474+ if (dev == NULL) {
32475+ PRINT_ERROR("Device %ld:%ld:%ld:%ld not found",
32476+ host, channel, id, lun);
32477+ res = -EINVAL;
32478+ goto out;
32479+ }
32480+
32481+ list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) {
32482+ if (!strcmp(dt->name, e)) {
32483+ handler = dt;
32484+ TRACE_DBG("Dev handler %p with name %s found",
32485+ dt, dt->name);
32486+ break;
32487+ }
32488+ }
32489+
32490+ if (handler == NULL) {
32491+ PRINT_ERROR("Handler %s not found", e);
32492+ res = -EINVAL;
32493+ goto out;
32494+ }
32495+
32496+ if (dev->scsi_dev->type != handler->type) {
32497+ PRINT_ERROR("Type %d of device %s differs from type "
32498+ "%d of dev handler %s", dev->type,
32499+ dev->handler->name, handler->type, handler->name);
32500+ res = -EINVAL;
32501+ goto out;
32502+ }
32503+
32504+ res = scst_assign_dev_handler(dev, handler);
32505+
32506+out:
32507+ TRACE_EXIT_RES(res);
32508+ return res;
32509+
32510+out_synt_err:
32511+ PRINT_ERROR("Syntax error on %s", p);
32512+ res = -EINVAL;
32513+ goto out;
32514+}
32515+
32516+static ssize_t scst_proc_groups_devices_write(struct file *file,
32517+ const char __user *buf,
32518+ size_t length, loff_t *off)
32519+{
32520+ int res, action, rc, read_only = 0;
32521+ char *buffer, *p, *e = NULL;
32522+ unsigned int virt_lun;
32523+ struct scst_acg *acg =
32524+ (struct scst_acg *)PDE(file->f_dentry->d_inode)->data;
32525+ struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
32526+ struct scst_device *d, *dev = NULL;
32527+
32528+ TRACE_ENTRY();
32529+
32530+ if (length > SCST_PROC_BLOCK_SIZE) {
32531+ res = -EOVERFLOW;
32532+ goto out;
32533+ }
32534+ if (!buf) {
32535+ res = -EINVAL;
32536+ goto out;
32537+ }
32538+ buffer = (char *)__get_free_page(GFP_KERNEL);
32539+ if (!buffer) {
32540+ res = -ENOMEM;
32541+ goto out;
32542+ }
32543+ if (copy_from_user(buffer, buf, length)) {
32544+ res = -EFAULT;
32545+ goto out_free;
32546+ }
32547+ if (length < PAGE_SIZE) {
32548+ buffer[length] = '\0';
32549+ } else if (buffer[PAGE_SIZE-1]) {
32550+ res = -EINVAL;
32551+ goto out_free;
32552+ }
32553+
32554+ /*
32555+ * Usage: echo "add|del H:C:I:L lun [READ_ONLY]" \
32556+ * >/proc/scsi_tgt/groups/GROUP_NAME/devices
32557+ * or echo "replace H:C:I:L lun [READ_ONLY]" \
32558+ * >/proc/scsi_tgt/groups/GROUP_NAME/devices
32559+ * or echo "add|del V_NAME lun [READ_ONLY]" \
32560+ * >/proc/scsi_tgt/groups/GROUP_NAME/devices
32561+ * or echo "replace V_NAME lun [READ_ONLY]" \
32562+ * >/proc/scsi_tgt/groups/GROUP_NAME/devices
32563+ * or echo "clear" >/proc/scsi_tgt/groups/GROUP_NAME/devices
32564+ */
32565+ p = buffer;
32566+ if (p[strlen(p) - 1] == '\n')
32567+ p[strlen(p) - 1] = '\0';
32568+ if (!strncasecmp("clear", p, 5)) {
32569+ action = SCST_PROC_ACTION_CLEAR;
32570+ } else if (!strncasecmp("add ", p, 4)) {
32571+ p += 4;
32572+ action = SCST_PROC_ACTION_ADD;
32573+ } else if (!strncasecmp("del ", p, 4)) {
32574+ p += 4;
32575+ action = SCST_PROC_ACTION_DEL;
32576+ } else if (!strncasecmp("replace ", p, 8)) {
32577+ p += 8;
32578+ action = SCST_PROC_ACTION_REPLACE;
32579+ } else {
32580+ PRINT_ERROR("Unknown action \"%s\"", p);
32581+ res = -EINVAL;
32582+ goto out_free;
32583+ }
32584+
32585+ res = scst_suspend_activity(true);
32586+ if (res != 0)
32587+ goto out_free;
32588+
32589+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
32590+ res = -EINTR;
32591+ goto out_free_resume;
32592+ }
32593+
32594+ res = length;
32595+
32596+ switch (action) {
32597+ case SCST_PROC_ACTION_ADD:
32598+ case SCST_PROC_ACTION_DEL:
32599+ case SCST_PROC_ACTION_REPLACE:
32600+ while (isspace(*p) && *p != '\0')
32601+ p++;
32602+ e = p; /* save p */
32603+ while (!isspace(*e) && *e != '\0')
32604+ e++;
32605+ *e = 0;
32606+
32607+ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
32608+ if (!strcmp(d->virt_name, p)) {
32609+ dev = d;
32610+ TRACE_DBG("Device %p (%s) found", dev, p);
32611+ break;
32612+ }
32613+ }
32614+ if (dev == NULL) {
32615+ PRINT_ERROR("Device %s not found", p);
32616+ res = -EINVAL;
32617+ goto out_free_up;
32618+ }
32619+ break;
32620+ }
32621+
32622+ /* ToDo: create separate functions */
32623+
32624+ switch (action) {
32625+ case SCST_PROC_ACTION_ADD:
32626+ case SCST_PROC_ACTION_REPLACE:
32627+ {
32628+ bool dev_replaced = false;
32629+
32630+ e++;
32631+ while (isspace(*e) && *e != '\0')
32632+ e++;
32633+ virt_lun = simple_strtoul(e, &e, 0);
32634+
32635+ while (isspace(*e) && *e != '\0')
32636+ e++;
32637+
32638+ if (*e != '\0') {
32639+ if (!strncasecmp("READ_ONLY", e, 9))
32640+ read_only = 1;
32641+ else {
32642+ PRINT_ERROR("Unknown option \"%s\"", e);
32643+ res = -EINVAL;
32644+ goto out_free_up;
32645+ }
32646+ }
32647+
32648+ list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
32649+ acg_dev_list_entry) {
32650+ if (acg_dev_tmp->lun == virt_lun) {
32651+ acg_dev = acg_dev_tmp;
32652+ break;
32653+ }
32654+ }
32655+ if (acg_dev != NULL) {
32656+ if (action == SCST_PROC_ACTION_ADD) {
32657+ PRINT_ERROR("virt lun %d already exists in "
32658+ "group %s", virt_lun, acg->acg_name);
32659+ res = -EEXIST;
32660+ goto out_free_up;
32661+ } else {
32662+ /* Replace */
32663+ rc = scst_acg_del_lun(acg, acg_dev->lun,
32664+ false);
32665+ if (rc) {
32666+ res = rc;
32667+ goto out_free_up;
32668+ }
32669+ dev_replaced = true;
32670+ }
32671+ }
32672+
32673+ rc = scst_acg_add_lun(acg, NULL, dev, virt_lun, read_only,
32674+ false, NULL);
32675+ if (rc) {
32676+ res = rc;
32677+ goto out_free_up;
32678+ }
32679+
32680+ if (action == SCST_PROC_ACTION_ADD)
32681+ scst_report_luns_changed(acg);
32682+
32683+ if (dev_replaced) {
32684+ struct scst_tgt_dev *tgt_dev;
32685+
32686+ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
32687+ dev_tgt_dev_list_entry) {
32688+ if ((tgt_dev->acg_dev->acg == acg) &&
32689+ (tgt_dev->lun == virt_lun)) {
32690+ TRACE_MGMT_DBG("INQUIRY DATA HAS CHANGED"
32691+ " on tgt_dev %p", tgt_dev);
32692+ scst_gen_aen_or_ua(tgt_dev,
32693+ SCST_LOAD_SENSE(scst_sense_inquery_data_changed));
32694+ }
32695+ }
32696+ }
32697+ break;
32698+ }
32699+ case SCST_PROC_ACTION_DEL:
32700+ {
32701+ /*
32702+ * This code doesn't handle if there are >1 LUNs for the same
32703+ * device in the group. Instead, it always deletes the first
32704+ * entry. It wasn't fixed for compatibility reasons, because
32705+ * procfs is now obsoleted.
32706+ */
32707+ struct scst_acg_dev *a;
32708+ list_for_each_entry(a, &acg->acg_dev_list, acg_dev_list_entry) {
32709+ if (a->dev == dev) {
32710+ rc = scst_acg_del_lun(acg, a->lun, true);
32711+ if (rc) {
32712+ res = rc;
32713+ goto out_free_up;
32714+ }
32715+ break;
32716+ }
32717+ }
32718+ PRINT_ERROR("Device is not found in group %s", acg->acg_name);
32719+ break;
32720+ }
32721+ case SCST_PROC_ACTION_CLEAR:
32722+ list_for_each_entry_safe(acg_dev, acg_dev_tmp,
32723+ &acg->acg_dev_list,
32724+ acg_dev_list_entry) {
32725+ rc = scst_acg_del_lun(acg, acg_dev->lun,
32726+ list_is_last(&acg_dev->acg_dev_list_entry,
32727+ &acg->acg_dev_list));
32728+ if (rc) {
32729+ res = rc;
32730+ goto out_free_up;
32731+ }
32732+ }
32733+ break;
32734+ }
32735+
32736+out_free_up:
32737+ mutex_unlock(&scst_mutex);
32738+
32739+out_free_resume:
32740+ scst_resume_activity();
32741+
32742+out_free:
32743+ free_page((unsigned long)buffer);
32744+
32745+out:
32746+ TRACE_EXIT_RES(res);
32747+ return res;
32748+}
32749+
32750+static ssize_t scst_proc_groups_names_write(struct file *file,
32751+ const char __user *buf,
32752+ size_t length, loff_t *off)
32753+{
32754+ int res = length, rc = 0, action;
32755+ char *buffer, *p, *pp = NULL;
32756+ struct scst_acg *acg =
32757+ (struct scst_acg *)PDE(file->f_dentry->d_inode)->data;
32758+ struct scst_acn *n, *nn;
32759+
32760+ TRACE_ENTRY();
32761+
32762+ if (length > SCST_PROC_BLOCK_SIZE) {
32763+ res = -EOVERFLOW;
32764+ goto out;
32765+ }
32766+ if (!buf) {
32767+ res = -EINVAL;
32768+ goto out;
32769+ }
32770+ buffer = (char *)__get_free_page(GFP_KERNEL);
32771+ if (!buffer) {
32772+ res = -ENOMEM;
32773+ goto out;
32774+ }
32775+ if (copy_from_user(buffer, buf, length)) {
32776+ res = -EFAULT;
32777+ goto out_free;
32778+ }
32779+ if (length < PAGE_SIZE) {
32780+ buffer[length] = '\0';
32781+ } else if (buffer[PAGE_SIZE-1]) {
32782+ res = -EINVAL;
32783+ goto out_free;
32784+ }
32785+
32786+ /*
32787+ * Usage: echo "add|del NAME" >/proc/scsi_tgt/groups/GROUP_NAME/names
32788+ * or echo "move NAME NEW_GROUP_NAME" >/proc/scsi_tgt/groups/OLD_GROUP_NAME/names"
32789+ * or echo "clear" >/proc/scsi_tgt/groups/GROUP_NAME/names
32790+ */
32791+ p = buffer;
32792+ if (p[strlen(p) - 1] == '\n')
32793+ p[strlen(p) - 1] = '\0';
32794+ if (!strncasecmp("clear", p, 5)) {
32795+ action = SCST_PROC_ACTION_CLEAR;
32796+ } else if (!strncasecmp("add ", p, 4)) {
32797+ p += 4;
32798+ action = SCST_PROC_ACTION_ADD;
32799+ } else if (!strncasecmp("del ", p, 4)) {
32800+ p += 4;
32801+ action = SCST_PROC_ACTION_DEL;
32802+ } else if (!strncasecmp("move ", p, 5)) {
32803+ p += 5;
32804+ action = SCST_PROC_ACTION_MOVE;
32805+ } else {
32806+ PRINT_ERROR("Unknown action \"%s\"", p);
32807+ res = -EINVAL;
32808+ goto out_free;
32809+ }
32810+
32811+ switch (action) {
32812+ case SCST_PROC_ACTION_ADD:
32813+ case SCST_PROC_ACTION_DEL:
32814+ case SCST_PROC_ACTION_MOVE:
32815+ while (isspace(*p) && *p != '\0')
32816+ p++;
32817+ pp = p;
32818+ while (!isspace(*pp) && *pp != '\0')
32819+ pp++;
32820+ if (*pp != '\0') {
32821+ *pp = '\0';
32822+ pp++;
32823+ while (isspace(*pp) && *pp != '\0')
32824+ pp++;
32825+ if (*pp != '\0') {
32826+ switch (action) {
32827+ case SCST_PROC_ACTION_ADD:
32828+ case SCST_PROC_ACTION_DEL:
32829+ PRINT_ERROR("%s", "Too many "
32830+ "arguments");
32831+ res = -EINVAL;
32832+ goto out_free;
32833+ }
32834+ }
32835+ }
32836+ break;
32837+ }
32838+
32839+ rc = scst_suspend_activity(true);
32840+ if (rc != 0)
32841+ goto out_free;
32842+
32843+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
32844+ res = -EINTR;
32845+ goto out_free_resume;
32846+ }
32847+
32848+ switch (action) {
32849+ case SCST_PROC_ACTION_ADD:
32850+ rc = scst_acg_add_acn(acg, p);
32851+ break;
32852+ case SCST_PROC_ACTION_DEL:
32853+ rc = scst_acg_remove_name(acg, p, true);
32854+ break;
32855+ case SCST_PROC_ACTION_MOVE:
32856+ {
32857+ struct scst_acg *a, *new_acg = NULL;
32858+ char *name = p;
32859+ p = pp;
32860+ while (!isspace(*pp) && *pp != '\0')
32861+ pp++;
32862+ if (*pp != '\0') {
32863+ *pp = '\0';
32864+ pp++;
32865+ while (isspace(*pp) && *pp != '\0')
32866+ pp++;
32867+ if (*pp != '\0') {
32868+ PRINT_ERROR("%s", "Too many arguments");
32869+ res = -EINVAL;
32870+ goto out_free_unlock;
32871+ }
32872+ }
32873+ list_for_each_entry(a, &scst_acg_list, acg_list_entry) {
32874+ if (strcmp(a->acg_name, p) == 0) {
32875+ TRACE_DBG("group (acg) %p %s found",
32876+ a, a->acg_name);
32877+ new_acg = a;
32878+ break;
32879+ }
32880+ }
32881+ if (new_acg == NULL) {
32882+ PRINT_ERROR("Group %s not found", p);
32883+ res = -EINVAL;
32884+ goto out_free_unlock;
32885+ }
32886+ rc = scst_acg_remove_name(acg, name, false);
32887+ if (rc != 0)
32888+ goto out_free_unlock;
32889+ rc = scst_acg_add_acn(new_acg, name);
32890+ if (rc != 0)
32891+ scst_acg_add_acn(acg, name);
32892+ break;
32893+ }
32894+ case SCST_PROC_ACTION_CLEAR:
32895+ list_for_each_entry_safe(n, nn, &acg->acn_list,
32896+ acn_list_entry) {
32897+ scst_del_free_acn(n, false);
32898+ }
32899+ scst_check_reassign_sessions();
32900+ break;
32901+ }
32902+
32903+out_free_unlock:
32904+ mutex_unlock(&scst_mutex);
32905+
32906+out_free_resume:
32907+ scst_resume_activity();
32908+
32909+out_free:
32910+ free_page((unsigned long)buffer);
32911+
32912+out:
32913+ if (rc < 0)
32914+ res = rc;
32915+
32916+ TRACE_EXIT_RES(res);
32917+ return res;
32918+}
32919+
32920+static int scst_version_info_show(struct seq_file *seq, void *v)
32921+{
32922+ TRACE_ENTRY();
32923+
32924+ seq_printf(seq, "%s\n", SCST_VERSION_STRING);
32925+
32926+#ifdef CONFIG_SCST_STRICT_SERIALIZING
32927+ seq_printf(seq, "STRICT_SERIALIZING\n");
32928+#endif
32929+
32930+#ifdef CONFIG_SCST_EXTRACHECKS
32931+ seq_printf(seq, "EXTRACHECKS\n");
32932+#endif
32933+
32934+#ifdef CONFIG_SCST_TRACING
32935+ seq_printf(seq, "TRACING\n");
32936+#endif
32937+
32938+#ifdef CONFIG_SCST_DEBUG
32939+ seq_printf(seq, "DEBUG\n");
32940+#endif
32941+
32942+#ifdef CONFIG_SCST_DEBUG_TM
32943+ seq_printf(seq, "DEBUG_TM\n");
32944+#endif
32945+
32946+#ifdef CONFIG_SCST_DEBUG_RETRY
32947+ seq_printf(seq, "DEBUG_RETRY\n");
32948+#endif
32949+
32950+#ifdef CONFIG_SCST_DEBUG_OOM
32951+ seq_printf(seq, "DEBUG_OOM\n");
32952+#endif
32953+
32954+#ifdef CONFIG_SCST_DEBUG_SN
32955+ seq_printf(seq, "DEBUG_SN\n");
32956+#endif
32957+
32958+#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
32959+ seq_printf(seq, "USE_EXPECTED_VALUES\n");
32960+#endif
32961+
32962+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
32963+ seq_printf(seq, "TEST_IO_IN_SIRQ\n");
32964+#endif
32965+
32966+#ifdef CONFIG_SCST_STRICT_SECURITY
32967+ seq_printf(seq, "STRICT_SECURITY\n");
32968+#endif
32969+
32970+ TRACE_EXIT();
32971+ return 0;
32972+}
32973+
32974+static struct scst_proc_data scst_version_proc_data = {
32975+ SCST_DEF_RW_SEQ_OP(NULL)
32976+ .show = scst_version_info_show,
32977+};
32978+
32979+static int scst_help_info_show(struct seq_file *seq, void *v)
32980+{
32981+ TRACE_ENTRY();
32982+
32983+ seq_printf(seq, "%s\n", scst_proc_help_string);
32984+
32985+ TRACE_EXIT();
32986+ return 0;
32987+}
32988+
32989+static struct scst_proc_data scst_help_proc_data = {
32990+ SCST_DEF_RW_SEQ_OP(NULL)
32991+ .show = scst_help_info_show,
32992+};
32993+
32994+static int scst_dev_handler_type_info_show(struct seq_file *seq, void *v)
32995+{
32996+ struct scst_dev_type *dev_type = (struct scst_dev_type *)seq->private;
32997+
32998+ TRACE_ENTRY();
32999+
33000+ seq_printf(seq, "%d - %s\n", dev_type->type,
33001+ dev_type->type > (int)ARRAY_SIZE(scst_proc_dev_handler_type)
33002+ ? "unknown" : scst_proc_dev_handler_type[dev_type->type]);
33003+
33004+ TRACE_EXIT();
33005+ return 0;
33006+}
33007+
33008+static struct scst_proc_data scst_dev_handler_type_proc_data = {
33009+ SCST_DEF_RW_SEQ_OP(NULL)
33010+ .show = scst_dev_handler_type_info_show,
33011+};
33012+
33013+static int scst_sessions_info_show(struct seq_file *seq, void *v)
33014+{
33015+ int res = 0;
33016+ struct scst_acg *acg;
33017+ struct scst_session *sess;
33018+
33019+ TRACE_ENTRY();
33020+
33021+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
33022+ res = -EINTR;
33023+ goto out;
33024+ }
33025+
33026+ seq_printf(seq, "%-20s %-45s %-35s %-15s\n",
33027+ "Target name", "Initiator name",
33028+ "Group name", "Active/All Commands Count");
33029+
33030+ list_for_each_entry(acg, &scst_acg_list, acg_list_entry) {
33031+ list_for_each_entry(sess, &acg->acg_sess_list,
33032+ acg_sess_list_entry) {
33033+ int active_cmds = 0, t;
33034+ for (t = TGT_DEV_HASH_SIZE-1; t >= 0; t--) {
33035+ struct list_head *sess_tgt_dev_list_head =
33036+ &sess->sess_tgt_dev_list_hash[t];
33037+ struct scst_tgt_dev *tgt_dev;
33038+ list_for_each_entry(tgt_dev,
33039+ sess_tgt_dev_list_head,
33040+ sess_tgt_dev_list_entry) {
33041+ active_cmds += atomic_read(&tgt_dev->tgt_dev_cmd_count);
33042+ }
33043+ }
33044+ seq_printf(seq, "%-20s %-45s %-35s %d/%d\n",
33045+ sess->tgt->tgtt->name,
33046+ sess->initiator_name,
33047+ acg->acg_name, active_cmds,
33048+ atomic_read(&sess->sess_cmd_count));
33049+ }
33050+ }
33051+
33052+ mutex_unlock(&scst_mutex);
33053+
33054+out:
33055+ TRACE_EXIT_RES(res);
33056+ return res;
33057+}
33058+
33059+static struct scst_proc_data scst_sessions_proc_data = {
33060+ SCST_DEF_RW_SEQ_OP(NULL)
33061+ .show = scst_sessions_info_show,
33062+};
33063+
33064+static struct scst_proc_data scst_sgv_proc_data = {
33065+ SCST_DEF_RW_SEQ_OP(NULL)
33066+ .show = sgv_procinfo_show,
33067+};
33068+
33069+static int scst_groups_names_show(struct seq_file *seq, void *v)
33070+{
33071+ int res = 0;
33072+ struct scst_acg *acg = (struct scst_acg *)seq->private;
33073+ struct scst_acn *name;
33074+
33075+ TRACE_ENTRY();
33076+
33077+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
33078+ res = -EINTR;
33079+ goto out;
33080+ }
33081+
33082+ list_for_each_entry(name, &acg->acn_list, acn_list_entry) {
33083+ seq_printf(seq, "%s\n", name->name);
33084+ }
33085+
33086+ mutex_unlock(&scst_mutex);
33087+
33088+out:
33089+ TRACE_EXIT_RES(res);
33090+ return res;
33091+}
33092+
33093+static struct scst_proc_data scst_groups_names_proc_data = {
33094+ SCST_DEF_RW_SEQ_OP(scst_proc_groups_names_write)
33095+ .show = scst_groups_names_show,
33096+};
33097+
33098+static int scst_groups_addr_method_show(struct seq_file *seq, void *v)
33099+{
33100+ int res = 0;
33101+ struct scst_acg *acg = (struct scst_acg *)seq->private;
33102+
33103+ TRACE_ENTRY();
33104+
33105+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
33106+ res = -EINTR;
33107+ goto out;
33108+ }
33109+
33110+ switch (acg->addr_method) {
33111+ case SCST_LUN_ADDR_METHOD_FLAT:
33112+ seq_printf(seq, "%s\n", "FLAT");
33113+ break;
33114+ case SCST_LUN_ADDR_METHOD_PERIPHERAL:
33115+ seq_printf(seq, "%s\n", "PERIPHERAL");
33116+ break;
33117+ default:
33118+ seq_printf(seq, "%s\n", "UNKNOWN");
33119+ break;
33120+ }
33121+
33122+ mutex_unlock(&scst_mutex);
33123+
33124+out:
33125+ TRACE_EXIT_RES(res);
33126+ return res;
33127+}
33128+static struct scst_proc_data scst_groups_addr_method_proc_data = {
33129+ SCST_DEF_RW_SEQ_OP(NULL)
33130+ .show = scst_groups_addr_method_show,
33131+};
33132+static int scst_groups_devices_show(struct seq_file *seq, void *v)
33133+{
33134+ int res = 0;
33135+ struct scst_acg *acg = (struct scst_acg *)seq->private;
33136+ struct scst_acg_dev *acg_dev;
33137+
33138+ TRACE_ENTRY();
33139+
33140+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
33141+ res = -EINTR;
33142+ goto out;
33143+ }
33144+
33145+ seq_printf(seq, "%-60s%-13s%s\n", "Device (host:ch:id:lun or name)",
33146+ "LUN", "Options");
33147+
33148+ list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
33149+ seq_printf(seq, "%-60s%-13lld%s\n",
33150+ acg_dev->dev->virt_name,
33151+ (long long unsigned int)acg_dev->lun,
33152+ acg_dev->rd_only ? "RO" : "");
33153+ }
33154+ mutex_unlock(&scst_mutex);
33155+
33156+out:
33157+ TRACE_EXIT_RES(res);
33158+ return res;
33159+}
33160+
33161+static struct scst_proc_data scst_groups_devices_proc_data = {
33162+ SCST_DEF_RW_SEQ_OP(scst_proc_groups_devices_write)
33163+ .show = scst_groups_devices_show,
33164+};
33165+
33166+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
33167+
33168+static int scst_proc_read_tlb(const struct scst_trace_log *tbl,
33169+ struct seq_file *seq,
33170+ unsigned long log_level, int *first)
33171+{
33172+ const struct scst_trace_log *t = tbl;
33173+ int res = 0;
33174+
33175+ while (t->token) {
33176+ if (log_level & t->val) {
33177+ seq_printf(seq, "%s%s", *first ? "" : " | ", t->token);
33178+ *first = 0;
33179+ }
33180+ t++;
33181+ }
33182+ return res;
33183+}
33184+
33185+int scst_proc_log_entry_read(struct seq_file *seq, unsigned long log_level,
33186+ const struct scst_trace_log *tbl)
33187+{
33188+ int res = 0, first = 1;
33189+
33190+ TRACE_ENTRY();
33191+
33192+ scst_proc_read_tlb(scst_proc_trace_tbl, seq, log_level, &first);
33193+
33194+ if (tbl)
33195+ scst_proc_read_tlb(tbl, seq, log_level, &first);
33196+
33197+ seq_printf(seq, "%s\n", first ? "none" : "");
33198+
33199+ TRACE_EXIT_RES(res);
33200+ return res;
33201+}
33202+EXPORT_SYMBOL_GPL(scst_proc_log_entry_read);
33203+
33204+static int log_info_show(struct seq_file *seq, void *v)
33205+{
33206+ int res;
33207+
33208+ TRACE_ENTRY();
33209+
33210+ if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
33211+ res = -EINTR;
33212+ goto out;
33213+ }
33214+
33215+ res = scst_proc_log_entry_read(seq, trace_flag,
33216+ scst_proc_local_trace_tbl);
33217+
33218+ mutex_unlock(&scst_log_mutex);
33219+
33220+out:
33221+ TRACE_EXIT_RES(res);
33222+ return res;
33223+}
33224+
33225+static struct scst_proc_data scst_log_proc_data = {
33226+ SCST_DEF_RW_SEQ_OP(scst_proc_scsi_tgt_gen_write_log)
33227+ .show = log_info_show,
33228+ .data = "scsi_tgt",
33229+};
33230+
33231+#endif
33232+
33233+static int scst_tgt_info_show(struct seq_file *seq, void *v)
33234+{
33235+ int res = 0;
33236+ struct scst_device *dev;
33237+
33238+ TRACE_ENTRY();
33239+
33240+ if (mutex_lock_interruptible(&scst_mutex) != 0) {
33241+ res = -EINTR;
33242+ goto out;
33243+ }
33244+
33245+ seq_printf(seq, "%-60s%s\n", "Device (host:ch:id:lun or name)",
33246+ "Device handler");
33247+ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
33248+ seq_printf(seq, "%-60s%s\n",
33249+ dev->virt_name, dev->handler->name);
33250+ }
33251+
33252+ mutex_unlock(&scst_mutex);
33253+
33254+out:
33255+ TRACE_EXIT_RES(res);
33256+ return res;
33257+}
33258+
33259+static struct scst_proc_data scst_tgt_proc_data = {
33260+ SCST_DEF_RW_SEQ_OP(scst_proc_scsi_tgt_gen_write)
33261+ .show = scst_tgt_info_show,
33262+};
33263+
33264+static int scst_threads_info_show(struct seq_file *seq, void *v)
33265+{
33266+ TRACE_ENTRY();
33267+
33268+ seq_printf(seq, "%d\n", scst_main_cmd_threads.nr_threads);
33269+
33270+ TRACE_EXIT();
33271+ return 0;
33272+}
33273+
33274+static struct scst_proc_data scst_threads_proc_data = {
33275+ SCST_DEF_RW_SEQ_OP(scst_proc_threads_write)
33276+ .show = scst_threads_info_show,
33277+};
33278+
33279+static int scst_scsi_tgtinfo_show(struct seq_file *seq, void *v)
33280+{
33281+ struct scst_tgt *vtt = seq->private;
33282+ int res = 0;
33283+
33284+ TRACE_ENTRY();
33285+
33286+ if (mutex_lock_interruptible(&scst_proc_mutex) != 0) {
33287+ res = -EINTR;
33288+ goto out;
33289+ }
33290+
33291+ if (vtt->tgtt->read_proc)
33292+ res = vtt->tgtt->read_proc(seq, vtt);
33293+
33294+ mutex_unlock(&scst_proc_mutex);
33295+out:
33296+ TRACE_EXIT_RES(res);
33297+ return res;
33298+}
33299+
33300+static struct scst_proc_data scst_scsi_tgt_proc_data = {
33301+ SCST_DEF_RW_SEQ_OP(scst_proc_scsi_tgt_write)
33302+ .show = scst_scsi_tgtinfo_show,
33303+};
33304+
33305+static int scst_dev_handler_info_show(struct seq_file *seq, void *v)
33306+{
33307+ struct scst_dev_type *dev_type = seq->private;
33308+ int res = 0;
33309+
33310+ TRACE_ENTRY();
33311+
33312+ if (mutex_lock_interruptible(&scst_proc_mutex) != 0) {
33313+ res = -EINTR;
33314+ goto out;
33315+ }
33316+
33317+ if (dev_type->read_proc)
33318+ res = dev_type->read_proc(seq, dev_type);
33319+
33320+ mutex_unlock(&scst_proc_mutex);
33321+
33322+out:
33323+ TRACE_EXIT_RES(res);
33324+ return res;
33325+}
33326+
33327+static struct scst_proc_data scst_dev_handler_proc_data = {
33328+ SCST_DEF_RW_SEQ_OP(scst_proc_scsi_dev_handler_write)
33329+ .show = scst_dev_handler_info_show,
33330+};
33331+
33332+struct proc_dir_entry *scst_create_proc_entry(struct proc_dir_entry *root,
33333+ const char *name, struct scst_proc_data *pdata)
33334+{
33335+ struct proc_dir_entry *p = NULL;
33336+
33337+ TRACE_ENTRY();
33338+
33339+ if (root) {
33340+ mode_t mode;
33341+
33342+ mode = S_IFREG | S_IRUGO | (pdata->seq_op.write ? S_IWUSR : 0);
33343+ p = create_proc_entry(name, mode, root);
33344+ if (p == NULL) {
33345+ PRINT_ERROR("Fail to create entry %s in /proc", name);
33346+ } else {
33347+ p->proc_fops = &pdata->seq_op;
33348+ p->data = pdata->data;
33349+ }
33350+ }
33351+
33352+ TRACE_EXIT();
33353+ return p;
33354+}
33355+EXPORT_SYMBOL_GPL(scst_create_proc_entry);
33356+
33357+int scst_single_seq_open(struct inode *inode, struct file *file)
33358+{
33359+ struct scst_proc_data *pdata = container_of(PDE(inode)->proc_fops,
33360+ struct scst_proc_data, seq_op);
33361+ return single_open(file, pdata->show, PDE(inode)->data);
33362+}
33363+EXPORT_SYMBOL_GPL(scst_single_seq_open);
33364+
33365+struct proc_dir_entry *scst_proc_get_tgt_root(
33366+ struct scst_tgt_template *vtt)
33367+{
33368+ return vtt->proc_tgt_root;
33369+}
33370+EXPORT_SYMBOL_GPL(scst_proc_get_tgt_root);
33371+
33372+struct proc_dir_entry *scst_proc_get_dev_type_root(
33373+ struct scst_dev_type *dtt)
33374+{
33375+ return dtt->proc_dev_type_root;
33376+}
33377+EXPORT_SYMBOL_GPL(scst_proc_get_dev_type_root);
33378diff -uprN orig/linux-2.6.35/include/scst/scst_sgv.h linux-2.6.35/include/scst/scst_sgv.h
33379--- orig/linux-2.6.35/include/scst/scst_sgv.h
33380+++ linux-2.6.35/include/scst/scst_sgv.h
33381@@ -0,0 +1,97 @@
33382+/*
33383+ * include/scst_sgv.h
33384+ *
33385+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
33386+ * Copyright (C) 2007 - 2010 ID7 Ltd.
33387+ *
33388+ * Include file for SCST SGV cache.
33389+ *
33390+ * This program is free software; you can redistribute it and/or
33391+ * modify it under the terms of the GNU General Public License
33392+ * as published by the Free Software Foundation, version 2
33393+ * of the License.
33394+ *
33395+ * This program is distributed in the hope that it will be useful,
33396+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33397+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33398+ * GNU General Public License for more details.
33399+ */
33400+#ifndef __SCST_SGV_H
33401+#define __SCST_SGV_H
33402+
33403+/** SGV pool routines and flag bits **/
33404+
33405+/* Set if the allocated object must be not from the cache */
33406+#define SGV_POOL_ALLOC_NO_CACHED 1
33407+
33408+/* Set if there should not be any memory allocations on a cache miss */
33409+#define SGV_POOL_NO_ALLOC_ON_CACHE_MISS 2
33410+
33411+/* Set an object should be returned even if it doesn't have SG vector built */
33412+#define SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL 4
33413+
33414+/*
33415+ * Set if the allocated object must be a new one, i.e. from the cache,
33416+ * but not cached
33417+ */
33418+#define SGV_POOL_ALLOC_GET_NEW 8
33419+
33420+struct sgv_pool_obj;
33421+struct sgv_pool;
33422+
33423+/*
33424+ * Structure to keep a memory limit for an SCST object
33425+ */
33426+struct scst_mem_lim {
33427+ /* How much memory allocated under this object */
33428+ atomic_t alloced_pages;
33429+
33430+ /*
33431+ * How much memory allowed to allocated under this object. Put here
33432+ * mostly to save a possible cache miss accessing scst_max_dev_cmd_mem.
33433+ */
33434+ int max_allowed_pages;
33435+};
33436+
33437+/* Types of clustering */
33438+enum sgv_clustering_types {
33439+ /* No clustering performed */
33440+ sgv_no_clustering = 0,
33441+
33442+ /*
33443+ * A page will only be merged with the latest previously allocated
33444+ * page, so the order of pages in the SG will be preserved.
33445+ */
33446+ sgv_tail_clustering,
33447+
33448+ /*
33449+ * Free merging of pages at any place in the SG is allowed. This mode
33450+ * usually provides the best merging rate.
33451+ */
33452+ sgv_full_clustering,
33453+};
33454+
33455+struct sgv_pool *sgv_pool_create(const char *name,
33456+ enum sgv_clustering_types clustered, int single_alloc_pages,
33457+ bool shared, int purge_interval);
33458+void sgv_pool_del(struct sgv_pool *pool);
33459+
33460+void sgv_pool_get(struct sgv_pool *pool);
33461+void sgv_pool_put(struct sgv_pool *pool);
33462+
33463+void sgv_pool_flush(struct sgv_pool *pool);
33464+
33465+void sgv_pool_set_allocator(struct sgv_pool *pool,
33466+ struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, void *),
33467+ void (*free_pages_fn)(struct scatterlist *, int, void *));
33468+
33469+struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
33470+ gfp_t gfp_mask, int flags, int *count,
33471+ struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv);
33472+void sgv_pool_free(struct sgv_pool_obj *sgv, struct scst_mem_lim *mem_lim);
33473+
33474+void *sgv_get_priv(struct sgv_pool_obj *sgv);
33475+
33476+void scst_init_mem_lim(struct scst_mem_lim *mem_lim);
33477+
33478+#endif /* __SCST_SGV_H */
33479diff -uprN orig/linux-2.6.35/drivers/scst/scst_mem.h linux-2.6.35/drivers/scst/scst_mem.h
33480--- orig/linux-2.6.35/drivers/scst/scst_mem.h
33481+++ linux-2.6.35/drivers/scst/scst_mem.h
33482@@ -0,0 +1,150 @@
33483+/*
33484+ * scst_mem.h
33485+ *
33486+ * Copyright (C) 2006 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
33487+ * Copyright (C) 2007 - 2010 ID7 Ltd.
33488+ *
33489+ * This program is free software; you can redistribute it and/or
33490+ * modify it under the terms of the GNU General Public License
33491+ * as published by the Free Software Foundation, version 2
33492+ * of the License.
33493+ *
33494+ * This program is distributed in the hope that it will be useful,
33495+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33496+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33497+ * GNU General Public License for more details.
33498+ */
33499+
33500+#include <linux/scatterlist.h>
33501+#include <linux/workqueue.h>
33502+
33503+#define SGV_POOL_ELEMENTS 11
33504+
33505+/*
33506+ * sg_num is indexed by the page number, pg_count is indexed by the sg number.
33507+ * Made in one entry to simplify the code (eg all sizeof(*) parts) and save
33508+ * some CPU cache for non-clustered case.
33509+ */
33510+struct trans_tbl_ent {
33511+ unsigned short sg_num;
33512+ unsigned short pg_count;
33513+};
33514+
33515+/*
33516+ * SGV pool object
33517+ */
33518+struct sgv_pool_obj {
33519+ int cache_num;
33520+ int pages;
33521+
33522+ /* jiffies, protected by sgv_pool_lock */
33523+ unsigned long time_stamp;
33524+
33525+ struct list_head recycling_list_entry;
33526+ struct list_head sorted_recycling_list_entry;
33527+
33528+ struct sgv_pool *owner_pool;
33529+ int orig_sg;
33530+ int orig_length;
33531+ int sg_count;
33532+ void *allocator_priv;
33533+ struct trans_tbl_ent *trans_tbl;
33534+ struct scatterlist *sg_entries;
33535+ struct scatterlist sg_entries_data[0];
33536+};
33537+
33538+/*
33539+ * SGV pool statistics accounting structure
33540+ */
33541+struct sgv_pool_cache_acc {
33542+ atomic_t total_alloc, hit_alloc;
33543+ atomic_t merged;
33544+};
33545+
33546+/*
33547+ * SGV pool allocation functions
33548+ */
33549+struct sgv_pool_alloc_fns {
33550+ struct page *(*alloc_pages_fn)(struct scatterlist *sg, gfp_t gfp_mask,
33551+ void *priv);
33552+ void (*free_pages_fn)(struct scatterlist *sg, int sg_count,
33553+ void *priv);
33554+};
33555+
33556+/*
33557+ * SGV pool
33558+ */
33559+struct sgv_pool {
33560+ enum sgv_clustering_types clustering_type;
33561+ int single_alloc_pages;
33562+ int max_cached_pages;
33563+
33564+ struct sgv_pool_alloc_fns alloc_fns;
33565+
33566+ /* <=4K, <=8, <=16, <=32, <=64, <=128, <=256, <=512, <=1024, <=2048 */
33567+ struct kmem_cache *caches[SGV_POOL_ELEMENTS];
33568+
33569+ spinlock_t sgv_pool_lock; /* outer lock for sgv_pools_lock! */
33570+
33571+ int purge_interval;
33572+
33573+ /* Protected by sgv_pool_lock, if necessary */
33574+ unsigned int purge_work_scheduled:1;
33575+
33576+ /* Protected by sgv_pool_lock */
33577+ struct list_head sorted_recycling_list;
33578+
33579+ int inactive_cached_pages; /* protected by sgv_pool_lock */
33580+
33581+ /* Protected by sgv_pool_lock */
33582+ struct list_head recycling_lists[SGV_POOL_ELEMENTS];
33583+
33584+ int cached_pages, cached_entries; /* protected by sgv_pool_lock */
33585+
33586+ struct sgv_pool_cache_acc cache_acc[SGV_POOL_ELEMENTS];
33587+
33588+ struct delayed_work sgv_purge_work;
33589+
33590+ struct list_head sgv_active_pools_list_entry;
33591+
33592+ atomic_t big_alloc, big_pages, big_merged;
33593+ atomic_t other_alloc, other_pages, other_merged;
33594+
33595+ atomic_t sgv_pool_ref;
33596+
33597+ int max_caches;
33598+
33599+ /* SCST_MAX_NAME + few more bytes to match scst_user expectations */
33600+ char cache_names[SGV_POOL_ELEMENTS][SCST_MAX_NAME + 10];
33601+ char name[SCST_MAX_NAME + 10];
33602+
33603+ struct mm_struct *owner_mm;
33604+
33605+ struct list_head sgv_pools_list_entry;
33606+
33607+ struct kobject sgv_kobj;
33608+
33609+ /* sysfs release completion */
33610+ struct completion sgv_kobj_release_cmpl;
33611+};
33612+
33613+static inline struct scatterlist *sgv_pool_sg(struct sgv_pool_obj *obj)
33614+{
33615+ return obj->sg_entries;
33616+}
33617+
33618+int scst_sgv_pools_init(unsigned long mem_hwmark, unsigned long mem_lwmark);
33619+void scst_sgv_pools_deinit(void);
33620+
33621+ssize_t sgv_sysfs_stat_show(struct kobject *kobj,
33622+ struct kobj_attribute *attr, char *buf);
33623+ssize_t sgv_sysfs_stat_reset(struct kobject *kobj,
33624+ struct kobj_attribute *attr, const char *buf, size_t count);
33625+ssize_t sgv_sysfs_global_stat_show(struct kobject *kobj,
33626+ struct kobj_attribute *attr, char *buf);
33627+ssize_t sgv_sysfs_global_stat_reset(struct kobject *kobj,
33628+ struct kobj_attribute *attr, const char *buf, size_t count);
33629+
33630+void scst_sgv_pool_use_norm(struct scst_tgt_dev *tgt_dev);
33631+void scst_sgv_pool_use_norm_clust(struct scst_tgt_dev *tgt_dev);
33632+void scst_sgv_pool_use_dma(struct scst_tgt_dev *tgt_dev);
33633diff -uprN orig/linux-2.6.35/drivers/scst/scst_mem.c linux-2.6.35/drivers/scst/scst_mem.c
33634--- orig/linux-2.6.35/drivers/scst/scst_mem.c
33635+++ linux-2.6.35/drivers/scst/scst_mem.c
33636@@ -0,0 +1,1879 @@
33637+/*
33638+ * scst_mem.c
33639+ *
33640+ * Copyright (C) 2006 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
33641+ * Copyright (C) 2007 - 2010 ID7 Ltd.
33642+ *
33643+ * This program is free software; you can redistribute it and/or
33644+ * modify it under the terms of the GNU General Public License
33645+ * as published by the Free Software Foundation, version 2
33646+ * of the License.
33647+ *
33648+ * This program is distributed in the hope that it will be useful,
33649+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33650+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33651+ * GNU General Public License for more details.
33652+ */
33653+
33654+#include <linux/init.h>
33655+#include <linux/kernel.h>
33656+#include <linux/errno.h>
33657+#include <linux/list.h>
33658+#include <linux/spinlock.h>
33659+#include <linux/slab.h>
33660+#include <linux/sched.h>
33661+#include <linux/mm.h>
33662+#include <linux/unistd.h>
33663+#include <linux/string.h>
33664+
33665+#include <scst/scst.h>
33666+#include "scst_priv.h"
33667+#include "scst_mem.h"
33668+
33669+#define SGV_DEFAULT_PURGE_INTERVAL (60 * HZ)
33670+#define SGV_MIN_SHRINK_INTERVAL (1 * HZ)
33671+
33672+/* Max pages freed from a pool per shrinking iteration */
33673+#define MAX_PAGES_PER_POOL 50
33674+
33675+static struct sgv_pool *sgv_norm_clust_pool, *sgv_norm_pool, *sgv_dma_pool;
33676+
33677+static atomic_t sgv_pages_total = ATOMIC_INIT(0);
33678+
33679+/* Both read-only */
33680+static int sgv_hi_wmk;
33681+static int sgv_lo_wmk;
33682+
33683+static int sgv_max_local_pages, sgv_max_trans_pages;
33684+
33685+static DEFINE_SPINLOCK(sgv_pools_lock); /* inner lock for sgv_pool_lock! */
33686+static DEFINE_MUTEX(sgv_pools_mutex);
33687+
33688+/* Both protected by sgv_pools_lock */
33689+static struct sgv_pool *sgv_cur_purge_pool;
33690+static LIST_HEAD(sgv_active_pools_list);
33691+
33692+static atomic_t sgv_releases_on_hiwmk = ATOMIC_INIT(0);
33693+static atomic_t sgv_releases_on_hiwmk_failed = ATOMIC_INIT(0);
33694+
33695+static atomic_t sgv_other_total_alloc = ATOMIC_INIT(0);
33696+
33697+static struct shrinker sgv_shrinker;
33698+
33699+/*
33700+ * Protected by sgv_pools_mutex AND sgv_pools_lock for writes,
33701+ * either one for reads.
33702+ */
33703+static LIST_HEAD(sgv_pools_list);
33704+
33705+static inline bool sgv_pool_clustered(const struct sgv_pool *pool)
33706+{
33707+ return pool->clustering_type != sgv_no_clustering;
33708+}
33709+
33710+void scst_sgv_pool_use_norm(struct scst_tgt_dev *tgt_dev)
33711+{
33712+ tgt_dev->gfp_mask = __GFP_NOWARN;
33713+ tgt_dev->pool = sgv_norm_pool;
33714+ clear_bit(SCST_TGT_DEV_CLUST_POOL, &tgt_dev->tgt_dev_flags);
33715+}
33716+
33717+void scst_sgv_pool_use_norm_clust(struct scst_tgt_dev *tgt_dev)
33718+{
33719+ TRACE_MEM("%s", "Use clustering");
33720+ tgt_dev->gfp_mask = __GFP_NOWARN;
33721+ tgt_dev->pool = sgv_norm_clust_pool;
33722+ set_bit(SCST_TGT_DEV_CLUST_POOL, &tgt_dev->tgt_dev_flags);
33723+}
33724+
33725+void scst_sgv_pool_use_dma(struct scst_tgt_dev *tgt_dev)
33726+{
33727+ TRACE_MEM("%s", "Use ISA DMA memory");
33728+ tgt_dev->gfp_mask = __GFP_NOWARN | GFP_DMA;
33729+ tgt_dev->pool = sgv_dma_pool;
33730+ clear_bit(SCST_TGT_DEV_CLUST_POOL, &tgt_dev->tgt_dev_flags);
33731+}
33732+
33733+/* Must be no locks */
33734+static void sgv_dtor_and_free(struct sgv_pool_obj *obj)
33735+{
33736+ struct sgv_pool *pool = obj->owner_pool;
33737+
33738+ TRACE_MEM("Destroying sgv obj %p", obj);
33739+
33740+ if (obj->sg_count != 0) {
33741+ pool->alloc_fns.free_pages_fn(obj->sg_entries,
33742+ obj->sg_count, obj->allocator_priv);
33743+ }
33744+ if (obj->sg_entries != obj->sg_entries_data) {
33745+ if (obj->trans_tbl !=
33746+ (struct trans_tbl_ent *)obj->sg_entries_data) {
33747+ /* kfree() handles NULL parameter */
33748+ kfree(obj->trans_tbl);
33749+ obj->trans_tbl = NULL;
33750+ }
33751+ kfree(obj->sg_entries);
33752+ }
33753+
33754+ kmem_cache_free(pool->caches[obj->cache_num], obj);
33755+ return;
33756+}
33757+
33758+/* Might be called under sgv_pool_lock */
33759+static inline void sgv_del_from_active(struct sgv_pool *pool)
33760+{
33761+ struct list_head *next;
33762+
33763+ TRACE_MEM("Deleting sgv pool %p from the active list", pool);
33764+
33765+ spin_lock_bh(&sgv_pools_lock);
33766+
33767+ next = pool->sgv_active_pools_list_entry.next;
33768+ list_del(&pool->sgv_active_pools_list_entry);
33769+
33770+ if (sgv_cur_purge_pool == pool) {
33771+ TRACE_MEM("Sgv pool %p is sgv cur purge pool", pool);
33772+
33773+ if (next == &sgv_active_pools_list)
33774+ next = next->next;
33775+
33776+ if (next == &sgv_active_pools_list) {
33777+ sgv_cur_purge_pool = NULL;
33778+ TRACE_MEM("%s", "Sgv active list now empty");
33779+ } else {
33780+ sgv_cur_purge_pool = list_entry(next, typeof(*pool),
33781+ sgv_active_pools_list_entry);
33782+ TRACE_MEM("New sgv cur purge pool %p",
33783+ sgv_cur_purge_pool);
33784+ }
33785+ }
33786+
33787+ spin_unlock_bh(&sgv_pools_lock);
33788+ return;
33789+}
33790+
33791+/* Must be called under sgv_pool_lock held */
33792+static void sgv_dec_cached_entries(struct sgv_pool *pool, int pages)
33793+{
33794+ pool->cached_entries--;
33795+ pool->cached_pages -= pages;
33796+
33797+ if (pool->cached_entries == 0)
33798+ sgv_del_from_active(pool);
33799+
33800+ return;
33801+}
33802+
33803+/* Must be called under sgv_pool_lock held */
33804+static void __sgv_purge_from_cache(struct sgv_pool_obj *obj)
33805+{
33806+ int pages = obj->pages;
33807+ struct sgv_pool *pool = obj->owner_pool;
33808+
33809+ TRACE_MEM("Purging sgv obj %p from pool %p (new cached_entries %d)",
33810+ obj, pool, pool->cached_entries-1);
33811+
33812+ list_del(&obj->sorted_recycling_list_entry);
33813+ list_del(&obj->recycling_list_entry);
33814+
33815+ pool->inactive_cached_pages -= pages;
33816+ sgv_dec_cached_entries(pool, pages);
33817+
33818+ atomic_sub(pages, &sgv_pages_total);
33819+
33820+ return;
33821+}
33822+
33823+/* Must be called under sgv_pool_lock held */
33824+static bool sgv_purge_from_cache(struct sgv_pool_obj *obj, int min_interval,
33825+ unsigned long cur_time)
33826+{
33827+ EXTRACHECKS_BUG_ON(min_interval < 0);
33828+
33829+ TRACE_MEM("Checking if sgv obj %p should be purged (cur time %ld, "
33830+ "obj time %ld, time to purge %ld)", obj, cur_time,
33831+ obj->time_stamp, obj->time_stamp + min_interval);
33832+
33833+ if (time_after_eq(cur_time, (obj->time_stamp + min_interval))) {
33834+ __sgv_purge_from_cache(obj);
33835+ return true;
33836+ }
33837+ return false;
33838+}
33839+
33840+/* No locks */
33841+static int sgv_shrink_pool(struct sgv_pool *pool, int nr, int min_interval,
33842+ unsigned long cur_time)
33843+{
33844+ int freed = 0;
33845+
33846+ TRACE_ENTRY();
33847+
33848+ TRACE_MEM("Trying to shrink pool %p (nr %d, min_interval %d)",
33849+ pool, nr, min_interval);
33850+
33851+ if (pool->purge_interval < 0) {
33852+ TRACE_MEM("Not shrinkable pool %p, skipping", pool);
33853+ goto out;
33854+ }
33855+
33856+ spin_lock_bh(&pool->sgv_pool_lock);
33857+
33858+ while (!list_empty(&pool->sorted_recycling_list) &&
33859+ (atomic_read(&sgv_pages_total) > sgv_lo_wmk)) {
33860+ struct sgv_pool_obj *obj = list_entry(
33861+ pool->sorted_recycling_list.next,
33862+ struct sgv_pool_obj, sorted_recycling_list_entry);
33863+
33864+ if (sgv_purge_from_cache(obj, min_interval, cur_time)) {
33865+ int pages = obj->pages;
33866+
33867+ freed += pages;
33868+ nr -= pages;
33869+
33870+ TRACE_MEM("%d pages purged from pool %p (nr left %d, "
33871+ "total freed %d)", pages, pool, nr, freed);
33872+
33873+ spin_unlock_bh(&pool->sgv_pool_lock);
33874+ sgv_dtor_and_free(obj);
33875+ spin_lock_bh(&pool->sgv_pool_lock);
33876+ } else
33877+ break;
33878+
33879+ if ((nr <= 0) || (freed >= MAX_PAGES_PER_POOL)) {
33880+ if (freed >= MAX_PAGES_PER_POOL)
33881+ TRACE_MEM("%d pages purged from pool %p, "
33882+ "leaving", freed, pool);
33883+ break;
33884+ }
33885+ }
33886+
33887+ spin_unlock_bh(&pool->sgv_pool_lock);
33888+
33889+out:
33890+ TRACE_EXIT_RES(nr);
33891+ return nr;
33892+}
33893+
33894+/* No locks */
33895+static int __sgv_shrink(int nr, int min_interval)
33896+{
33897+ struct sgv_pool *pool;
33898+ unsigned long cur_time = jiffies;
33899+ int prev_nr = nr;
33900+ bool circle = false;
33901+
33902+ TRACE_ENTRY();
33903+
33904+ TRACE_MEM("Trying to shrink %d pages from all sgv pools "
33905+ "(min_interval %d)", nr, min_interval);
33906+
33907+ while (nr > 0) {
33908+ struct list_head *next;
33909+
33910+ spin_lock_bh(&sgv_pools_lock);
33911+
33912+ pool = sgv_cur_purge_pool;
33913+ if (pool == NULL) {
33914+ if (list_empty(&sgv_active_pools_list)) {
33915+ TRACE_MEM("%s", "Active pools list is empty");
33916+ goto out_unlock;
33917+ }
33918+
33919+ pool = list_entry(sgv_active_pools_list.next,
33920+ typeof(*pool),
33921+ sgv_active_pools_list_entry);
33922+ }
33923+ sgv_pool_get(pool);
33924+
33925+ next = pool->sgv_active_pools_list_entry.next;
33926+ if (next == &sgv_active_pools_list) {
33927+ if (circle && (prev_nr == nr)) {
33928+ TRACE_MEM("Full circle done, but no progress, "
33929+ "leaving (nr %d)", nr);
33930+ goto out_unlock_put;
33931+ }
33932+ circle = true;
33933+ prev_nr = nr;
33934+
33935+ next = next->next;
33936+ }
33937+
33938+ sgv_cur_purge_pool = list_entry(next, typeof(*pool),
33939+ sgv_active_pools_list_entry);
33940+ TRACE_MEM("New cur purge pool %p", sgv_cur_purge_pool);
33941+
33942+ spin_unlock_bh(&sgv_pools_lock);
33943+
33944+ nr = sgv_shrink_pool(pool, nr, min_interval, cur_time);
33945+
33946+ sgv_pool_put(pool);
33947+ }
33948+
33949+out:
33950+ TRACE_EXIT_RES(nr);
33951+ return nr;
33952+
33953+out_unlock:
33954+ spin_unlock_bh(&sgv_pools_lock);
33955+ goto out;
33956+
33957+out_unlock_put:
33958+ spin_unlock_bh(&sgv_pools_lock);
33959+ sgv_pool_put(pool);
33960+ goto out;
33961+}
33962+
33963+static int sgv_shrink(struct shrinker *shrinker, int nr, gfp_t gfpm)
33964+{
33965+ TRACE_ENTRY();
33966+
33967+ if (nr > 0) {
33968+ nr = __sgv_shrink(nr, SGV_MIN_SHRINK_INTERVAL);
33969+ TRACE_MEM("Left %d", nr);
33970+ } else {
33971+ struct sgv_pool *pool;
33972+ int inactive_pages = 0;
33973+
33974+ spin_lock_bh(&sgv_pools_lock);
33975+ list_for_each_entry(pool, &sgv_active_pools_list,
33976+ sgv_active_pools_list_entry) {
33977+ if (pool->purge_interval > 0)
33978+ inactive_pages += pool->inactive_cached_pages;
33979+ }
33980+ spin_unlock_bh(&sgv_pools_lock);
33981+
33982+ nr = max((int)0, inactive_pages - sgv_lo_wmk);
33983+ TRACE_MEM("Can free %d (total %d)", nr,
33984+ atomic_read(&sgv_pages_total));
33985+ }
33986+
33987+ TRACE_EXIT_RES(nr);
33988+ return nr;
33989+}
33990+
33991+static void sgv_purge_work_fn(struct delayed_work *work)
33992+{
33993+ unsigned long cur_time = jiffies;
33994+ struct sgv_pool *pool = container_of(work, struct sgv_pool,
33995+ sgv_purge_work);
33996+
33997+ TRACE_ENTRY();
33998+
33999+ TRACE_MEM("Purge work for pool %p", pool);
34000+
34001+ spin_lock_bh(&pool->sgv_pool_lock);
34002+
34003+ pool->purge_work_scheduled = false;
34004+
34005+ while (!list_empty(&pool->sorted_recycling_list)) {
34006+ struct sgv_pool_obj *obj = list_entry(
34007+ pool->sorted_recycling_list.next,
34008+ struct sgv_pool_obj, sorted_recycling_list_entry);
34009+
34010+ if (sgv_purge_from_cache(obj, pool->purge_interval, cur_time)) {
34011+ spin_unlock_bh(&pool->sgv_pool_lock);
34012+ sgv_dtor_and_free(obj);
34013+ spin_lock_bh(&pool->sgv_pool_lock);
34014+ } else {
34015+ /*
34016+ * Let's reschedule it for full period to not get here
34017+ * too often. In the worst case we have shrinker
34018+ * to reclaim buffers quickier.
34019+ */
34020+ TRACE_MEM("Rescheduling purge work for pool %p (delay "
34021+ "%d HZ/%d sec)", pool, pool->purge_interval,
34022+ pool->purge_interval/HZ);
34023+ schedule_delayed_work(&pool->sgv_purge_work,
34024+ pool->purge_interval);
34025+ pool->purge_work_scheduled = true;
34026+ break;
34027+ }
34028+ }
34029+
34030+ spin_unlock_bh(&pool->sgv_pool_lock);
34031+
34032+ TRACE_MEM("Leaving purge work for pool %p", pool);
34033+
34034+ TRACE_EXIT();
34035+ return;
34036+}
34037+
34038+static int sgv_check_full_clustering(struct scatterlist *sg, int cur, int hint)
34039+{
34040+ int res = -1;
34041+ int i = hint;
34042+ unsigned long pfn_cur = page_to_pfn(sg_page(&sg[cur]));
34043+ int len_cur = sg[cur].length;
34044+ unsigned long pfn_cur_next = pfn_cur + (len_cur >> PAGE_SHIFT);
34045+ int full_page_cur = (len_cur & (PAGE_SIZE - 1)) == 0;
34046+ unsigned long pfn, pfn_next;
34047+ bool full_page;
34048+
34049+#if 0
34050+ TRACE_MEM("pfn_cur %ld, pfn_cur_next %ld, len_cur %d, full_page_cur %d",
34051+ pfn_cur, pfn_cur_next, len_cur, full_page_cur);
34052+#endif
34053+
34054+ /* check the hint first */
34055+ if (i >= 0) {
34056+ pfn = page_to_pfn(sg_page(&sg[i]));
34057+ pfn_next = pfn + (sg[i].length >> PAGE_SHIFT);
34058+ full_page = (sg[i].length & (PAGE_SIZE - 1)) == 0;
34059+
34060+ if ((pfn == pfn_cur_next) && full_page_cur)
34061+ goto out_head;
34062+
34063+ if ((pfn_next == pfn_cur) && full_page)
34064+ goto out_tail;
34065+ }
34066+
34067+ /* ToDo: implement more intelligent search */
34068+ for (i = cur - 1; i >= 0; i--) {
34069+ pfn = page_to_pfn(sg_page(&sg[i]));
34070+ pfn_next = pfn + (sg[i].length >> PAGE_SHIFT);
34071+ full_page = (sg[i].length & (PAGE_SIZE - 1)) == 0;
34072+
34073+ if ((pfn == pfn_cur_next) && full_page_cur)
34074+ goto out_head;
34075+
34076+ if ((pfn_next == pfn_cur) && full_page)
34077+ goto out_tail;
34078+ }
34079+
34080+out:
34081+ return res;
34082+
34083+out_tail:
34084+ TRACE_MEM("SG segment %d will be tail merged with segment %d", cur, i);
34085+ sg[i].length += len_cur;
34086+ sg_clear(&sg[cur]);
34087+ res = i;
34088+ goto out;
34089+
34090+out_head:
34091+ TRACE_MEM("SG segment %d will be head merged with segment %d", cur, i);
34092+ sg_assign_page(&sg[i], sg_page(&sg[cur]));
34093+ sg[i].length += len_cur;
34094+ sg_clear(&sg[cur]);
34095+ res = i;
34096+ goto out;
34097+}
34098+
34099+static int sgv_check_tail_clustering(struct scatterlist *sg, int cur, int hint)
34100+{
34101+ int res = -1;
34102+ unsigned long pfn_cur = page_to_pfn(sg_page(&sg[cur]));
34103+ int len_cur = sg[cur].length;
34104+ int prev;
34105+ unsigned long pfn_prev;
34106+ bool full_page;
34107+
34108+#ifdef SCST_HIGHMEM
34109+ if (page >= highmem_start_page) {
34110+ TRACE_MEM("%s", "HIGHMEM page allocated, no clustering")
34111+ goto out;
34112+ }
34113+#endif
34114+
34115+#if 0
34116+ TRACE_MEM("pfn_cur %ld, pfn_cur_next %ld, len_cur %d, full_page_cur %d",
34117+ pfn_cur, pfn_cur_next, len_cur, full_page_cur);
34118+#endif
34119+
34120+ if (cur == 0)
34121+ goto out;
34122+
34123+ prev = cur - 1;
34124+ pfn_prev = page_to_pfn(sg_page(&sg[prev])) +
34125+ (sg[prev].length >> PAGE_SHIFT);
34126+ full_page = (sg[prev].length & (PAGE_SIZE - 1)) == 0;
34127+
34128+ if ((pfn_prev == pfn_cur) && full_page) {
34129+ TRACE_MEM("SG segment %d will be tail merged with segment %d",
34130+ cur, prev);
34131+ sg[prev].length += len_cur;
34132+ sg_clear(&sg[cur]);
34133+ res = prev;
34134+ }
34135+
34136+out:
34137+ return res;
34138+}
34139+
34140+static void sgv_free_sys_sg_entries(struct scatterlist *sg, int sg_count,
34141+ void *priv)
34142+{
34143+ int i;
34144+
34145+ TRACE_MEM("sg=%p, sg_count=%d", sg, sg_count);
34146+
34147+ for (i = 0; i < sg_count; i++) {
34148+ struct page *p = sg_page(&sg[i]);
34149+ int len = sg[i].length;
34150+ int pages =
34151+ (len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0);
34152+
34153+ TRACE_MEM("page %lx, len %d, pages %d",
34154+ (unsigned long)p, len, pages);
34155+
34156+ while (pages > 0) {
34157+ int order = 0;
34158+
34159+/*
34160+ * __free_pages() doesn't like freeing pages with not that order with
34161+ * which they were allocated, so disable this small optimization.
34162+ */
34163+#if 0
34164+ if (len > 0) {
34165+ while (((1 << order) << PAGE_SHIFT) < len)
34166+ order++;
34167+ len = 0;
34168+ }
34169+#endif
34170+ TRACE_MEM("free_pages(): order %d, page %lx",
34171+ order, (unsigned long)p);
34172+
34173+ __free_pages(p, order);
34174+
34175+ pages -= 1 << order;
34176+ p += 1 << order;
34177+ }
34178+ }
34179+}
34180+
34181+static struct page *sgv_alloc_sys_pages(struct scatterlist *sg,
34182+ gfp_t gfp_mask, void *priv)
34183+{
34184+ struct page *page = alloc_pages(gfp_mask, 0);
34185+
34186+ sg_set_page(sg, page, PAGE_SIZE, 0);
34187+ TRACE_MEM("page=%p, sg=%p, priv=%p", page, sg, priv);
34188+ if (page == NULL) {
34189+ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of "
34190+ "sg page failed");
34191+ }
34192+ return page;
34193+}
34194+
34195+static int sgv_alloc_sg_entries(struct scatterlist *sg, int pages,
34196+ gfp_t gfp_mask, enum sgv_clustering_types clustering_type,
34197+ struct trans_tbl_ent *trans_tbl,
34198+ const struct sgv_pool_alloc_fns *alloc_fns, void *priv)
34199+{
34200+ int sg_count = 0;
34201+ int pg, i, j;
34202+ int merged = -1;
34203+
34204+ TRACE_MEM("pages=%d, clustering_type=%d", pages, clustering_type);
34205+
34206+#if 0
34207+ gfp_mask |= __GFP_COLD;
34208+#endif
34209+#ifdef CONFIG_SCST_STRICT_SECURITY
34210+ gfp_mask |= __GFP_ZERO;
34211+#endif
34212+
34213+ for (pg = 0; pg < pages; pg++) {
34214+ void *rc;
34215+#ifdef CONFIG_SCST_DEBUG_OOM
34216+ if (((gfp_mask & __GFP_NOFAIL) != __GFP_NOFAIL) &&
34217+ ((scst_random() % 10000) == 55))
34218+ rc = NULL;
34219+ else
34220+#endif
34221+ rc = alloc_fns->alloc_pages_fn(&sg[sg_count], gfp_mask,
34222+ priv);
34223+ if (rc == NULL)
34224+ goto out_no_mem;
34225+
34226+ /*
34227+ * This code allows compiler to see full body of the clustering
34228+ * functions and gives it a chance to generate better code.
34229+ * At least, the resulting code is smaller, comparing to
34230+ * calling them using a function pointer.
34231+ */
34232+ if (clustering_type == sgv_full_clustering)
34233+ merged = sgv_check_full_clustering(sg, sg_count, merged);
34234+ else if (clustering_type == sgv_tail_clustering)
34235+ merged = sgv_check_tail_clustering(sg, sg_count, merged);
34236+ else
34237+ merged = -1;
34238+
34239+ if (merged == -1)
34240+ sg_count++;
34241+
34242+ TRACE_MEM("pg=%d, merged=%d, sg_count=%d", pg, merged,
34243+ sg_count);
34244+ }
34245+
34246+ if ((clustering_type != sgv_no_clustering) && (trans_tbl != NULL)) {
34247+ pg = 0;
34248+ for (i = 0; i < pages; i++) {
34249+ int n = (sg[i].length >> PAGE_SHIFT) +
34250+ ((sg[i].length & ~PAGE_MASK) != 0);
34251+ trans_tbl[i].pg_count = pg;
34252+ for (j = 0; j < n; j++)
34253+ trans_tbl[pg++].sg_num = i+1;
34254+ TRACE_MEM("i=%d, n=%d, pg_count=%d", i, n,
34255+ trans_tbl[i].pg_count);
34256+ }
34257+ }
34258+
34259+out:
34260+ TRACE_MEM("sg_count=%d", sg_count);
34261+ return sg_count;
34262+
34263+out_no_mem:
34264+ alloc_fns->free_pages_fn(sg, sg_count, priv);
34265+ sg_count = 0;
34266+ goto out;
34267+}
34268+
34269+static int sgv_alloc_arrays(struct sgv_pool_obj *obj,
34270+ int pages_to_alloc, gfp_t gfp_mask)
34271+{
34272+ int sz, tsz = 0;
34273+ int res = 0;
34274+
34275+ TRACE_ENTRY();
34276+
34277+ sz = pages_to_alloc * sizeof(obj->sg_entries[0]);
34278+
34279+ obj->sg_entries = kmalloc(sz, gfp_mask);
34280+ if (unlikely(obj->sg_entries == NULL)) {
34281+ TRACE(TRACE_OUT_OF_MEM, "Allocation of sgv_pool_obj "
34282+ "SG vector failed (size %d)", sz);
34283+ res = -ENOMEM;
34284+ goto out;
34285+ }
34286+
34287+ sg_init_table(obj->sg_entries, pages_to_alloc);
34288+
34289+ if (sgv_pool_clustered(obj->owner_pool)) {
34290+ if (pages_to_alloc <= sgv_max_trans_pages) {
34291+ obj->trans_tbl =
34292+ (struct trans_tbl_ent *)obj->sg_entries_data;
34293+ /*
34294+ * No need to clear trans_tbl, if needed, it will be
34295+ * fully rewritten in sgv_alloc_sg_entries()
34296+ */
34297+ } else {
34298+ tsz = pages_to_alloc * sizeof(obj->trans_tbl[0]);
34299+ obj->trans_tbl = kzalloc(tsz, gfp_mask);
34300+ if (unlikely(obj->trans_tbl == NULL)) {
34301+ TRACE(TRACE_OUT_OF_MEM, "Allocation of "
34302+ "trans_tbl failed (size %d)", tsz);
34303+ res = -ENOMEM;
34304+ goto out_free;
34305+ }
34306+ }
34307+ }
34308+
34309+ TRACE_MEM("pages_to_alloc %d, sz %d, tsz %d, obj %p, sg_entries %p, "
34310+ "trans_tbl %p", pages_to_alloc, sz, tsz, obj, obj->sg_entries,
34311+ obj->trans_tbl);
34312+
34313+out:
34314+ TRACE_EXIT_RES(res);
34315+ return res;
34316+
34317+out_free:
34318+ kfree(obj->sg_entries);
34319+ obj->sg_entries = NULL;
34320+ goto out;
34321+}
34322+
34323+static struct sgv_pool_obj *sgv_get_obj(struct sgv_pool *pool, int cache_num,
34324+ int pages, gfp_t gfp_mask, bool get_new)
34325+{
34326+ struct sgv_pool_obj *obj;
34327+
34328+ spin_lock_bh(&pool->sgv_pool_lock);
34329+
34330+ if (unlikely(get_new)) {
34331+ /* Used only for buffers preallocation */
34332+ goto get_new;
34333+ }
34334+
34335+ if (likely(!list_empty(&pool->recycling_lists[cache_num]))) {
34336+ obj = list_entry(pool->recycling_lists[cache_num].next,
34337+ struct sgv_pool_obj, recycling_list_entry);
34338+
34339+ list_del(&obj->sorted_recycling_list_entry);
34340+ list_del(&obj->recycling_list_entry);
34341+
34342+ pool->inactive_cached_pages -= pages;
34343+
34344+ spin_unlock_bh(&pool->sgv_pool_lock);
34345+ goto out;
34346+ }
34347+
34348+get_new:
34349+ if (pool->cached_entries == 0) {
34350+ TRACE_MEM("Adding pool %p to the active list", pool);
34351+ spin_lock_bh(&sgv_pools_lock);
34352+ list_add_tail(&pool->sgv_active_pools_list_entry,
34353+ &sgv_active_pools_list);
34354+ spin_unlock_bh(&sgv_pools_lock);
34355+ }
34356+
34357+ pool->cached_entries++;
34358+ pool->cached_pages += pages;
34359+
34360+ spin_unlock_bh(&pool->sgv_pool_lock);
34361+
34362+ TRACE_MEM("New cached entries %d (pool %p)", pool->cached_entries,
34363+ pool);
34364+
34365+ obj = kmem_cache_alloc(pool->caches[cache_num],
34366+ gfp_mask & ~(__GFP_HIGHMEM|GFP_DMA));
34367+ if (likely(obj)) {
34368+ memset(obj, 0, sizeof(*obj));
34369+ obj->cache_num = cache_num;
34370+ obj->pages = pages;
34371+ obj->owner_pool = pool;
34372+ } else {
34373+ spin_lock_bh(&pool->sgv_pool_lock);
34374+ sgv_dec_cached_entries(pool, pages);
34375+ spin_unlock_bh(&pool->sgv_pool_lock);
34376+ }
34377+
34378+out:
34379+ return obj;
34380+}
34381+
34382+static void sgv_put_obj(struct sgv_pool_obj *obj)
34383+{
34384+ struct sgv_pool *pool = obj->owner_pool;
34385+ struct list_head *entry;
34386+ struct list_head *list = &pool->recycling_lists[obj->cache_num];
34387+ int pages = obj->pages;
34388+
34389+ spin_lock_bh(&pool->sgv_pool_lock);
34390+
34391+ TRACE_MEM("sgv %p, cache num %d, pages %d, sg_count %d", obj,
34392+ obj->cache_num, pages, obj->sg_count);
34393+
34394+ if (sgv_pool_clustered(pool)) {
34395+ /* Make objects with less entries more preferred */
34396+ __list_for_each(entry, list) {
34397+ struct sgv_pool_obj *tmp = list_entry(entry,
34398+ struct sgv_pool_obj, recycling_list_entry);
34399+
34400+ TRACE_MEM("tmp %p, cache num %d, pages %d, sg_count %d",
34401+ tmp, tmp->cache_num, tmp->pages, tmp->sg_count);
34402+
34403+ if (obj->sg_count <= tmp->sg_count)
34404+ break;
34405+ }
34406+ entry = entry->prev;
34407+ } else
34408+ entry = list;
34409+
34410+ TRACE_MEM("Adding in %p (list %p)", entry, list);
34411+ list_add(&obj->recycling_list_entry, entry);
34412+
34413+ list_add_tail(&obj->sorted_recycling_list_entry,
34414+ &pool->sorted_recycling_list);
34415+
34416+ obj->time_stamp = jiffies;
34417+
34418+ pool->inactive_cached_pages += pages;
34419+
34420+ if (!pool->purge_work_scheduled) {
34421+ TRACE_MEM("Scheduling purge work for pool %p", pool);
34422+ pool->purge_work_scheduled = true;
34423+ schedule_delayed_work(&pool->sgv_purge_work,
34424+ pool->purge_interval);
34425+ }
34426+
34427+ spin_unlock_bh(&pool->sgv_pool_lock);
34428+ return;
34429+}
34430+
34431+/* No locks */
34432+static int sgv_hiwmk_check(int pages_to_alloc)
34433+{
34434+ int res = 0;
34435+ int pages = pages_to_alloc;
34436+
34437+ pages += atomic_read(&sgv_pages_total);
34438+
34439+ if (unlikely(pages > sgv_hi_wmk)) {
34440+ pages -= sgv_hi_wmk;
34441+ atomic_inc(&sgv_releases_on_hiwmk);
34442+
34443+ pages = __sgv_shrink(pages, 0);
34444+ if (pages > 0) {
34445+ TRACE(TRACE_OUT_OF_MEM, "Requested amount of "
34446+ "memory (%d pages) for being executed "
34447+ "commands together with the already "
34448+ "allocated memory exceeds the allowed "
34449+ "maximum %d. Should you increase "
34450+ "scst_max_cmd_mem?", pages_to_alloc,
34451+ sgv_hi_wmk);
34452+ atomic_inc(&sgv_releases_on_hiwmk_failed);
34453+ res = -ENOMEM;
34454+ goto out_unlock;
34455+ }
34456+ }
34457+
34458+ atomic_add(pages_to_alloc, &sgv_pages_total);
34459+
34460+out_unlock:
34461+ TRACE_MEM("pages_to_alloc %d, new total %d", pages_to_alloc,
34462+ atomic_read(&sgv_pages_total));
34463+
34464+ return res;
34465+}
34466+
34467+/* No locks */
34468+static void sgv_hiwmk_uncheck(int pages)
34469+{
34470+ atomic_sub(pages, &sgv_pages_total);
34471+ TRACE_MEM("pages %d, new total %d", pages,
34472+ atomic_read(&sgv_pages_total));
34473+ return;
34474+}
34475+
34476+/* No locks */
34477+static bool sgv_check_allowed_mem(struct scst_mem_lim *mem_lim, int pages)
34478+{
34479+ int alloced;
34480+ bool res = true;
34481+
34482+ alloced = atomic_add_return(pages, &mem_lim->alloced_pages);
34483+ if (unlikely(alloced > mem_lim->max_allowed_pages)) {
34484+ TRACE(TRACE_OUT_OF_MEM, "Requested amount of memory "
34485+ "(%d pages) for being executed commands on a device "
34486+ "together with the already allocated memory exceeds "
34487+ "the allowed maximum %d. Should you increase "
34488+ "scst_max_dev_cmd_mem?", pages,
34489+ mem_lim->max_allowed_pages);
34490+ atomic_sub(pages, &mem_lim->alloced_pages);
34491+ res = false;
34492+ }
34493+
34494+ TRACE_MEM("mem_lim %p, pages %d, res %d, new alloced %d", mem_lim,
34495+ pages, res, atomic_read(&mem_lim->alloced_pages));
34496+
34497+ return res;
34498+}
34499+
34500+/* No locks */
34501+static void sgv_uncheck_allowed_mem(struct scst_mem_lim *mem_lim, int pages)
34502+{
34503+ atomic_sub(pages, &mem_lim->alloced_pages);
34504+
34505+ TRACE_MEM("mem_lim %p, pages %d, new alloced %d", mem_lim,
34506+ pages, atomic_read(&mem_lim->alloced_pages));
34507+ return;
34508+}
34509+
34510+/**
34511+ * sgv_pool_alloc - allocate an SG vector from the SGV pool
34512+ * @pool: the cache to alloc from
34513+ * @size: size of the resulting SG vector in bytes
34514+ * @gfp_mask: the allocation mask
34515+ * @flags: the allocation flags
34516+ * @count: the resulting count of SG entries in the resulting SG vector
34517+ * @sgv: the resulting SGV object
34518+ * @mem_lim: memory limits
34519+ * @priv: pointer to private for this allocation data
34520+ *
34521+ * Description:
34522+ * Allocate an SG vector from the SGV pool and returns pointer to it or
34523+ * NULL in case of any error. See the SGV pool documentation for more details.
34524+ */
34525+struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
34526+ gfp_t gfp_mask, int flags, int *count,
34527+ struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv)
34528+{
34529+ struct sgv_pool_obj *obj;
34530+ int cache_num, pages, cnt;
34531+ struct scatterlist *res = NULL;
34532+ int pages_to_alloc;
34533+ int no_cached = flags & SGV_POOL_ALLOC_NO_CACHED;
34534+ bool allowed_mem_checked = false, hiwmk_checked = false;
34535+
34536+ TRACE_ENTRY();
34537+
34538+ if (unlikely(size == 0))
34539+ goto out;
34540+
34541+ EXTRACHECKS_BUG_ON((gfp_mask & __GFP_NOFAIL) == __GFP_NOFAIL);
34542+
34543+ pages = ((size + PAGE_SIZE - 1) >> PAGE_SHIFT);
34544+ if (pool->single_alloc_pages == 0) {
34545+ int pages_order = get_order(size);
34546+ cache_num = pages_order;
34547+ pages_to_alloc = (1 << pages_order);
34548+ } else {
34549+ cache_num = 0;
34550+ pages_to_alloc = max(pool->single_alloc_pages, pages);
34551+ }
34552+
34553+ TRACE_MEM("size=%d, pages=%d, pages_to_alloc=%d, cache num=%d, "
34554+ "flags=%x, no_cached=%d, *sgv=%p", size, pages,
34555+ pages_to_alloc, cache_num, flags, no_cached, *sgv);
34556+
34557+ if (*sgv != NULL) {
34558+ obj = *sgv;
34559+
34560+ TRACE_MEM("Supplied obj %p, cache num %d", obj, obj->cache_num);
34561+
34562+ EXTRACHECKS_BUG_ON(obj->sg_count != 0);
34563+
34564+ if (unlikely(!sgv_check_allowed_mem(mem_lim, pages_to_alloc)))
34565+ goto out_fail_free_sg_entries;
34566+ allowed_mem_checked = true;
34567+
34568+ if (unlikely(sgv_hiwmk_check(pages_to_alloc) != 0))
34569+ goto out_fail_free_sg_entries;
34570+ hiwmk_checked = true;
34571+ } else if ((pages_to_alloc <= pool->max_cached_pages) && !no_cached) {
34572+ if (unlikely(!sgv_check_allowed_mem(mem_lim, pages_to_alloc)))
34573+ goto out_fail;
34574+ allowed_mem_checked = true;
34575+
34576+ obj = sgv_get_obj(pool, cache_num, pages_to_alloc, gfp_mask,
34577+ flags & SGV_POOL_ALLOC_GET_NEW);
34578+ if (unlikely(obj == NULL)) {
34579+ TRACE(TRACE_OUT_OF_MEM, "Allocation of "
34580+ "sgv_pool_obj failed (size %d)", size);
34581+ goto out_fail;
34582+ }
34583+
34584+ if (obj->sg_count != 0) {
34585+ TRACE_MEM("Cached obj %p", obj);
34586+ atomic_inc(&pool->cache_acc[cache_num].hit_alloc);
34587+ goto success;
34588+ }
34589+
34590+ if (flags & SGV_POOL_NO_ALLOC_ON_CACHE_MISS) {
34591+ if (!(flags & SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL))
34592+ goto out_fail_free;
34593+ }
34594+
34595+ TRACE_MEM("Brand new obj %p", obj);
34596+
34597+ if (pages_to_alloc <= sgv_max_local_pages) {
34598+ obj->sg_entries = obj->sg_entries_data;
34599+ sg_init_table(obj->sg_entries, pages_to_alloc);
34600+ TRACE_MEM("sg_entries %p", obj->sg_entries);
34601+ if (sgv_pool_clustered(pool)) {
34602+ obj->trans_tbl = (struct trans_tbl_ent *)
34603+ (obj->sg_entries + pages_to_alloc);
34604+ TRACE_MEM("trans_tbl %p", obj->trans_tbl);
34605+ /*
34606+ * No need to clear trans_tbl, if needed, it
34607+ * will be fully rewritten in
34608+ * sgv_alloc_sg_entries().
34609+ */
34610+ }
34611+ } else {
34612+ if (unlikely(sgv_alloc_arrays(obj, pages_to_alloc,
34613+ gfp_mask) != 0))
34614+ goto out_fail_free;
34615+ }
34616+
34617+ if ((flags & SGV_POOL_NO_ALLOC_ON_CACHE_MISS) &&
34618+ (flags & SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL))
34619+ goto out_return;
34620+
34621+ obj->allocator_priv = priv;
34622+
34623+ if (unlikely(sgv_hiwmk_check(pages_to_alloc) != 0))
34624+ goto out_fail_free_sg_entries;
34625+ hiwmk_checked = true;
34626+ } else {
34627+ int sz;
34628+
34629+ pages_to_alloc = pages;
34630+
34631+ if (unlikely(!sgv_check_allowed_mem(mem_lim, pages_to_alloc)))
34632+ goto out_fail;
34633+ allowed_mem_checked = true;
34634+
34635+ if (flags & SGV_POOL_NO_ALLOC_ON_CACHE_MISS)
34636+ goto out_return2;
34637+
34638+ sz = sizeof(*obj) + pages * sizeof(obj->sg_entries[0]);
34639+
34640+ obj = kmalloc(sz, gfp_mask);
34641+ if (unlikely(obj == NULL)) {
34642+ TRACE(TRACE_OUT_OF_MEM, "Allocation of "
34643+ "sgv_pool_obj failed (size %d)", size);
34644+ goto out_fail;
34645+ }
34646+ memset(obj, 0, sizeof(*obj));
34647+
34648+ obj->owner_pool = pool;
34649+ cache_num = -1;
34650+ obj->cache_num = cache_num;
34651+ obj->pages = pages_to_alloc;
34652+ obj->allocator_priv = priv;
34653+
34654+ obj->sg_entries = obj->sg_entries_data;
34655+ sg_init_table(obj->sg_entries, pages);
34656+
34657+ if (unlikely(sgv_hiwmk_check(pages_to_alloc) != 0))
34658+ goto out_fail_free_sg_entries;
34659+ hiwmk_checked = true;
34660+
34661+ TRACE_MEM("Big or no_cached obj %p (size %d)", obj, sz);
34662+ }
34663+
34664+ obj->sg_count = sgv_alloc_sg_entries(obj->sg_entries,
34665+ pages_to_alloc, gfp_mask, pool->clustering_type,
34666+ obj->trans_tbl, &pool->alloc_fns, priv);
34667+ if (unlikely(obj->sg_count <= 0)) {
34668+ obj->sg_count = 0;
34669+ if ((flags & SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL) &&
34670+ (cache_num >= 0))
34671+ goto out_return1;
34672+ else
34673+ goto out_fail_free_sg_entries;
34674+ }
34675+
34676+ if (cache_num >= 0) {
34677+ atomic_add(pages_to_alloc - obj->sg_count,
34678+ &pool->cache_acc[cache_num].merged);
34679+ } else {
34680+ if (no_cached) {
34681+ atomic_add(pages_to_alloc,
34682+ &pool->other_pages);
34683+ atomic_add(pages_to_alloc - obj->sg_count,
34684+ &pool->other_merged);
34685+ } else {
34686+ atomic_add(pages_to_alloc,
34687+ &pool->big_pages);
34688+ atomic_add(pages_to_alloc - obj->sg_count,
34689+ &pool->big_merged);
34690+ }
34691+ }
34692+
34693+success:
34694+ if (cache_num >= 0) {
34695+ int sg;
34696+ atomic_inc(&pool->cache_acc[cache_num].total_alloc);
34697+ if (sgv_pool_clustered(pool))
34698+ cnt = obj->trans_tbl[pages-1].sg_num;
34699+ else
34700+ cnt = pages;
34701+ sg = cnt-1;
34702+ obj->orig_sg = sg;
34703+ obj->orig_length = obj->sg_entries[sg].length;
34704+ if (sgv_pool_clustered(pool)) {
34705+ obj->sg_entries[sg].length =
34706+ (pages - obj->trans_tbl[sg].pg_count) << PAGE_SHIFT;
34707+ }
34708+ } else {
34709+ cnt = obj->sg_count;
34710+ if (no_cached)
34711+ atomic_inc(&pool->other_alloc);
34712+ else
34713+ atomic_inc(&pool->big_alloc);
34714+ }
34715+
34716+ *count = cnt;
34717+ res = obj->sg_entries;
34718+ *sgv = obj;
34719+
34720+ if (size & ~PAGE_MASK)
34721+ obj->sg_entries[cnt-1].length -=
34722+ PAGE_SIZE - (size & ~PAGE_MASK);
34723+
34724+ TRACE_MEM("obj=%p, sg_entries %p (size=%d, pages=%d, sg_count=%d, "
34725+ "count=%d, last_len=%d)", obj, obj->sg_entries, size, pages,
34726+ obj->sg_count, *count, obj->sg_entries[obj->orig_sg].length);
34727+
34728+out:
34729+ TRACE_EXIT_HRES(res);
34730+ return res;
34731+
34732+out_return:
34733+ obj->allocator_priv = priv;
34734+ obj->owner_pool = pool;
34735+
34736+out_return1:
34737+ *sgv = obj;
34738+ TRACE_MEM("Returning failed obj %p (count %d)", obj, *count);
34739+
34740+out_return2:
34741+ *count = pages_to_alloc;
34742+ res = NULL;
34743+ goto out_uncheck;
34744+
34745+out_fail_free_sg_entries:
34746+ if (obj->sg_entries != obj->sg_entries_data) {
34747+ if (obj->trans_tbl !=
34748+ (struct trans_tbl_ent *)obj->sg_entries_data) {
34749+ /* kfree() handles NULL parameter */
34750+ kfree(obj->trans_tbl);
34751+ obj->trans_tbl = NULL;
34752+ }
34753+ kfree(obj->sg_entries);
34754+ obj->sg_entries = NULL;
34755+ }
34756+
34757+out_fail_free:
34758+ if (cache_num >= 0) {
34759+ spin_lock_bh(&pool->sgv_pool_lock);
34760+ sgv_dec_cached_entries(pool, pages_to_alloc);
34761+ spin_unlock_bh(&pool->sgv_pool_lock);
34762+
34763+ kmem_cache_free(pool->caches[obj->cache_num], obj);
34764+ } else
34765+ kfree(obj);
34766+
34767+out_fail:
34768+ res = NULL;
34769+ *count = 0;
34770+ *sgv = NULL;
34771+ TRACE_MEM("%s", "Allocation failed");
34772+
34773+out_uncheck:
34774+ if (hiwmk_checked)
34775+ sgv_hiwmk_uncheck(pages_to_alloc);
34776+ if (allowed_mem_checked)
34777+ sgv_uncheck_allowed_mem(mem_lim, pages_to_alloc);
34778+ goto out;
34779+}
34780+EXPORT_SYMBOL_GPL(sgv_pool_alloc);
34781+
34782+/**
34783+ * sgv_get_priv - return the private allocation data
34784+ *
34785+ * Allows to get the allocation private data for this SGV
34786+ * cache object. The private data supposed to be set by sgv_pool_alloc().
34787+ */
34788+void *sgv_get_priv(struct sgv_pool_obj *obj)
34789+{
34790+ return obj->allocator_priv;
34791+}
34792+EXPORT_SYMBOL_GPL(sgv_get_priv);
34793+
34794+/**
34795+ * sgv_pool_free - free previously allocated SG vector
34796+ * @sgv: the SGV object to free
34797+ * @mem_lim: memory limits
34798+ *
34799+ * Description:
34800+ * Frees previously allocated SG vector and updates memory limits
34801+ */
34802+void sgv_pool_free(struct sgv_pool_obj *obj, struct scst_mem_lim *mem_lim)
34803+{
34804+ int pages = (obj->sg_count != 0) ? obj->pages : 0;
34805+
34806+ TRACE_MEM("Freeing obj %p, cache num %d, pages %d, sg_entries %p, "
34807+ "sg_count %d, allocator_priv %p", obj, obj->cache_num, pages,
34808+ obj->sg_entries, obj->sg_count, obj->allocator_priv);
34809+
34810+/*
34811+ * Enable it if you are investigating a data corruption and want to make
34812+ * sure that target or dev handler didn't leave the pages mapped somewhere and,
34813+ * hence, provoked a data corruption.
34814+ *
34815+ * Make sure the check value for _count is set correctly. In most cases, 1 is
34816+ * correct, but, e.g., iSCSI-SCST can call it with value 2, because
34817+ * it frees the corresponding cmd before the last put_page() call from
34818+ * net_put_page() for the last page in the SG. Also, user space dev handlers
34819+ * usually have their memory mapped in their address space.
34820+ */
34821+#if 0
34822+ {
34823+ struct scatterlist *sg = obj->sg_entries;
34824+ int i;
34825+ for (i = 0; i < obj->sg_count; i++) {
34826+ struct page *p = sg_page(&sg[i]);
34827+ int len = sg[i].length;
34828+ int pages = (len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0);
34829+ while (pages > 0) {
34830+ if (atomic_read(&p->_count) != 1) {
34831+ PRINT_WARNING("Freeing page %p with "
34832+ "additional owners (_count %d). "
34833+ "Data corruption possible!",
34834+ p, atomic_read(&p->_count));
34835+ WARN_ON(1);
34836+ }
34837+ pages--;
34838+ p++;
34839+ }
34840+ }
34841+ }
34842+#endif
34843+
34844+ if (obj->cache_num >= 0) {
34845+ obj->sg_entries[obj->orig_sg].length = obj->orig_length;
34846+ sgv_put_obj(obj);
34847+ } else {
34848+ obj->owner_pool->alloc_fns.free_pages_fn(obj->sg_entries,
34849+ obj->sg_count, obj->allocator_priv);
34850+ kfree(obj);
34851+ sgv_hiwmk_uncheck(pages);
34852+ }
34853+
34854+ sgv_uncheck_allowed_mem(mem_lim, pages);
34855+ return;
34856+}
34857+EXPORT_SYMBOL_GPL(sgv_pool_free);
34858+
34859+/**
34860+ * scst_alloc() - allocates an SG vector
34861+ *
34862+ * Allocates and returns pointer to SG vector with data size "size".
34863+ * In *count returned the count of entries in the vector.
34864+ * Returns NULL for failure.
34865+ */
34866+struct scatterlist *scst_alloc(int size, gfp_t gfp_mask, int *count)
34867+{
34868+ struct scatterlist *res;
34869+ int pages = (size >> PAGE_SHIFT) + ((size & ~PAGE_MASK) != 0);
34870+ struct sgv_pool_alloc_fns sys_alloc_fns = {
34871+ sgv_alloc_sys_pages, sgv_free_sys_sg_entries };
34872+ int no_fail = ((gfp_mask & __GFP_NOFAIL) == __GFP_NOFAIL);
34873+ int cnt;
34874+
34875+ TRACE_ENTRY();
34876+
34877+ atomic_inc(&sgv_other_total_alloc);
34878+
34879+ if (unlikely(sgv_hiwmk_check(pages) != 0)) {
34880+ if (!no_fail) {
34881+ res = NULL;
34882+ goto out;
34883+ } else {
34884+ /*
34885+ * Update active_pages_total since alloc can't fail.
34886+ * If it wasn't updated then the counter would cross 0
34887+ * on free again.
34888+ */
34889+ sgv_hiwmk_uncheck(-pages);
34890+ }
34891+ }
34892+
34893+ res = kmalloc(pages*sizeof(*res), gfp_mask);
34894+ if (res == NULL) {
34895+ TRACE(TRACE_OUT_OF_MEM, "Unable to allocate sg for %d pages",
34896+ pages);
34897+ goto out_uncheck;
34898+ }
34899+
34900+ sg_init_table(res, pages);
34901+
34902+ /*
34903+ * If we allow use clustering here, we will have troubles in
34904+ * scst_free() to figure out how many pages are in the SG vector.
34905+ * So, let's always don't use clustering.
34906+ */
34907+ cnt = sgv_alloc_sg_entries(res, pages, gfp_mask, sgv_no_clustering,
34908+ NULL, &sys_alloc_fns, NULL);
34909+ if (cnt <= 0)
34910+ goto out_free;
34911+
34912+ if (size & ~PAGE_MASK)
34913+ res[cnt-1].length -= PAGE_SIZE - (size & ~PAGE_MASK);
34914+
34915+ *count = cnt;
34916+
34917+out:
34918+ TRACE_MEM("Alloced sg %p (count %d, no_fail %d)", res, *count, no_fail);
34919+
34920+ TRACE_EXIT_HRES(res);
34921+ return res;
34922+
34923+out_free:
34924+ kfree(res);
34925+ res = NULL;
34926+
34927+out_uncheck:
34928+ if (!no_fail)
34929+ sgv_hiwmk_uncheck(pages);
34930+ goto out;
34931+}
34932+EXPORT_SYMBOL_GPL(scst_alloc);
34933+
34934+/**
34935+ * scst_free() - frees SG vector
34936+ *
34937+ * Frees SG vector returned by scst_alloc().
34938+ */
34939+void scst_free(struct scatterlist *sg, int count)
34940+{
34941+ TRACE_MEM("Freeing sg=%p", sg);
34942+
34943+ sgv_hiwmk_uncheck(count);
34944+
34945+ sgv_free_sys_sg_entries(sg, count, NULL);
34946+ kfree(sg);
34947+ return;
34948+}
34949+EXPORT_SYMBOL_GPL(scst_free);
34950+
34951+/* Must be called under sgv_pools_mutex */
34952+static void sgv_pool_init_cache(struct sgv_pool *pool, int cache_num)
34953+{
34954+ int size;
34955+ int pages;
34956+ struct sgv_pool_obj *obj;
34957+
34958+ atomic_set(&pool->cache_acc[cache_num].total_alloc, 0);
34959+ atomic_set(&pool->cache_acc[cache_num].hit_alloc, 0);
34960+ atomic_set(&pool->cache_acc[cache_num].merged, 0);
34961+
34962+ if (pool->single_alloc_pages == 0)
34963+ pages = 1 << cache_num;
34964+ else
34965+ pages = pool->single_alloc_pages;
34966+
34967+ if (pages <= sgv_max_local_pages) {
34968+ size = sizeof(*obj) + pages *
34969+ (sizeof(obj->sg_entries[0]) +
34970+ ((pool->clustering_type != sgv_no_clustering) ?
34971+ sizeof(obj->trans_tbl[0]) : 0));
34972+ } else if (pages <= sgv_max_trans_pages) {
34973+ /*
34974+ * sg_entries is allocated outside object,
34975+ * but trans_tbl is still embedded.
34976+ */
34977+ size = sizeof(*obj) + pages *
34978+ (((pool->clustering_type != sgv_no_clustering) ?
34979+ sizeof(obj->trans_tbl[0]) : 0));
34980+ } else {
34981+ size = sizeof(*obj);
34982+ /* both sgv and trans_tbl are kmalloc'ed() */
34983+ }
34984+
34985+ TRACE_MEM("pages=%d, size=%d", pages, size);
34986+
34987+ scnprintf(pool->cache_names[cache_num],
34988+ sizeof(pool->cache_names[cache_num]),
34989+ "%s-%uK", pool->name, (pages << PAGE_SHIFT) >> 10);
34990+ pool->caches[cache_num] = kmem_cache_create(
34991+ pool->cache_names[cache_num], size, 0, SCST_SLAB_FLAGS, NULL
34992+ );
34993+ return;
34994+}
34995+
34996+/* Must be called under sgv_pools_mutex */
34997+static int sgv_pool_init(struct sgv_pool *pool, const char *name,
34998+ enum sgv_clustering_types clustering_type, int single_alloc_pages,
34999+ int purge_interval)
35000+{
35001+ int res = -ENOMEM;
35002+ int i;
35003+
35004+ TRACE_ENTRY();
35005+
35006+ if (single_alloc_pages < 0) {
35007+ PRINT_ERROR("Wrong single_alloc_pages value %d",
35008+ single_alloc_pages);
35009+ res = -EINVAL;
35010+ goto out;
35011+ }
35012+
35013+ memset(pool, 0, sizeof(*pool));
35014+
35015+ atomic_set(&pool->big_alloc, 0);
35016+ atomic_set(&pool->big_pages, 0);
35017+ atomic_set(&pool->big_merged, 0);
35018+ atomic_set(&pool->other_alloc, 0);
35019+ atomic_set(&pool->other_pages, 0);
35020+ atomic_set(&pool->other_merged, 0);
35021+
35022+ pool->clustering_type = clustering_type;
35023+ pool->single_alloc_pages = single_alloc_pages;
35024+ if (purge_interval != 0) {
35025+ pool->purge_interval = purge_interval;
35026+ if (purge_interval < 0) {
35027+ /* Let's pretend that it's always scheduled */
35028+ pool->purge_work_scheduled = 1;
35029+ }
35030+ } else
35031+ pool->purge_interval = SGV_DEFAULT_PURGE_INTERVAL;
35032+ if (single_alloc_pages == 0) {
35033+ pool->max_caches = SGV_POOL_ELEMENTS;
35034+ pool->max_cached_pages = 1 << (SGV_POOL_ELEMENTS - 1);
35035+ } else {
35036+ pool->max_caches = 1;
35037+ pool->max_cached_pages = single_alloc_pages;
35038+ }
35039+ pool->alloc_fns.alloc_pages_fn = sgv_alloc_sys_pages;
35040+ pool->alloc_fns.free_pages_fn = sgv_free_sys_sg_entries;
35041+
35042+ TRACE_MEM("name %s, sizeof(*obj)=%zd, clustering_type=%d, "
35043+ "single_alloc_pages=%d, max_caches=%d, max_cached_pages=%d",
35044+ name, sizeof(struct sgv_pool_obj), clustering_type,
35045+ single_alloc_pages, pool->max_caches, pool->max_cached_pages);
35046+
35047+ strlcpy(pool->name, name, sizeof(pool->name)-1);
35048+
35049+ pool->owner_mm = current->mm;
35050+
35051+ for (i = 0; i < pool->max_caches; i++) {
35052+ sgv_pool_init_cache(pool, i);
35053+ if (pool->caches[i] == NULL) {
35054+ TRACE(TRACE_OUT_OF_MEM, "Allocation of sgv_pool "
35055+ "cache %s(%d) failed", name, i);
35056+ goto out_free;
35057+ }
35058+ }
35059+
35060+ atomic_set(&pool->sgv_pool_ref, 1);
35061+ spin_lock_init(&pool->sgv_pool_lock);
35062+ INIT_LIST_HEAD(&pool->sorted_recycling_list);
35063+ for (i = 0; i < pool->max_caches; i++)
35064+ INIT_LIST_HEAD(&pool->recycling_lists[i]);
35065+
35066+ INIT_DELAYED_WORK(&pool->sgv_purge_work,
35067+ (void (*)(struct work_struct *))sgv_purge_work_fn);
35068+
35069+ spin_lock_bh(&sgv_pools_lock);
35070+ list_add_tail(&pool->sgv_pools_list_entry, &sgv_pools_list);
35071+ spin_unlock_bh(&sgv_pools_lock);
35072+
35073+ res = scst_sgv_sysfs_create(pool);
35074+ if (res != 0)
35075+ goto out_del;
35076+
35077+ res = 0;
35078+
35079+out:
35080+ TRACE_EXIT_RES(res);
35081+ return res;
35082+
35083+out_del:
35084+ spin_lock_bh(&sgv_pools_lock);
35085+ list_del(&pool->sgv_pools_list_entry);
35086+ spin_unlock_bh(&sgv_pools_lock);
35087+
35088+out_free:
35089+ for (i = 0; i < pool->max_caches; i++) {
35090+ if (pool->caches[i]) {
35091+ kmem_cache_destroy(pool->caches[i]);
35092+ pool->caches[i] = NULL;
35093+ } else
35094+ break;
35095+ }
35096+ goto out;
35097+}
35098+
35099+static void sgv_evaluate_local_max_pages(void)
35100+{
35101+ int space4sgv_ttbl = PAGE_SIZE - sizeof(struct sgv_pool_obj);
35102+
35103+ sgv_max_local_pages = space4sgv_ttbl /
35104+ (sizeof(struct trans_tbl_ent) + sizeof(struct scatterlist));
35105+
35106+ sgv_max_trans_pages = space4sgv_ttbl / sizeof(struct trans_tbl_ent);
35107+
35108+ TRACE_MEM("sgv_max_local_pages %d, sgv_max_trans_pages %d",
35109+ sgv_max_local_pages, sgv_max_trans_pages);
35110+ return;
35111+}
35112+
35113+/**
35114+ * sgv_pool_flush - flushe the SGV pool
35115+ *
35116+ * Flushes, i.e. frees, all the cached entries in the SGV pool.
35117+ */
35118+void sgv_pool_flush(struct sgv_pool *pool)
35119+{
35120+ int i;
35121+
35122+ TRACE_ENTRY();
35123+
35124+ for (i = 0; i < pool->max_caches; i++) {
35125+ struct sgv_pool_obj *obj;
35126+
35127+ spin_lock_bh(&pool->sgv_pool_lock);
35128+
35129+ while (!list_empty(&pool->recycling_lists[i])) {
35130+ obj = list_entry(pool->recycling_lists[i].next,
35131+ struct sgv_pool_obj, recycling_list_entry);
35132+
35133+ __sgv_purge_from_cache(obj);
35134+
35135+ spin_unlock_bh(&pool->sgv_pool_lock);
35136+
35137+ EXTRACHECKS_BUG_ON(obj->owner_pool != pool);
35138+ sgv_dtor_and_free(obj);
35139+
35140+ spin_lock_bh(&pool->sgv_pool_lock);
35141+ }
35142+ spin_unlock_bh(&pool->sgv_pool_lock);
35143+ }
35144+
35145+ TRACE_EXIT();
35146+ return;
35147+}
35148+EXPORT_SYMBOL_GPL(sgv_pool_flush);
35149+
35150+static void sgv_pool_destroy(struct sgv_pool *pool)
35151+{
35152+ int i;
35153+
35154+ TRACE_ENTRY();
35155+
35156+ cancel_delayed_work_sync(&pool->sgv_purge_work);
35157+
35158+ sgv_pool_flush(pool);
35159+
35160+ mutex_lock(&sgv_pools_mutex);
35161+ spin_lock_bh(&sgv_pools_lock);
35162+ list_del(&pool->sgv_pools_list_entry);
35163+ spin_unlock_bh(&sgv_pools_lock);
35164+ mutex_unlock(&sgv_pools_mutex);
35165+
35166+ scst_sgv_sysfs_del(pool);
35167+
35168+ for (i = 0; i < pool->max_caches; i++) {
35169+ if (pool->caches[i])
35170+ kmem_cache_destroy(pool->caches[i]);
35171+ pool->caches[i] = NULL;
35172+ }
35173+
35174+ kfree(pool);
35175+
35176+ TRACE_EXIT();
35177+ return;
35178+}
35179+
35180+/**
35181+ * sgv_pool_set_allocator - set custom pages allocator
35182+ * @pool: the cache
35183+ * @alloc_pages_fn: pages allocation function
35184+ * @free_pages_fn: pages freeing function
35185+ *
35186+ * Description:
35187+ * Allows to set custom pages allocator for the SGV pool.
35188+ * See the SGV pool documentation for more details.
35189+ */
35190+void sgv_pool_set_allocator(struct sgv_pool *pool,
35191+ struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, void *),
35192+ void (*free_pages_fn)(struct scatterlist *, int, void *))
35193+{
35194+ pool->alloc_fns.alloc_pages_fn = alloc_pages_fn;
35195+ pool->alloc_fns.free_pages_fn = free_pages_fn;
35196+ return;
35197+}
35198+EXPORT_SYMBOL_GPL(sgv_pool_set_allocator);
35199+
35200+/**
35201+ * sgv_pool_create - creates and initializes an SGV pool
35202+ * @name: the name of the SGV pool
35203+ * @clustered: sets type of the pages clustering.
35204+ * @single_alloc_pages: if 0, then the SGV pool will work in the set of
35205+ * power 2 size buffers mode. If >0, then the SGV pool will
35206+ * work in the fixed size buffers mode. In this case
35207+ * single_alloc_pages sets the size of each buffer in pages.
35208+ * @shared: sets if the SGV pool can be shared between devices or not.
35209+ * The cache sharing allowed only between devices created inside
35210+ * the same address space. If an SGV pool is shared, each
35211+ * subsequent call of sgv_pool_create() with the same cache name
35212+ * will not create a new cache, but instead return a reference
35213+ * to it.
35214+ * @purge_interval: sets the cache purging interval. I.e., an SG buffer
35215+ * will be freed if it's unused for time t
35216+ * purge_interval <= t < 2*purge_interval. If purge_interval
35217+ * is 0, then the default interval will be used (60 seconds).
35218+ * If purge_interval <0, then the automatic purging will be
35219+ * disabled.
35220+ *
35221+ * Description:
35222+ * Returns the resulting SGV pool or NULL in case of any error.
35223+ */
35224+struct sgv_pool *sgv_pool_create(const char *name,
35225+ enum sgv_clustering_types clustering_type,
35226+ int single_alloc_pages, bool shared, int purge_interval)
35227+{
35228+ struct sgv_pool *pool;
35229+ int rc;
35230+
35231+ TRACE_ENTRY();
35232+
35233+ mutex_lock(&sgv_pools_mutex);
35234+
35235+ list_for_each_entry(pool, &sgv_pools_list, sgv_pools_list_entry) {
35236+ if (strcmp(pool->name, name) == 0) {
35237+ if (shared) {
35238+ if (pool->owner_mm != current->mm) {
35239+ PRINT_ERROR("Attempt of a shared use "
35240+ "of SGV pool %s with "
35241+ "different MM", name);
35242+ goto out_unlock;
35243+ }
35244+ sgv_pool_get(pool);
35245+ goto out_unlock;
35246+ } else {
35247+ PRINT_ERROR("SGV pool %s already exists", name);
35248+ pool = NULL;
35249+ goto out_unlock;
35250+ }
35251+ }
35252+ }
35253+
35254+ pool = kzalloc(sizeof(*pool), GFP_KERNEL);
35255+ if (pool == NULL) {
35256+ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of sgv_pool failed");
35257+ goto out_unlock;
35258+ }
35259+
35260+ rc = sgv_pool_init(pool, name, clustering_type, single_alloc_pages,
35261+ purge_interval);
35262+ if (rc != 0)
35263+ goto out_free;
35264+
35265+out_unlock:
35266+ mutex_unlock(&sgv_pools_mutex);
35267+
35268+ TRACE_EXIT_RES(pool != NULL);
35269+ return pool;
35270+
35271+out_free:
35272+ kfree(pool);
35273+ goto out_unlock;
35274+}
35275+EXPORT_SYMBOL_GPL(sgv_pool_create);
35276+
35277+/**
35278+ * sgv_pool_get - increase ref counter for the corresponding SGV pool
35279+ *
35280+ * Increases ref counter for the corresponding SGV pool
35281+ */
35282+void sgv_pool_get(struct sgv_pool *pool)
35283+{
35284+ atomic_inc(&pool->sgv_pool_ref);
35285+ TRACE_MEM("Incrementing sgv pool %p ref (new value %d)",
35286+ pool, atomic_read(&pool->sgv_pool_ref));
35287+ return;
35288+}
35289+EXPORT_SYMBOL_GPL(sgv_pool_get);
35290+
35291+/**
35292+ * sgv_pool_put - decrease ref counter for the corresponding SGV pool
35293+ *
35294+ * Decreases ref counter for the corresponding SGV pool. If the ref
35295+ * counter reaches 0, the cache will be destroyed.
35296+ */
35297+void sgv_pool_put(struct sgv_pool *pool)
35298+{
35299+ TRACE_MEM("Decrementing sgv pool %p ref (new value %d)",
35300+ pool, atomic_read(&pool->sgv_pool_ref)-1);
35301+ if (atomic_dec_and_test(&pool->sgv_pool_ref))
35302+ sgv_pool_destroy(pool);
35303+ return;
35304+}
35305+EXPORT_SYMBOL_GPL(sgv_pool_put);
35306+
35307+/**
35308+ * sgv_pool_del - deletes the corresponding SGV pool
35309+ * @pool: the cache to delete.
35310+ *
35311+ * Description:
35312+ * If the cache is shared, it will decrease its reference counter.
35313+ * If the reference counter reaches 0, the cache will be destroyed.
35314+ */
35315+void sgv_pool_del(struct sgv_pool *pool)
35316+{
35317+ TRACE_ENTRY();
35318+
35319+ sgv_pool_put(pool);
35320+
35321+ TRACE_EXIT();
35322+ return;
35323+}
35324+EXPORT_SYMBOL_GPL(sgv_pool_del);
35325+
35326+/* Both parameters in pages */
35327+int scst_sgv_pools_init(unsigned long mem_hwmark, unsigned long mem_lwmark)
35328+{
35329+ int res = 0;
35330+
35331+ TRACE_ENTRY();
35332+
35333+ sgv_hi_wmk = mem_hwmark;
35334+ sgv_lo_wmk = mem_lwmark;
35335+
35336+ sgv_evaluate_local_max_pages();
35337+
35338+ sgv_norm_pool = sgv_pool_create("sgv", sgv_no_clustering, 0, false, 0);
35339+ if (sgv_norm_pool == NULL)
35340+ goto out_err;
35341+
35342+ sgv_norm_clust_pool = sgv_pool_create("sgv-clust",
35343+ sgv_full_clustering, 0, false, 0);
35344+ if (sgv_norm_clust_pool == NULL)
35345+ goto out_free_norm;
35346+
35347+ sgv_dma_pool = sgv_pool_create("sgv-dma", sgv_no_clustering, 0,
35348+ false, 0);
35349+ if (sgv_dma_pool == NULL)
35350+ goto out_free_clust;
35351+
35352+ sgv_shrinker.shrink = sgv_shrink;
35353+ sgv_shrinker.seeks = DEFAULT_SEEKS;
35354+ register_shrinker(&sgv_shrinker);
35355+
35356+out:
35357+ TRACE_EXIT_RES(res);
35358+ return res;
35359+
35360+out_free_clust:
35361+ sgv_pool_destroy(sgv_norm_clust_pool);
35362+
35363+out_free_norm:
35364+ sgv_pool_destroy(sgv_norm_pool);
35365+
35366+out_err:
35367+ res = -ENOMEM;
35368+ goto out;
35369+}
35370+
35371+void scst_sgv_pools_deinit(void)
35372+{
35373+ TRACE_ENTRY();
35374+
35375+ unregister_shrinker(&sgv_shrinker);
35376+
35377+ sgv_pool_destroy(sgv_dma_pool);
35378+ sgv_pool_destroy(sgv_norm_pool);
35379+ sgv_pool_destroy(sgv_norm_clust_pool);
35380+
35381+ flush_scheduled_work();
35382+
35383+ TRACE_EXIT();
35384+ return;
35385+}
35386+
35387+ssize_t sgv_sysfs_stat_show(struct kobject *kobj,
35388+ struct kobj_attribute *attr, char *buf)
35389+{
35390+ struct sgv_pool *pool;
35391+ int i, total = 0, hit = 0, merged = 0, allocated = 0;
35392+ int oa, om, res;
35393+
35394+ pool = container_of(kobj, struct sgv_pool, sgv_kobj);
35395+
35396+ for (i = 0; i < SGV_POOL_ELEMENTS; i++) {
35397+ int t;
35398+
35399+ hit += atomic_read(&pool->cache_acc[i].hit_alloc);
35400+ total += atomic_read(&pool->cache_acc[i].total_alloc);
35401+
35402+ t = atomic_read(&pool->cache_acc[i].total_alloc) -
35403+ atomic_read(&pool->cache_acc[i].hit_alloc);
35404+ allocated += t * (1 << i);
35405+ merged += atomic_read(&pool->cache_acc[i].merged);
35406+ }
35407+
35408+ res = sprintf(buf, "%-30s %-11s %-11s %-11s %-11s", "Name", "Hit", "Total",
35409+ "% merged", "Cached (P/I/O)");
35410+
35411+ res += sprintf(&buf[res], "\n%-30s %-11d %-11d %-11d %d/%d/%d\n",
35412+ pool->name, hit, total,
35413+ (allocated != 0) ? merged*100/allocated : 0,
35414+ pool->cached_pages, pool->inactive_cached_pages,
35415+ pool->cached_entries);
35416+
35417+ for (i = 0; i < SGV_POOL_ELEMENTS; i++) {
35418+ int t = atomic_read(&pool->cache_acc[i].total_alloc) -
35419+ atomic_read(&pool->cache_acc[i].hit_alloc);
35420+ allocated = t * (1 << i);
35421+ merged = atomic_read(&pool->cache_acc[i].merged);
35422+
35423+ res += sprintf(&buf[res], " %-28s %-11d %-11d %d\n",
35424+ pool->cache_names[i],
35425+ atomic_read(&pool->cache_acc[i].hit_alloc),
35426+ atomic_read(&pool->cache_acc[i].total_alloc),
35427+ (allocated != 0) ? merged*100/allocated : 0);
35428+ }
35429+
35430+ allocated = atomic_read(&pool->big_pages);
35431+ merged = atomic_read(&pool->big_merged);
35432+ oa = atomic_read(&pool->other_pages);
35433+ om = atomic_read(&pool->other_merged);
35434+
35435+ res += sprintf(&buf[res], " %-40s %d/%-9d %d/%d\n", "big/other",
35436+ atomic_read(&pool->big_alloc), atomic_read(&pool->other_alloc),
35437+ (allocated != 0) ? merged*100/allocated : 0,
35438+ (oa != 0) ? om/oa : 0);
35439+
35440+ return res;
35441+}
35442+
35443+ssize_t sgv_sysfs_stat_reset(struct kobject *kobj,
35444+ struct kobj_attribute *attr, const char *buf, size_t count)
35445+{
35446+ struct sgv_pool *pool;
35447+ int i;
35448+
35449+ TRACE_ENTRY();
35450+
35451+ pool = container_of(kobj, struct sgv_pool, sgv_kobj);
35452+
35453+ for (i = 0; i < SGV_POOL_ELEMENTS; i++) {
35454+ atomic_set(&pool->cache_acc[i].hit_alloc, 0);
35455+ atomic_set(&pool->cache_acc[i].total_alloc, 0);
35456+ atomic_set(&pool->cache_acc[i].merged, 0);
35457+ }
35458+
35459+ atomic_set(&pool->big_pages, 0);
35460+ atomic_set(&pool->big_merged, 0);
35461+ atomic_set(&pool->big_alloc, 0);
35462+ atomic_set(&pool->other_pages, 0);
35463+ atomic_set(&pool->other_merged, 0);
35464+ atomic_set(&pool->other_alloc, 0);
35465+
35466+ PRINT_INFO("Statistics for SGV pool %s resetted", pool->name);
35467+
35468+ TRACE_EXIT_RES(count);
35469+ return count;
35470+}
35471+
35472+ssize_t sgv_sysfs_global_stat_show(struct kobject *kobj,
35473+ struct kobj_attribute *attr, char *buf)
35474+{
35475+ struct sgv_pool *pool;
35476+ int inactive_pages = 0, res;
35477+
35478+ TRACE_ENTRY();
35479+
35480+ spin_lock_bh(&sgv_pools_lock);
35481+ list_for_each_entry(pool, &sgv_active_pools_list,
35482+ sgv_active_pools_list_entry) {
35483+ inactive_pages += pool->inactive_cached_pages;
35484+ }
35485+ spin_unlock_bh(&sgv_pools_lock);
35486+
35487+ res = sprintf(buf, "%-42s %d/%d\n%-42s %d/%d\n%-42s %d/%d\n"
35488+ "%-42s %-11d\n",
35489+ "Inactive/active pages", inactive_pages,
35490+ atomic_read(&sgv_pages_total) - inactive_pages,
35491+ "Hi/lo watermarks [pages]", sgv_hi_wmk, sgv_lo_wmk,
35492+ "Hi watermark releases/failures",
35493+ atomic_read(&sgv_releases_on_hiwmk),
35494+ atomic_read(&sgv_releases_on_hiwmk_failed),
35495+ "Other allocs", atomic_read(&sgv_other_total_alloc));
35496+
35497+ TRACE_EXIT();
35498+ return res;
35499+}
35500+
35501+ssize_t sgv_sysfs_global_stat_reset(struct kobject *kobj,
35502+ struct kobj_attribute *attr, const char *buf, size_t count)
35503+{
35504+ TRACE_ENTRY();
35505+
35506+ atomic_set(&sgv_releases_on_hiwmk, 0);
35507+ atomic_set(&sgv_releases_on_hiwmk_failed, 0);
35508+ atomic_set(&sgv_other_total_alloc, 0);
35509+
35510+ PRINT_INFO("%s", "Global SGV pool statistics resetted");
35511+
35512+ TRACE_EXIT_RES(count);
35513+ return count;
35514+}
35515+
35516diff -uprN orig/linux-2.6.35/Documentation/scst/sgv_cache.txt linux-2.6.35/Documentation/scst/sgv_cache.txt
35517--- orig/linux-2.6.35/Documentation/scst/sgv_cache.txt
35518+++ linux-2.6.35/Documentation/scst/sgv_cache.txt
35519@@ -0,0 +1,224 @@
35520+ SCST SGV CACHE.
35521+
35522+ PROGRAMMING INTERFACE DESCRIPTION.
35523+
35524+ For SCST version 1.0.2
35525+
35526+SCST SGV cache is a memory management subsystem in SCST. One can call it
35527+a "memory pool", but Linux kernel already have a mempool interface,
35528+which serves different purposes. SGV cache provides to SCST core, target
35529+drivers and backend dev handlers facilities to allocate, build and cache
35530+SG vectors for data buffers. The main advantage of it is the caching
35531+facility, when it doesn't free to the system each vector, which is not
35532+used anymore, but keeps it for a while (possibly indefinitely) to let it
35533+be reused by the next consecutive command. This allows to:
35534+
35535+ - Reduce commands processing latencies and, hence, improve performance;
35536+
35537+ - Make commands processing latencies predictable, which is essential
35538+ for RT applications.
35539+
35540+The freed SG vectors are kept by the SGV cache either for some (possibly
35541+indefinite) time, or, optionally, until the system needs more memory and
35542+asks to free some using the set_shrinker() interface. Also the SGV cache
35543+allows to:
35544+
35545+ - Cluster pages together. "Cluster" means merging adjacent pages in a
35546+single SG entry. It allows to have less SG entries in the resulting SG
35547+vector, hence improve performance handling it as well as allow to
35548+work with bigger buffers on hardware with limited SG capabilities.
35549+
35550+ - Set custom page allocator functions. For instance, scst_user device
35551+handler uses this facility to eliminate unneeded mapping/unmapping of
35552+user space pages and avoid unneeded IOCTL calls for buffers allocations.
35553+In fileio_tgt application, which uses a regular malloc() function to
35554+allocate data buffers, this facility allows ~30% less CPU load and
35555+considerable performance increase.
35556+
35557+ - Prevent each initiator or all initiators altogether to allocate too
35558+much memory and DoS the target. Consider 10 initiators, which can have
35559+access to 10 devices each. Any of them can queue up to 64 commands, each
35560+can transfer up to 1MB of data. So, all of them in a peak can allocate
35561+up to 10*10*64 = ~6.5GB of memory for data buffers. This amount must be
35562+limited somehow and the SGV cache performs this function.
35563+
35564+From implementation POV the SGV cache is a simple extension of the kmem
35565+cache. It can work in 2 modes:
35566+
35567+1. With fixed size buffers.
35568+
35569+2. With a set of power 2 size buffers. In this mode each SGV cache
35570+(struct sgv_pool) has SGV_POOL_ELEMENTS (11 currently) of kmem caches.
35571+Each of those kmem caches keeps SGV cache objects (struct sgv_pool_obj)
35572+corresponding to SG vectors with size of order X pages. For instance,
35573+request to allocate 4 pages will be served from kmem cache[2], since the
35574+order of the of number of requested pages is 2. If later request to
35575+allocate 11KB comes, the same SG vector with 4 pages will be reused (see
35576+below). This mode is in average allows less memory overhead comparing
35577+with the fixed size buffers mode.
35578+
35579+Consider how the SGV cache works in the set of buffers mode. When a
35580+request to allocate new SG vector comes, sgv_pool_alloc() via
35581+sgv_get_obj() checks if there is already a cached vector with that
35582+order. If yes, then that vector will be reused and its length, if
35583+necessary, will be modified to match the requested size. In the above
35584+example request for 11KB buffer, 4 pages vector will be reused and
35585+modified using trans_tbl to contain 3 pages and the last entry will be
35586+modified to contain the requested length - 2*PAGE_SIZE. If there is no
35587+cached object, then a new sgv_pool_obj will be allocated from the
35588+corresponding kmem cache, chosen by the order of number of requested
35589+pages. Then that vector will be filled by pages and returned.
35590+
35591+In the fixed size buffers mode the SGV cache works similarly, except
35592+that it always allocate buffer with the predefined fixed size. I.e.
35593+even for 4K request the whole buffer with predefined size, say, 1MB,
35594+will be used.
35595+
35596+In both modes, if size of a request exceeds the maximum allowed for
35597+caching buffer size, the requested buffer will be allocated, but not
35598+cached.
35599+
35600+Freed cached sgv_pool_obj objects are actually freed to the system
35601+either by the purge work, which is scheduled once in 60 seconds, or in
35602+sgv_shrink() called by system, when it's asking for memory.
35603+
35604+ Interface.
35605+
35606+struct sgv_pool *sgv_pool_create(const char *name,
35607+ enum sgv_clustering_types clustered, int single_alloc_pages,
35608+ bool shared, int purge_interval)
35609+
35610+This function creates and initializes an SGV cache. It has the following
35611+arguments:
35612+
35613+ - name - the name of the SGV cache
35614+
35615+ - clustered - sets type of the pages clustering. The type can be:
35616+
35617+ * sgv_no_clustering - no clustering performed.
35618+
35619+ * sgv_tail_clustering - a page will only be merged with the latest
35620+ previously allocated page, so the order of pages in the SG will be
35621+ preserved
35622+
35623+ * sgv_full_clustering - free merging of pages at any place in
35624+ the SG is allowed. This mode usually provides the best merging
35625+ rate.
35626+
35627+ - single_alloc_pages - if 0, then the SGV cache will work in the set of
35628+ power 2 size buffers mode. If >0, then the SGV cache will work in the
35629+ fixed size buffers mode. In this case single_alloc_pages sets the
35630+ size of each buffer in pages.
35631+
35632+ - shared - sets if the SGV cache can be shared between devices or not.
35633+ The cache sharing allowed only between devices created inside the same
35634+ address space. If an SGV cache is shared, each subsequent call of
35635+ sgv_pool_create() with the same cache name will not create a new cache,
35636+ but instead return a reference to it.
35637+
35638+ - purge_interval - sets the cache purging interval. I.e. an SG buffer
35639+ will be freed if it's unused for time t purge_interval <= t <
35640+ 2*purge_interval. If purge_interval is 0, then the default interval
35641+ will be used (60 seconds). If purge_interval <0, then the automatic
35642+ purging will be disabled. Shrinking by the system's demand will also
35643+ be disabled.
35644+
35645+Returns the resulting SGV cache or NULL in case of any error.
35646+
35647+void sgv_pool_del(struct sgv_pool *pool)
35648+
35649+This function deletes the corresponding SGV cache. If the cache is
35650+shared, it will decrease its reference counter. If the reference counter
35651+reaches 0, the cache will be destroyed.
35652+
35653+void sgv_pool_flush(struct sgv_pool *pool)
35654+
35655+This function flushes, i.e. frees, all the cached entries in the SGV
35656+cache.
35657+
35658+void sgv_pool_set_allocator(struct sgv_pool *pool,
35659+ struct page *(*alloc_pages_fn)(struct scatterlist *sg, gfp_t gfp, void *priv),
35660+ void (*free_pages_fn)(struct scatterlist *sg, int sg_count, void *priv));
35661+
35662+This function allows to set for the SGV cache a custom pages allocator. For
35663+instance, scst_user uses such function to supply to the cache mapped from
35664+user space pages.
35665+
35666+alloc_pages_fn() has the following parameters:
35667+
35668+ - sg - SG entry, to which the allocated page should be added.
35669+
35670+ - gfp - the allocation GFP flags
35671+
35672+ - priv - pointer to a private data supplied to sgv_pool_alloc()
35673+
35674+This function should return the allocated page or NULL, if no page was
35675+allocated.
35676+
35677+free_pages_fn() has the following parameters:
35678+
35679+ - sg - SG vector to free
35680+
35681+ - sg_count - number of SG entries in the sg
35682+
35683+ - priv - pointer to a private data supplied to the corresponding sgv_pool_alloc()
35684+
35685+struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
35686+ gfp_t gfp_mask, int flags, int *count,
35687+ struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv)
35688+
35689+This function allocates an SG vector from the SGV cache. It has the
35690+following parameters:
35691+
35692+ - pool - the cache to alloc from
35693+
35694+ - size - size of the resulting SG vector in bytes
35695+
35696+ - gfp_mask - the allocation mask
35697+
35698+ - flags - the allocation flags. The following flags are possible and
35699+ can be set using OR operation:
35700+
35701+ * SGV_POOL_ALLOC_NO_CACHED - the SG vector must not be cached.
35702+
35703+ * SGV_POOL_NO_ALLOC_ON_CACHE_MISS - don't do an allocation on a
35704+ cache miss.
35705+
35706+ * SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL - return an empty SGV object,
35707+ i.e. without the SG vector, if the allocation can't be completed.
35708+ For instance, because SGV_POOL_NO_ALLOC_ON_CACHE_MISS flag set.
35709+
35710+ - count - the resulting count of SG entries in the resulting SG vector.
35711+
35712+ - sgv - the resulting SGV object. It should be used to free the
35713+ resulting SG vector.
35714+
35715+ - mem_lim - memory limits, see below.
35716+
35717+ - priv - pointer to private for this allocation data. This pointer will
35718+ be supplied to alloc_pages_fn() and free_pages_fn() and can be
35719+ retrieved by sgv_get_priv().
35720+
35721+This function returns pointer to the resulting SG vector or NULL in case
35722+of any error.
35723+
35724+void sgv_pool_free(struct sgv_pool_obj *sgv, struct scst_mem_lim *mem_lim)
35725+
35726+This function frees previously allocated SG vector, referenced by SGV
35727+cache object sgv.
35728+
35729+void *sgv_get_priv(struct sgv_pool_obj *sgv)
35730+
35731+This function allows to get the allocation private data for this SGV
35732+cache object sgv. The private data are set by sgv_pool_alloc().
35733+
35734+void scst_init_mem_lim(struct scst_mem_lim *mem_lim)
35735+
35736+This function initializes memory limits structure mem_lim according to
35737+the current system configuration. This structure should be latter used
35738+to track and limit allocated by one or more SGV caches memory.
35739+
35740+ Runtime information and statistics.
35741+
35742+Runtime information and statistics is available in /sys/kernel/scst_tgt/sgv.
35743+
35744diff -uprN orig/linux-2.6.35/include/scst/scst_user.h linux-2.6.35/include/scst/scst_user.h
35745--- orig/linux-2.6.35/include/scst/scst_user.h
35746+++ linux-2.6.35/include/scst/scst_user.h
35747@@ -0,0 +1,321 @@
35748+/*
35749+ * include/scst_user.h
35750+ *
35751+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
35752+ * Copyright (C) 2007 - 2010 ID7 Ltd.
35753+ *
35754+ * Contains constants and data structures for scst_user module.
35755+ * See http://scst.sourceforge.net/doc/scst_user_spec.txt or
35756+ * scst_user_spec.txt for description.
35757+ *
35758+ * This program is free software; you can redistribute it and/or
35759+ * modify it under the terms of the GNU General Public License
35760+ * as published by the Free Software Foundation, version 2
35761+ * of the License.
35762+ *
35763+ * This program is distributed in the hope that it will be useful,
35764+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35765+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35766+ * GNU General Public License for more details.
35767+ */
35768+
35769+#ifndef __SCST_USER_H
35770+#define __SCST_USER_H
35771+
35772+#include <scst/scst_const.h>
35773+
35774+#define DEV_USER_NAME "scst_user"
35775+#define DEV_USER_PATH "/dev/"
35776+#define DEV_USER_VERSION_NAME "2.0.0-rc3"
35777+#define DEV_USER_VERSION \
35778+ DEV_USER_VERSION_NAME "$Revision: 2091 $" SCST_CONST_VERSION
35779+
35780+#define SCST_USER_PARSE_STANDARD 0
35781+#define SCST_USER_PARSE_CALL 1
35782+#define SCST_USER_PARSE_EXCEPTION 2
35783+#define SCST_USER_MAX_PARSE_OPT SCST_USER_PARSE_EXCEPTION
35784+
35785+#define SCST_USER_ON_FREE_CMD_CALL 0
35786+#define SCST_USER_ON_FREE_CMD_IGNORE 1
35787+#define SCST_USER_MAX_ON_FREE_CMD_OPT SCST_USER_ON_FREE_CMD_IGNORE
35788+
35789+#define SCST_USER_MEM_NO_REUSE 0
35790+#define SCST_USER_MEM_REUSE_READ 1
35791+#define SCST_USER_MEM_REUSE_WRITE 2
35792+#define SCST_USER_MEM_REUSE_ALL 3
35793+#define SCST_USER_MAX_MEM_REUSE_OPT SCST_USER_MEM_REUSE_ALL
35794+
35795+#define SCST_USER_PARTIAL_TRANSFERS_NOT_SUPPORTED 0
35796+#define SCST_USER_PARTIAL_TRANSFERS_SUPPORTED_ORDERED 1
35797+#define SCST_USER_PARTIAL_TRANSFERS_SUPPORTED 2
35798+#define SCST_USER_MAX_PARTIAL_TRANSFERS_OPT \
35799+ SCST_USER_PARTIAL_TRANSFERS_SUPPORTED
35800+
35801+#ifndef aligned_u64
35802+#define aligned_u64 uint64_t __attribute__((aligned(8)))
35803+#endif
35804+
35805+/*************************************************************
35806+ ** Private ucmd states
35807+ *************************************************************/
35808+#define UCMD_STATE_NEW 0
35809+#define UCMD_STATE_PARSING 1
35810+#define UCMD_STATE_BUF_ALLOCING 2
35811+#define UCMD_STATE_EXECING 3
35812+#define UCMD_STATE_ON_FREEING 4
35813+#define UCMD_STATE_ON_FREE_SKIPPED 5
35814+#define UCMD_STATE_ON_CACHE_FREEING 6
35815+#define UCMD_STATE_TM_EXECING 7
35816+
35817+#define UCMD_STATE_ATTACH_SESS 0x20
35818+#define UCMD_STATE_DETACH_SESS 0x21
35819+
35820+struct scst_user_opt {
35821+ uint8_t parse_type;
35822+ uint8_t on_free_cmd_type;
35823+ uint8_t memory_reuse_type;
35824+ uint8_t partial_transfers_type;
35825+ int32_t partial_len;
35826+
35827+ /* SCSI control mode page parameters, see SPC */
35828+ uint8_t tst;
35829+ uint8_t queue_alg;
35830+ uint8_t tas;
35831+ uint8_t swp;
35832+ uint8_t d_sense;
35833+
35834+ uint8_t has_own_order_mgmt;
35835+};
35836+
35837+struct scst_user_dev_desc {
35838+ aligned_u64 version_str;
35839+ aligned_u64 license_str;
35840+ uint8_t type;
35841+ uint8_t sgv_shared;
35842+ uint8_t sgv_disable_clustered_pool;
35843+ int32_t sgv_single_alloc_pages;
35844+ int32_t sgv_purge_interval;
35845+ struct scst_user_opt opt;
35846+ uint32_t block_size;
35847+ uint8_t enable_pr_cmds_notifications;
35848+ char name[SCST_MAX_NAME];
35849+ char sgv_name[SCST_MAX_NAME];
35850+};
35851+
35852+struct scst_user_sess {
35853+ aligned_u64 sess_h;
35854+ aligned_u64 lun;
35855+ uint16_t threads_num;
35856+ uint8_t rd_only;
35857+ uint16_t scsi_transport_version;
35858+ uint16_t phys_transport_version;
35859+ char initiator_name[SCST_MAX_EXTERNAL_NAME];
35860+ char target_name[SCST_MAX_EXTERNAL_NAME];
35861+};
35862+
35863+struct scst_user_scsi_cmd_parse {
35864+ aligned_u64 sess_h;
35865+
35866+ uint8_t cdb[SCST_MAX_CDB_SIZE];
35867+ uint16_t cdb_len;
35868+ uint16_t ext_cdb_len;
35869+
35870+ int32_t timeout;
35871+ int32_t bufflen;
35872+ int32_t out_bufflen;
35873+
35874+ uint32_t op_flags;
35875+
35876+ uint8_t queue_type;
35877+ uint8_t data_direction;
35878+
35879+ uint8_t expected_values_set;
35880+ uint8_t expected_data_direction;
35881+ int32_t expected_transfer_len;
35882+ int32_t expected_out_transfer_len;
35883+
35884+ uint32_t sn;
35885+};
35886+
35887+struct scst_user_scsi_cmd_alloc_mem {
35888+ aligned_u64 sess_h;
35889+
35890+ uint8_t cdb[SCST_MAX_CDB_SIZE];
35891+ uint16_t cdb_len;
35892+ uint16_t ext_cdb_len;
35893+
35894+ int32_t alloc_len;
35895+
35896+ uint8_t queue_type;
35897+ uint8_t data_direction;
35898+
35899+ uint32_t sn;
35900+};
35901+
35902+struct scst_user_scsi_cmd_exec {
35903+ aligned_u64 sess_h;
35904+
35905+ uint8_t cdb[SCST_MAX_CDB_SIZE];
35906+ uint16_t cdb_len;
35907+ uint16_t ext_cdb_len;
35908+
35909+ int32_t data_len;
35910+ int32_t bufflen;
35911+ int32_t alloc_len;
35912+ aligned_u64 pbuf;
35913+ uint8_t queue_type;
35914+ uint8_t data_direction;
35915+ uint8_t partial;
35916+ int32_t timeout;
35917+
35918+ aligned_u64 p_out_buf;
35919+ int32_t out_bufflen;
35920+
35921+ uint32_t sn;
35922+
35923+ uint32_t parent_cmd_h;
35924+ int32_t parent_cmd_data_len;
35925+ uint32_t partial_offset;
35926+};
35927+
35928+struct scst_user_scsi_on_free_cmd {
35929+ aligned_u64 pbuf;
35930+ int32_t resp_data_len;
35931+ uint8_t buffer_cached;
35932+ uint8_t aborted;
35933+ uint8_t status;
35934+ uint8_t delivery_status;
35935+};
35936+
35937+struct scst_user_on_cached_mem_free {
35938+ aligned_u64 pbuf;
35939+};
35940+
35941+struct scst_user_tm {
35942+ aligned_u64 sess_h;
35943+ uint32_t fn;
35944+ uint32_t cmd_h_to_abort;
35945+ uint32_t cmd_sn;
35946+ uint8_t cmd_sn_set;
35947+};
35948+
35949+struct scst_user_get_cmd {
35950+ uint32_t cmd_h;
35951+ uint32_t subcode;
35952+ union {
35953+ aligned_u64 preply;
35954+ struct scst_user_sess sess;
35955+ struct scst_user_scsi_cmd_parse parse_cmd;
35956+ struct scst_user_scsi_cmd_alloc_mem alloc_cmd;
35957+ struct scst_user_scsi_cmd_exec exec_cmd;
35958+ struct scst_user_scsi_on_free_cmd on_free_cmd;
35959+ struct scst_user_on_cached_mem_free on_cached_mem_free;
35960+ struct scst_user_tm tm_cmd;
35961+ };
35962+};
35963+
35964+/* Be careful adding new members here, this structure is allocated on stack! */
35965+struct scst_user_scsi_cmd_reply_parse {
35966+ uint8_t status;
35967+ union {
35968+ struct {
35969+ uint8_t queue_type;
35970+ uint8_t data_direction;
35971+ uint16_t cdb_len;
35972+ uint32_t op_flags;
35973+ int32_t data_len;
35974+ int32_t bufflen;
35975+ };
35976+ struct {
35977+ uint8_t sense_len;
35978+ aligned_u64 psense_buffer;
35979+ };
35980+ };
35981+};
35982+
35983+/* Be careful adding new members here, this structure is allocated on stack! */
35984+struct scst_user_scsi_cmd_reply_alloc_mem {
35985+ aligned_u64 pbuf;
35986+};
35987+
35988+/* Be careful adding new members here, this structure is allocated on stack! */
35989+struct scst_user_scsi_cmd_reply_exec {
35990+ int32_t resp_data_len;
35991+ aligned_u64 pbuf;
35992+
35993+#define SCST_EXEC_REPLY_BACKGROUND 0
35994+#define SCST_EXEC_REPLY_COMPLETED 1
35995+ uint8_t reply_type;
35996+
35997+ uint8_t status;
35998+ uint8_t sense_len;
35999+ aligned_u64 psense_buffer;
36000+};
36001+
36002+/* Be careful adding new members here, this structure is allocated on stack! */
36003+struct scst_user_reply_cmd {
36004+ uint32_t cmd_h;
36005+ uint32_t subcode;
36006+ union {
36007+ int32_t result;
36008+ struct scst_user_scsi_cmd_reply_parse parse_reply;
36009+ struct scst_user_scsi_cmd_reply_alloc_mem alloc_reply;
36010+ struct scst_user_scsi_cmd_reply_exec exec_reply;
36011+ };
36012+};
36013+
36014+/* Be careful adding new members here, this structure is allocated on stack! */
36015+struct scst_user_get_ext_cdb {
36016+ uint32_t cmd_h;
36017+ aligned_u64 ext_cdb_buffer;
36018+};
36019+
36020+/* Be careful adding new members here, this structure is allocated on stack! */
36021+struct scst_user_prealloc_buffer_in {
36022+ aligned_u64 pbuf;
36023+ uint32_t bufflen;
36024+ uint8_t for_clust_pool;
36025+};
36026+
36027+/* Be careful adding new members here, this structure is allocated on stack! */
36028+struct scst_user_prealloc_buffer_out {
36029+ uint32_t cmd_h;
36030+};
36031+
36032+/* Be careful adding new members here, this structure is allocated on stack! */
36033+union scst_user_prealloc_buffer {
36034+ struct scst_user_prealloc_buffer_in in;
36035+ struct scst_user_prealloc_buffer_out out;
36036+};
36037+
36038+#define SCST_USER_REGISTER_DEVICE _IOW('u', 1, struct scst_user_dev_desc)
36039+#define SCST_USER_UNREGISTER_DEVICE _IO('u', 2)
36040+#define SCST_USER_SET_OPTIONS _IOW('u', 3, struct scst_user_opt)
36041+#define SCST_USER_GET_OPTIONS _IOR('u', 4, struct scst_user_opt)
36042+#define SCST_USER_REPLY_AND_GET_CMD _IOWR('u', 5, struct scst_user_get_cmd)
36043+#define SCST_USER_REPLY_CMD _IOW('u', 6, struct scst_user_reply_cmd)
36044+#define SCST_USER_FLUSH_CACHE _IO('u', 7)
36045+#define SCST_USER_DEVICE_CAPACITY_CHANGED _IO('u', 8)
36046+#define SCST_USER_GET_EXTENDED_CDB _IOWR('u', 9, struct scst_user_get_ext_cdb)
36047+#define SCST_USER_PREALLOC_BUFFER _IOWR('u', 10, union scst_user_prealloc_buffer)
36048+
36049+/* Values for scst_user_get_cmd.subcode */
36050+#define SCST_USER_ATTACH_SESS \
36051+ _IOR('s', UCMD_STATE_ATTACH_SESS, struct scst_user_sess)
36052+#define SCST_USER_DETACH_SESS \
36053+ _IOR('s', UCMD_STATE_DETACH_SESS, struct scst_user_sess)
36054+#define SCST_USER_PARSE \
36055+ _IOWR('s', UCMD_STATE_PARSING, struct scst_user_scsi_cmd_parse)
36056+#define SCST_USER_ALLOC_MEM \
36057+ _IOWR('s', UCMD_STATE_BUF_ALLOCING, struct scst_user_scsi_cmd_alloc_mem)
36058+#define SCST_USER_EXEC \
36059+ _IOWR('s', UCMD_STATE_EXECING, struct scst_user_scsi_cmd_exec)
36060+#define SCST_USER_ON_FREE_CMD \
36061+ _IOR('s', UCMD_STATE_ON_FREEING, struct scst_user_scsi_on_free_cmd)
36062+#define SCST_USER_ON_CACHED_MEM_FREE \
36063+ _IOR('s', UCMD_STATE_ON_CACHE_FREEING, \
36064+ struct scst_user_on_cached_mem_free)
36065+#define SCST_USER_TASK_MGMT \
36066+ _IOWR('s', UCMD_STATE_TM_EXECING, struct scst_user_tm)
36067+
36068+#endif /* __SCST_USER_H */
36069diff -uprN orig/linux-2.6.35/drivers/scst/dev_handlers/scst_user.c linux-2.6.35/drivers/scst/dev_handlers/scst_user.c
36070--- orig/linux-2.6.35/drivers/scst/dev_handlers/scst_user.c
36071+++ linux-2.6.35/drivers/scst/dev_handlers/scst_user.c
36072@@ -0,0 +1,3738 @@
36073+/*
36074+ * scst_user.c
36075+ *
36076+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
36077+ * Copyright (C) 2007 - 2010 ID7 Ltd.
36078+ *
36079+ * SCSI virtual user space device handler
36080+ *
36081+ * This program is free software; you can redistribute it and/or
36082+ * modify it under the terms of the GNU General Public License
36083+ * as published by the Free Software Foundation, version 2
36084+ * of the License.
36085+ *
36086+ * This program is distributed in the hope that it will be useful,
36087+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36088+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36089+ * GNU General Public License for more details.
36090+ */
36091+
36092+#include <linux/kthread.h>
36093+#include <linux/delay.h>
36094+#include <linux/poll.h>
36095+#include <linux/stddef.h>
36096+#include <linux/slab.h>
36097+
36098+#define LOG_PREFIX DEV_USER_NAME
36099+
36100+#include <scst/scst.h>
36101+#include <scst/scst_user.h>
36102+#include "scst_dev_handler.h"
36103+
36104+#define DEV_USER_CMD_HASH_ORDER 6
36105+#define DEV_USER_ATTACH_TIMEOUT (5*HZ)
36106+
36107+struct scst_user_dev {
36108+ struct rw_semaphore dev_rwsem;
36109+
36110+ /*
36111+ * Must be kept here, because it's needed on the cleanup time,
36112+ * when corresponding scst_dev is already dead.
36113+ */
36114+ struct scst_cmd_threads udev_cmd_threads;
36115+
36116+ /* Protected by udev_cmd_threads.cmd_list_lock */
36117+ struct list_head ready_cmd_list;
36118+
36119+ /* Protected by dev_rwsem or don't need any protection */
36120+ unsigned int blocking:1;
36121+ unsigned int cleanup_done:1;
36122+ unsigned int tst:3;
36123+ unsigned int queue_alg:4;
36124+ unsigned int tas:1;
36125+ unsigned int swp:1;
36126+ unsigned int d_sense:1;
36127+ unsigned int has_own_order_mgmt:1;
36128+
36129+ int (*generic_parse)(struct scst_cmd *cmd,
36130+ int (*get_block)(struct scst_cmd *cmd));
36131+
36132+ int block;
36133+ int def_block;
36134+
36135+ struct scst_mem_lim udev_mem_lim;
36136+ struct sgv_pool *pool;
36137+ struct sgv_pool *pool_clust;
36138+
36139+ uint8_t parse_type;
36140+ uint8_t on_free_cmd_type;
36141+ uint8_t memory_reuse_type;
36142+ uint8_t partial_transfers_type;
36143+ uint32_t partial_len;
36144+
36145+ struct scst_dev_type devtype;
36146+
36147+ /* Both protected by udev_cmd_threads.cmd_list_lock */
36148+ unsigned int handle_counter;
36149+ struct list_head ucmd_hash[1 << DEV_USER_CMD_HASH_ORDER];
36150+
36151+ struct scst_device *sdev;
36152+
36153+ int virt_id;
36154+ struct list_head dev_list_entry;
36155+ char name[SCST_MAX_NAME];
36156+
36157+ struct list_head cleanup_list_entry;
36158+ struct completion cleanup_cmpl;
36159+};
36160+
36161+/* Most fields are unprotected, since only one thread at time can access them */
36162+struct scst_user_cmd {
36163+ struct scst_cmd *cmd;
36164+ struct scst_user_dev *dev;
36165+
36166+ atomic_t ucmd_ref;
36167+
36168+ unsigned int buff_cached:1;
36169+ unsigned int buf_dirty:1;
36170+ unsigned int background_exec:1;
36171+ unsigned int aborted:1;
36172+
36173+ struct scst_user_cmd *buf_ucmd;
36174+
36175+ int cur_data_page;
36176+ int num_data_pages;
36177+ int first_page_offset;
36178+ unsigned long ubuff;
36179+ struct page **data_pages;
36180+ struct sgv_pool_obj *sgv;
36181+
36182+ /*
36183+ * Special flags, which can be accessed asynchronously (hence "long").
36184+ * Protected by udev_cmd_threads.cmd_list_lock.
36185+ */
36186+ unsigned long sent_to_user:1;
36187+ unsigned long jammed:1;
36188+ unsigned long this_state_unjammed:1;
36189+ unsigned long seen_by_user:1; /* here only as a small optimization */
36190+
36191+ unsigned int state;
36192+
36193+ struct list_head ready_cmd_list_entry;
36194+
36195+ unsigned int h;
36196+ struct list_head hash_list_entry;
36197+
36198+ int user_cmd_payload_len;
36199+ struct scst_user_get_cmd user_cmd;
36200+
36201+ /* cmpl used only by ATTACH_SESS, mcmd used only by TM */
36202+ union {
36203+ struct completion *cmpl;
36204+ struct scst_mgmt_cmd *mcmd;
36205+ };
36206+ int result;
36207+};
36208+
36209+static struct scst_user_cmd *dev_user_alloc_ucmd(struct scst_user_dev *dev,
36210+ gfp_t gfp_mask);
36211+static void dev_user_free_ucmd(struct scst_user_cmd *ucmd);
36212+
36213+static int dev_user_parse(struct scst_cmd *cmd);
36214+static int dev_user_alloc_data_buf(struct scst_cmd *cmd);
36215+static int dev_user_exec(struct scst_cmd *cmd);
36216+static void dev_user_on_free_cmd(struct scst_cmd *cmd);
36217+static int dev_user_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
36218+ struct scst_tgt_dev *tgt_dev);
36219+
36220+static int dev_user_disk_done(struct scst_cmd *cmd);
36221+static int dev_user_tape_done(struct scst_cmd *cmd);
36222+
36223+static struct page *dev_user_alloc_pages(struct scatterlist *sg,
36224+ gfp_t gfp_mask, void *priv);
36225+static void dev_user_free_sg_entries(struct scatterlist *sg, int sg_count,
36226+ void *priv);
36227+
36228+static void dev_user_add_to_ready(struct scst_user_cmd *ucmd);
36229+
36230+static void dev_user_unjam_cmd(struct scst_user_cmd *ucmd, int busy,
36231+ unsigned long *flags);
36232+
36233+static int dev_user_process_reply_on_free(struct scst_user_cmd *ucmd);
36234+static int dev_user_process_reply_tm_exec(struct scst_user_cmd *ucmd,
36235+ int status);
36236+static int dev_user_process_reply_sess(struct scst_user_cmd *ucmd, int status);
36237+static int dev_user_register_dev(struct file *file,
36238+ const struct scst_user_dev_desc *dev_desc);
36239+static int dev_user_unregister_dev(struct file *file);
36240+static int dev_user_flush_cache(struct file *file);
36241+static int dev_user_capacity_changed(struct file *file);
36242+static int dev_user_prealloc_buffer(struct file *file, void __user *arg);
36243+static int __dev_user_set_opt(struct scst_user_dev *dev,
36244+ const struct scst_user_opt *opt);
36245+static int dev_user_set_opt(struct file *file, const struct scst_user_opt *opt);
36246+static int dev_user_get_opt(struct file *file, void __user *arg);
36247+
36248+static unsigned int dev_user_poll(struct file *filp, poll_table *wait);
36249+static long dev_user_ioctl(struct file *file, unsigned int cmd,
36250+ unsigned long arg);
36251+static int dev_user_release(struct inode *inode, struct file *file);
36252+static int dev_user_exit_dev(struct scst_user_dev *dev);
36253+
36254+static ssize_t dev_user_sysfs_commands_show(struct kobject *kobj,
36255+ struct kobj_attribute *attr, char *buf);
36256+
36257+static struct kobj_attribute dev_user_commands_attr =
36258+ __ATTR(commands, S_IRUGO, dev_user_sysfs_commands_show, NULL);
36259+
36260+static const struct attribute *dev_user_dev_attrs[] = {
36261+ &dev_user_commands_attr.attr,
36262+ NULL,
36263+};
36264+
36265+static int dev_usr_parse(struct scst_cmd *cmd);
36266+
36267+/** Data **/
36268+
36269+static struct kmem_cache *user_cmd_cachep;
36270+static struct kmem_cache *user_get_cmd_cachep;
36271+
36272+static DEFINE_MUTEX(dev_priv_mutex);
36273+
36274+static const struct file_operations dev_user_fops = {
36275+ .poll = dev_user_poll,
36276+ .unlocked_ioctl = dev_user_ioctl,
36277+#ifdef CONFIG_COMPAT
36278+ .compat_ioctl = dev_user_ioctl,
36279+#endif
36280+ .release = dev_user_release,
36281+};
36282+
36283+static struct scst_dev_type dev_user_devtype = {
36284+ .name = DEV_USER_NAME,
36285+ .type = -1,
36286+ .parse = dev_usr_parse,
36287+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
36288+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
36289+ .trace_flags = &trace_flag,
36290+#endif
36291+};
36292+
36293+static int dev_user_major;
36294+
36295+static struct class *dev_user_sysfs_class;
36296+
36297+static DEFINE_SPINLOCK(dev_list_lock);
36298+static LIST_HEAD(dev_list);
36299+
36300+static DEFINE_SPINLOCK(cleanup_lock);
36301+static LIST_HEAD(cleanup_list);
36302+static DECLARE_WAIT_QUEUE_HEAD(cleanup_list_waitQ);
36303+static struct task_struct *cleanup_thread;
36304+
36305+/*
36306+ * Skip this command if result is not 0. Must be called under
36307+ * udev_cmd_threads.cmd_list_lock and IRQ off.
36308+ */
36309+static inline bool ucmd_get_check(struct scst_user_cmd *ucmd)
36310+{
36311+ int r = atomic_inc_return(&ucmd->ucmd_ref);
36312+ int res;
36313+ if (unlikely(r == 1)) {
36314+ TRACE_DBG("ucmd %p is being destroyed", ucmd);
36315+ atomic_dec(&ucmd->ucmd_ref);
36316+ res = true;
36317+ /*
36318+ * Necessary code is serialized by cmd_list_lock in
36319+ * cmd_remove_hash()
36320+ */
36321+ } else {
36322+ TRACE_DBG("ucmd %p, new ref_cnt %d", ucmd,
36323+ atomic_read(&ucmd->ucmd_ref));
36324+ res = false;
36325+ }
36326+ return res;
36327+}
36328+
36329+static inline void ucmd_get(struct scst_user_cmd *ucmd)
36330+{
36331+ TRACE_DBG("ucmd %p, ucmd_ref %d", ucmd, atomic_read(&ucmd->ucmd_ref));
36332+ atomic_inc(&ucmd->ucmd_ref);
36333+ /*
36334+ * For the same reason as in kref_get(). Let's be safe and
36335+ * always do it.
36336+ */
36337+ smp_mb__after_atomic_inc();
36338+}
36339+
36340+/* Must not be called under cmd_list_lock!! */
36341+static inline void ucmd_put(struct scst_user_cmd *ucmd)
36342+{
36343+ TRACE_DBG("ucmd %p, ucmd_ref %d", ucmd, atomic_read(&ucmd->ucmd_ref));
36344+
36345+ EXTRACHECKS_BUG_ON(atomic_read(&ucmd->ucmd_ref) == 0);
36346+
36347+ if (atomic_dec_and_test(&ucmd->ucmd_ref))
36348+ dev_user_free_ucmd(ucmd);
36349+}
36350+
36351+static inline int calc_num_pg(unsigned long buf, int len)
36352+{
36353+ len += buf & ~PAGE_MASK;
36354+ return (len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0);
36355+}
36356+
36357+static void __dev_user_not_reg(void)
36358+{
36359+ TRACE_MGMT_DBG("%s", "Device not registered");
36360+ return;
36361+}
36362+
36363+static inline int dev_user_check_reg(struct scst_user_dev *dev)
36364+{
36365+ if (dev == NULL) {
36366+ __dev_user_not_reg();
36367+ return -ENODEV;
36368+ }
36369+ return 0;
36370+}
36371+
36372+static inline int scst_user_cmd_hashfn(int h)
36373+{
36374+ return h & ((1 << DEV_USER_CMD_HASH_ORDER) - 1);
36375+}
36376+
36377+static inline struct scst_user_cmd *__ucmd_find_hash(struct scst_user_dev *dev,
36378+ unsigned int h)
36379+{
36380+ struct list_head *head;
36381+ struct scst_user_cmd *ucmd;
36382+
36383+ head = &dev->ucmd_hash[scst_user_cmd_hashfn(h)];
36384+ list_for_each_entry(ucmd, head, hash_list_entry) {
36385+ if (ucmd->h == h) {
36386+ TRACE_DBG("Found ucmd %p", ucmd);
36387+ return ucmd;
36388+ }
36389+ }
36390+ return NULL;
36391+}
36392+
36393+static void cmd_insert_hash(struct scst_user_cmd *ucmd)
36394+{
36395+ struct list_head *head;
36396+ struct scst_user_dev *dev = ucmd->dev;
36397+ struct scst_user_cmd *u;
36398+ unsigned long flags;
36399+
36400+ spin_lock_irqsave(&dev->udev_cmd_threads.cmd_list_lock, flags);
36401+ do {
36402+ ucmd->h = dev->handle_counter++;
36403+ u = __ucmd_find_hash(dev, ucmd->h);
36404+ } while (u != NULL);
36405+ head = &dev->ucmd_hash[scst_user_cmd_hashfn(ucmd->h)];
36406+ list_add_tail(&ucmd->hash_list_entry, head);
36407+ spin_unlock_irqrestore(&dev->udev_cmd_threads.cmd_list_lock, flags);
36408+
36409+ TRACE_DBG("Inserted ucmd %p, h=%d (dev %s)", ucmd, ucmd->h, dev->name);
36410+ return;
36411+}
36412+
36413+static inline void cmd_remove_hash(struct scst_user_cmd *ucmd)
36414+{
36415+ unsigned long flags;
36416+
36417+ spin_lock_irqsave(&ucmd->dev->udev_cmd_threads.cmd_list_lock, flags);
36418+ list_del(&ucmd->hash_list_entry);
36419+ spin_unlock_irqrestore(&ucmd->dev->udev_cmd_threads.cmd_list_lock, flags);
36420+
36421+ TRACE_DBG("Removed ucmd %p, h=%d", ucmd, ucmd->h);
36422+ return;
36423+}
36424+
36425+static void dev_user_free_ucmd(struct scst_user_cmd *ucmd)
36426+{
36427+ TRACE_ENTRY();
36428+
36429+ TRACE_MEM("Freeing ucmd %p", ucmd);
36430+
36431+ cmd_remove_hash(ucmd);
36432+ EXTRACHECKS_BUG_ON(ucmd->cmd != NULL);
36433+
36434+ kmem_cache_free(user_cmd_cachep, ucmd);
36435+
36436+ TRACE_EXIT();
36437+ return;
36438+}
36439+
36440+static struct page *dev_user_alloc_pages(struct scatterlist *sg,
36441+ gfp_t gfp_mask, void *priv)
36442+{
36443+ struct scst_user_cmd *ucmd = (struct scst_user_cmd *)priv;
36444+ int offset = 0;
36445+
36446+ TRACE_ENTRY();
36447+
36448+ /* *sg supposed to be zeroed */
36449+
36450+ TRACE_MEM("ucmd %p, ubuff %lx, ucmd->cur_data_page %d", ucmd,
36451+ ucmd->ubuff, ucmd->cur_data_page);
36452+
36453+ if (ucmd->cur_data_page == 0) {
36454+ TRACE_MEM("ucmd->first_page_offset %d",
36455+ ucmd->first_page_offset);
36456+ offset = ucmd->first_page_offset;
36457+ ucmd_get(ucmd);
36458+ }
36459+
36460+ if (ucmd->cur_data_page >= ucmd->num_data_pages)
36461+ goto out;
36462+
36463+ sg_set_page(sg, ucmd->data_pages[ucmd->cur_data_page],
36464+ PAGE_SIZE - offset, offset);
36465+ ucmd->cur_data_page++;
36466+
36467+ TRACE_MEM("page=%p, length=%d, offset=%d", sg_page(sg), sg->length,
36468+ sg->offset);
36469+ TRACE_BUFFER("Page data", sg_virt(sg), sg->length);
36470+
36471+out:
36472+ TRACE_EXIT();
36473+ return sg_page(sg);
36474+}
36475+
36476+static void dev_user_on_cached_mem_free(struct scst_user_cmd *ucmd)
36477+{
36478+ TRACE_ENTRY();
36479+
36480+ TRACE_MEM("Preparing ON_CACHED_MEM_FREE (ucmd %p, h %d, ubuff %lx)",
36481+ ucmd, ucmd->h, ucmd->ubuff);
36482+
36483+ ucmd->user_cmd_payload_len =
36484+ offsetof(struct scst_user_get_cmd, on_cached_mem_free) +
36485+ sizeof(ucmd->user_cmd.on_cached_mem_free);
36486+ ucmd->user_cmd.cmd_h = ucmd->h;
36487+ ucmd->user_cmd.subcode = SCST_USER_ON_CACHED_MEM_FREE;
36488+ ucmd->user_cmd.on_cached_mem_free.pbuf = ucmd->ubuff;
36489+
36490+ ucmd->state = UCMD_STATE_ON_CACHE_FREEING;
36491+
36492+ dev_user_add_to_ready(ucmd);
36493+
36494+ TRACE_EXIT();
36495+ return;
36496+}
36497+
36498+static void dev_user_unmap_buf(struct scst_user_cmd *ucmd)
36499+{
36500+ int i;
36501+
36502+ TRACE_ENTRY();
36503+
36504+ TRACE_MEM("Unmapping data pages (ucmd %p, ubuff %lx, num %d)", ucmd,
36505+ ucmd->ubuff, ucmd->num_data_pages);
36506+
36507+ for (i = 0; i < ucmd->num_data_pages; i++) {
36508+ struct page *page = ucmd->data_pages[i];
36509+
36510+ if (ucmd->buf_dirty)
36511+ SetPageDirty(page);
36512+
36513+ page_cache_release(page);
36514+ }
36515+
36516+ kfree(ucmd->data_pages);
36517+ ucmd->data_pages = NULL;
36518+
36519+ TRACE_EXIT();
36520+ return;
36521+}
36522+
36523+static void __dev_user_free_sg_entries(struct scst_user_cmd *ucmd)
36524+{
36525+ TRACE_ENTRY();
36526+
36527+ BUG_ON(ucmd->data_pages == NULL);
36528+
36529+ TRACE_MEM("Freeing data pages (ucmd=%p, ubuff=%lx, buff_cached=%d)",
36530+ ucmd, ucmd->ubuff, ucmd->buff_cached);
36531+
36532+ dev_user_unmap_buf(ucmd);
36533+
36534+ if (ucmd->buff_cached)
36535+ dev_user_on_cached_mem_free(ucmd);
36536+ else
36537+ ucmd_put(ucmd);
36538+
36539+ TRACE_EXIT();
36540+ return;
36541+}
36542+
36543+static void dev_user_free_sg_entries(struct scatterlist *sg, int sg_count,
36544+ void *priv)
36545+{
36546+ struct scst_user_cmd *ucmd = (struct scst_user_cmd *)priv;
36547+
36548+ TRACE_MEM("Freeing data pages (sg=%p, sg_count=%d, priv %p)", sg,
36549+ sg_count, ucmd);
36550+
36551+ __dev_user_free_sg_entries(ucmd);
36552+
36553+ return;
36554+}
36555+
36556+static inline int is_buff_cached(struct scst_user_cmd *ucmd)
36557+{
36558+ int mem_reuse_type = ucmd->dev->memory_reuse_type;
36559+
36560+ if ((mem_reuse_type == SCST_USER_MEM_REUSE_ALL) ||
36561+ ((ucmd->cmd->data_direction == SCST_DATA_READ) &&
36562+ (mem_reuse_type == SCST_USER_MEM_REUSE_READ)) ||
36563+ ((ucmd->cmd->data_direction == SCST_DATA_WRITE) &&
36564+ (mem_reuse_type == SCST_USER_MEM_REUSE_WRITE)))
36565+ return 1;
36566+ else
36567+ return 0;
36568+}
36569+
36570+static inline int is_need_offs_page(unsigned long buf, int len)
36571+{
36572+ return ((buf & ~PAGE_MASK) != 0) &&
36573+ ((buf & PAGE_MASK) != ((buf+len-1) & PAGE_MASK));
36574+}
36575+
36576+/*
36577+ * Returns 0 for success, <0 for fatal failure, >0 - need pages.
36578+ * Unmaps the buffer, if needed in case of error
36579+ */
36580+static int dev_user_alloc_sg(struct scst_user_cmd *ucmd, int cached_buff)
36581+{
36582+ int res = 0;
36583+ struct scst_cmd *cmd = ucmd->cmd;
36584+ struct scst_user_dev *dev = ucmd->dev;
36585+ struct sgv_pool *pool;
36586+ gfp_t gfp_mask;
36587+ int flags = 0;
36588+ int bufflen, orig_bufflen;
36589+ int last_len = 0;
36590+ int out_sg_pages = 0;
36591+
36592+ TRACE_ENTRY();
36593+
36594+ gfp_mask = __GFP_NOWARN;
36595+ gfp_mask |= (scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
36596+
36597+ if (cmd->data_direction != SCST_DATA_BIDI) {
36598+ orig_bufflen = cmd->bufflen;
36599+ pool = (struct sgv_pool *)cmd->tgt_dev->dh_priv;
36600+ } else {
36601+ /* Make out_sg->offset 0 */
36602+ int len = cmd->bufflen + ucmd->first_page_offset;
36603+ out_sg_pages = (len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0);
36604+ orig_bufflen = (out_sg_pages << PAGE_SHIFT) + cmd->out_bufflen;
36605+ pool = dev->pool;
36606+ }
36607+ bufflen = orig_bufflen;
36608+
36609+ EXTRACHECKS_BUG_ON(bufflen == 0);
36610+
36611+ if (cached_buff) {
36612+ flags |= SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL;
36613+ if (ucmd->ubuff == 0)
36614+ flags |= SGV_POOL_NO_ALLOC_ON_CACHE_MISS;
36615+ } else {
36616+ TRACE_MEM("%s", "Not cached buff");
36617+ flags |= SGV_POOL_ALLOC_NO_CACHED;
36618+ if (ucmd->ubuff == 0) {
36619+ res = 1;
36620+ goto out;
36621+ }
36622+ bufflen += ucmd->first_page_offset;
36623+ if (is_need_offs_page(ucmd->ubuff, orig_bufflen))
36624+ last_len = bufflen & ~PAGE_MASK;
36625+ else
36626+ last_len = orig_bufflen & ~PAGE_MASK;
36627+ }
36628+ ucmd->buff_cached = cached_buff;
36629+
36630+ cmd->sg = sgv_pool_alloc(pool, bufflen, gfp_mask, flags, &cmd->sg_cnt,
36631+ &ucmd->sgv, &dev->udev_mem_lim, ucmd);
36632+ if (cmd->sg != NULL) {
36633+ struct scst_user_cmd *buf_ucmd =
36634+ (struct scst_user_cmd *)sgv_get_priv(ucmd->sgv);
36635+
36636+ TRACE_MEM("Buf ucmd %p (cmd->sg_cnt %d, last seg len %d, "
36637+ "last_len %d, bufflen %d)", buf_ucmd, cmd->sg_cnt,
36638+ cmd->sg[cmd->sg_cnt-1].length, last_len, bufflen);
36639+
36640+ ucmd->ubuff = buf_ucmd->ubuff;
36641+ ucmd->buf_ucmd = buf_ucmd;
36642+
36643+ EXTRACHECKS_BUG_ON((ucmd->data_pages != NULL) &&
36644+ (ucmd != buf_ucmd));
36645+
36646+ if (last_len != 0) {
36647+ cmd->sg[cmd->sg_cnt-1].length &= PAGE_MASK;
36648+ cmd->sg[cmd->sg_cnt-1].length += last_len;
36649+ }
36650+
36651+ TRACE_MEM("Buf alloced (ucmd %p, cached_buff %d, ubuff %lx, "
36652+ "last seg len %d)", ucmd, cached_buff, ucmd->ubuff,
36653+ cmd->sg[cmd->sg_cnt-1].length);
36654+
36655+ if (cmd->data_direction == SCST_DATA_BIDI) {
36656+ cmd->out_sg = &cmd->sg[out_sg_pages];
36657+ cmd->out_sg_cnt = cmd->sg_cnt - out_sg_pages;
36658+ cmd->sg_cnt = out_sg_pages;
36659+ TRACE_MEM("cmd %p, out_sg %p, out_sg_cnt %d, sg_cnt %d",
36660+ cmd, cmd->out_sg, cmd->out_sg_cnt, cmd->sg_cnt);
36661+ }
36662+
36663+ if (unlikely(cmd->sg_cnt > cmd->tgt_dev->max_sg_cnt)) {
36664+ static int ll;
36665+ if ((ll < 10) || TRACING_MINOR()) {
36666+ PRINT_INFO("Unable to complete command due to "
36667+ "SG IO count limitation (requested %d, "
36668+ "available %d, tgt lim %d)",
36669+ cmd->sg_cnt, cmd->tgt_dev->max_sg_cnt,
36670+ cmd->tgt->sg_tablesize);
36671+ ll++;
36672+ }
36673+ cmd->sg = NULL;
36674+ /* sgv will be freed in dev_user_free_sgv() */
36675+ res = -1;
36676+ }
36677+ } else {
36678+ TRACE_MEM("Buf not alloced (ucmd %p, h %d, buff_cached, %d, "
36679+ "sg_cnt %d, ubuff %lx, sgv %p", ucmd, ucmd->h,
36680+ ucmd->buff_cached, cmd->sg_cnt, ucmd->ubuff, ucmd->sgv);
36681+ if (unlikely(cmd->sg_cnt == 0)) {
36682+ TRACE_MEM("Refused allocation (ucmd %p)", ucmd);
36683+ BUG_ON(ucmd->sgv != NULL);
36684+ res = -1;
36685+ } else {
36686+ switch (ucmd->state) {
36687+ case UCMD_STATE_BUF_ALLOCING:
36688+ res = 1;
36689+ break;
36690+ case UCMD_STATE_EXECING:
36691+ res = -1;
36692+ break;
36693+ default:
36694+ BUG();
36695+ break;
36696+ }
36697+ }
36698+ }
36699+
36700+out:
36701+ TRACE_EXIT_RES(res);
36702+ return res;
36703+}
36704+
36705+static int dev_user_alloc_space(struct scst_user_cmd *ucmd)
36706+{
36707+ int rc, res = SCST_CMD_STATE_DEFAULT;
36708+ struct scst_cmd *cmd = ucmd->cmd;
36709+
36710+ TRACE_ENTRY();
36711+
36712+ ucmd->state = UCMD_STATE_BUF_ALLOCING;
36713+ scst_cmd_set_dh_data_buff_alloced(cmd);
36714+
36715+ rc = dev_user_alloc_sg(ucmd, is_buff_cached(ucmd));
36716+ if (rc == 0)
36717+ goto out;
36718+ else if (rc < 0) {
36719+ scst_set_busy(cmd);
36720+ res = scst_set_cmd_abnormal_done_state(cmd);
36721+ goto out;
36722+ }
36723+
36724+ if (!(cmd->data_direction & SCST_DATA_WRITE) &&
36725+ !scst_is_cmd_local(cmd)) {
36726+ TRACE_DBG("Delayed alloc, ucmd %p", ucmd);
36727+ goto out;
36728+ }
36729+
36730+ ucmd->user_cmd_payload_len =
36731+ offsetof(struct scst_user_get_cmd, alloc_cmd) +
36732+ sizeof(ucmd->user_cmd.alloc_cmd);
36733+ ucmd->user_cmd.cmd_h = ucmd->h;
36734+ ucmd->user_cmd.subcode = SCST_USER_ALLOC_MEM;
36735+ ucmd->user_cmd.alloc_cmd.sess_h = (unsigned long)cmd->tgt_dev;
36736+ memcpy(ucmd->user_cmd.alloc_cmd.cdb, cmd->cdb, cmd->cdb_len);
36737+ ucmd->user_cmd.alloc_cmd.cdb_len = cmd->cdb_len;
36738+ ucmd->user_cmd.alloc_cmd.ext_cdb_len = cmd->ext_cdb_len;
36739+ ucmd->user_cmd.alloc_cmd.alloc_len = ucmd->buff_cached ?
36740+ (cmd->sg_cnt << PAGE_SHIFT) : cmd->bufflen;
36741+ ucmd->user_cmd.alloc_cmd.queue_type = cmd->queue_type;
36742+ ucmd->user_cmd.alloc_cmd.data_direction = cmd->data_direction;
36743+ ucmd->user_cmd.alloc_cmd.sn = cmd->tgt_sn;
36744+
36745+ dev_user_add_to_ready(ucmd);
36746+
36747+ res = SCST_CMD_STATE_STOP;
36748+
36749+out:
36750+ TRACE_EXIT_RES(res);
36751+ return res;
36752+}
36753+
36754+static struct scst_user_cmd *dev_user_alloc_ucmd(struct scst_user_dev *dev,
36755+ gfp_t gfp_mask)
36756+{
36757+ struct scst_user_cmd *ucmd = NULL;
36758+
36759+ TRACE_ENTRY();
36760+
36761+ ucmd = kmem_cache_zalloc(user_cmd_cachep, gfp_mask);
36762+ if (unlikely(ucmd == NULL)) {
36763+ TRACE(TRACE_OUT_OF_MEM, "Unable to allocate "
36764+ "user cmd (gfp_mask %x)", gfp_mask);
36765+ goto out;
36766+ }
36767+ ucmd->dev = dev;
36768+ atomic_set(&ucmd->ucmd_ref, 1);
36769+
36770+ cmd_insert_hash(ucmd);
36771+
36772+ TRACE_MEM("ucmd %p allocated", ucmd);
36773+
36774+out:
36775+ TRACE_EXIT_HRES((unsigned long)ucmd);
36776+ return ucmd;
36777+}
36778+
36779+static int dev_user_get_block(struct scst_cmd *cmd)
36780+{
36781+ struct scst_user_dev *dev = (struct scst_user_dev *)cmd->dev->dh_priv;
36782+ /*
36783+ * No need for locks here, since *_detach() can not be
36784+ * called, when there are existing commands.
36785+ */
36786+ TRACE_EXIT_RES(dev->block);
36787+ return dev->block;
36788+}
36789+
36790+static int dev_user_parse(struct scst_cmd *cmd)
36791+{
36792+ int rc, res = SCST_CMD_STATE_DEFAULT;
36793+ struct scst_user_cmd *ucmd;
36794+ int atomic = scst_cmd_atomic(cmd);
36795+ struct scst_user_dev *dev = (struct scst_user_dev *)cmd->dev->dh_priv;
36796+ gfp_t gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
36797+
36798+ TRACE_ENTRY();
36799+
36800+ if (cmd->dh_priv == NULL) {
36801+ ucmd = dev_user_alloc_ucmd(dev, gfp_mask);
36802+ if (unlikely(ucmd == NULL)) {
36803+ if (atomic) {
36804+ res = SCST_CMD_STATE_NEED_THREAD_CTX;
36805+ goto out;
36806+ } else {
36807+ scst_set_busy(cmd);
36808+ goto out_error;
36809+ }
36810+ }
36811+ ucmd->cmd = cmd;
36812+ cmd->dh_priv = ucmd;
36813+ } else {
36814+ ucmd = (struct scst_user_cmd *)cmd->dh_priv;
36815+ TRACE_DBG("Used ucmd %p, state %x", ucmd, ucmd->state);
36816+ }
36817+
36818+ TRACE_DBG("ucmd %p, cmd %p, state %x", ucmd, cmd, ucmd->state);
36819+
36820+ if (ucmd->state == UCMD_STATE_PARSING) {
36821+ /* We've already done */
36822+ goto done;
36823+ }
36824+
36825+ EXTRACHECKS_BUG_ON(ucmd->state != UCMD_STATE_NEW);
36826+
36827+ switch (dev->parse_type) {
36828+ case SCST_USER_PARSE_STANDARD:
36829+ TRACE_DBG("PARSE STANDARD: ucmd %p", ucmd);
36830+ rc = dev->generic_parse(cmd, dev_user_get_block);
36831+ if (rc != 0)
36832+ goto out_invalid;
36833+ break;
36834+
36835+ case SCST_USER_PARSE_EXCEPTION:
36836+ TRACE_DBG("PARSE EXCEPTION: ucmd %p", ucmd);
36837+ rc = dev->generic_parse(cmd, dev_user_get_block);
36838+ if ((rc == 0) && (cmd->op_flags & SCST_INFO_VALID))
36839+ break;
36840+ else if (rc == SCST_CMD_STATE_NEED_THREAD_CTX) {
36841+ TRACE_MEM("Restarting PARSE to thread context "
36842+ "(ucmd %p)", ucmd);
36843+ res = SCST_CMD_STATE_NEED_THREAD_CTX;
36844+ goto out;
36845+ }
36846+ /* else go through */
36847+
36848+ case SCST_USER_PARSE_CALL:
36849+ TRACE_DBG("Preparing PARSE for user space (ucmd=%p, h=%d, "
36850+ "bufflen %d)", ucmd, ucmd->h, cmd->bufflen);
36851+ ucmd->user_cmd_payload_len =
36852+ offsetof(struct scst_user_get_cmd, parse_cmd) +
36853+ sizeof(ucmd->user_cmd.parse_cmd);
36854+ ucmd->user_cmd.cmd_h = ucmd->h;
36855+ ucmd->user_cmd.subcode = SCST_USER_PARSE;
36856+ ucmd->user_cmd.parse_cmd.sess_h = (unsigned long)cmd->tgt_dev;
36857+ memcpy(ucmd->user_cmd.parse_cmd.cdb, cmd->cdb, cmd->cdb_len);
36858+ ucmd->user_cmd.parse_cmd.cdb_len = cmd->cdb_len;
36859+ ucmd->user_cmd.parse_cmd.ext_cdb_len = cmd->ext_cdb_len;
36860+ ucmd->user_cmd.parse_cmd.timeout = cmd->timeout / HZ;
36861+ ucmd->user_cmd.parse_cmd.bufflen = cmd->bufflen;
36862+ ucmd->user_cmd.parse_cmd.out_bufflen = cmd->out_bufflen;
36863+ ucmd->user_cmd.parse_cmd.queue_type = cmd->queue_type;
36864+ ucmd->user_cmd.parse_cmd.data_direction = cmd->data_direction;
36865+ ucmd->user_cmd.parse_cmd.expected_values_set =
36866+ cmd->expected_values_set;
36867+ ucmd->user_cmd.parse_cmd.expected_data_direction =
36868+ cmd->expected_data_direction;
36869+ ucmd->user_cmd.parse_cmd.expected_transfer_len =
36870+ cmd->expected_transfer_len;
36871+ ucmd->user_cmd.parse_cmd.expected_out_transfer_len =
36872+ cmd->expected_out_transfer_len;
36873+ ucmd->user_cmd.parse_cmd.sn = cmd->tgt_sn;
36874+ ucmd->user_cmd.parse_cmd.op_flags = cmd->op_flags;
36875+ ucmd->state = UCMD_STATE_PARSING;
36876+ dev_user_add_to_ready(ucmd);
36877+ res = SCST_CMD_STATE_STOP;
36878+ goto out;
36879+
36880+ default:
36881+ BUG();
36882+ goto out;
36883+ }
36884+
36885+done:
36886+ if (cmd->bufflen == 0) {
36887+ /*
36888+ * According to SPC bufflen 0 for data transfer commands isn't
36889+ * an error, so we need to fix the transfer direction.
36890+ */
36891+ cmd->data_direction = SCST_DATA_NONE;
36892+ }
36893+
36894+out:
36895+ TRACE_EXIT_RES(res);
36896+ return res;
36897+
36898+out_invalid:
36899+ PRINT_ERROR("PARSE failed (ucmd %p, rc %d)", ucmd, rc);
36900+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_opcode));
36901+
36902+out_error:
36903+ res = scst_set_cmd_abnormal_done_state(cmd);
36904+ goto out;
36905+}
36906+
36907+static int dev_user_alloc_data_buf(struct scst_cmd *cmd)
36908+{
36909+ int res = SCST_CMD_STATE_DEFAULT;
36910+ struct scst_user_cmd *ucmd = (struct scst_user_cmd *)cmd->dh_priv;
36911+
36912+ TRACE_ENTRY();
36913+
36914+ EXTRACHECKS_BUG_ON((ucmd->state != UCMD_STATE_NEW) &&
36915+ (ucmd->state != UCMD_STATE_PARSING) &&
36916+ (ucmd->state != UCMD_STATE_BUF_ALLOCING));
36917+
36918+ res = dev_user_alloc_space(ucmd);
36919+
36920+ TRACE_EXIT_RES(res);
36921+ return res;
36922+}
36923+
36924+static void dev_user_flush_dcache(struct scst_user_cmd *ucmd)
36925+{
36926+ struct scst_user_cmd *buf_ucmd = ucmd->buf_ucmd;
36927+ unsigned long start = buf_ucmd->ubuff;
36928+ int i, bufflen = ucmd->cmd->bufflen;
36929+
36930+ TRACE_ENTRY();
36931+
36932+ if (start == 0)
36933+ goto out;
36934+
36935+ /*
36936+ * Possibly, flushing of all the pages from ucmd->cmd->sg can be
36937+ * faster, since it should be cache hot, while ucmd->buf_ucmd and
36938+ * buf_ucmd->data_pages are cache cold. But, from other side,
36939+ * sizeof(buf_ucmd->data_pages[0]) is considerably smaller, than
36940+ * sizeof(ucmd->cmd->sg[0]), so on big buffers going over
36941+ * data_pages array can lead to less cache misses. So, real numbers are
36942+ * needed. ToDo.
36943+ */
36944+
36945+ for (i = 0; (bufflen > 0) && (i < buf_ucmd->num_data_pages); i++) {
36946+ struct page *page;
36947+ page = buf_ucmd->data_pages[i];
36948+#ifdef ARCH_HAS_FLUSH_ANON_PAGE
36949+ struct vm_area_struct *vma = find_vma(current->mm, start);
36950+ if (vma != NULL)
36951+ flush_anon_page(vma, page, start);
36952+#endif
36953+ flush_dcache_page(page);
36954+ start += PAGE_SIZE;
36955+ bufflen -= PAGE_SIZE;
36956+ }
36957+
36958+out:
36959+ TRACE_EXIT();
36960+ return;
36961+}
36962+
36963+static int dev_user_exec(struct scst_cmd *cmd)
36964+{
36965+ struct scst_user_cmd *ucmd = (struct scst_user_cmd *)cmd->dh_priv;
36966+ int res = SCST_EXEC_COMPLETED;
36967+
36968+ TRACE_ENTRY();
36969+
36970+ TRACE_DBG("Preparing EXEC for user space (ucmd=%p, h=%d, "
36971+ "bufflen %d, data_len %d, ubuff %lx)", ucmd, ucmd->h,
36972+ cmd->bufflen, cmd->data_len, ucmd->ubuff);
36973+
36974+ if (cmd->data_direction & SCST_DATA_WRITE)
36975+ dev_user_flush_dcache(ucmd);
36976+
36977+ BUILD_BUG_ON(sizeof(ucmd->user_cmd.exec_cmd.cdb) != sizeof(cmd->cdb));
36978+
36979+ ucmd->user_cmd_payload_len =
36980+ offsetof(struct scst_user_get_cmd, exec_cmd) +
36981+ sizeof(ucmd->user_cmd.exec_cmd);
36982+ ucmd->user_cmd.cmd_h = ucmd->h;
36983+ ucmd->user_cmd.subcode = SCST_USER_EXEC;
36984+ ucmd->user_cmd.exec_cmd.sess_h = (unsigned long)cmd->tgt_dev;
36985+ memcpy(ucmd->user_cmd.exec_cmd.cdb, cmd->cdb, cmd->cdb_len);
36986+ ucmd->user_cmd.exec_cmd.cdb_len = cmd->cdb_len;
36987+ ucmd->user_cmd.exec_cmd.ext_cdb_len = cmd->ext_cdb_len;
36988+ ucmd->user_cmd.exec_cmd.bufflen = cmd->bufflen;
36989+ ucmd->user_cmd.exec_cmd.data_len = cmd->data_len;
36990+ ucmd->user_cmd.exec_cmd.pbuf = ucmd->ubuff;
36991+ if ((ucmd->ubuff == 0) && (cmd->data_direction != SCST_DATA_NONE)) {
36992+ ucmd->user_cmd.exec_cmd.alloc_len = ucmd->buff_cached ?
36993+ (cmd->sg_cnt << PAGE_SHIFT) : cmd->bufflen;
36994+ }
36995+ ucmd->user_cmd.exec_cmd.queue_type = cmd->queue_type;
36996+ ucmd->user_cmd.exec_cmd.data_direction = cmd->data_direction;
36997+ ucmd->user_cmd.exec_cmd.partial = 0;
36998+ ucmd->user_cmd.exec_cmd.timeout = cmd->timeout / HZ;
36999+ ucmd->user_cmd.exec_cmd.p_out_buf = ucmd->ubuff +
37000+ (cmd->sg_cnt << PAGE_SHIFT);
37001+ ucmd->user_cmd.exec_cmd.out_bufflen = cmd->out_bufflen;
37002+ ucmd->user_cmd.exec_cmd.sn = cmd->tgt_sn;
37003+
37004+ ucmd->state = UCMD_STATE_EXECING;
37005+
37006+ dev_user_add_to_ready(ucmd);
37007+
37008+ TRACE_EXIT_RES(res);
37009+ return res;
37010+}
37011+
37012+static void dev_user_free_sgv(struct scst_user_cmd *ucmd)
37013+{
37014+ if (ucmd->sgv != NULL) {
37015+ sgv_pool_free(ucmd->sgv, &ucmd->dev->udev_mem_lim);
37016+ ucmd->sgv = NULL;
37017+ } else if (ucmd->data_pages != NULL) {
37018+ /* We mapped pages, but for some reason didn't allocate them */
37019+ ucmd_get(ucmd);
37020+ __dev_user_free_sg_entries(ucmd);
37021+ }
37022+ return;
37023+}
37024+
37025+static void dev_user_on_free_cmd(struct scst_cmd *cmd)
37026+{
37027+ struct scst_user_cmd *ucmd = (struct scst_user_cmd *)cmd->dh_priv;
37028+
37029+ TRACE_ENTRY();
37030+
37031+ if (unlikely(ucmd == NULL))
37032+ goto out;
37033+
37034+ TRACE_MEM("ucmd %p, cmd %p, buff_cached %d, ubuff %lx", ucmd, ucmd->cmd,
37035+ ucmd->buff_cached, ucmd->ubuff);
37036+
37037+ ucmd->cmd = NULL;
37038+ if ((cmd->data_direction & SCST_DATA_WRITE) && ucmd->buf_ucmd != NULL)
37039+ ucmd->buf_ucmd->buf_dirty = 1;
37040+
37041+ if (ucmd->dev->on_free_cmd_type == SCST_USER_ON_FREE_CMD_IGNORE) {
37042+ ucmd->state = UCMD_STATE_ON_FREE_SKIPPED;
37043+ /* The state assignment must be before freeing sgv! */
37044+ goto out_reply;
37045+ }
37046+
37047+ if (unlikely(!ucmd->seen_by_user)) {
37048+ TRACE_MGMT_DBG("Not seen by user ucmd %p", ucmd);
37049+ goto out_reply;
37050+ }
37051+
37052+ ucmd->user_cmd_payload_len =
37053+ offsetof(struct scst_user_get_cmd, on_free_cmd) +
37054+ sizeof(ucmd->user_cmd.on_free_cmd);
37055+ ucmd->user_cmd.cmd_h = ucmd->h;
37056+ ucmd->user_cmd.subcode = SCST_USER_ON_FREE_CMD;
37057+ ucmd->user_cmd.on_free_cmd.pbuf = ucmd->ubuff;
37058+ ucmd->user_cmd.on_free_cmd.resp_data_len = cmd->resp_data_len;
37059+ ucmd->user_cmd.on_free_cmd.buffer_cached = ucmd->buff_cached;
37060+ ucmd->user_cmd.on_free_cmd.aborted = ucmd->aborted;
37061+ ucmd->user_cmd.on_free_cmd.status = cmd->status;
37062+ ucmd->user_cmd.on_free_cmd.delivery_status = cmd->delivery_status;
37063+
37064+ ucmd->state = UCMD_STATE_ON_FREEING;
37065+
37066+ dev_user_add_to_ready(ucmd);
37067+
37068+out:
37069+ TRACE_EXIT();
37070+ return;
37071+
37072+out_reply:
37073+ dev_user_process_reply_on_free(ucmd);
37074+ goto out;
37075+}
37076+
37077+static void dev_user_set_block(struct scst_cmd *cmd, int block)
37078+{
37079+ struct scst_user_dev *dev = (struct scst_user_dev *)cmd->dev->dh_priv;
37080+ /*
37081+ * No need for locks here, since *_detach() can not be
37082+ * called, when there are existing commands.
37083+ */
37084+ TRACE_DBG("dev %p, new block %d", dev, block);
37085+ if (block != 0)
37086+ dev->block = block;
37087+ else
37088+ dev->block = dev->def_block;
37089+ return;
37090+}
37091+
37092+static int dev_user_disk_done(struct scst_cmd *cmd)
37093+{
37094+ int res = SCST_CMD_STATE_DEFAULT;
37095+
37096+ TRACE_ENTRY();
37097+
37098+ res = scst_block_generic_dev_done(cmd, dev_user_set_block);
37099+
37100+ TRACE_EXIT_RES(res);
37101+ return res;
37102+}
37103+
37104+static int dev_user_tape_done(struct scst_cmd *cmd)
37105+{
37106+ int res = SCST_CMD_STATE_DEFAULT;
37107+
37108+ TRACE_ENTRY();
37109+
37110+ res = scst_tape_generic_dev_done(cmd, dev_user_set_block);
37111+
37112+ TRACE_EXIT_RES(res);
37113+ return res;
37114+}
37115+
37116+static void dev_user_add_to_ready(struct scst_user_cmd *ucmd)
37117+{
37118+ struct scst_user_dev *dev = ucmd->dev;
37119+ unsigned long flags;
37120+ int do_wake = in_interrupt();
37121+
37122+ TRACE_ENTRY();
37123+
37124+ if (ucmd->cmd)
37125+ do_wake |= ucmd->cmd->preprocessing_only;
37126+
37127+ spin_lock_irqsave(&dev->udev_cmd_threads.cmd_list_lock, flags);
37128+
37129+ ucmd->this_state_unjammed = 0;
37130+
37131+ if ((ucmd->state == UCMD_STATE_PARSING) ||
37132+ (ucmd->state == UCMD_STATE_BUF_ALLOCING)) {
37133+ /*
37134+ * If we don't put such commands in the queue head, then under
37135+ * high load we might delay threads, waiting for memory
37136+ * allocations, for too long and start loosing NOPs, which
37137+ * would lead to consider us by remote initiators as
37138+ * unresponsive and stuck => broken connections, etc. If none
37139+ * of our commands completed in NOP timeout to allow the head
37140+ * commands to go, then we are really overloaded and/or stuck.
37141+ */
37142+ TRACE_DBG("Adding ucmd %p (state %d) to head of ready "
37143+ "cmd list", ucmd, ucmd->state);
37144+ list_add(&ucmd->ready_cmd_list_entry,
37145+ &dev->ready_cmd_list);
37146+ } else if (unlikely(ucmd->state == UCMD_STATE_TM_EXECING) ||
37147+ unlikely(ucmd->state == UCMD_STATE_ATTACH_SESS) ||
37148+ unlikely(ucmd->state == UCMD_STATE_DETACH_SESS)) {
37149+ TRACE_MGMT_DBG("Adding mgmt ucmd %p (state %d) to head of "
37150+ "ready cmd list", ucmd, ucmd->state);
37151+ list_add(&ucmd->ready_cmd_list_entry,
37152+ &dev->ready_cmd_list);
37153+ do_wake = 1;
37154+ } else {
37155+ if ((ucmd->cmd != NULL) &&
37156+ unlikely((ucmd->cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))) {
37157+ TRACE_DBG("Adding HQ ucmd %p to head of ready cmd list",
37158+ ucmd);
37159+ list_add(&ucmd->ready_cmd_list_entry,
37160+ &dev->ready_cmd_list);
37161+ } else {
37162+ TRACE_DBG("Adding ucmd %p to ready cmd list", ucmd);
37163+ list_add_tail(&ucmd->ready_cmd_list_entry,
37164+ &dev->ready_cmd_list);
37165+ }
37166+ do_wake |= ((ucmd->state == UCMD_STATE_ON_CACHE_FREEING) ||
37167+ (ucmd->state == UCMD_STATE_ON_FREEING));
37168+ }
37169+
37170+ if (do_wake) {
37171+ TRACE_DBG("Waking up dev %p", dev);
37172+ wake_up(&dev->udev_cmd_threads.cmd_list_waitQ);
37173+ }
37174+
37175+ spin_unlock_irqrestore(&dev->udev_cmd_threads.cmd_list_lock, flags);
37176+
37177+ TRACE_EXIT();
37178+ return;
37179+}
37180+
37181+static int dev_user_map_buf(struct scst_user_cmd *ucmd, unsigned long ubuff,
37182+ int num_pg)
37183+{
37184+ int res = 0, rc;
37185+ int i;
37186+ struct task_struct *tsk = current;
37187+
37188+ TRACE_ENTRY();
37189+
37190+ if (unlikely(ubuff == 0))
37191+ goto out_nomem;
37192+
37193+ BUG_ON(ucmd->data_pages != NULL);
37194+
37195+ ucmd->num_data_pages = num_pg;
37196+
37197+ ucmd->data_pages =
37198+ kmalloc(sizeof(*ucmd->data_pages) * ucmd->num_data_pages,
37199+ GFP_KERNEL);
37200+ if (ucmd->data_pages == NULL) {
37201+ TRACE(TRACE_OUT_OF_MEM, "Unable to allocate data_pages array "
37202+ "(num_data_pages=%d)", ucmd->num_data_pages);
37203+ res = -ENOMEM;
37204+ goto out_nomem;
37205+ }
37206+
37207+ TRACE_MEM("Mapping buffer (ucmd %p, ubuff %lx, ucmd->num_data_pages %d,"
37208+ " first_page_offset %d, len %d)", ucmd, ubuff,
37209+ ucmd->num_data_pages, (int)(ubuff & ~PAGE_MASK),
37210+ (ucmd->cmd != NULL) ? ucmd->cmd->bufflen : -1);
37211+
37212+ down_read(&tsk->mm->mmap_sem);
37213+ rc = get_user_pages(tsk, tsk->mm, ubuff, ucmd->num_data_pages,
37214+ 1/*writable*/, 0/*don't force*/, ucmd->data_pages, NULL);
37215+ up_read(&tsk->mm->mmap_sem);
37216+
37217+ /* get_user_pages() flushes dcache */
37218+
37219+ if (rc < ucmd->num_data_pages)
37220+ goto out_unmap;
37221+
37222+ ucmd->ubuff = ubuff;
37223+ ucmd->first_page_offset = (ubuff & ~PAGE_MASK);
37224+
37225+out:
37226+ TRACE_EXIT_RES(res);
37227+ return res;
37228+
37229+out_nomem:
37230+ if (ucmd->cmd != NULL)
37231+ scst_set_busy(ucmd->cmd);
37232+ /* go through */
37233+
37234+out_err:
37235+ if (ucmd->cmd != NULL)
37236+ scst_set_cmd_abnormal_done_state(ucmd->cmd);
37237+ goto out;
37238+
37239+out_unmap:
37240+ PRINT_ERROR("Failed to get %d user pages (rc %d)",
37241+ ucmd->num_data_pages, rc);
37242+ if (rc > 0) {
37243+ for (i = 0; i < rc; i++)
37244+ page_cache_release(ucmd->data_pages[i]);
37245+ }
37246+ kfree(ucmd->data_pages);
37247+ ucmd->data_pages = NULL;
37248+ res = -EFAULT;
37249+ if (ucmd->cmd != NULL)
37250+ scst_set_cmd_error(ucmd->cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
37251+ goto out_err;
37252+}
37253+
37254+static int dev_user_process_reply_alloc(struct scst_user_cmd *ucmd,
37255+ struct scst_user_reply_cmd *reply)
37256+{
37257+ int res = 0;
37258+ struct scst_cmd *cmd = ucmd->cmd;
37259+
37260+ TRACE_ENTRY();
37261+
37262+ TRACE_DBG("ucmd %p, pbuf %llx", ucmd, reply->alloc_reply.pbuf);
37263+
37264+ if (likely(reply->alloc_reply.pbuf != 0)) {
37265+ int pages;
37266+ if (ucmd->buff_cached) {
37267+ if (unlikely((reply->alloc_reply.pbuf & ~PAGE_MASK) != 0)) {
37268+ PRINT_ERROR("Supplied pbuf %llx isn't "
37269+ "page aligned",
37270+ reply->alloc_reply.pbuf);
37271+ goto out_hwerr;
37272+ }
37273+ pages = cmd->sg_cnt;
37274+ } else
37275+ pages = calc_num_pg(reply->alloc_reply.pbuf,
37276+ cmd->bufflen);
37277+ res = dev_user_map_buf(ucmd, reply->alloc_reply.pbuf, pages);
37278+ } else {
37279+ scst_set_busy(ucmd->cmd);
37280+ scst_set_cmd_abnormal_done_state(ucmd->cmd);
37281+ }
37282+
37283+out_process:
37284+ scst_post_alloc_data_buf(cmd);
37285+ scst_process_active_cmd(cmd, false);
37286+
37287+ TRACE_EXIT_RES(res);
37288+ return res;
37289+
37290+out_hwerr:
37291+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
37292+ scst_set_cmd_abnormal_done_state(ucmd->cmd);
37293+ res = -EINVAL;
37294+ goto out_process;
37295+}
37296+
37297+static int dev_user_process_reply_parse(struct scst_user_cmd *ucmd,
37298+ struct scst_user_reply_cmd *reply)
37299+{
37300+ int res = 0, rc;
37301+ struct scst_user_scsi_cmd_reply_parse *preply =
37302+ &reply->parse_reply;
37303+ struct scst_cmd *cmd = ucmd->cmd;
37304+
37305+ TRACE_ENTRY();
37306+
37307+ if (preply->status != 0)
37308+ goto out_status;
37309+
37310+ if (unlikely(preply->queue_type > SCST_CMD_QUEUE_ACA))
37311+ goto out_inval;
37312+
37313+ if (unlikely((preply->data_direction != SCST_DATA_WRITE) &&
37314+ (preply->data_direction != SCST_DATA_READ) &&
37315+ (preply->data_direction != SCST_DATA_BIDI) &&
37316+ (preply->data_direction != SCST_DATA_NONE)))
37317+ goto out_inval;
37318+
37319+ if (unlikely((preply->data_direction != SCST_DATA_NONE) &&
37320+ (preply->bufflen == 0)))
37321+ goto out_inval;
37322+
37323+ if (unlikely((preply->bufflen < 0) || (preply->data_len < 0)))
37324+ goto out_inval;
37325+
37326+ if (unlikely(preply->cdb_len > SCST_MAX_CDB_SIZE))
37327+ goto out_inval;
37328+
37329+ TRACE_DBG("ucmd %p, queue_type %x, data_direction, %x, bufflen %d, "
37330+ "data_len %d, pbuf %llx, cdb_len %d, op_flags %x", ucmd,
37331+ preply->queue_type, preply->data_direction, preply->bufflen,
37332+ preply->data_len, reply->alloc_reply.pbuf, preply->cdb_len,
37333+ preply->op_flags);
37334+
37335+ cmd->queue_type = preply->queue_type;
37336+ cmd->data_direction = preply->data_direction;
37337+ cmd->bufflen = preply->bufflen;
37338+ cmd->data_len = preply->data_len;
37339+ if (preply->cdb_len > 0)
37340+ cmd->cdb_len = preply->cdb_len;
37341+ if (preply->op_flags & SCST_INFO_VALID)
37342+ cmd->op_flags = preply->op_flags;
37343+
37344+out_process:
37345+ scst_post_parse(cmd);
37346+ scst_process_active_cmd(cmd, false);
37347+
37348+ TRACE_EXIT_RES(res);
37349+ return res;
37350+
37351+out_inval:
37352+ PRINT_ERROR("Invalid parse_reply parameters (LUN %lld, op %x, cmd %p)",
37353+ (long long unsigned int)cmd->lun, cmd->cdb[0], cmd);
37354+ PRINT_BUFFER("Invalid parse_reply", reply, sizeof(*reply));
37355+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
37356+ res = -EINVAL;
37357+ goto out_abnormal;
37358+
37359+out_hwerr_res_set:
37360+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
37361+
37362+out_abnormal:
37363+ scst_set_cmd_abnormal_done_state(cmd);
37364+ goto out_process;
37365+
37366+out_status:
37367+ TRACE_DBG("ucmd %p returned with error from user status %x",
37368+ ucmd, preply->status);
37369+
37370+ if (preply->sense_len != 0) {
37371+ int sense_len;
37372+
37373+ res = scst_alloc_sense(cmd, 0);
37374+ if (res != 0)
37375+ goto out_hwerr_res_set;
37376+
37377+ sense_len = min_t(int, cmd->sense_buflen, preply->sense_len);
37378+
37379+ rc = copy_from_user(cmd->sense,
37380+ (void __user *)(unsigned long)preply->psense_buffer,
37381+ sense_len);
37382+ if (rc != 0) {
37383+ PRINT_ERROR("Failed to copy %d sense's bytes", rc);
37384+ res = -EFAULT;
37385+ goto out_hwerr_res_set;
37386+ }
37387+ cmd->sense_valid_len = sense_len;
37388+ }
37389+ scst_set_cmd_error_status(cmd, preply->status);
37390+ goto out_abnormal;
37391+}
37392+
37393+static int dev_user_process_reply_on_free(struct scst_user_cmd *ucmd)
37394+{
37395+ int res = 0;
37396+
37397+ TRACE_ENTRY();
37398+
37399+ TRACE_DBG("ON FREE ucmd %p", ucmd);
37400+
37401+ dev_user_free_sgv(ucmd);
37402+ ucmd_put(ucmd);
37403+
37404+ TRACE_EXIT_RES(res);
37405+ return res;
37406+}
37407+
37408+static int dev_user_process_reply_on_cache_free(struct scst_user_cmd *ucmd)
37409+{
37410+ int res = 0;
37411+
37412+ TRACE_ENTRY();
37413+
37414+ TRACE_DBG("ON CACHE FREE ucmd %p", ucmd);
37415+
37416+ ucmd_put(ucmd);
37417+
37418+ TRACE_EXIT_RES(res);
37419+ return res;
37420+}
37421+
37422+static int dev_user_process_reply_exec(struct scst_user_cmd *ucmd,
37423+ struct scst_user_reply_cmd *reply)
37424+{
37425+ int res = 0;
37426+ struct scst_user_scsi_cmd_reply_exec *ereply =
37427+ &reply->exec_reply;
37428+ struct scst_cmd *cmd = ucmd->cmd;
37429+
37430+ TRACE_ENTRY();
37431+
37432+ if (ereply->reply_type == SCST_EXEC_REPLY_COMPLETED) {
37433+ if (ucmd->background_exec) {
37434+ TRACE_DBG("Background ucmd %p finished", ucmd);
37435+ ucmd_put(ucmd);
37436+ goto out;
37437+ }
37438+ if (unlikely(ereply->resp_data_len > cmd->bufflen))
37439+ goto out_inval;
37440+ if (unlikely((cmd->data_direction != SCST_DATA_READ) &&
37441+ (ereply->resp_data_len != 0)))
37442+ goto out_inval;
37443+ } else if (ereply->reply_type == SCST_EXEC_REPLY_BACKGROUND) {
37444+ if (unlikely(ucmd->background_exec))
37445+ goto out_inval;
37446+ if (unlikely((cmd->data_direction & SCST_DATA_READ) ||
37447+ (cmd->resp_data_len != 0)))
37448+ goto out_inval;
37449+ /*
37450+ * background_exec assignment must be after ucmd get.
37451+ * Otherwise, due to reorder, in dev_user_process_reply()
37452+ * it is possible that ucmd is destroyed before it "got" here.
37453+ */
37454+ ucmd_get(ucmd);
37455+ ucmd->background_exec = 1;
37456+ TRACE_DBG("Background ucmd %p", ucmd);
37457+ goto out_compl;
37458+ } else
37459+ goto out_inval;
37460+
37461+ TRACE_DBG("ucmd %p, status %d, resp_data_len %d", ucmd,
37462+ ereply->status, ereply->resp_data_len);
37463+
37464+ cmd->atomic = 0;
37465+
37466+ if (ereply->resp_data_len != 0) {
37467+ if (ucmd->ubuff == 0) {
37468+ int pages, rc;
37469+ if (unlikely(ereply->pbuf == 0))
37470+ goto out_busy;
37471+ if (ucmd->buff_cached) {
37472+ if (unlikely((ereply->pbuf & ~PAGE_MASK) != 0)) {
37473+ PRINT_ERROR("Supplied pbuf %llx isn't "
37474+ "page aligned", ereply->pbuf);
37475+ goto out_hwerr;
37476+ }
37477+ pages = cmd->sg_cnt;
37478+ } else
37479+ pages = calc_num_pg(ereply->pbuf, cmd->bufflen);
37480+ rc = dev_user_map_buf(ucmd, ereply->pbuf, pages);
37481+ if ((rc != 0) || (ucmd->ubuff == 0))
37482+ goto out_compl;
37483+
37484+ rc = dev_user_alloc_sg(ucmd, ucmd->buff_cached);
37485+ if (unlikely(rc != 0))
37486+ goto out_busy;
37487+ } else
37488+ dev_user_flush_dcache(ucmd);
37489+ cmd->may_need_dma_sync = 1;
37490+ scst_set_resp_data_len(cmd, ereply->resp_data_len);
37491+ } else if (cmd->resp_data_len != ereply->resp_data_len) {
37492+ if (ucmd->ubuff == 0) {
37493+ /*
37494+ * We have an empty SG, so can't call
37495+ * scst_set_resp_data_len()
37496+ */
37497+ cmd->resp_data_len = ereply->resp_data_len;
37498+ cmd->resid_possible = 1;
37499+ } else
37500+ scst_set_resp_data_len(cmd, ereply->resp_data_len);
37501+ }
37502+
37503+ cmd->status = ereply->status;
37504+ if (ereply->sense_len != 0) {
37505+ int sense_len, rc;
37506+
37507+ res = scst_alloc_sense(cmd, 0);
37508+ if (res != 0)
37509+ goto out_compl;
37510+
37511+ sense_len = min((int)cmd->sense_buflen, (int)ereply->sense_len);
37512+
37513+ rc = copy_from_user(cmd->sense,
37514+ (void __user *)(unsigned long)ereply->psense_buffer,
37515+ sense_len);
37516+ if (rc != 0) {
37517+ PRINT_ERROR("Failed to copy %d sense's bytes", rc);
37518+ res = -EFAULT;
37519+ goto out_hwerr_res_set;
37520+ }
37521+ cmd->sense_valid_len = sense_len;
37522+ }
37523+
37524+out_compl:
37525+ cmd->completed = 1;
37526+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_DIRECT);
37527+ /* !! At this point cmd can be already freed !! */
37528+
37529+out:
37530+ TRACE_EXIT_RES(res);
37531+ return res;
37532+
37533+out_inval:
37534+ PRINT_ERROR("Invalid exec_reply parameters (LUN %lld, op %x, cmd %p)",
37535+ (long long unsigned int)cmd->lun, cmd->cdb[0], cmd);
37536+ PRINT_BUFFER("Invalid exec_reply", reply, sizeof(*reply));
37537+
37538+out_hwerr:
37539+ res = -EINVAL;
37540+
37541+out_hwerr_res_set:
37542+ if (ucmd->background_exec) {
37543+ ucmd_put(ucmd);
37544+ goto out;
37545+ } else {
37546+ scst_set_cmd_error(cmd,
37547+ SCST_LOAD_SENSE(scst_sense_hardw_error));
37548+ goto out_compl;
37549+ }
37550+
37551+out_busy:
37552+ scst_set_busy(cmd);
37553+ goto out_compl;
37554+}
37555+
37556+static int dev_user_process_reply(struct scst_user_dev *dev,
37557+ struct scst_user_reply_cmd *reply)
37558+{
37559+ int res = 0;
37560+ struct scst_user_cmd *ucmd;
37561+ int state;
37562+
37563+ TRACE_ENTRY();
37564+
37565+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37566+
37567+ ucmd = __ucmd_find_hash(dev, reply->cmd_h);
37568+ if (unlikely(ucmd == NULL)) {
37569+ TRACE_MGMT_DBG("cmd_h %d not found", reply->cmd_h);
37570+ res = -ESRCH;
37571+ goto out_unlock;
37572+ }
37573+
37574+ if (unlikely(ucmd_get_check(ucmd))) {
37575+ TRACE_MGMT_DBG("Found being destroyed cmd_h %d", reply->cmd_h);
37576+ res = -ESRCH;
37577+ goto out_unlock;
37578+ }
37579+
37580+ /* To sync. with dev_user_process_reply_exec(). See comment there. */
37581+ smp_mb();
37582+ if (ucmd->background_exec) {
37583+ state = UCMD_STATE_EXECING;
37584+ goto unlock_process;
37585+ }
37586+
37587+ if (unlikely(ucmd->this_state_unjammed)) {
37588+ TRACE_MGMT_DBG("Reply on unjammed ucmd %p, ignoring",
37589+ ucmd);
37590+ goto out_unlock_put;
37591+ }
37592+
37593+ if (unlikely(!ucmd->sent_to_user)) {
37594+ TRACE_MGMT_DBG("Ucmd %p isn't in the sent to user "
37595+ "state %x", ucmd, ucmd->state);
37596+ res = -EINVAL;
37597+ goto out_unlock_put;
37598+ }
37599+
37600+ if (unlikely(reply->subcode != ucmd->user_cmd.subcode))
37601+ goto out_wrong_state;
37602+
37603+ if (unlikely(_IOC_NR(reply->subcode) != ucmd->state))
37604+ goto out_wrong_state;
37605+
37606+ state = ucmd->state;
37607+ ucmd->sent_to_user = 0;
37608+
37609+unlock_process:
37610+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37611+
37612+ switch (state) {
37613+ case UCMD_STATE_PARSING:
37614+ res = dev_user_process_reply_parse(ucmd, reply);
37615+ break;
37616+
37617+ case UCMD_STATE_BUF_ALLOCING:
37618+ res = dev_user_process_reply_alloc(ucmd, reply);
37619+ break;
37620+
37621+ case UCMD_STATE_EXECING:
37622+ res = dev_user_process_reply_exec(ucmd, reply);
37623+ break;
37624+
37625+ case UCMD_STATE_ON_FREEING:
37626+ res = dev_user_process_reply_on_free(ucmd);
37627+ break;
37628+
37629+ case UCMD_STATE_ON_CACHE_FREEING:
37630+ res = dev_user_process_reply_on_cache_free(ucmd);
37631+ break;
37632+
37633+ case UCMD_STATE_TM_EXECING:
37634+ res = dev_user_process_reply_tm_exec(ucmd, reply->result);
37635+ break;
37636+
37637+ case UCMD_STATE_ATTACH_SESS:
37638+ case UCMD_STATE_DETACH_SESS:
37639+ res = dev_user_process_reply_sess(ucmd, reply->result);
37640+ break;
37641+
37642+ default:
37643+ BUG();
37644+ break;
37645+ }
37646+
37647+out_put:
37648+ ucmd_put(ucmd);
37649+
37650+out:
37651+ TRACE_EXIT_RES(res);
37652+ return res;
37653+
37654+out_wrong_state:
37655+ PRINT_ERROR("Command's %p subcode %x doesn't match internal "
37656+ "command's state %x or reply->subcode (%x) != ucmd->subcode "
37657+ "(%x)", ucmd, _IOC_NR(reply->subcode), ucmd->state,
37658+ reply->subcode, ucmd->user_cmd.subcode);
37659+ res = -EINVAL;
37660+ dev_user_unjam_cmd(ucmd, 0, NULL);
37661+
37662+out_unlock_put:
37663+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37664+ goto out_put;
37665+
37666+out_unlock:
37667+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37668+ goto out;
37669+}
37670+
37671+static int dev_user_reply_cmd(struct file *file, void __user *arg)
37672+{
37673+ int res = 0, rc;
37674+ struct scst_user_dev *dev;
37675+ struct scst_user_reply_cmd reply;
37676+
37677+ TRACE_ENTRY();
37678+
37679+ mutex_lock(&dev_priv_mutex);
37680+ dev = (struct scst_user_dev *)file->private_data;
37681+ res = dev_user_check_reg(dev);
37682+ if (unlikely(res != 0)) {
37683+ mutex_unlock(&dev_priv_mutex);
37684+ goto out;
37685+ }
37686+ down_read(&dev->dev_rwsem);
37687+ mutex_unlock(&dev_priv_mutex);
37688+
37689+ rc = copy_from_user(&reply, arg, sizeof(reply));
37690+ if (unlikely(rc != 0)) {
37691+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
37692+ res = -EFAULT;
37693+ goto out_up;
37694+ }
37695+
37696+ TRACE_DBG("Reply for dev %s", dev->name);
37697+
37698+ TRACE_BUFFER("Reply", &reply, sizeof(reply));
37699+
37700+ res = dev_user_process_reply(dev, &reply);
37701+ if (unlikely(res < 0))
37702+ goto out_up;
37703+
37704+out_up:
37705+ up_read(&dev->dev_rwsem);
37706+
37707+out:
37708+ TRACE_EXIT_RES(res);
37709+ return res;
37710+}
37711+
37712+static int dev_user_get_ext_cdb(struct file *file, void __user *arg)
37713+{
37714+ int res = 0, rc;
37715+ struct scst_user_dev *dev;
37716+ struct scst_user_cmd *ucmd;
37717+ struct scst_cmd *cmd = NULL;
37718+ struct scst_user_get_ext_cdb get;
37719+
37720+ TRACE_ENTRY();
37721+
37722+ mutex_lock(&dev_priv_mutex);
37723+ dev = (struct scst_user_dev *)file->private_data;
37724+ res = dev_user_check_reg(dev);
37725+ if (unlikely(res != 0)) {
37726+ mutex_unlock(&dev_priv_mutex);
37727+ goto out;
37728+ }
37729+ down_read(&dev->dev_rwsem);
37730+ mutex_unlock(&dev_priv_mutex);
37731+
37732+ rc = copy_from_user(&get, arg, sizeof(get));
37733+ if (unlikely(rc != 0)) {
37734+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
37735+ res = -EFAULT;
37736+ goto out_up;
37737+ }
37738+
37739+ TRACE_MGMT_DBG("Get ext cdb for dev %s", dev->name);
37740+
37741+ TRACE_BUFFER("Get ext cdb", &get, sizeof(get));
37742+
37743+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37744+
37745+ ucmd = __ucmd_find_hash(dev, get.cmd_h);
37746+ if (unlikely(ucmd == NULL)) {
37747+ TRACE_MGMT_DBG("cmd_h %d not found", get.cmd_h);
37748+ res = -ESRCH;
37749+ goto out_unlock;
37750+ }
37751+
37752+ if (unlikely(ucmd_get_check(ucmd))) {
37753+ TRACE_MGMT_DBG("Found being destroyed cmd_h %d", get.cmd_h);
37754+ res = -ESRCH;
37755+ goto out_unlock;
37756+ }
37757+
37758+ if ((ucmd->cmd != NULL) && (ucmd->state <= UCMD_STATE_EXECING) &&
37759+ (ucmd->sent_to_user || ucmd->background_exec)) {
37760+ cmd = ucmd->cmd;
37761+ scst_cmd_get(cmd);
37762+ } else {
37763+ TRACE_MGMT_DBG("Invalid ucmd state %d for cmd_h %d",
37764+ ucmd->state, get.cmd_h);
37765+ res = -EINVAL;
37766+ goto out_unlock;
37767+ }
37768+
37769+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37770+
37771+ if (cmd == NULL)
37772+ goto out_put;
37773+
37774+ if (cmd->ext_cdb == NULL)
37775+ goto out_cmd_put;
37776+
37777+ TRACE_BUFFER("EXT CDB", cmd->ext_cdb, cmd->ext_cdb_len);
37778+ rc = copy_to_user((void __user *)(unsigned long)get.ext_cdb_buffer,
37779+ cmd->ext_cdb, cmd->ext_cdb_len);
37780+ if (unlikely(rc != 0)) {
37781+ PRINT_ERROR("Failed to copy to user %d bytes", rc);
37782+ res = -EFAULT;
37783+ goto out_cmd_put;
37784+ }
37785+
37786+out_cmd_put:
37787+ scst_cmd_put(cmd);
37788+
37789+out_put:
37790+ ucmd_put(ucmd);
37791+
37792+out_up:
37793+ up_read(&dev->dev_rwsem);
37794+
37795+out:
37796+ TRACE_EXIT_RES(res);
37797+ return res;
37798+
37799+out_unlock:
37800+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37801+ goto out_up;
37802+}
37803+
37804+static int dev_user_process_scst_commands(struct scst_user_dev *dev)
37805+ __releases(&dev->udev_cmd_threads.cmd_list_lock)
37806+ __acquires(&dev->udev_cmd_threads.cmd_list_lock)
37807+{
37808+ int res = 0;
37809+
37810+ TRACE_ENTRY();
37811+
37812+ while (!list_empty(&dev->udev_cmd_threads.active_cmd_list)) {
37813+ struct scst_cmd *cmd = list_entry(
37814+ dev->udev_cmd_threads.active_cmd_list.next, typeof(*cmd),
37815+ cmd_list_entry);
37816+ TRACE_DBG("Deleting cmd %p from active cmd list", cmd);
37817+ list_del(&cmd->cmd_list_entry);
37818+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37819+ scst_process_active_cmd(cmd, false);
37820+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37821+ res++;
37822+ }
37823+
37824+ TRACE_EXIT_RES(res);
37825+ return res;
37826+}
37827+
37828+/* Called under udev_cmd_threads.cmd_list_lock and IRQ off */
37829+static struct scst_user_cmd *__dev_user_get_next_cmd(struct list_head *cmd_list)
37830+ __releases(&dev->udev_cmd_threads.cmd_list_lock)
37831+ __acquires(&dev->udev_cmd_threads.cmd_list_lock)
37832+{
37833+ struct scst_user_cmd *u;
37834+
37835+again:
37836+ u = NULL;
37837+ if (!list_empty(cmd_list)) {
37838+ u = list_entry(cmd_list->next, typeof(*u),
37839+ ready_cmd_list_entry);
37840+
37841+ TRACE_DBG("Found ready ucmd %p", u);
37842+ list_del(&u->ready_cmd_list_entry);
37843+
37844+ EXTRACHECKS_BUG_ON(u->this_state_unjammed);
37845+
37846+ if (u->cmd != NULL) {
37847+ if (u->state == UCMD_STATE_EXECING) {
37848+ struct scst_user_dev *dev = u->dev;
37849+ int rc;
37850+
37851+ EXTRACHECKS_BUG_ON(u->jammed);
37852+
37853+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37854+
37855+ rc = scst_check_local_events(u->cmd);
37856+ if (unlikely(rc != 0)) {
37857+ u->cmd->scst_cmd_done(u->cmd,
37858+ SCST_CMD_STATE_DEFAULT,
37859+ SCST_CONTEXT_DIRECT);
37860+ /*
37861+ * !! At this point cmd & u can be !!
37862+ * !! already freed !!
37863+ */
37864+ spin_lock_irq(
37865+ &dev->udev_cmd_threads.cmd_list_lock);
37866+ goto again;
37867+ }
37868+
37869+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37870+ } else if (unlikely(test_bit(SCST_CMD_ABORTED,
37871+ &u->cmd->cmd_flags))) {
37872+ switch (u->state) {
37873+ case UCMD_STATE_PARSING:
37874+ case UCMD_STATE_BUF_ALLOCING:
37875+ TRACE_MGMT_DBG("Aborting ucmd %p", u);
37876+ dev_user_unjam_cmd(u, 0, NULL);
37877+ goto again;
37878+ case UCMD_STATE_EXECING:
37879+ EXTRACHECKS_BUG_ON(1);
37880+ }
37881+ }
37882+ }
37883+ u->sent_to_user = 1;
37884+ u->seen_by_user = 1;
37885+ }
37886+ return u;
37887+}
37888+
37889+static inline int test_cmd_threads(struct scst_user_dev *dev)
37890+{
37891+ int res = !list_empty(&dev->udev_cmd_threads.active_cmd_list) ||
37892+ !list_empty(&dev->ready_cmd_list) ||
37893+ !dev->blocking || dev->cleanup_done ||
37894+ signal_pending(current);
37895+ return res;
37896+}
37897+
37898+/* Called under udev_cmd_threads.cmd_list_lock and IRQ off */
37899+static int dev_user_get_next_cmd(struct scst_user_dev *dev,
37900+ struct scst_user_cmd **ucmd)
37901+{
37902+ int res = 0;
37903+ wait_queue_t wait;
37904+
37905+ TRACE_ENTRY();
37906+
37907+ init_waitqueue_entry(&wait, current);
37908+
37909+ while (1) {
37910+ if (!test_cmd_threads(dev)) {
37911+ add_wait_queue_exclusive_head(
37912+ &dev->udev_cmd_threads.cmd_list_waitQ,
37913+ &wait);
37914+ for (;;) {
37915+ set_current_state(TASK_INTERRUPTIBLE);
37916+ if (test_cmd_threads(dev))
37917+ break;
37918+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37919+ schedule();
37920+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
37921+ }
37922+ set_current_state(TASK_RUNNING);
37923+ remove_wait_queue(&dev->udev_cmd_threads.cmd_list_waitQ,
37924+ &wait);
37925+ }
37926+
37927+ dev_user_process_scst_commands(dev);
37928+
37929+ *ucmd = __dev_user_get_next_cmd(&dev->ready_cmd_list);
37930+ if (*ucmd != NULL)
37931+ break;
37932+
37933+ if (!dev->blocking || dev->cleanup_done) {
37934+ res = -EAGAIN;
37935+ TRACE_DBG("No ready commands, returning %d", res);
37936+ break;
37937+ }
37938+
37939+ if (signal_pending(current)) {
37940+ res = -EINTR;
37941+ TRACE_DBG("Signal pending, returning %d", res);
37942+ break;
37943+ }
37944+ }
37945+
37946+ TRACE_EXIT_RES(res);
37947+ return res;
37948+}
37949+
37950+static int dev_user_reply_get_cmd(struct file *file, void __user *arg)
37951+{
37952+ int res = 0, rc;
37953+ struct scst_user_dev *dev;
37954+ struct scst_user_get_cmd *cmd;
37955+ struct scst_user_reply_cmd *reply;
37956+ struct scst_user_cmd *ucmd;
37957+ uint64_t ureply;
37958+
37959+ TRACE_ENTRY();
37960+
37961+ mutex_lock(&dev_priv_mutex);
37962+ dev = (struct scst_user_dev *)file->private_data;
37963+ res = dev_user_check_reg(dev);
37964+ if (unlikely(res != 0)) {
37965+ mutex_unlock(&dev_priv_mutex);
37966+ goto out;
37967+ }
37968+ down_read(&dev->dev_rwsem);
37969+ mutex_unlock(&dev_priv_mutex);
37970+
37971+ /* get_user() can't be used with 64-bit values on x86_32 */
37972+ rc = copy_from_user(&ureply, (uint64_t __user *)
37973+ &((struct scst_user_get_cmd __user *)arg)->preply,
37974+ sizeof(ureply));
37975+ if (unlikely(rc != 0)) {
37976+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
37977+ res = -EFAULT;
37978+ goto out_up;
37979+ }
37980+
37981+ TRACE_DBG("ureply %lld (dev %s)", (long long unsigned int)ureply,
37982+ dev->name);
37983+
37984+ cmd = kmem_cache_alloc(user_get_cmd_cachep, GFP_KERNEL);
37985+ if (unlikely(cmd == NULL)) {
37986+ res = -ENOMEM;
37987+ goto out_up;
37988+ }
37989+
37990+ if (ureply != 0) {
37991+ unsigned long u = (unsigned long)ureply;
37992+ reply = (struct scst_user_reply_cmd *)cmd;
37993+ rc = copy_from_user(reply, (void __user *)u, sizeof(*reply));
37994+ if (unlikely(rc != 0)) {
37995+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
37996+ res = -EFAULT;
37997+ goto out_free;
37998+ }
37999+
38000+ TRACE_BUFFER("Reply", reply, sizeof(*reply));
38001+
38002+ res = dev_user_process_reply(dev, reply);
38003+ if (unlikely(res < 0))
38004+ goto out_free;
38005+ }
38006+
38007+ kmem_cache_free(user_get_cmd_cachep, cmd);
38008+
38009+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38010+again:
38011+ res = dev_user_get_next_cmd(dev, &ucmd);
38012+ if (res == 0) {
38013+ int len;
38014+ /*
38015+ * A misbehaving user space handler can make ucmd to get dead
38016+ * immediately after we released the lock, which can lead to
38017+ * copy of dead data to the user space, which can lead to a
38018+ * leak of sensitive information.
38019+ */
38020+ if (unlikely(ucmd_get_check(ucmd))) {
38021+ /* Oops, this ucmd is already being destroyed. Retry. */
38022+ goto again;
38023+ }
38024+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38025+
38026+ EXTRACHECKS_BUG_ON(ucmd->user_cmd_payload_len == 0);
38027+
38028+ len = ucmd->user_cmd_payload_len;
38029+ TRACE_DBG("ucmd %p (user_cmd %p), payload_len %d (len %d)",
38030+ ucmd, &ucmd->user_cmd, ucmd->user_cmd_payload_len, len);
38031+ TRACE_BUFFER("UCMD", &ucmd->user_cmd, len);
38032+ rc = copy_to_user(arg, &ucmd->user_cmd, len);
38033+ if (unlikely(rc != 0)) {
38034+ PRINT_ERROR("Copy to user failed (%d), requeuing ucmd "
38035+ "%p back to head of ready cmd list", rc, ucmd);
38036+ res = -EFAULT;
38037+ /* Requeue ucmd back */
38038+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38039+ list_add(&ucmd->ready_cmd_list_entry,
38040+ &dev->ready_cmd_list);
38041+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38042+ }
38043+#ifdef CONFIG_SCST_EXTRACHECKS
38044+ else
38045+ ucmd->user_cmd_payload_len = 0;
38046+#endif
38047+ ucmd_put(ucmd);
38048+ } else
38049+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38050+
38051+out_up:
38052+ up_read(&dev->dev_rwsem);
38053+
38054+out:
38055+ TRACE_EXIT_RES(res);
38056+ return res;
38057+
38058+out_free:
38059+ kmem_cache_free(user_get_cmd_cachep, cmd);
38060+ goto out_up;
38061+}
38062+
38063+static long dev_user_ioctl(struct file *file, unsigned int cmd,
38064+ unsigned long arg)
38065+{
38066+ long res, rc;
38067+
38068+ TRACE_ENTRY();
38069+
38070+ switch (cmd) {
38071+ case SCST_USER_REPLY_AND_GET_CMD:
38072+ TRACE_DBG("%s", "REPLY_AND_GET_CMD");
38073+ res = dev_user_reply_get_cmd(file, (void __user *)arg);
38074+ break;
38075+
38076+ case SCST_USER_REPLY_CMD:
38077+ TRACE_DBG("%s", "REPLY_CMD");
38078+ res = dev_user_reply_cmd(file, (void __user *)arg);
38079+ break;
38080+
38081+ case SCST_USER_GET_EXTENDED_CDB:
38082+ TRACE_DBG("%s", "GET_EXTENDED_CDB");
38083+ res = dev_user_get_ext_cdb(file, (void __user *)arg);
38084+ break;
38085+
38086+ case SCST_USER_REGISTER_DEVICE:
38087+ {
38088+ struct scst_user_dev_desc *dev_desc;
38089+ TRACE_DBG("%s", "REGISTER_DEVICE");
38090+ dev_desc = kmalloc(sizeof(*dev_desc), GFP_KERNEL);
38091+ if (dev_desc == NULL) {
38092+ res = -ENOMEM;
38093+ goto out;
38094+ }
38095+ rc = copy_from_user(dev_desc, (void __user *)arg,
38096+ sizeof(*dev_desc));
38097+ if (rc != 0) {
38098+ PRINT_ERROR("Failed to copy %ld user's bytes", rc);
38099+ res = -EFAULT;
38100+ kfree(dev_desc);
38101+ goto out;
38102+ }
38103+ TRACE_BUFFER("dev_desc", dev_desc, sizeof(*dev_desc));
38104+ dev_desc->name[sizeof(dev_desc->name)-1] = '\0';
38105+ dev_desc->sgv_name[sizeof(dev_desc->sgv_name)-1] = '\0';
38106+ res = dev_user_register_dev(file, dev_desc);
38107+ kfree(dev_desc);
38108+ break;
38109+ }
38110+
38111+ case SCST_USER_UNREGISTER_DEVICE:
38112+ TRACE_DBG("%s", "UNREGISTER_DEVICE");
38113+ res = dev_user_unregister_dev(file);
38114+ break;
38115+
38116+ case SCST_USER_FLUSH_CACHE:
38117+ TRACE_DBG("%s", "FLUSH_CACHE");
38118+ res = dev_user_flush_cache(file);
38119+ break;
38120+
38121+ case SCST_USER_SET_OPTIONS:
38122+ {
38123+ struct scst_user_opt opt;
38124+ TRACE_DBG("%s", "SET_OPTIONS");
38125+ rc = copy_from_user(&opt, (void __user *)arg, sizeof(opt));
38126+ if (rc != 0) {
38127+ PRINT_ERROR("Failed to copy %ld user's bytes", rc);
38128+ res = -EFAULT;
38129+ goto out;
38130+ }
38131+ TRACE_BUFFER("opt", &opt, sizeof(opt));
38132+ res = dev_user_set_opt(file, &opt);
38133+ break;
38134+ }
38135+
38136+ case SCST_USER_GET_OPTIONS:
38137+ TRACE_DBG("%s", "GET_OPTIONS");
38138+ res = dev_user_get_opt(file, (void __user *)arg);
38139+ break;
38140+
38141+ case SCST_USER_DEVICE_CAPACITY_CHANGED:
38142+ TRACE_DBG("%s", "CAPACITY_CHANGED");
38143+ res = dev_user_capacity_changed(file);
38144+ break;
38145+
38146+ case SCST_USER_PREALLOC_BUFFER:
38147+ TRACE_DBG("%s", "PREALLOC_BUFFER");
38148+ res = dev_user_prealloc_buffer(file, (void __user *)arg);
38149+ break;
38150+
38151+ default:
38152+ PRINT_ERROR("Invalid ioctl cmd %x", cmd);
38153+ res = -EINVAL;
38154+ goto out;
38155+ }
38156+
38157+out:
38158+ TRACE_EXIT_RES(res);
38159+ return res;
38160+}
38161+
38162+static unsigned int dev_user_poll(struct file *file, poll_table *wait)
38163+{
38164+ int res = 0;
38165+ struct scst_user_dev *dev;
38166+
38167+ TRACE_ENTRY();
38168+
38169+ mutex_lock(&dev_priv_mutex);
38170+ dev = (struct scst_user_dev *)file->private_data;
38171+ res = dev_user_check_reg(dev);
38172+ if (unlikely(res != 0)) {
38173+ mutex_unlock(&dev_priv_mutex);
38174+ goto out;
38175+ }
38176+ down_read(&dev->dev_rwsem);
38177+ mutex_unlock(&dev_priv_mutex);
38178+
38179+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38180+
38181+ if (!list_empty(&dev->ready_cmd_list) ||
38182+ !list_empty(&dev->udev_cmd_threads.active_cmd_list)) {
38183+ res |= POLLIN | POLLRDNORM;
38184+ goto out_unlock;
38185+ }
38186+
38187+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38188+
38189+ TRACE_DBG("Before poll_wait() (dev %s)", dev->name);
38190+ poll_wait(file, &dev->udev_cmd_threads.cmd_list_waitQ, wait);
38191+ TRACE_DBG("After poll_wait() (dev %s)", dev->name);
38192+
38193+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38194+
38195+ if (!list_empty(&dev->ready_cmd_list) ||
38196+ !list_empty(&dev->udev_cmd_threads.active_cmd_list)) {
38197+ res |= POLLIN | POLLRDNORM;
38198+ goto out_unlock;
38199+ }
38200+
38201+out_unlock:
38202+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38203+
38204+ up_read(&dev->dev_rwsem);
38205+
38206+out:
38207+ TRACE_EXIT_HRES(res);
38208+ return res;
38209+}
38210+
38211+/*
38212+ * Called under udev_cmd_threads.cmd_list_lock, but can drop it inside,
38213+ * then reacquire.
38214+ */
38215+static void dev_user_unjam_cmd(struct scst_user_cmd *ucmd, int busy,
38216+ unsigned long *flags)
38217+ __releases(&dev->udev_cmd_threads.cmd_list_lock)
38218+ __acquires(&dev->udev_cmd_threads.cmd_list_lock)
38219+{
38220+ int state = ucmd->state;
38221+ struct scst_user_dev *dev = ucmd->dev;
38222+
38223+ TRACE_ENTRY();
38224+
38225+ if (ucmd->this_state_unjammed)
38226+ goto out;
38227+
38228+ TRACE_MGMT_DBG("Unjamming ucmd %p (busy %d, state %x)", ucmd, busy,
38229+ state);
38230+
38231+ ucmd->jammed = 1;
38232+ ucmd->this_state_unjammed = 1;
38233+ ucmd->sent_to_user = 0;
38234+
38235+ switch (state) {
38236+ case UCMD_STATE_PARSING:
38237+ case UCMD_STATE_BUF_ALLOCING:
38238+ if (test_bit(SCST_CMD_ABORTED, &ucmd->cmd->cmd_flags))
38239+ ucmd->aborted = 1;
38240+ else {
38241+ if (busy)
38242+ scst_set_busy(ucmd->cmd);
38243+ else
38244+ scst_set_cmd_error(ucmd->cmd,
38245+ SCST_LOAD_SENSE(scst_sense_hardw_error));
38246+ }
38247+ scst_set_cmd_abnormal_done_state(ucmd->cmd);
38248+
38249+ if (state == UCMD_STATE_PARSING)
38250+ scst_post_parse(ucmd->cmd);
38251+ else
38252+ scst_post_alloc_data_buf(ucmd->cmd);
38253+
38254+ TRACE_MGMT_DBG("Adding ucmd %p to active list", ucmd);
38255+ list_add(&ucmd->cmd->cmd_list_entry,
38256+ &ucmd->cmd->cmd_threads->active_cmd_list);
38257+ wake_up(&ucmd->cmd->cmd_threads->cmd_list_waitQ);
38258+ break;
38259+
38260+ case UCMD_STATE_EXECING:
38261+ if (flags != NULL)
38262+ spin_unlock_irqrestore(&dev->udev_cmd_threads.cmd_list_lock,
38263+ *flags);
38264+ else
38265+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38266+
38267+ TRACE_MGMT_DBG("EXEC: unjamming ucmd %p", ucmd);
38268+
38269+ if (test_bit(SCST_CMD_ABORTED, &ucmd->cmd->cmd_flags))
38270+ ucmd->aborted = 1;
38271+ else {
38272+ if (busy)
38273+ scst_set_busy(ucmd->cmd);
38274+ else
38275+ scst_set_cmd_error(ucmd->cmd,
38276+ SCST_LOAD_SENSE(scst_sense_hardw_error));
38277+ }
38278+
38279+ ucmd->cmd->scst_cmd_done(ucmd->cmd, SCST_CMD_STATE_DEFAULT,
38280+ SCST_CONTEXT_DIRECT);
38281+ /* !! At this point cmd and ucmd can be already freed !! */
38282+
38283+ if (flags != NULL)
38284+ spin_lock_irqsave(&dev->udev_cmd_threads.cmd_list_lock,
38285+ *flags);
38286+ else
38287+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38288+ break;
38289+
38290+ case UCMD_STATE_ON_FREEING:
38291+ case UCMD_STATE_ON_CACHE_FREEING:
38292+ case UCMD_STATE_TM_EXECING:
38293+ case UCMD_STATE_ATTACH_SESS:
38294+ case UCMD_STATE_DETACH_SESS:
38295+ if (flags != NULL)
38296+ spin_unlock_irqrestore(&dev->udev_cmd_threads.cmd_list_lock,
38297+ *flags);
38298+ else
38299+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38300+
38301+ switch (state) {
38302+ case UCMD_STATE_ON_FREEING:
38303+ dev_user_process_reply_on_free(ucmd);
38304+ break;
38305+
38306+ case UCMD_STATE_ON_CACHE_FREEING:
38307+ dev_user_process_reply_on_cache_free(ucmd);
38308+ break;
38309+
38310+ case UCMD_STATE_TM_EXECING:
38311+ dev_user_process_reply_tm_exec(ucmd,
38312+ SCST_MGMT_STATUS_FAILED);
38313+ break;
38314+
38315+ case UCMD_STATE_ATTACH_SESS:
38316+ case UCMD_STATE_DETACH_SESS:
38317+ dev_user_process_reply_sess(ucmd, -EFAULT);
38318+ break;
38319+ }
38320+
38321+ if (flags != NULL)
38322+ spin_lock_irqsave(&dev->udev_cmd_threads.cmd_list_lock,
38323+ *flags);
38324+ else
38325+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38326+ break;
38327+
38328+ default:
38329+ PRINT_CRIT_ERROR("Wrong ucmd state %x", state);
38330+ BUG();
38331+ break;
38332+ }
38333+
38334+out:
38335+ TRACE_EXIT();
38336+ return;
38337+}
38338+
38339+static int dev_user_unjam_dev(struct scst_user_dev *dev)
38340+ __releases(&dev->udev_cmd_threads.cmd_list_lock)
38341+ __acquires(&dev->udev_cmd_threads.cmd_list_lock)
38342+{
38343+ int i, res = 0;
38344+ struct scst_user_cmd *ucmd;
38345+
38346+ TRACE_ENTRY();
38347+
38348+ TRACE_MGMT_DBG("Unjamming dev %p", dev);
38349+
38350+ sgv_pool_flush(dev->pool);
38351+ sgv_pool_flush(dev->pool_clust);
38352+
38353+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38354+
38355+repeat:
38356+ for (i = 0; i < (int)ARRAY_SIZE(dev->ucmd_hash); i++) {
38357+ struct list_head *head = &dev->ucmd_hash[i];
38358+
38359+ list_for_each_entry(ucmd, head, hash_list_entry) {
38360+ res++;
38361+
38362+ if (!ucmd->sent_to_user)
38363+ continue;
38364+
38365+ if (ucmd_get_check(ucmd))
38366+ continue;
38367+
38368+ TRACE_MGMT_DBG("ucmd %p, state %x, scst_cmd %p", ucmd,
38369+ ucmd->state, ucmd->cmd);
38370+
38371+ dev_user_unjam_cmd(ucmd, 0, NULL);
38372+
38373+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38374+ ucmd_put(ucmd);
38375+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38376+
38377+ goto repeat;
38378+ }
38379+ }
38380+
38381+ if (dev_user_process_scst_commands(dev) != 0)
38382+ goto repeat;
38383+
38384+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38385+
38386+ TRACE_EXIT_RES(res);
38387+ return res;
38388+}
38389+
38390+static int dev_user_process_reply_tm_exec(struct scst_user_cmd *ucmd,
38391+ int status)
38392+{
38393+ int res = 0;
38394+
38395+ TRACE_ENTRY();
38396+
38397+ TRACE_MGMT_DBG("TM reply (ucmd %p, fn %d, status %d)", ucmd,
38398+ ucmd->user_cmd.tm_cmd.fn, status);
38399+
38400+ if (status == SCST_MGMT_STATUS_TASK_NOT_EXIST) {
38401+ /*
38402+ * It is possible that user space seen TM cmd before cmd
38403+ * to abort or will never see it at all, because it was
38404+ * aborted on the way there. So, it is safe to return
38405+ * success instead, because, if there is the TM cmd at this
38406+ * point, then the cmd to abort apparrently does exist.
38407+ */
38408+ status = SCST_MGMT_STATUS_SUCCESS;
38409+ }
38410+
38411+ scst_async_mcmd_completed(ucmd->mcmd, status);
38412+
38413+ ucmd_put(ucmd);
38414+
38415+ TRACE_EXIT_RES(res);
38416+ return res;
38417+}
38418+
38419+static void dev_user_abort_ready_commands(struct scst_user_dev *dev)
38420+{
38421+ struct scst_user_cmd *ucmd;
38422+ unsigned long flags;
38423+
38424+ TRACE_ENTRY();
38425+
38426+ spin_lock_irqsave(&dev->udev_cmd_threads.cmd_list_lock, flags);
38427+again:
38428+ list_for_each_entry(ucmd, &dev->ready_cmd_list, ready_cmd_list_entry) {
38429+ if ((ucmd->cmd != NULL) && !ucmd->seen_by_user &&
38430+ test_bit(SCST_CMD_ABORTED, &ucmd->cmd->cmd_flags)) {
38431+ switch (ucmd->state) {
38432+ case UCMD_STATE_PARSING:
38433+ case UCMD_STATE_BUF_ALLOCING:
38434+ case UCMD_STATE_EXECING:
38435+ TRACE_MGMT_DBG("Aborting ready ucmd %p", ucmd);
38436+ list_del(&ucmd->ready_cmd_list_entry);
38437+ dev_user_unjam_cmd(ucmd, 0, &flags);
38438+ goto again;
38439+ }
38440+ }
38441+ }
38442+
38443+ spin_unlock_irqrestore(&dev->udev_cmd_threads.cmd_list_lock, flags);
38444+
38445+ TRACE_EXIT();
38446+ return;
38447+}
38448+
38449+static int dev_user_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
38450+ struct scst_tgt_dev *tgt_dev)
38451+{
38452+ struct scst_user_cmd *ucmd;
38453+ struct scst_user_dev *dev =
38454+ (struct scst_user_dev *)tgt_dev->dev->dh_priv;
38455+ struct scst_user_cmd *ucmd_to_abort = NULL;
38456+
38457+ TRACE_ENTRY();
38458+
38459+ /*
38460+ * In the used approach we don't do anything with hung devices, which
38461+ * stopped responding and/or have stuck commands. We forcedly abort such
38462+ * commands only if they not yet sent to the user space or if the device
38463+ * is getting unloaded, e.g. if its handler program gets killed. This is
38464+ * because it's pretty hard to distinguish between stuck and temporary
38465+ * overloaded states of the device. There are several reasons for that:
38466+ *
38467+ * 1. Some commands need a lot of time to complete (several hours),
38468+ * so for an impatient user such command(s) will always look as
38469+ * stuck.
38470+ *
38471+ * 2. If we forcedly abort, i.e. abort before it's actually completed
38472+ * in the user space, just one command, we will have to put the whole
38473+ * device offline until we are sure that no more previously aborted
38474+ * commands will get executed. Otherwise, we might have a possibility
38475+ * for data corruption, when aborted and reported as completed
38476+ * command actually gets executed *after* new commands sent
38477+ * after the force abort was done. Many journaling file systems and
38478+ * databases use "provide required commands order via queue draining"
38479+ * approach and not putting the whole device offline after the forced
38480+ * abort will break it. This makes our decision, if a command stuck
38481+ * or not, cost a lot.
38482+ *
38483+ * So, we leave policy definition if a device stuck or not to
38484+ * the user space and simply let all commands live until they are
38485+ * completed or their devices get closed/killed. This approach is very
38486+ * much OK, but can affect management commands, which need activity
38487+ * suspending via scst_suspend_activity() function such as devices or
38488+ * targets registration/removal. But during normal life such commands
38489+ * should be rare. Plus, when possible, scst_suspend_activity() will
38490+ * return after timeout EBUSY status to allow caller to not stuck
38491+ * forever as well.
38492+ *
38493+ * But, anyway, ToDo, we should reimplement that in the SCST core, so
38494+ * stuck commands would affect only related devices.
38495+ */
38496+
38497+ dev_user_abort_ready_commands(dev);
38498+
38499+ /* We can't afford missing TM command due to memory shortage */
38500+ ucmd = dev_user_alloc_ucmd(dev, GFP_KERNEL|__GFP_NOFAIL);
38501+
38502+ ucmd->user_cmd_payload_len =
38503+ offsetof(struct scst_user_get_cmd, tm_cmd) +
38504+ sizeof(ucmd->user_cmd.tm_cmd);
38505+ ucmd->user_cmd.cmd_h = ucmd->h;
38506+ ucmd->user_cmd.subcode = SCST_USER_TASK_MGMT;
38507+ ucmd->user_cmd.tm_cmd.sess_h = (unsigned long)tgt_dev;
38508+ ucmd->user_cmd.tm_cmd.fn = mcmd->fn;
38509+ ucmd->user_cmd.tm_cmd.cmd_sn = mcmd->cmd_sn;
38510+ ucmd->user_cmd.tm_cmd.cmd_sn_set = mcmd->cmd_sn_set;
38511+
38512+ if (mcmd->cmd_to_abort != NULL) {
38513+ ucmd_to_abort =
38514+ (struct scst_user_cmd *)mcmd->cmd_to_abort->dh_priv;
38515+ if (ucmd_to_abort != NULL)
38516+ ucmd->user_cmd.tm_cmd.cmd_h_to_abort = ucmd_to_abort->h;
38517+ }
38518+
38519+ TRACE_MGMT_DBG("Preparing TM ucmd %p (h %d, fn %d, cmd_to_abort %p, "
38520+ "ucmd_to_abort %p, cmd_h_to_abort %d, mcmd %p)", ucmd, ucmd->h,
38521+ mcmd->fn, mcmd->cmd_to_abort, ucmd_to_abort,
38522+ ucmd->user_cmd.tm_cmd.cmd_h_to_abort, mcmd);
38523+
38524+ ucmd->mcmd = mcmd;
38525+ ucmd->state = UCMD_STATE_TM_EXECING;
38526+
38527+ scst_prepare_async_mcmd(mcmd);
38528+
38529+ dev_user_add_to_ready(ucmd);
38530+
38531+ TRACE_EXIT();
38532+ return SCST_DEV_TM_NOT_COMPLETED;
38533+}
38534+
38535+static int dev_user_attach(struct scst_device *sdev)
38536+{
38537+ int res = 0;
38538+ struct scst_user_dev *dev = NULL, *d;
38539+
38540+ TRACE_ENTRY();
38541+
38542+ spin_lock(&dev_list_lock);
38543+ list_for_each_entry(d, &dev_list, dev_list_entry) {
38544+ if (strcmp(d->name, sdev->virt_name) == 0) {
38545+ dev = d;
38546+ break;
38547+ }
38548+ }
38549+ spin_unlock(&dev_list_lock);
38550+ if (dev == NULL) {
38551+ PRINT_ERROR("Device %s not found", sdev->virt_name);
38552+ res = -EINVAL;
38553+ goto out;
38554+ }
38555+
38556+ sdev->dh_priv = dev;
38557+ sdev->tst = dev->tst;
38558+ sdev->queue_alg = dev->queue_alg;
38559+ sdev->swp = dev->swp;
38560+ sdev->tas = dev->tas;
38561+ sdev->d_sense = dev->d_sense;
38562+ sdev->has_own_order_mgmt = dev->has_own_order_mgmt;
38563+
38564+ dev->sdev = sdev;
38565+
38566+ PRINT_INFO("Attached user space virtual device \"%s\"",
38567+ dev->name);
38568+
38569+out:
38570+ TRACE_EXIT();
38571+ return res;
38572+}
38573+
38574+static void dev_user_detach(struct scst_device *sdev)
38575+{
38576+ struct scst_user_dev *dev = (struct scst_user_dev *)sdev->dh_priv;
38577+
38578+ TRACE_ENTRY();
38579+
38580+ TRACE_DBG("virt_id %d", sdev->virt_id);
38581+
38582+ PRINT_INFO("Detached user space virtual device \"%s\"",
38583+ dev->name);
38584+
38585+ /* dev will be freed by the caller */
38586+ sdev->dh_priv = NULL;
38587+ dev->sdev = NULL;
38588+
38589+ TRACE_EXIT();
38590+ return;
38591+}
38592+
38593+static int dev_user_process_reply_sess(struct scst_user_cmd *ucmd, int status)
38594+{
38595+ int res = 0;
38596+ unsigned long flags;
38597+
38598+ TRACE_ENTRY();
38599+
38600+ TRACE_MGMT_DBG("ucmd %p, cmpl %p, status %d", ucmd, ucmd->cmpl, status);
38601+
38602+ spin_lock_irqsave(&ucmd->dev->udev_cmd_threads.cmd_list_lock, flags);
38603+
38604+ if (ucmd->state == UCMD_STATE_ATTACH_SESS) {
38605+ TRACE_MGMT_DBG("%s", "ATTACH_SESS finished");
38606+ ucmd->result = status;
38607+ } else if (ucmd->state == UCMD_STATE_DETACH_SESS) {
38608+ TRACE_MGMT_DBG("%s", "DETACH_SESS finished");
38609+ } else
38610+ BUG();
38611+
38612+ if (ucmd->cmpl != NULL)
38613+ complete_all(ucmd->cmpl);
38614+
38615+ spin_unlock_irqrestore(&ucmd->dev->udev_cmd_threads.cmd_list_lock, flags);
38616+
38617+ ucmd_put(ucmd);
38618+
38619+ TRACE_EXIT_RES(res);
38620+ return res;
38621+}
38622+
38623+static int dev_user_attach_tgt(struct scst_tgt_dev *tgt_dev)
38624+{
38625+ struct scst_user_dev *dev =
38626+ (struct scst_user_dev *)tgt_dev->dev->dh_priv;
38627+ int res = 0, rc;
38628+ struct scst_user_cmd *ucmd;
38629+ DECLARE_COMPLETION_ONSTACK(cmpl);
38630+ struct scst_tgt_template *tgtt = tgt_dev->sess->tgt->tgtt;
38631+ struct scst_tgt *tgt = tgt_dev->sess->tgt;
38632+
38633+ TRACE_ENTRY();
38634+
38635+ tgt_dev->active_cmd_threads = &dev->udev_cmd_threads;
38636+
38637+ /*
38638+ * We can't replace tgt_dev->pool, because it can be used to allocate
38639+ * memory for SCST local commands, like REPORT LUNS, where there is no
38640+ * corresponding ucmd. Otherwise we will crash in dev_user_alloc_sg().
38641+ */
38642+ if (test_bit(SCST_TGT_DEV_CLUST_POOL, &tgt_dev->tgt_dev_flags))
38643+ tgt_dev->dh_priv = dev->pool_clust;
38644+ else
38645+ tgt_dev->dh_priv = dev->pool;
38646+
38647+ ucmd = dev_user_alloc_ucmd(dev, GFP_KERNEL);
38648+ if (ucmd == NULL)
38649+ goto out_nomem;
38650+
38651+ ucmd->cmpl = &cmpl;
38652+
38653+ ucmd->user_cmd_payload_len = offsetof(struct scst_user_get_cmd, sess) +
38654+ sizeof(ucmd->user_cmd.sess);
38655+ ucmd->user_cmd.cmd_h = ucmd->h;
38656+ ucmd->user_cmd.subcode = SCST_USER_ATTACH_SESS;
38657+ ucmd->user_cmd.sess.sess_h = (unsigned long)tgt_dev;
38658+ ucmd->user_cmd.sess.lun = (uint64_t)tgt_dev->lun;
38659+ ucmd->user_cmd.sess.threads_num = tgt_dev->sess->tgt->tgtt->threads_num;
38660+ ucmd->user_cmd.sess.rd_only = tgt_dev->acg_dev->rd_only;
38661+ if (tgtt->get_phys_transport_version != NULL)
38662+ ucmd->user_cmd.sess.phys_transport_version =
38663+ tgtt->get_phys_transport_version(tgt);
38664+ if (tgtt->get_scsi_transport_version != NULL)
38665+ ucmd->user_cmd.sess.scsi_transport_version =
38666+ tgtt->get_scsi_transport_version(tgt);
38667+ strlcpy(ucmd->user_cmd.sess.initiator_name,
38668+ tgt_dev->sess->initiator_name,
38669+ sizeof(ucmd->user_cmd.sess.initiator_name)-1);
38670+ strlcpy(ucmd->user_cmd.sess.target_name,
38671+ tgt_dev->sess->tgt->tgt_name,
38672+ sizeof(ucmd->user_cmd.sess.target_name)-1);
38673+
38674+ TRACE_MGMT_DBG("Preparing ATTACH_SESS %p (h %d, sess_h %llx, LUN %llx, "
38675+ "threads_num %d, rd_only %d, initiator %s, target %s)",
38676+ ucmd, ucmd->h, ucmd->user_cmd.sess.sess_h,
38677+ ucmd->user_cmd.sess.lun, ucmd->user_cmd.sess.threads_num,
38678+ ucmd->user_cmd.sess.rd_only, ucmd->user_cmd.sess.initiator_name,
38679+ ucmd->user_cmd.sess.target_name);
38680+
38681+ ucmd->state = UCMD_STATE_ATTACH_SESS;
38682+
38683+ ucmd_get(ucmd);
38684+
38685+ dev_user_add_to_ready(ucmd);
38686+
38687+ rc = wait_for_completion_timeout(ucmd->cmpl, DEV_USER_ATTACH_TIMEOUT);
38688+ if (rc > 0)
38689+ res = ucmd->result;
38690+ else {
38691+ PRINT_ERROR("%s", "ATTACH_SESS command timeout");
38692+ res = -EFAULT;
38693+ }
38694+
38695+ BUG_ON(irqs_disabled());
38696+
38697+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38698+ ucmd->cmpl = NULL;
38699+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
38700+
38701+ ucmd_put(ucmd);
38702+
38703+out:
38704+ TRACE_EXIT_RES(res);
38705+ return res;
38706+
38707+out_nomem:
38708+ res = -ENOMEM;
38709+ goto out;
38710+}
38711+
38712+static void dev_user_detach_tgt(struct scst_tgt_dev *tgt_dev)
38713+{
38714+ struct scst_user_dev *dev =
38715+ (struct scst_user_dev *)tgt_dev->dev->dh_priv;
38716+ struct scst_user_cmd *ucmd;
38717+
38718+ TRACE_ENTRY();
38719+
38720+ /*
38721+ * We can't miss TM command due to memory shortage, because it might
38722+ * lead to a memory leak in the user space handler.
38723+ */
38724+ ucmd = dev_user_alloc_ucmd(dev, GFP_KERNEL|__GFP_NOFAIL);
38725+ if (ucmd == NULL)
38726+ goto out;
38727+
38728+ TRACE_MGMT_DBG("Preparing DETACH_SESS %p (h %d, sess_h %llx)", ucmd,
38729+ ucmd->h, ucmd->user_cmd.sess.sess_h);
38730+
38731+ ucmd->user_cmd_payload_len = offsetof(struct scst_user_get_cmd, sess) +
38732+ sizeof(ucmd->user_cmd.sess);
38733+ ucmd->user_cmd.cmd_h = ucmd->h;
38734+ ucmd->user_cmd.subcode = SCST_USER_DETACH_SESS;
38735+ ucmd->user_cmd.sess.sess_h = (unsigned long)tgt_dev;
38736+
38737+ ucmd->state = UCMD_STATE_DETACH_SESS;
38738+
38739+ dev_user_add_to_ready(ucmd);
38740+
38741+out:
38742+ TRACE_EXIT();
38743+ return;
38744+}
38745+
38746+/* No locks are needed, but the activity must be suspended */
38747+static void dev_user_setup_functions(struct scst_user_dev *dev)
38748+{
38749+ TRACE_ENTRY();
38750+
38751+ dev->devtype.parse = dev_user_parse;
38752+ dev->devtype.alloc_data_buf = dev_user_alloc_data_buf;
38753+ dev->devtype.dev_done = NULL;
38754+
38755+ if (dev->parse_type != SCST_USER_PARSE_CALL) {
38756+ switch (dev->devtype.type) {
38757+ case TYPE_DISK:
38758+ dev->generic_parse = scst_sbc_generic_parse;
38759+ dev->devtype.dev_done = dev_user_disk_done;
38760+ break;
38761+
38762+ case TYPE_TAPE:
38763+ dev->generic_parse = scst_tape_generic_parse;
38764+ dev->devtype.dev_done = dev_user_tape_done;
38765+ break;
38766+
38767+ case TYPE_MOD:
38768+ dev->generic_parse = scst_modisk_generic_parse;
38769+ dev->devtype.dev_done = dev_user_disk_done;
38770+ break;
38771+
38772+ case TYPE_ROM:
38773+ dev->generic_parse = scst_cdrom_generic_parse;
38774+ dev->devtype.dev_done = dev_user_disk_done;
38775+ break;
38776+
38777+ case TYPE_MEDIUM_CHANGER:
38778+ dev->generic_parse = scst_changer_generic_parse;
38779+ break;
38780+
38781+ case TYPE_PROCESSOR:
38782+ dev->generic_parse = scst_processor_generic_parse;
38783+ break;
38784+
38785+ case TYPE_RAID:
38786+ dev->generic_parse = scst_raid_generic_parse;
38787+ break;
38788+
38789+ default:
38790+ PRINT_INFO("Unknown SCSI type %x, using PARSE_CALL "
38791+ "for it", dev->devtype.type);
38792+ dev->parse_type = SCST_USER_PARSE_CALL;
38793+ break;
38794+ }
38795+ } else {
38796+ dev->generic_parse = NULL;
38797+ dev->devtype.dev_done = NULL;
38798+ }
38799+
38800+ TRACE_EXIT();
38801+ return;
38802+}
38803+
38804+static int dev_user_check_version(const struct scst_user_dev_desc *dev_desc)
38805+{
38806+ char str[sizeof(DEV_USER_VERSION) > 20 ? sizeof(DEV_USER_VERSION) : 20];
38807+ int res = 0, rc;
38808+
38809+ rc = copy_from_user(str,
38810+ (void __user *)(unsigned long)dev_desc->license_str,
38811+ sizeof(str));
38812+ if (rc != 0) {
38813+ PRINT_ERROR("%s", "Unable to get license string");
38814+ res = -EFAULT;
38815+ goto out;
38816+ }
38817+ str[sizeof(str)-1] = '\0';
38818+
38819+ if ((strcmp(str, "GPL") != 0) &&
38820+ (strcmp(str, "GPL v2") != 0) &&
38821+ (strcmp(str, "Dual BSD/GPL") != 0) &&
38822+ (strcmp(str, "Dual MIT/GPL") != 0) &&
38823+ (strcmp(str, "Dual MPL/GPL") != 0)) {
38824+ /* ->name already 0-terminated in dev_user_ioctl() */
38825+ PRINT_ERROR("Unsupported license of user device %s (%s). "
38826+ "Ask license@scst-tgt.com for more info.",
38827+ dev_desc->name, str);
38828+ res = -EPERM;
38829+ goto out;
38830+ }
38831+
38832+ rc = copy_from_user(str,
38833+ (void __user *)(unsigned long)dev_desc->version_str,
38834+ sizeof(str));
38835+ if (rc != 0) {
38836+ PRINT_ERROR("%s", "Unable to get version string");
38837+ res = -EFAULT;
38838+ goto out;
38839+ }
38840+ str[sizeof(str)-1] = '\0';
38841+
38842+ if (strcmp(str, DEV_USER_VERSION) != 0) {
38843+ /* ->name already 0-terminated in dev_user_ioctl() */
38844+ PRINT_ERROR("Incorrect version of user device %s (%s). "
38845+ "Expected: %s", dev_desc->name, str,
38846+ DEV_USER_VERSION);
38847+ res = -EINVAL;
38848+ goto out;
38849+ }
38850+
38851+out:
38852+ return res;
38853+}
38854+
38855+static int dev_user_register_dev(struct file *file,
38856+ const struct scst_user_dev_desc *dev_desc)
38857+{
38858+ int res, i;
38859+ struct scst_user_dev *dev, *d;
38860+ int block;
38861+
38862+ TRACE_ENTRY();
38863+
38864+ res = dev_user_check_version(dev_desc);
38865+ if (res != 0)
38866+ goto out;
38867+
38868+ switch (dev_desc->type) {
38869+ case TYPE_DISK:
38870+ case TYPE_ROM:
38871+ case TYPE_MOD:
38872+ if (dev_desc->block_size == 0) {
38873+ PRINT_ERROR("Wrong block size %d",
38874+ dev_desc->block_size);
38875+ res = -EINVAL;
38876+ goto out;
38877+ }
38878+ block = scst_calc_block_shift(dev_desc->block_size);
38879+ if (block == -1) {
38880+ res = -EINVAL;
38881+ goto out;
38882+ }
38883+ break;
38884+ default:
38885+ block = dev_desc->block_size;
38886+ break;
38887+ }
38888+
38889+ if (!try_module_get(THIS_MODULE)) {
38890+ PRINT_ERROR("%s", "Fail to get module");
38891+ res = -ETXTBSY;
38892+ goto out;
38893+ }
38894+
38895+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
38896+ if (dev == NULL) {
38897+ res = -ENOMEM;
38898+ goto out_put;
38899+ }
38900+
38901+ init_rwsem(&dev->dev_rwsem);
38902+ INIT_LIST_HEAD(&dev->ready_cmd_list);
38903+ if (file->f_flags & O_NONBLOCK) {
38904+ TRACE_DBG("%s", "Non-blocking operations");
38905+ dev->blocking = 0;
38906+ } else
38907+ dev->blocking = 1;
38908+ for (i = 0; i < (int)ARRAY_SIZE(dev->ucmd_hash); i++)
38909+ INIT_LIST_HEAD(&dev->ucmd_hash[i]);
38910+
38911+ scst_init_threads(&dev->udev_cmd_threads);
38912+
38913+ strlcpy(dev->name, dev_desc->name, sizeof(dev->name)-1);
38914+
38915+ scst_init_mem_lim(&dev->udev_mem_lim);
38916+
38917+ scnprintf(dev->devtype.name, sizeof(dev->devtype.name), "%s",
38918+ (dev_desc->sgv_name[0] == '\0') ? dev->name :
38919+ dev_desc->sgv_name);
38920+ dev->pool = sgv_pool_create(dev->devtype.name, sgv_no_clustering,
38921+ dev_desc->sgv_single_alloc_pages,
38922+ dev_desc->sgv_shared,
38923+ dev_desc->sgv_purge_interval);
38924+ if (dev->pool == NULL) {
38925+ res = -ENOMEM;
38926+ goto out_deinit_threads;
38927+ }
38928+ sgv_pool_set_allocator(dev->pool, dev_user_alloc_pages,
38929+ dev_user_free_sg_entries);
38930+
38931+ if (!dev_desc->sgv_disable_clustered_pool) {
38932+ scnprintf(dev->devtype.name, sizeof(dev->devtype.name),
38933+ "%s-clust",
38934+ (dev_desc->sgv_name[0] == '\0') ? dev->name :
38935+ dev_desc->sgv_name);
38936+ dev->pool_clust = sgv_pool_create(dev->devtype.name,
38937+ sgv_tail_clustering,
38938+ dev_desc->sgv_single_alloc_pages,
38939+ dev_desc->sgv_shared,
38940+ dev_desc->sgv_purge_interval);
38941+ if (dev->pool_clust == NULL) {
38942+ res = -ENOMEM;
38943+ goto out_free0;
38944+ }
38945+ sgv_pool_set_allocator(dev->pool_clust, dev_user_alloc_pages,
38946+ dev_user_free_sg_entries);
38947+ } else {
38948+ dev->pool_clust = dev->pool;
38949+ sgv_pool_get(dev->pool_clust);
38950+ }
38951+
38952+ scnprintf(dev->devtype.name, sizeof(dev->devtype.name), "%s",
38953+ dev->name);
38954+ dev->devtype.type = dev_desc->type;
38955+ dev->devtype.threads_num = -1;
38956+ dev->devtype.parse_atomic = 1;
38957+ dev->devtype.alloc_data_buf_atomic = 1;
38958+ dev->devtype.dev_done_atomic = 1;
38959+ dev->devtype.dev_attrs = dev_user_dev_attrs;
38960+ dev->devtype.attach = dev_user_attach;
38961+ dev->devtype.detach = dev_user_detach;
38962+ dev->devtype.attach_tgt = dev_user_attach_tgt;
38963+ dev->devtype.detach_tgt = dev_user_detach_tgt;
38964+ dev->devtype.exec = dev_user_exec;
38965+ dev->devtype.on_free_cmd = dev_user_on_free_cmd;
38966+ dev->devtype.task_mgmt_fn = dev_user_task_mgmt_fn;
38967+ if (dev_desc->enable_pr_cmds_notifications)
38968+ dev->devtype.pr_cmds_notifications = 1;
38969+
38970+ init_completion(&dev->cleanup_cmpl);
38971+ dev->block = block;
38972+ dev->def_block = block;
38973+
38974+ res = __dev_user_set_opt(dev, &dev_desc->opt);
38975+ if (res != 0)
38976+ goto out_free;
38977+
38978+ TRACE_MEM("dev %p, name %s", dev, dev->name);
38979+
38980+ spin_lock(&dev_list_lock);
38981+
38982+ list_for_each_entry(d, &dev_list, dev_list_entry) {
38983+ if (strcmp(d->name, dev->name) == 0) {
38984+ PRINT_ERROR("Device %s already exist",
38985+ dev->name);
38986+ res = -EEXIST;
38987+ spin_unlock(&dev_list_lock);
38988+ goto out_free;
38989+ }
38990+ }
38991+
38992+ list_add_tail(&dev->dev_list_entry, &dev_list);
38993+
38994+ spin_unlock(&dev_list_lock);
38995+
38996+ res = scst_register_virtual_dev_driver(&dev->devtype);
38997+ if (res < 0)
38998+ goto out_del_free;
38999+
39000+ dev->virt_id = scst_register_virtual_device(&dev->devtype, dev->name);
39001+ if (dev->virt_id < 0) {
39002+ res = dev->virt_id;
39003+ goto out_unreg_handler;
39004+ }
39005+
39006+ mutex_lock(&dev_priv_mutex);
39007+ if (file->private_data != NULL) {
39008+ mutex_unlock(&dev_priv_mutex);
39009+ PRINT_ERROR("%s", "Device already registered");
39010+ res = -EINVAL;
39011+ goto out_unreg_drv;
39012+ }
39013+ file->private_data = dev;
39014+ mutex_unlock(&dev_priv_mutex);
39015+
39016+out:
39017+ TRACE_EXIT_RES(res);
39018+ return res;
39019+
39020+out_unreg_drv:
39021+ scst_unregister_virtual_device(dev->virt_id);
39022+
39023+out_unreg_handler:
39024+ scst_unregister_virtual_dev_driver(&dev->devtype);
39025+
39026+out_del_free:
39027+ spin_lock(&dev_list_lock);
39028+ list_del(&dev->dev_list_entry);
39029+ spin_unlock(&dev_list_lock);
39030+
39031+out_free:
39032+ sgv_pool_del(dev->pool_clust);
39033+
39034+out_free0:
39035+ sgv_pool_del(dev->pool);
39036+
39037+out_deinit_threads:
39038+ scst_deinit_threads(&dev->udev_cmd_threads);
39039+
39040+ kfree(dev);
39041+
39042+out_put:
39043+ module_put(THIS_MODULE);
39044+ goto out;
39045+}
39046+
39047+static int dev_user_unregister_dev(struct file *file)
39048+{
39049+ int res;
39050+ struct scst_user_dev *dev;
39051+
39052+ TRACE_ENTRY();
39053+
39054+ mutex_lock(&dev_priv_mutex);
39055+ dev = (struct scst_user_dev *)file->private_data;
39056+ res = dev_user_check_reg(dev);
39057+ if (res != 0) {
39058+ mutex_unlock(&dev_priv_mutex);
39059+ goto out;
39060+ }
39061+ down_read(&dev->dev_rwsem);
39062+ mutex_unlock(&dev_priv_mutex);
39063+
39064+ res = scst_suspend_activity(true);
39065+ if (res != 0)
39066+ goto out_up;
39067+
39068+ up_read(&dev->dev_rwsem);
39069+
39070+ mutex_lock(&dev_priv_mutex);
39071+ dev = (struct scst_user_dev *)file->private_data;
39072+ if (dev == NULL) {
39073+ mutex_unlock(&dev_priv_mutex);
39074+ goto out_resume;
39075+ }
39076+
39077+ dev->blocking = 0;
39078+ wake_up_all(&dev->udev_cmd_threads.cmd_list_waitQ);
39079+
39080+ down_write(&dev->dev_rwsem);
39081+ file->private_data = NULL;
39082+ mutex_unlock(&dev_priv_mutex);
39083+
39084+ dev_user_exit_dev(dev);
39085+
39086+ up_write(&dev->dev_rwsem); /* to make lockdep happy */
39087+
39088+ kfree(dev);
39089+
39090+out_resume:
39091+ scst_resume_activity();
39092+
39093+out:
39094+ TRACE_EXIT_RES(res);
39095+ return res;
39096+
39097+out_up:
39098+ up_read(&dev->dev_rwsem);
39099+ goto out;
39100+}
39101+
39102+static int dev_user_flush_cache(struct file *file)
39103+{
39104+ int res;
39105+ struct scst_user_dev *dev;
39106+
39107+ TRACE_ENTRY();
39108+
39109+ mutex_lock(&dev_priv_mutex);
39110+ dev = (struct scst_user_dev *)file->private_data;
39111+ res = dev_user_check_reg(dev);
39112+ if (res != 0) {
39113+ mutex_unlock(&dev_priv_mutex);
39114+ goto out;
39115+ }
39116+ down_read(&dev->dev_rwsem);
39117+ mutex_unlock(&dev_priv_mutex);
39118+
39119+ res = scst_suspend_activity(true);
39120+ if (res != 0)
39121+ goto out_up;
39122+
39123+ sgv_pool_flush(dev->pool);
39124+ sgv_pool_flush(dev->pool_clust);
39125+
39126+ scst_resume_activity();
39127+
39128+out_up:
39129+ up_read(&dev->dev_rwsem);
39130+
39131+out:
39132+ TRACE_EXIT_RES(res);
39133+ return res;
39134+}
39135+
39136+static int dev_user_capacity_changed(struct file *file)
39137+{
39138+ int res;
39139+ struct scst_user_dev *dev;
39140+
39141+ TRACE_ENTRY();
39142+
39143+ mutex_lock(&dev_priv_mutex);
39144+ dev = (struct scst_user_dev *)file->private_data;
39145+ res = dev_user_check_reg(dev);
39146+ if (res != 0) {
39147+ mutex_unlock(&dev_priv_mutex);
39148+ goto out;
39149+ }
39150+ down_read(&dev->dev_rwsem);
39151+ mutex_unlock(&dev_priv_mutex);
39152+
39153+ scst_capacity_data_changed(dev->sdev);
39154+
39155+ up_read(&dev->dev_rwsem);
39156+
39157+out:
39158+ TRACE_EXIT_RES(res);
39159+ return res;
39160+}
39161+
39162+static int dev_user_prealloc_buffer(struct file *file, void __user *arg)
39163+{
39164+ int res = 0, rc;
39165+ struct scst_user_dev *dev;
39166+ union scst_user_prealloc_buffer pre;
39167+ aligned_u64 pbuf;
39168+ uint32_t bufflen;
39169+ struct scst_user_cmd *ucmd;
39170+ int pages, sg_cnt;
39171+ struct sgv_pool *pool;
39172+ struct scatterlist *sg;
39173+
39174+ TRACE_ENTRY();
39175+
39176+ mutex_lock(&dev_priv_mutex);
39177+ dev = (struct scst_user_dev *)file->private_data;
39178+ res = dev_user_check_reg(dev);
39179+ if (unlikely(res != 0)) {
39180+ mutex_unlock(&dev_priv_mutex);
39181+ goto out;
39182+ }
39183+ down_read(&dev->dev_rwsem);
39184+ mutex_unlock(&dev_priv_mutex);
39185+
39186+ rc = copy_from_user(&pre.in, arg, sizeof(pre.in));
39187+ if (unlikely(rc != 0)) {
39188+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
39189+ res = -EFAULT;
39190+ goto out_up;
39191+ }
39192+
39193+ TRACE_MEM("Prealloc buffer with size %dKB for dev %s",
39194+ pre.in.bufflen / 1024, dev->name);
39195+ TRACE_BUFFER("Input param", &pre.in, sizeof(pre.in));
39196+
39197+ pbuf = pre.in.pbuf;
39198+ bufflen = pre.in.bufflen;
39199+
39200+ ucmd = dev_user_alloc_ucmd(dev, GFP_KERNEL);
39201+ if (ucmd == NULL) {
39202+ res = -ENOMEM;
39203+ goto out_up;
39204+ }
39205+
39206+ ucmd->buff_cached = 1;
39207+
39208+ TRACE_MEM("ucmd %p, pbuf %llx", ucmd, pbuf);
39209+
39210+ if (unlikely((pbuf & ~PAGE_MASK) != 0)) {
39211+ PRINT_ERROR("Supplied pbuf %llx isn't page aligned", pbuf);
39212+ res = -EINVAL;
39213+ goto out_put;
39214+ }
39215+
39216+ pages = calc_num_pg(pbuf, bufflen);
39217+ res = dev_user_map_buf(ucmd, pbuf, pages);
39218+ if (res != 0)
39219+ goto out_put;
39220+
39221+ if (pre.in.for_clust_pool)
39222+ pool = dev->pool_clust;
39223+ else
39224+ pool = dev->pool;
39225+
39226+ sg = sgv_pool_alloc(pool, bufflen, GFP_KERNEL, SGV_POOL_ALLOC_GET_NEW,
39227+ &sg_cnt, &ucmd->sgv, &dev->udev_mem_lim, ucmd);
39228+ if (sg != NULL) {
39229+ struct scst_user_cmd *buf_ucmd =
39230+ (struct scst_user_cmd *)sgv_get_priv(ucmd->sgv);
39231+
39232+ TRACE_MEM("Buf ucmd %p (sg_cnt %d, last seg len %d, "
39233+ "bufflen %d)", buf_ucmd, sg_cnt,
39234+ sg[sg_cnt-1].length, bufflen);
39235+
39236+ EXTRACHECKS_BUG_ON(ucmd != buf_ucmd);
39237+
39238+ ucmd->buf_ucmd = buf_ucmd;
39239+ } else {
39240+ res = -ENOMEM;
39241+ goto out_put;
39242+ }
39243+
39244+ dev_user_free_sgv(ucmd);
39245+
39246+ pre.out.cmd_h = ucmd->h;
39247+ rc = copy_to_user(arg, &pre.out, sizeof(pre.out));
39248+ if (unlikely(rc != 0)) {
39249+ PRINT_ERROR("Failed to copy to user %d bytes", rc);
39250+ res = -EFAULT;
39251+ goto out_put;
39252+ }
39253+
39254+out_put:
39255+ ucmd_put(ucmd);
39256+
39257+out_up:
39258+ up_read(&dev->dev_rwsem);
39259+
39260+out:
39261+ TRACE_EXIT_RES(res);
39262+ return res;
39263+}
39264+
39265+static int __dev_user_set_opt(struct scst_user_dev *dev,
39266+ const struct scst_user_opt *opt)
39267+{
39268+ int res = 0;
39269+
39270+ TRACE_ENTRY();
39271+
39272+ TRACE_DBG("dev %s, parse_type %x, on_free_cmd_type %x, "
39273+ "memory_reuse_type %x, partial_transfers_type %x, "
39274+ "partial_len %d", dev->name, opt->parse_type,
39275+ opt->on_free_cmd_type, opt->memory_reuse_type,
39276+ opt->partial_transfers_type, opt->partial_len);
39277+
39278+ if (opt->parse_type > SCST_USER_MAX_PARSE_OPT ||
39279+ opt->on_free_cmd_type > SCST_USER_MAX_ON_FREE_CMD_OPT ||
39280+ opt->memory_reuse_type > SCST_USER_MAX_MEM_REUSE_OPT ||
39281+ opt->partial_transfers_type > SCST_USER_MAX_PARTIAL_TRANSFERS_OPT) {
39282+ PRINT_ERROR("%s", "Invalid option");
39283+ res = -EINVAL;
39284+ goto out;
39285+ }
39286+
39287+ if (((opt->tst != SCST_CONTR_MODE_ONE_TASK_SET) &&
39288+ (opt->tst != SCST_CONTR_MODE_SEP_TASK_SETS)) ||
39289+ ((opt->queue_alg != SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER) &&
39290+ (opt->queue_alg != SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER)) ||
39291+ (opt->swp > 1) || (opt->tas > 1) || (opt->has_own_order_mgmt > 1) ||
39292+ (opt->d_sense > 1)) {
39293+ PRINT_ERROR("Invalid SCSI option (tst %x, queue_alg %x, swp %x,"
39294+ " tas %x, d_sense %d, has_own_order_mgmt %x)", opt->tst,
39295+ opt->queue_alg, opt->swp, opt->tas, opt->d_sense,
39296+ opt->has_own_order_mgmt);
39297+ res = -EINVAL;
39298+ goto out;
39299+ }
39300+
39301+ dev->parse_type = opt->parse_type;
39302+ dev->on_free_cmd_type = opt->on_free_cmd_type;
39303+ dev->memory_reuse_type = opt->memory_reuse_type;
39304+ dev->partial_transfers_type = opt->partial_transfers_type;
39305+ dev->partial_len = opt->partial_len;
39306+
39307+ dev->tst = opt->tst;
39308+ dev->queue_alg = opt->queue_alg;
39309+ dev->swp = opt->swp;
39310+ dev->tas = opt->tas;
39311+ dev->tst = opt->tst;
39312+ dev->d_sense = opt->d_sense;
39313+ dev->has_own_order_mgmt = opt->has_own_order_mgmt;
39314+ if (dev->sdev != NULL) {
39315+ dev->sdev->tst = opt->tst;
39316+ dev->sdev->queue_alg = opt->queue_alg;
39317+ dev->sdev->swp = opt->swp;
39318+ dev->sdev->tas = opt->tas;
39319+ dev->sdev->d_sense = opt->d_sense;
39320+ dev->sdev->has_own_order_mgmt = opt->has_own_order_mgmt;
39321+ }
39322+
39323+ dev_user_setup_functions(dev);
39324+
39325+out:
39326+ TRACE_EXIT_RES(res);
39327+ return res;
39328+}
39329+
39330+static int dev_user_set_opt(struct file *file, const struct scst_user_opt *opt)
39331+{
39332+ int res;
39333+ struct scst_user_dev *dev;
39334+
39335+ TRACE_ENTRY();
39336+
39337+ mutex_lock(&dev_priv_mutex);
39338+ dev = (struct scst_user_dev *)file->private_data;
39339+ res = dev_user_check_reg(dev);
39340+ if (res != 0) {
39341+ mutex_unlock(&dev_priv_mutex);
39342+ goto out;
39343+ }
39344+ down_read(&dev->dev_rwsem);
39345+ mutex_unlock(&dev_priv_mutex);
39346+
39347+ res = scst_suspend_activity(true);
39348+ if (res != 0)
39349+ goto out_up;
39350+
39351+ res = __dev_user_set_opt(dev, opt);
39352+
39353+ scst_resume_activity();
39354+
39355+out_up:
39356+ up_read(&dev->dev_rwsem);
39357+
39358+out:
39359+ TRACE_EXIT_RES(res);
39360+ return res;
39361+}
39362+
39363+static int dev_user_get_opt(struct file *file, void __user *arg)
39364+{
39365+ int res, rc;
39366+ struct scst_user_dev *dev;
39367+ struct scst_user_opt opt;
39368+
39369+ TRACE_ENTRY();
39370+
39371+ mutex_lock(&dev_priv_mutex);
39372+ dev = (struct scst_user_dev *)file->private_data;
39373+ res = dev_user_check_reg(dev);
39374+ if (res != 0) {
39375+ mutex_unlock(&dev_priv_mutex);
39376+ goto out;
39377+ }
39378+ down_read(&dev->dev_rwsem);
39379+ mutex_unlock(&dev_priv_mutex);
39380+
39381+ opt.parse_type = dev->parse_type;
39382+ opt.on_free_cmd_type = dev->on_free_cmd_type;
39383+ opt.memory_reuse_type = dev->memory_reuse_type;
39384+ opt.partial_transfers_type = dev->partial_transfers_type;
39385+ opt.partial_len = dev->partial_len;
39386+ opt.tst = dev->tst;
39387+ opt.queue_alg = dev->queue_alg;
39388+ opt.tas = dev->tas;
39389+ opt.swp = dev->swp;
39390+ opt.d_sense = dev->d_sense;
39391+ opt.has_own_order_mgmt = dev->has_own_order_mgmt;
39392+
39393+ TRACE_DBG("dev %s, parse_type %x, on_free_cmd_type %x, "
39394+ "memory_reuse_type %x, partial_transfers_type %x, "
39395+ "partial_len %d", dev->name, opt.parse_type,
39396+ opt.on_free_cmd_type, opt.memory_reuse_type,
39397+ opt.partial_transfers_type, opt.partial_len);
39398+
39399+ rc = copy_to_user(arg, &opt, sizeof(opt));
39400+ if (unlikely(rc != 0)) {
39401+ PRINT_ERROR("Failed to copy to user %d bytes", rc);
39402+ res = -EFAULT;
39403+ goto out_up;
39404+ }
39405+
39406+out_up:
39407+ up_read(&dev->dev_rwsem);
39408+
39409+out:
39410+ TRACE_EXIT_RES(res);
39411+ return res;
39412+}
39413+
39414+static int dev_usr_parse(struct scst_cmd *cmd)
39415+{
39416+ BUG();
39417+ return SCST_CMD_STATE_DEFAULT;
39418+}
39419+
39420+static int dev_user_exit_dev(struct scst_user_dev *dev)
39421+{
39422+ TRACE_ENTRY();
39423+
39424+ TRACE(TRACE_MGMT, "Releasing dev %s", dev->name);
39425+
39426+ spin_lock(&dev_list_lock);
39427+ list_del(&dev->dev_list_entry);
39428+ spin_unlock(&dev_list_lock);
39429+
39430+ dev->blocking = 0;
39431+ wake_up_all(&dev->udev_cmd_threads.cmd_list_waitQ);
39432+
39433+ spin_lock(&cleanup_lock);
39434+ list_add_tail(&dev->cleanup_list_entry, &cleanup_list);
39435+ spin_unlock(&cleanup_lock);
39436+
39437+ wake_up(&cleanup_list_waitQ);
39438+
39439+ scst_unregister_virtual_device(dev->virt_id);
39440+ scst_unregister_virtual_dev_driver(&dev->devtype);
39441+
39442+ sgv_pool_flush(dev->pool_clust);
39443+ sgv_pool_flush(dev->pool);
39444+
39445+ TRACE_MGMT_DBG("Unregistering finished (dev %p)", dev);
39446+
39447+ dev->cleanup_done = 1;
39448+
39449+ wake_up(&cleanup_list_waitQ);
39450+ wake_up(&dev->udev_cmd_threads.cmd_list_waitQ);
39451+
39452+ wait_for_completion(&dev->cleanup_cmpl);
39453+
39454+ sgv_pool_del(dev->pool_clust);
39455+ sgv_pool_del(dev->pool);
39456+
39457+ scst_deinit_threads(&dev->udev_cmd_threads);
39458+
39459+ TRACE_MGMT_DBG("Releasing completed (dev %p)", dev);
39460+
39461+ module_put(THIS_MODULE);
39462+
39463+ TRACE_EXIT();
39464+ return 0;
39465+}
39466+
39467+static int __dev_user_release(void *arg)
39468+{
39469+ struct scst_user_dev *dev = (struct scst_user_dev *)arg;
39470+ dev_user_exit_dev(dev);
39471+ kfree(dev);
39472+ return 0;
39473+}
39474+
39475+static int dev_user_release(struct inode *inode, struct file *file)
39476+{
39477+ struct scst_user_dev *dev;
39478+ struct task_struct *t;
39479+
39480+ TRACE_ENTRY();
39481+
39482+ dev = (struct scst_user_dev *)file->private_data;
39483+ if (dev == NULL)
39484+ goto out;
39485+ file->private_data = NULL;
39486+
39487+ TRACE_MGMT_DBG("Going to release dev %s", dev->name);
39488+
39489+ t = kthread_run(__dev_user_release, dev, "scst_usr_released");
39490+ if (IS_ERR(t)) {
39491+ PRINT_CRIT_ERROR("kthread_run() failed (%ld), releasing device "
39492+ "%p directly. If you have several devices under load "
39493+ "it might deadlock!", PTR_ERR(t), dev);
39494+ __dev_user_release(dev);
39495+ }
39496+
39497+out:
39498+ TRACE_EXIT();
39499+ return 0;
39500+}
39501+
39502+static int dev_user_process_cleanup(struct scst_user_dev *dev)
39503+{
39504+ struct scst_user_cmd *ucmd;
39505+ int rc = 0, res = 1;
39506+
39507+ TRACE_ENTRY();
39508+
39509+ BUG_ON(dev->blocking);
39510+ wake_up_all(&dev->udev_cmd_threads.cmd_list_waitQ); /* just in case */
39511+
39512+ while (1) {
39513+ int rc1;
39514+
39515+ TRACE_DBG("Cleanuping dev %p", dev);
39516+
39517+ rc1 = dev_user_unjam_dev(dev);
39518+ if ((rc1 == 0) && (rc == -EAGAIN) && dev->cleanup_done)
39519+ break;
39520+
39521+ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
39522+
39523+ rc = dev_user_get_next_cmd(dev, &ucmd);
39524+ if (rc == 0)
39525+ dev_user_unjam_cmd(ucmd, 1, NULL);
39526+
39527+ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
39528+
39529+ if (rc == -EAGAIN) {
39530+ if (!dev->cleanup_done) {
39531+ TRACE_DBG("No more commands (dev %p)", dev);
39532+ goto out;
39533+ }
39534+ }
39535+ }
39536+
39537+#ifdef CONFIG_SCST_EXTRACHECKS
39538+{
39539+ int i;
39540+ for (i = 0; i < (int)ARRAY_SIZE(dev->ucmd_hash); i++) {
39541+ struct list_head *head = &dev->ucmd_hash[i];
39542+ struct scst_user_cmd *ucmd2;
39543+again:
39544+ list_for_each_entry(ucmd2, head, hash_list_entry) {
39545+ PRINT_ERROR("Lost ucmd %p (state %x, ref %d)", ucmd2,
39546+ ucmd2->state, atomic_read(&ucmd2->ucmd_ref));
39547+ ucmd_put(ucmd2);
39548+ goto again;
39549+ }
39550+ }
39551+}
39552+#endif
39553+
39554+ TRACE_DBG("Cleanuping done (dev %p)", dev);
39555+ complete_all(&dev->cleanup_cmpl);
39556+ res = 0;
39557+
39558+out:
39559+ TRACE_EXIT_RES(res);
39560+ return res;
39561+}
39562+
39563+static ssize_t dev_user_sysfs_commands_show(struct kobject *kobj,
39564+ struct kobj_attribute *attr, char *buf)
39565+{
39566+ int pos = 0, ppos, i;
39567+ struct scst_device *dev;
39568+ struct scst_user_dev *udev;
39569+ unsigned long flags;
39570+
39571+ TRACE_ENTRY();
39572+
39573+ dev = container_of(kobj, struct scst_device, dev_kobj);
39574+ udev = (struct scst_user_dev *)dev->dh_priv;
39575+
39576+ spin_lock_irqsave(&udev->udev_cmd_threads.cmd_list_lock, flags);
39577+ for (i = 0; i < (int)ARRAY_SIZE(udev->ucmd_hash); i++) {
39578+ struct list_head *head = &udev->ucmd_hash[i];
39579+ struct scst_user_cmd *ucmd;
39580+ list_for_each_entry(ucmd, head, hash_list_entry) {
39581+ ppos = pos;
39582+ pos += scnprintf(&buf[pos],
39583+ SCST_SYSFS_BLOCK_SIZE - pos,
39584+ "ucmd %p (state %x, ref %d), "
39585+ "sent_to_user %d, seen_by_user %d, "
39586+ "aborted %d, jammed %d, scst_cmd %p\n",
39587+ ucmd, ucmd->state,
39588+ atomic_read(&ucmd->ucmd_ref),
39589+ ucmd->sent_to_user, ucmd->seen_by_user,
39590+ ucmd->aborted, ucmd->jammed, ucmd->cmd);
39591+ if (pos >= SCST_SYSFS_BLOCK_SIZE-1) {
39592+ ppos += scnprintf(&buf[ppos],
39593+ SCST_SYSFS_BLOCK_SIZE - ppos, "...\n");
39594+ pos = ppos;
39595+ break;
39596+ }
39597+ }
39598+ }
39599+ spin_unlock_irqrestore(&udev->udev_cmd_threads.cmd_list_lock, flags);
39600+
39601+ TRACE_EXIT_RES(pos);
39602+ return pos;
39603+}
39604+
39605+static inline int test_cleanup_list(void)
39606+{
39607+ int res = !list_empty(&cleanup_list) ||
39608+ unlikely(kthread_should_stop());
39609+ return res;
39610+}
39611+
39612+static int dev_user_cleanup_thread(void *arg)
39613+{
39614+ TRACE_ENTRY();
39615+
39616+ PRINT_INFO("Cleanup thread started, PID %d", current->pid);
39617+
39618+ current->flags |= PF_NOFREEZE;
39619+
39620+ spin_lock(&cleanup_lock);
39621+ while (!kthread_should_stop()) {
39622+ wait_queue_t wait;
39623+ init_waitqueue_entry(&wait, current);
39624+
39625+ if (!test_cleanup_list()) {
39626+ add_wait_queue_exclusive(&cleanup_list_waitQ, &wait);
39627+ for (;;) {
39628+ set_current_state(TASK_INTERRUPTIBLE);
39629+ if (test_cleanup_list())
39630+ break;
39631+ spin_unlock(&cleanup_lock);
39632+ schedule();
39633+ spin_lock(&cleanup_lock);
39634+ }
39635+ set_current_state(TASK_RUNNING);
39636+ remove_wait_queue(&cleanup_list_waitQ, &wait);
39637+ }
39638+
39639+ /*
39640+ * We have to poll devices, because commands can go from SCST
39641+ * core on cmd_list_waitQ and we have no practical way to
39642+ * detect them.
39643+ */
39644+
39645+ while (1) {
39646+ struct scst_user_dev *dev;
39647+ LIST_HEAD(cl_devs);
39648+
39649+ while (!list_empty(&cleanup_list)) {
39650+ int rc;
39651+
39652+ dev = list_entry(cleanup_list.next,
39653+ typeof(*dev), cleanup_list_entry);
39654+ list_del(&dev->cleanup_list_entry);
39655+
39656+ spin_unlock(&cleanup_lock);
39657+ rc = dev_user_process_cleanup(dev);
39658+ spin_lock(&cleanup_lock);
39659+
39660+ if (rc != 0)
39661+ list_add_tail(&dev->cleanup_list_entry,
39662+ &cl_devs);
39663+ }
39664+
39665+ if (list_empty(&cl_devs))
39666+ break;
39667+
39668+ spin_unlock(&cleanup_lock);
39669+ msleep(100);
39670+ spin_lock(&cleanup_lock);
39671+
39672+ while (!list_empty(&cl_devs)) {
39673+ dev = list_entry(cl_devs.next, typeof(*dev),
39674+ cleanup_list_entry);
39675+ list_move_tail(&dev->cleanup_list_entry,
39676+ &cleanup_list);
39677+ }
39678+ }
39679+ }
39680+ spin_unlock(&cleanup_lock);
39681+
39682+ /*
39683+ * If kthread_should_stop() is true, we are guaranteed to be
39684+ * on the module unload, so cleanup_list must be empty.
39685+ */
39686+ BUG_ON(!list_empty(&cleanup_list));
39687+
39688+ PRINT_INFO("Cleanup thread PID %d finished", current->pid);
39689+
39690+ TRACE_EXIT();
39691+ return 0;
39692+}
39693+
39694+static int __init init_scst_user(void)
39695+{
39696+ int res = 0;
39697+ struct max_get_reply {
39698+ union {
39699+ struct scst_user_get_cmd g;
39700+ struct scst_user_reply_cmd r;
39701+ };
39702+ };
39703+ struct device *dev;
39704+
39705+ TRACE_ENTRY();
39706+
39707+ user_cmd_cachep = KMEM_CACHE(scst_user_cmd, SCST_SLAB_FLAGS);
39708+ if (user_cmd_cachep == NULL) {
39709+ res = -ENOMEM;
39710+ goto out;
39711+ }
39712+
39713+ user_get_cmd_cachep = KMEM_CACHE(max_get_reply, SCST_SLAB_FLAGS);
39714+ if (user_get_cmd_cachep == NULL) {
39715+ res = -ENOMEM;
39716+ goto out_cache;
39717+ }
39718+
39719+ dev_user_devtype.module = THIS_MODULE;
39720+
39721+ res = scst_register_virtual_dev_driver(&dev_user_devtype);
39722+ if (res < 0)
39723+ goto out_cache1;
39724+
39725+ dev_user_sysfs_class = class_create(THIS_MODULE, DEV_USER_NAME);
39726+ if (IS_ERR(dev_user_sysfs_class)) {
39727+ PRINT_ERROR("%s", "Unable create sysfs class for SCST user "
39728+ "space handler");
39729+ res = PTR_ERR(dev_user_sysfs_class);
39730+ goto out_unreg;
39731+ }
39732+
39733+ dev_user_major = register_chrdev(0, DEV_USER_NAME, &dev_user_fops);
39734+ if (dev_user_major < 0) {
39735+ PRINT_ERROR("register_chrdev() failed: %d", res);
39736+ res = dev_user_major;
39737+ goto out_class;
39738+ }
39739+
39740+ dev = device_create(dev_user_sysfs_class, NULL,
39741+ MKDEV(dev_user_major, 0),
39742+ NULL,
39743+ DEV_USER_NAME);
39744+ if (IS_ERR(dev)) {
39745+ res = PTR_ERR(dev);
39746+ goto out_chrdev;
39747+ }
39748+
39749+ cleanup_thread = kthread_run(dev_user_cleanup_thread, NULL,
39750+ "scst_usr_cleanupd");
39751+ if (IS_ERR(cleanup_thread)) {
39752+ res = PTR_ERR(cleanup_thread);
39753+ PRINT_ERROR("kthread_create() failed: %d", res);
39754+ goto out_dev;
39755+ }
39756+
39757+out:
39758+ TRACE_EXIT_RES(res);
39759+ return res;
39760+
39761+out_dev:
39762+ device_destroy(dev_user_sysfs_class, MKDEV(dev_user_major, 0));
39763+
39764+out_chrdev:
39765+ unregister_chrdev(dev_user_major, DEV_USER_NAME);
39766+
39767+out_class:
39768+ class_destroy(dev_user_sysfs_class);
39769+
39770+out_unreg:
39771+ scst_unregister_dev_driver(&dev_user_devtype);
39772+
39773+out_cache1:
39774+ kmem_cache_destroy(user_get_cmd_cachep);
39775+
39776+out_cache:
39777+ kmem_cache_destroy(user_cmd_cachep);
39778+ goto out;
39779+}
39780+
39781+static void __exit exit_scst_user(void)
39782+{
39783+ int rc;
39784+
39785+ TRACE_ENTRY();
39786+
39787+ rc = kthread_stop(cleanup_thread);
39788+ if (rc < 0)
39789+ TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
39790+
39791+ unregister_chrdev(dev_user_major, DEV_USER_NAME);
39792+ device_destroy(dev_user_sysfs_class, MKDEV(dev_user_major, 0));
39793+ class_destroy(dev_user_sysfs_class);
39794+
39795+ scst_unregister_virtual_dev_driver(&dev_user_devtype);
39796+
39797+ kmem_cache_destroy(user_get_cmd_cachep);
39798+ kmem_cache_destroy(user_cmd_cachep);
39799+
39800+ TRACE_EXIT();
39801+ return;
39802+}
39803+
39804+module_init(init_scst_user);
39805+module_exit(exit_scst_user);
39806+
39807+MODULE_AUTHOR("Vladislav Bolkhovitin");
39808+MODULE_LICENSE("GPL");
39809+MODULE_DESCRIPTION("User space device handler for SCST");
39810+MODULE_VERSION(SCST_VERSION_STRING);
39811diff -uprN orig/linux-2.6.35/drivers/scst/dev_handlers/scst_vdisk.c linux-2.6.35/drivers/scst/dev_handlers/scst_vdisk.c
39812--- orig/linux-2.6.35/drivers/scst/dev_handlers/scst_vdisk.c
39813+++ linux-2.6.35/drivers/scst/dev_handlers/scst_vdisk.c
39814@@ -0,0 +1,4160 @@
39815+/*
39816+ * scst_vdisk.c
39817+ *
39818+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
39819+ * Copyright (C) 2004 - 2005 Leonid Stoljar
39820+ * Copyright (C) 2007 Ming Zhang <blackmagic02881 at gmail dot com>
39821+ * Copyright (C) 2007 Ross Walker <rswwalker at hotmail dot com>
39822+ * Copyright (C) 2007 - 2010 ID7 Ltd.
39823+ *
39824+ * SCSI disk (type 0) and CDROM (type 5) dev handler using files
39825+ * on file systems or block devices (VDISK)
39826+ *
39827+ * This program is free software; you can redistribute it and/or
39828+ * modify it under the terms of the GNU General Public License
39829+ * as published by the Free Software Foundation, version 2
39830+ * of the License.
39831+ *
39832+ * This program is distributed in the hope that it will be useful,
39833+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
39834+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39835+ * GNU General Public License for more details.
39836+ */
39837+
39838+#include <linux/file.h>
39839+#include <linux/fs.h>
39840+#include <linux/string.h>
39841+#include <linux/types.h>
39842+#include <linux/unistd.h>
39843+#include <linux/smp_lock.h>
39844+#include <linux/spinlock.h>
39845+#include <linux/init.h>
39846+#include <linux/uio.h>
39847+#include <linux/list.h>
39848+#include <linux/ctype.h>
39849+#include <linux/writeback.h>
39850+#include <linux/vmalloc.h>
39851+#include <asm/atomic.h>
39852+#include <linux/kthread.h>
39853+#include <linux/sched.h>
39854+#include <linux/version.h>
39855+#include <asm/div64.h>
39856+#include <asm/unaligned.h>
39857+#include <linux/slab.h>
39858+#include <linux/bio.h>
39859+
39860+#define LOG_PREFIX "dev_vdisk"
39861+
39862+#include <scst/scst.h>
39863+
39864+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
39865+
39866+#define TRACE_ORDER 0x80000000
39867+
39868+static struct scst_trace_log vdisk_local_trace_tbl[] = {
39869+ { TRACE_ORDER, "order" },
39870+ { 0, NULL }
39871+};
39872+#define trace_log_tbl vdisk_local_trace_tbl
39873+
39874+#define VDISK_TRACE_TLB_HELP ", order"
39875+
39876+#endif
39877+
39878+#include "scst_dev_handler.h"
39879+
39880+/* 8 byte ASCII Vendor */
39881+#define SCST_FIO_VENDOR "SCST_FIO"
39882+#define SCST_BIO_VENDOR "SCST_BIO"
39883+/* 4 byte ASCII Product Revision Level - left aligned */
39884+#define SCST_FIO_REV " 200"
39885+
39886+#define MAX_USN_LEN (20+1) /* For '\0' */
39887+
39888+#define INQ_BUF_SZ 128
39889+#define EVPD 0x01
39890+#define CMDDT 0x02
39891+
39892+#define MSENSE_BUF_SZ 256
39893+#define DBD 0x08 /* disable block descriptor */
39894+#define WP 0x80 /* write protect */
39895+#define DPOFUA 0x10 /* DPOFUA bit */
39896+#define WCE 0x04 /* write cache enable */
39897+
39898+#define PF 0x10 /* page format */
39899+#define SP 0x01 /* save pages */
39900+#define PS 0x80 /* parameter saveable */
39901+
39902+#define BYTE 8
39903+#define DEF_DISK_BLOCKSIZE_SHIFT 9
39904+#define DEF_DISK_BLOCKSIZE (1 << DEF_DISK_BLOCKSIZE_SHIFT)
39905+#define DEF_CDROM_BLOCKSIZE_SHIFT 11
39906+#define DEF_CDROM_BLOCKSIZE (1 << DEF_CDROM_BLOCKSIZE_SHIFT)
39907+#define DEF_SECTORS 56
39908+#define DEF_HEADS 255
39909+#define LEN_MEM (32 * 1024)
39910+#define DEF_RD_ONLY 0
39911+#define DEF_WRITE_THROUGH 0
39912+#define DEF_NV_CACHE 0
39913+#define DEF_O_DIRECT 0
39914+#define DEF_REMOVABLE 0
39915+
39916+#define VDISK_NULLIO_SIZE (3LL*1024*1024*1024*1024/2)
39917+
39918+#define DEF_TST SCST_CONTR_MODE_SEP_TASK_SETS
39919+/*
39920+ * Since we can't control backstorage device's reordering, we have to always
39921+ * report unrestricted reordering.
39922+ */
39923+#define DEF_QUEUE_ALG_WT SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER
39924+#define DEF_QUEUE_ALG SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER
39925+#define DEF_SWP 0
39926+#define DEF_TAS 0
39927+
39928+#define DEF_DSENSE SCST_CONTR_MODE_FIXED_SENSE
39929+
39930+static unsigned int random_values[256] = {
39931+ 9862592UL, 3744545211UL, 2348289082UL, 4036111983UL,
39932+ 435574201UL, 3110343764UL, 2383055570UL, 1826499182UL,
39933+ 4076766377UL, 1549935812UL, 3696752161UL, 1200276050UL,
39934+ 3878162706UL, 1783530428UL, 2291072214UL, 125807985UL,
39935+ 3407668966UL, 547437109UL, 3961389597UL, 969093968UL,
39936+ 56006179UL, 2591023451UL, 1849465UL, 1614540336UL,
39937+ 3699757935UL, 479961779UL, 3768703953UL, 2529621525UL,
39938+ 4157893312UL, 3673555386UL, 4091110867UL, 2193909423UL,
39939+ 2800464448UL, 3052113233UL, 450394455UL, 3424338713UL,
39940+ 2113709130UL, 4082064373UL, 3708640918UL, 3841182218UL,
39941+ 3141803315UL, 1032476030UL, 1166423150UL, 1169646901UL,
39942+ 2686611738UL, 575517645UL, 2829331065UL, 1351103339UL,
39943+ 2856560215UL, 2402488288UL, 867847666UL, 8524618UL,
39944+ 704790297UL, 2228765657UL, 231508411UL, 1425523814UL,
39945+ 2146764591UL, 1287631730UL, 4142687914UL, 3879884598UL,
39946+ 729945311UL, 310596427UL, 2263511876UL, 1983091134UL,
39947+ 3500916580UL, 1642490324UL, 3858376049UL, 695342182UL,
39948+ 780528366UL, 1372613640UL, 1100993200UL, 1314818946UL,
39949+ 572029783UL, 3775573540UL, 776262915UL, 2684520905UL,
39950+ 1007252738UL, 3505856396UL, 1974886670UL, 3115856627UL,
39951+ 4194842288UL, 2135793908UL, 3566210707UL, 7929775UL,
39952+ 1321130213UL, 2627281746UL, 3587067247UL, 2025159890UL,
39953+ 2587032000UL, 3098513342UL, 3289360258UL, 130594898UL,
39954+ 2258149812UL, 2275857755UL, 3966929942UL, 1521739999UL,
39955+ 4191192765UL, 958953550UL, 4153558347UL, 1011030335UL,
39956+ 524382185UL, 4099757640UL, 498828115UL, 2396978754UL,
39957+ 328688935UL, 826399828UL, 3174103611UL, 3921966365UL,
39958+ 2187456284UL, 2631406787UL, 3930669674UL, 4282803915UL,
39959+ 1776755417UL, 374959755UL, 2483763076UL, 844956392UL,
39960+ 2209187588UL, 3647277868UL, 291047860UL, 3485867047UL,
39961+ 2223103546UL, 2526736133UL, 3153407604UL, 3828961796UL,
39962+ 3355731910UL, 2322269798UL, 2752144379UL, 519897942UL,
39963+ 3430536488UL, 1801511593UL, 1953975728UL, 3286944283UL,
39964+ 1511612621UL, 1050133852UL, 409321604UL, 1037601109UL,
39965+ 3352316843UL, 4198371381UL, 617863284UL, 994672213UL,
39966+ 1540735436UL, 2337363549UL, 1242368492UL, 665473059UL,
39967+ 2330728163UL, 3443103219UL, 2291025133UL, 3420108120UL,
39968+ 2663305280UL, 1608969839UL, 2278959931UL, 1389747794UL,
39969+ 2226946970UL, 2131266900UL, 3856979144UL, 1894169043UL,
39970+ 2692697628UL, 3797290626UL, 3248126844UL, 3922786277UL,
39971+ 343705271UL, 3739749888UL, 2191310783UL, 2962488787UL,
39972+ 4119364141UL, 1403351302UL, 2984008923UL, 3822407178UL,
39973+ 1932139782UL, 2323869332UL, 2793574182UL, 1852626483UL,
39974+ 2722460269UL, 1136097522UL, 1005121083UL, 1805201184UL,
39975+ 2212824936UL, 2979547931UL, 4133075915UL, 2585731003UL,
39976+ 2431626071UL, 134370235UL, 3763236829UL, 1171434827UL,
39977+ 2251806994UL, 1289341038UL, 3616320525UL, 392218563UL,
39978+ 1544502546UL, 2993937212UL, 1957503701UL, 3579140080UL,
39979+ 4270846116UL, 2030149142UL, 1792286022UL, 366604999UL,
39980+ 2625579499UL, 790898158UL, 770833822UL, 815540197UL,
39981+ 2747711781UL, 3570468835UL, 3976195842UL, 1257621341UL,
39982+ 1198342980UL, 1860626190UL, 3247856686UL, 351473955UL,
39983+ 993440563UL, 340807146UL, 1041994520UL, 3573925241UL,
39984+ 480246395UL, 2104806831UL, 1020782793UL, 3362132583UL,
39985+ 2272911358UL, 3440096248UL, 2356596804UL, 259492703UL,
39986+ 3899500740UL, 252071876UL, 2177024041UL, 4284810959UL,
39987+ 2775999888UL, 2653420445UL, 2876046047UL, 1025771859UL,
39988+ 1994475651UL, 3564987377UL, 4112956647UL, 1821511719UL,
39989+ 3113447247UL, 455315102UL, 1585273189UL, 2311494568UL,
39990+ 774051541UL, 1898115372UL, 2637499516UL, 247231365UL,
39991+ 1475014417UL, 803585727UL, 3911097303UL, 1714292230UL,
39992+ 476579326UL, 2496900974UL, 3397613314UL, 341202244UL,
39993+ 807790202UL, 4221326173UL, 499979741UL, 1301488547UL,
39994+ 1056807896UL, 3525009458UL, 1174811641UL, 3049738746UL,
39995+};
39996+
39997+struct scst_vdisk_dev {
39998+ uint32_t block_size;
39999+ uint64_t nblocks;
40000+ int block_shift;
40001+ loff_t file_size; /* in bytes */
40002+
40003+ /*
40004+ * This lock can be taken on both SIRQ and thread context, but in
40005+ * all cases for each particular instance it's taken consistenly either
40006+ * on SIRQ or thread context. Mix of them is forbidden.
40007+ */
40008+ spinlock_t flags_lock;
40009+
40010+ /*
40011+ * Below flags are protected by flags_lock or suspended activity
40012+ * with scst_vdisk_mutex.
40013+ */
40014+ unsigned int rd_only:1;
40015+ unsigned int wt_flag:1;
40016+ unsigned int nv_cache:1;
40017+ unsigned int o_direct_flag:1;
40018+ unsigned int media_changed:1;
40019+ unsigned int prevent_allow_medium_removal:1;
40020+ unsigned int nullio:1;
40021+ unsigned int blockio:1;
40022+ unsigned int cdrom_empty:1;
40023+ unsigned int removable:1;
40024+
40025+ int virt_id;
40026+ char name[16+1]; /* Name of the virtual device,
40027+ must be <= SCSI Model + 1 */
40028+ char *filename; /* File name, protected by
40029+ scst_mutex and suspended activities */
40030+ uint16_t command_set_version;
40031+ unsigned int t10_dev_id_set:1; /* true if t10_dev_id manually set */
40032+ char t10_dev_id[16+8+2]; /* T10 device ID */
40033+ char usn[MAX_USN_LEN];
40034+ struct scst_device *dev;
40035+ struct list_head vdev_list_entry;
40036+
40037+ struct scst_dev_type *vdev_devt;
40038+};
40039+
40040+struct scst_vdisk_thr {
40041+ struct scst_thr_data_hdr hdr;
40042+ struct file *fd;
40043+ struct block_device *bdev;
40044+ struct iovec *iv;
40045+ int iv_count;
40046+};
40047+
40048+/* Context RA patch supposed to be applied on the kernel */
40049+#define DEF_NUM_THREADS 8
40050+static int num_threads = DEF_NUM_THREADS;
40051+
40052+module_param_named(num_threads, num_threads, int, S_IRUGO);
40053+MODULE_PARM_DESC(num_threads, "vdisk threads count");
40054+
40055+static int vdisk_attach(struct scst_device *dev);
40056+static void vdisk_detach(struct scst_device *dev);
40057+static int vdisk_attach_tgt(struct scst_tgt_dev *tgt_dev);
40058+static void vdisk_detach_tgt(struct scst_tgt_dev *tgt_dev);
40059+static int vdisk_parse(struct scst_cmd *);
40060+static int vdisk_do_job(struct scst_cmd *cmd);
40061+static int vcdrom_parse(struct scst_cmd *);
40062+static int vcdrom_exec(struct scst_cmd *cmd);
40063+static void vdisk_exec_read(struct scst_cmd *cmd,
40064+ struct scst_vdisk_thr *thr, loff_t loff);
40065+static void vdisk_exec_write(struct scst_cmd *cmd,
40066+ struct scst_vdisk_thr *thr, loff_t loff);
40067+static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
40068+ u64 lba_start, int write);
40069+static int blockio_flush(struct block_device *bdev);
40070+static void vdisk_exec_verify(struct scst_cmd *cmd,
40071+ struct scst_vdisk_thr *thr, loff_t loff);
40072+static void vdisk_exec_read_capacity(struct scst_cmd *cmd);
40073+static void vdisk_exec_read_capacity16(struct scst_cmd *cmd);
40074+static void vdisk_exec_inquiry(struct scst_cmd *cmd);
40075+static void vdisk_exec_request_sense(struct scst_cmd *cmd);
40076+static void vdisk_exec_mode_sense(struct scst_cmd *cmd);
40077+static void vdisk_exec_mode_select(struct scst_cmd *cmd);
40078+static void vdisk_exec_log(struct scst_cmd *cmd);
40079+static void vdisk_exec_read_toc(struct scst_cmd *cmd);
40080+static void vdisk_exec_prevent_allow_medium_removal(struct scst_cmd *cmd);
40081+static int vdisk_fsync(struct scst_vdisk_thr *thr, loff_t loff,
40082+ loff_t len, struct scst_cmd *cmd, struct scst_device *dev);
40083+static ssize_t vdisk_add_fileio_device(const char *device_name, char *params);
40084+static ssize_t vdisk_add_blockio_device(const char *device_name, char *params);
40085+static ssize_t vdisk_add_nullio_device(const char *device_name, char *params);
40086+static ssize_t vdisk_del_device(const char *device_name);
40087+static ssize_t vcdrom_add_device(const char *device_name, char *params);
40088+static ssize_t vcdrom_del_device(const char *device_name);
40089+static int vdisk_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
40090+ struct scst_tgt_dev *tgt_dev);
40091+static uint64_t vdisk_gen_dev_id_num(const char *virt_dev_name);
40092+
40093+/** SYSFS **/
40094+
40095+static ssize_t vdev_sysfs_size_show(struct kobject *kobj,
40096+ struct kobj_attribute *attr, char *buf);
40097+static ssize_t vdisk_sysfs_blocksize_show(struct kobject *kobj,
40098+ struct kobj_attribute *attr, char *buf);
40099+static ssize_t vdisk_sysfs_rd_only_show(struct kobject *kobj,
40100+ struct kobj_attribute *attr, char *buf);
40101+static ssize_t vdisk_sysfs_wt_show(struct kobject *kobj,
40102+ struct kobj_attribute *attr, char *buf);
40103+static ssize_t vdisk_sysfs_nv_cache_show(struct kobject *kobj,
40104+ struct kobj_attribute *attr, char *buf);
40105+static ssize_t vdisk_sysfs_o_direct_show(struct kobject *kobj,
40106+ struct kobj_attribute *attr, char *buf);
40107+static ssize_t vdisk_sysfs_removable_show(struct kobject *kobj,
40108+ struct kobj_attribute *attr, char *buf);
40109+static ssize_t vdev_sysfs_filename_show(struct kobject *kobj,
40110+ struct kobj_attribute *attr, char *buf);
40111+static ssize_t vdisk_sysfs_resync_size_store(struct kobject *kobj,
40112+ struct kobj_attribute *attr, const char *buf, size_t count);
40113+static ssize_t vdev_sysfs_t10_dev_id_store(struct kobject *kobj,
40114+ struct kobj_attribute *attr, const char *buf, size_t count);
40115+static ssize_t vdev_sysfs_t10_dev_id_show(struct kobject *kobj,
40116+ struct kobj_attribute *attr, char *buf);
40117+static ssize_t vdev_sysfs_usn_show(struct kobject *kobj,
40118+ struct kobj_attribute *attr, char *buf);
40119+
40120+static ssize_t vcdrom_sysfs_filename_store(struct kobject *kobj,
40121+ struct kobj_attribute *attr, const char *buf, size_t count);
40122+
40123+static struct kobj_attribute vdev_size_attr =
40124+ __ATTR(size_mb, S_IRUGO, vdev_sysfs_size_show, NULL);
40125+static struct kobj_attribute vdisk_blocksize_attr =
40126+ __ATTR(blocksize, S_IRUGO, vdisk_sysfs_blocksize_show, NULL);
40127+static struct kobj_attribute vdisk_rd_only_attr =
40128+ __ATTR(read_only, S_IRUGO, vdisk_sysfs_rd_only_show, NULL);
40129+static struct kobj_attribute vdisk_wt_attr =
40130+ __ATTR(write_through, S_IRUGO, vdisk_sysfs_wt_show, NULL);
40131+static struct kobj_attribute vdisk_nv_cache_attr =
40132+ __ATTR(nv_cache, S_IRUGO, vdisk_sysfs_nv_cache_show, NULL);
40133+static struct kobj_attribute vdisk_o_direct_attr =
40134+ __ATTR(o_direct, S_IRUGO, vdisk_sysfs_o_direct_show, NULL);
40135+static struct kobj_attribute vdisk_removable_attr =
40136+ __ATTR(removable, S_IRUGO, vdisk_sysfs_removable_show, NULL);
40137+static struct kobj_attribute vdisk_filename_attr =
40138+ __ATTR(filename, S_IRUGO, vdev_sysfs_filename_show, NULL);
40139+static struct kobj_attribute vdisk_resync_size_attr =
40140+ __ATTR(resync_size, S_IWUSR, NULL, vdisk_sysfs_resync_size_store);
40141+static struct kobj_attribute vdev_t10_dev_id_attr =
40142+ __ATTR(t10_dev_id, S_IWUSR|S_IRUGO, vdev_sysfs_t10_dev_id_show,
40143+ vdev_sysfs_t10_dev_id_store);
40144+static struct kobj_attribute vdev_usn_attr =
40145+ __ATTR(usn, S_IRUGO, vdev_sysfs_usn_show, NULL);
40146+
40147+static struct kobj_attribute vcdrom_filename_attr =
40148+ __ATTR(filename, S_IRUGO|S_IWUSR, vdev_sysfs_filename_show,
40149+ vcdrom_sysfs_filename_store);
40150+
40151+static const struct attribute *vdisk_fileio_attrs[] = {
40152+ &vdev_size_attr.attr,
40153+ &vdisk_blocksize_attr.attr,
40154+ &vdisk_rd_only_attr.attr,
40155+ &vdisk_wt_attr.attr,
40156+ &vdisk_nv_cache_attr.attr,
40157+ &vdisk_o_direct_attr.attr,
40158+ &vdisk_removable_attr.attr,
40159+ &vdisk_filename_attr.attr,
40160+ &vdisk_resync_size_attr.attr,
40161+ &vdev_t10_dev_id_attr.attr,
40162+ &vdev_usn_attr.attr,
40163+ NULL,
40164+};
40165+
40166+static const struct attribute *vdisk_blockio_attrs[] = {
40167+ &vdev_size_attr.attr,
40168+ &vdisk_blocksize_attr.attr,
40169+ &vdisk_rd_only_attr.attr,
40170+ &vdisk_nv_cache_attr.attr,
40171+ &vdisk_removable_attr.attr,
40172+ &vdisk_filename_attr.attr,
40173+ &vdisk_resync_size_attr.attr,
40174+ &vdev_t10_dev_id_attr.attr,
40175+ &vdev_usn_attr.attr,
40176+ NULL,
40177+};
40178+
40179+static const struct attribute *vdisk_nullio_attrs[] = {
40180+ &vdev_size_attr.attr,
40181+ &vdisk_blocksize_attr.attr,
40182+ &vdisk_rd_only_attr.attr,
40183+ &vdisk_removable_attr.attr,
40184+ &vdev_t10_dev_id_attr.attr,
40185+ &vdev_usn_attr.attr,
40186+ NULL,
40187+};
40188+
40189+static const struct attribute *vcdrom_attrs[] = {
40190+ &vdev_size_attr.attr,
40191+ &vcdrom_filename_attr.attr,
40192+ &vdev_t10_dev_id_attr.attr,
40193+ &vdev_usn_attr.attr,
40194+ NULL,
40195+};
40196+
40197+/* Protects vdisks addition/deletion and related activities, like search */
40198+static DEFINE_MUTEX(scst_vdisk_mutex);
40199+static DEFINE_RWLOCK(vdisk_t10_dev_id_rwlock);
40200+
40201+/* Protected by scst_vdisk_mutex */
40202+static LIST_HEAD(vdev_list);
40203+
40204+static struct kmem_cache *vdisk_thr_cachep;
40205+
40206+/*
40207+ * Be careful changing "name" field, since it is the name of the corresponding
40208+ * /sys/kernel/scst_tgt entry, hence a part of user space ABI.
40209+ */
40210+
40211+static struct scst_dev_type vdisk_file_devtype = {
40212+ .name = "vdisk_fileio",
40213+ .type = TYPE_DISK,
40214+ .exec_sync = 1,
40215+ .threads_num = -1,
40216+ .parse_atomic = 1,
40217+ .dev_done_atomic = 1,
40218+ .attach = vdisk_attach,
40219+ .detach = vdisk_detach,
40220+ .attach_tgt = vdisk_attach_tgt,
40221+ .detach_tgt = vdisk_detach_tgt,
40222+ .parse = vdisk_parse,
40223+ .exec = vdisk_do_job,
40224+ .task_mgmt_fn = vdisk_task_mgmt_fn,
40225+ .add_device = vdisk_add_fileio_device,
40226+ .del_device = vdisk_del_device,
40227+ .dev_attrs = vdisk_fileio_attrs,
40228+ .add_device_parameters = "filename, blocksize, write_through, "
40229+ "nv_cache, o_direct, read_only, removable",
40230+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
40231+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
40232+ .trace_flags = &trace_flag,
40233+ .trace_tbl = vdisk_local_trace_tbl,
40234+ .trace_tbl_help = VDISK_TRACE_TLB_HELP,
40235+#endif
40236+};
40237+
40238+static struct kmem_cache *blockio_work_cachep;
40239+
40240+static struct scst_dev_type vdisk_blk_devtype = {
40241+ .name = "vdisk_blockio",
40242+ .type = TYPE_DISK,
40243+ .threads_num = 1,
40244+ .parse_atomic = 1,
40245+ .dev_done_atomic = 1,
40246+ .attach = vdisk_attach,
40247+ .detach = vdisk_detach,
40248+ .attach_tgt = vdisk_attach_tgt,
40249+ .detach_tgt = vdisk_detach_tgt,
40250+ .parse = vdisk_parse,
40251+ .exec = vdisk_do_job,
40252+ .task_mgmt_fn = vdisk_task_mgmt_fn,
40253+ .add_device = vdisk_add_blockio_device,
40254+ .del_device = vdisk_del_device,
40255+ .dev_attrs = vdisk_blockio_attrs,
40256+ .add_device_parameters = "filename, blocksize, nv_cache, read_only, "
40257+ "removable",
40258+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
40259+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
40260+ .trace_flags = &trace_flag,
40261+ .trace_tbl = vdisk_local_trace_tbl,
40262+ .trace_tbl_help = VDISK_TRACE_TLB_HELP,
40263+#endif
40264+};
40265+
40266+static struct scst_dev_type vdisk_null_devtype = {
40267+ .name = "vdisk_nullio",
40268+ .type = TYPE_DISK,
40269+ .threads_num = 0,
40270+ .parse_atomic = 1,
40271+ .dev_done_atomic = 1,
40272+ .attach = vdisk_attach,
40273+ .detach = vdisk_detach,
40274+ .attach_tgt = vdisk_attach_tgt,
40275+ .detach_tgt = vdisk_detach_tgt,
40276+ .parse = vdisk_parse,
40277+ .exec = vdisk_do_job,
40278+ .task_mgmt_fn = vdisk_task_mgmt_fn,
40279+ .add_device = vdisk_add_nullio_device,
40280+ .del_device = vdisk_del_device,
40281+ .dev_attrs = vdisk_nullio_attrs,
40282+ .add_device_parameters = "blocksize, read_only, removable",
40283+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
40284+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
40285+ .trace_flags = &trace_flag,
40286+ .trace_tbl = vdisk_local_trace_tbl,
40287+ .trace_tbl_help = VDISK_TRACE_TLB_HELP,
40288+#endif
40289+};
40290+
40291+static struct scst_dev_type vcdrom_devtype = {
40292+ .name = "vcdrom",
40293+ .type = TYPE_ROM,
40294+ .exec_sync = 1,
40295+ .threads_num = -1,
40296+ .parse_atomic = 1,
40297+ .dev_done_atomic = 1,
40298+ .attach = vdisk_attach,
40299+ .detach = vdisk_detach,
40300+ .attach_tgt = vdisk_attach_tgt,
40301+ .detach_tgt = vdisk_detach_tgt,
40302+ .parse = vcdrom_parse,
40303+ .exec = vcdrom_exec,
40304+ .task_mgmt_fn = vdisk_task_mgmt_fn,
40305+ .add_device = vcdrom_add_device,
40306+ .del_device = vcdrom_del_device,
40307+ .dev_attrs = vcdrom_attrs,
40308+ .add_device_parameters = NULL,
40309+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
40310+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
40311+ .trace_flags = &trace_flag,
40312+ .trace_tbl = vdisk_local_trace_tbl,
40313+ .trace_tbl_help = VDISK_TRACE_TLB_HELP,
40314+#endif
40315+};
40316+
40317+static struct scst_vdisk_thr nullio_thr_data;
40318+
40319+static const char *vdev_get_filename(const struct scst_vdisk_dev *virt_dev)
40320+{
40321+ if (virt_dev->filename != NULL)
40322+ return virt_dev->filename;
40323+ else
40324+ return "none";
40325+}
40326+
40327+/* Returns fd, use IS_ERR(fd) to get error status */
40328+static struct file *vdev_open_fd(const struct scst_vdisk_dev *virt_dev)
40329+{
40330+ int open_flags = 0;
40331+ struct file *fd;
40332+
40333+ TRACE_ENTRY();
40334+
40335+ if (virt_dev->dev->rd_only)
40336+ open_flags |= O_RDONLY;
40337+ else
40338+ open_flags |= O_RDWR;
40339+ if (virt_dev->o_direct_flag)
40340+ open_flags |= O_DIRECT;
40341+ if (virt_dev->wt_flag && !virt_dev->nv_cache)
40342+ open_flags |= O_SYNC;
40343+ TRACE_DBG("Opening file %s, flags 0x%x",
40344+ virt_dev->filename, open_flags);
40345+ fd = filp_open(virt_dev->filename, O_LARGEFILE | open_flags, 0600);
40346+
40347+ TRACE_EXIT();
40348+ return fd;
40349+}
40350+
40351+static void vdisk_blockio_check_flush_support(struct scst_vdisk_dev *virt_dev)
40352+{
40353+ struct inode *inode;
40354+ struct file *fd;
40355+
40356+ TRACE_ENTRY();
40357+
40358+ if (!virt_dev->blockio || virt_dev->rd_only || virt_dev->nv_cache)
40359+ goto out;
40360+
40361+ fd = filp_open(virt_dev->filename, O_LARGEFILE, 0600);
40362+ if (IS_ERR(fd)) {
40363+ PRINT_ERROR("filp_open(%s) returned error %ld",
40364+ virt_dev->filename, PTR_ERR(fd));
40365+ goto out;
40366+ }
40367+
40368+ inode = fd->f_dentry->d_inode;
40369+
40370+ if (!S_ISBLK(inode->i_mode)) {
40371+ PRINT_ERROR("%s is NOT a block device", virt_dev->filename);
40372+ goto out_close;
40373+ }
40374+
40375+ if (blockio_flush(inode->i_bdev) != 0) {
40376+ PRINT_WARNING("Device %s doesn't support barriers, switching "
40377+ "to NV_CACHE mode. Read README for more details.",
40378+ virt_dev->filename);
40379+ virt_dev->nv_cache = 1;
40380+ }
40381+
40382+out_close:
40383+ filp_close(fd, NULL);
40384+
40385+out:
40386+ TRACE_EXIT();
40387+ return;
40388+}
40389+
40390+/* Returns 0 on success and file size in *file_size, error code otherwise */
40391+static int vdisk_get_file_size(const char *filename, bool blockio,
40392+ loff_t *file_size)
40393+{
40394+ struct inode *inode;
40395+ int res = 0;
40396+ struct file *fd;
40397+
40398+ TRACE_ENTRY();
40399+
40400+ *file_size = 0;
40401+
40402+ fd = filp_open(filename, O_LARGEFILE | O_RDONLY, 0600);
40403+ if (IS_ERR(fd)) {
40404+ res = PTR_ERR(fd);
40405+ PRINT_ERROR("filp_open(%s) returned error %d", filename, res);
40406+ goto out;
40407+ }
40408+
40409+ inode = fd->f_dentry->d_inode;
40410+
40411+ if (blockio && !S_ISBLK(inode->i_mode)) {
40412+ PRINT_ERROR("File %s is NOT a block device", filename);
40413+ res = -EINVAL;
40414+ goto out_close;
40415+ }
40416+
40417+ if (S_ISREG(inode->i_mode))
40418+ /* Nothing to do */;
40419+ else if (S_ISBLK(inode->i_mode))
40420+ inode = inode->i_bdev->bd_inode;
40421+ else {
40422+ res = -EINVAL;
40423+ goto out_close;
40424+ }
40425+
40426+ *file_size = inode->i_size;
40427+
40428+out_close:
40429+ filp_close(fd, NULL);
40430+
40431+out:
40432+ TRACE_EXIT_RES(res);
40433+ return res;
40434+}
40435+
40436+static int vdisk_attach(struct scst_device *dev)
40437+{
40438+ int res = 0;
40439+ loff_t err;
40440+ struct scst_vdisk_dev *virt_dev = NULL, *vv;
40441+
40442+ TRACE_ENTRY();
40443+
40444+ TRACE_DBG("virt_id %d (%s)", dev->virt_id, dev->virt_name);
40445+
40446+ if (dev->virt_id == 0) {
40447+ PRINT_ERROR("%s", "Not a virtual device");
40448+ res = -EINVAL;
40449+ goto out;
40450+ }
40451+
40452+ /*
40453+ * scst_vdisk_mutex must be already taken before
40454+ * scst_register_virtual_device()
40455+ */
40456+ list_for_each_entry(vv, &vdev_list, vdev_list_entry) {
40457+ if (strcmp(vv->name, dev->virt_name) == 0) {
40458+ virt_dev = vv;
40459+ break;
40460+ }
40461+ }
40462+
40463+ if (virt_dev == NULL) {
40464+ PRINT_ERROR("Device %s not found", dev->virt_name);
40465+ res = -EINVAL;
40466+ goto out;
40467+ }
40468+
40469+ virt_dev->dev = dev;
40470+
40471+ dev->rd_only = virt_dev->rd_only;
40472+
40473+ if (!virt_dev->cdrom_empty) {
40474+ if (virt_dev->nullio)
40475+ err = VDISK_NULLIO_SIZE;
40476+ else {
40477+ res = vdisk_get_file_size(virt_dev->filename,
40478+ virt_dev->blockio, &err);
40479+ if (res != 0)
40480+ goto out;
40481+ }
40482+ virt_dev->file_size = err;
40483+
40484+ TRACE_DBG("size of file: %lld", (long long unsigned int)err);
40485+
40486+ vdisk_blockio_check_flush_support(virt_dev);
40487+ } else
40488+ virt_dev->file_size = 0;
40489+
40490+ virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift;
40491+
40492+ if (!virt_dev->cdrom_empty) {
40493+ PRINT_INFO("Attached SCSI target virtual %s %s "
40494+ "(file=\"%s\", fs=%lldMB, bs=%d, nblocks=%lld,"
40495+ " cyln=%lld%s)",
40496+ (dev->type == TYPE_DISK) ? "disk" : "cdrom",
40497+ virt_dev->name, vdev_get_filename(virt_dev),
40498+ virt_dev->file_size >> 20, virt_dev->block_size,
40499+ (long long unsigned int)virt_dev->nblocks,
40500+ (long long unsigned int)virt_dev->nblocks/64/32,
40501+ virt_dev->nblocks < 64*32
40502+ ? " !WARNING! cyln less than 1" : "");
40503+ } else {
40504+ PRINT_INFO("Attached empty SCSI target virtual cdrom %s",
40505+ virt_dev->name);
40506+ }
40507+
40508+ dev->dh_priv = virt_dev;
40509+
40510+ dev->tst = DEF_TST;
40511+ dev->d_sense = DEF_DSENSE;
40512+ if (virt_dev->wt_flag && !virt_dev->nv_cache)
40513+ dev->queue_alg = DEF_QUEUE_ALG_WT;
40514+ else
40515+ dev->queue_alg = DEF_QUEUE_ALG;
40516+ dev->swp = DEF_SWP;
40517+ dev->tas = DEF_TAS;
40518+
40519+out:
40520+ TRACE_EXIT();
40521+ return res;
40522+}
40523+
40524+/* scst_mutex supposed to be held */
40525+static void vdisk_detach(struct scst_device *dev)
40526+{
40527+ struct scst_vdisk_dev *virt_dev =
40528+ (struct scst_vdisk_dev *)dev->dh_priv;
40529+
40530+ TRACE_ENTRY();
40531+
40532+ TRACE_DBG("virt_id %d", dev->virt_id);
40533+
40534+ PRINT_INFO("Detached virtual device %s (\"%s\")",
40535+ virt_dev->name, vdev_get_filename(virt_dev));
40536+
40537+ /* virt_dev will be freed by the caller */
40538+ dev->dh_priv = NULL;
40539+
40540+ TRACE_EXIT();
40541+ return;
40542+}
40543+
40544+static void vdisk_free_thr_data(struct scst_thr_data_hdr *d)
40545+{
40546+ struct scst_vdisk_thr *thr =
40547+ container_of(d, struct scst_vdisk_thr, hdr);
40548+
40549+ TRACE_ENTRY();
40550+
40551+ if (thr->fd)
40552+ filp_close(thr->fd, NULL);
40553+
40554+ kfree(thr->iv);
40555+
40556+ kmem_cache_free(vdisk_thr_cachep, thr);
40557+
40558+ TRACE_EXIT();
40559+ return;
40560+}
40561+
40562+static struct scst_vdisk_thr *vdisk_init_thr_data(
40563+ struct scst_tgt_dev *tgt_dev)
40564+{
40565+ struct scst_vdisk_thr *res;
40566+ struct scst_vdisk_dev *virt_dev =
40567+ (struct scst_vdisk_dev *)tgt_dev->dev->dh_priv;
40568+
40569+ TRACE_ENTRY();
40570+
40571+ EXTRACHECKS_BUG_ON(virt_dev->nullio);
40572+
40573+ res = kmem_cache_zalloc(vdisk_thr_cachep, GFP_KERNEL);
40574+ if (res == NULL) {
40575+ TRACE(TRACE_OUT_OF_MEM, "%s", "Unable to allocate struct "
40576+ "scst_vdisk_thr");
40577+ goto out;
40578+ }
40579+
40580+ if (!virt_dev->cdrom_empty) {
40581+ res->fd = vdev_open_fd(virt_dev);
40582+ if (IS_ERR(res->fd)) {
40583+ PRINT_ERROR("filp_open(%s) returned an error %ld",
40584+ virt_dev->filename, PTR_ERR(res->fd));
40585+ goto out_free;
40586+ }
40587+ if (virt_dev->blockio)
40588+ res->bdev = res->fd->f_dentry->d_inode->i_bdev;
40589+ else
40590+ res->bdev = NULL;
40591+ } else
40592+ res->fd = NULL;
40593+
40594+ scst_add_thr_data(tgt_dev, &res->hdr, vdisk_free_thr_data);
40595+
40596+out:
40597+ TRACE_EXIT_HRES((unsigned long)res);
40598+ return res;
40599+
40600+out_free:
40601+ kmem_cache_free(vdisk_thr_cachep, res);
40602+ res = NULL;
40603+ goto out;
40604+}
40605+
40606+static int vdisk_attach_tgt(struct scst_tgt_dev *tgt_dev)
40607+{
40608+ int res = 0;
40609+
40610+ TRACE_ENTRY();
40611+
40612+ /* Nothing to do */
40613+
40614+ TRACE_EXIT_RES(res);
40615+ return res;
40616+}
40617+
40618+static void vdisk_detach_tgt(struct scst_tgt_dev *tgt_dev)
40619+{
40620+ TRACE_ENTRY();
40621+
40622+ scst_del_all_thr_data(tgt_dev);
40623+
40624+ TRACE_EXIT();
40625+ return;
40626+}
40627+
40628+static int vdisk_do_job(struct scst_cmd *cmd)
40629+{
40630+ int rc, res;
40631+ uint64_t lba_start = 0;
40632+ loff_t data_len = 0;
40633+ uint8_t *cdb = cmd->cdb;
40634+ int opcode = cdb[0];
40635+ loff_t loff;
40636+ struct scst_device *dev = cmd->dev;
40637+ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
40638+ struct scst_vdisk_dev *virt_dev =
40639+ (struct scst_vdisk_dev *)dev->dh_priv;
40640+ struct scst_thr_data_hdr *d;
40641+ struct scst_vdisk_thr *thr = NULL;
40642+ int fua = 0;
40643+
40644+ TRACE_ENTRY();
40645+
40646+ switch (cmd->queue_type) {
40647+ case SCST_CMD_QUEUE_ORDERED:
40648+ TRACE(TRACE_ORDER, "ORDERED cmd %p (op %x)", cmd, cmd->cdb[0]);
40649+ break;
40650+ case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
40651+ TRACE(TRACE_ORDER, "HQ cmd %p (op %x)", cmd, cmd->cdb[0]);
40652+ break;
40653+ default:
40654+ break;
40655+ }
40656+
40657+ rc = scst_check_local_events(cmd);
40658+ if (unlikely(rc != 0))
40659+ goto out_done;
40660+
40661+ cmd->status = 0;
40662+ cmd->msg_status = 0;
40663+ cmd->host_status = DID_OK;
40664+ cmd->driver_status = 0;
40665+
40666+ if (!virt_dev->nullio) {
40667+ d = scst_find_thr_data(tgt_dev);
40668+ if (unlikely(d == NULL)) {
40669+ thr = vdisk_init_thr_data(tgt_dev);
40670+ if (thr == NULL) {
40671+ scst_set_busy(cmd);
40672+ goto out_compl;
40673+ }
40674+ scst_thr_data_get(&thr->hdr);
40675+ } else
40676+ thr = container_of(d, struct scst_vdisk_thr, hdr);
40677+ } else {
40678+ thr = &nullio_thr_data;
40679+ scst_thr_data_get(&thr->hdr);
40680+ }
40681+
40682+ switch (opcode) {
40683+ case READ_6:
40684+ case WRITE_6:
40685+ case VERIFY_6:
40686+ lba_start = (((cdb[1] & 0x1f) << (BYTE * 2)) +
40687+ (cdb[2] << (BYTE * 1)) +
40688+ (cdb[3] << (BYTE * 0)));
40689+ data_len = cmd->bufflen;
40690+ break;
40691+ case READ_10:
40692+ case READ_12:
40693+ case WRITE_10:
40694+ case WRITE_12:
40695+ case VERIFY:
40696+ case WRITE_VERIFY:
40697+ case WRITE_VERIFY_12:
40698+ case VERIFY_12:
40699+ lba_start |= ((u64)cdb[2]) << 24;
40700+ lba_start |= ((u64)cdb[3]) << 16;
40701+ lba_start |= ((u64)cdb[4]) << 8;
40702+ lba_start |= ((u64)cdb[5]);
40703+ data_len = cmd->bufflen;
40704+ break;
40705+ case READ_16:
40706+ case WRITE_16:
40707+ case WRITE_VERIFY_16:
40708+ case VERIFY_16:
40709+ lba_start |= ((u64)cdb[2]) << 56;
40710+ lba_start |= ((u64)cdb[3]) << 48;
40711+ lba_start |= ((u64)cdb[4]) << 40;
40712+ lba_start |= ((u64)cdb[5]) << 32;
40713+ lba_start |= ((u64)cdb[6]) << 24;
40714+ lba_start |= ((u64)cdb[7]) << 16;
40715+ lba_start |= ((u64)cdb[8]) << 8;
40716+ lba_start |= ((u64)cdb[9]);
40717+ data_len = cmd->bufflen;
40718+ break;
40719+ case SYNCHRONIZE_CACHE:
40720+ lba_start |= ((u64)cdb[2]) << 24;
40721+ lba_start |= ((u64)cdb[3]) << 16;
40722+ lba_start |= ((u64)cdb[4]) << 8;
40723+ lba_start |= ((u64)cdb[5]);
40724+ data_len = ((cdb[7] << (BYTE * 1)) + (cdb[8] << (BYTE * 0)))
40725+ << virt_dev->block_shift;
40726+ if (data_len == 0)
40727+ data_len = virt_dev->file_size -
40728+ ((loff_t)lba_start << virt_dev->block_shift);
40729+ break;
40730+ }
40731+
40732+ loff = (loff_t)lba_start << virt_dev->block_shift;
40733+ TRACE_DBG("cmd %p, lba_start %lld, loff %lld, data_len %lld", cmd,
40734+ (long long unsigned int)lba_start,
40735+ (long long unsigned int)loff,
40736+ (long long unsigned int)data_len);
40737+ if (unlikely(loff < 0) || unlikely(data_len < 0) ||
40738+ unlikely((loff + data_len) > virt_dev->file_size)) {
40739+ PRINT_INFO("Access beyond the end of the device "
40740+ "(%lld of %lld, len %lld)",
40741+ (long long unsigned int)loff,
40742+ (long long unsigned int)virt_dev->file_size,
40743+ (long long unsigned int)data_len);
40744+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
40745+ scst_sense_block_out_range_error));
40746+ goto out_compl;
40747+ }
40748+
40749+ switch (opcode) {
40750+ case WRITE_10:
40751+ case WRITE_12:
40752+ case WRITE_16:
40753+ fua = (cdb[1] & 0x8);
40754+ if (fua) {
40755+ TRACE(TRACE_ORDER, "FUA: loff=%lld, "
40756+ "data_len=%lld", (long long unsigned int)loff,
40757+ (long long unsigned int)data_len);
40758+ }
40759+ break;
40760+ }
40761+
40762+ switch (opcode) {
40763+ case READ_6:
40764+ case READ_10:
40765+ case READ_12:
40766+ case READ_16:
40767+ if (virt_dev->blockio) {
40768+ blockio_exec_rw(cmd, thr, lba_start, 0);
40769+ goto out_thr;
40770+ } else
40771+ vdisk_exec_read(cmd, thr, loff);
40772+ break;
40773+ case WRITE_6:
40774+ case WRITE_10:
40775+ case WRITE_12:
40776+ case WRITE_16:
40777+ {
40778+ if (virt_dev->blockio) {
40779+ blockio_exec_rw(cmd, thr, lba_start, 1);
40780+ goto out_thr;
40781+ } else
40782+ vdisk_exec_write(cmd, thr, loff);
40783+ /* O_SYNC flag is used for WT devices */
40784+ if (fua)
40785+ vdisk_fsync(thr, loff, data_len, cmd, dev);
40786+ break;
40787+ }
40788+ case WRITE_VERIFY:
40789+ case WRITE_VERIFY_12:
40790+ case WRITE_VERIFY_16:
40791+ {
40792+ /* ToDo: BLOCKIO VERIFY */
40793+ vdisk_exec_write(cmd, thr, loff);
40794+ /* O_SYNC flag is used for WT devices */
40795+ if (scsi_status_is_good(cmd->status))
40796+ vdisk_exec_verify(cmd, thr, loff);
40797+ break;
40798+ }
40799+ case SYNCHRONIZE_CACHE:
40800+ {
40801+ int immed = cdb[1] & 0x2;
40802+ TRACE(TRACE_ORDER, "SYNCHRONIZE_CACHE: "
40803+ "loff=%lld, data_len=%lld, immed=%d",
40804+ (long long unsigned int)loff,
40805+ (long long unsigned int)data_len, immed);
40806+ if (immed) {
40807+ scst_cmd_get(cmd); /* to protect dev */
40808+ cmd->completed = 1;
40809+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT,
40810+ SCST_CONTEXT_SAME);
40811+ vdisk_fsync(thr, loff, data_len, NULL, dev);
40812+ /* ToDo: vdisk_fsync() error processing */
40813+ scst_cmd_put(cmd);
40814+ goto out_thr;
40815+ } else {
40816+ vdisk_fsync(thr, loff, data_len, cmd, dev);
40817+ break;
40818+ }
40819+ }
40820+ case VERIFY_6:
40821+ case VERIFY:
40822+ case VERIFY_12:
40823+ case VERIFY_16:
40824+ vdisk_exec_verify(cmd, thr, loff);
40825+ break;
40826+ case MODE_SENSE:
40827+ case MODE_SENSE_10:
40828+ vdisk_exec_mode_sense(cmd);
40829+ break;
40830+ case MODE_SELECT:
40831+ case MODE_SELECT_10:
40832+ vdisk_exec_mode_select(cmd);
40833+ break;
40834+ case LOG_SELECT:
40835+ case LOG_SENSE:
40836+ vdisk_exec_log(cmd);
40837+ break;
40838+ case ALLOW_MEDIUM_REMOVAL:
40839+ vdisk_exec_prevent_allow_medium_removal(cmd);
40840+ break;
40841+ case READ_TOC:
40842+ vdisk_exec_read_toc(cmd);
40843+ break;
40844+ case START_STOP:
40845+ vdisk_fsync(thr, 0, virt_dev->file_size, cmd, dev);
40846+ break;
40847+ case RESERVE:
40848+ case RESERVE_10:
40849+ case RELEASE:
40850+ case RELEASE_10:
40851+ case TEST_UNIT_READY:
40852+ break;
40853+ case INQUIRY:
40854+ vdisk_exec_inquiry(cmd);
40855+ break;
40856+ case REQUEST_SENSE:
40857+ vdisk_exec_request_sense(cmd);
40858+ break;
40859+ case READ_CAPACITY:
40860+ vdisk_exec_read_capacity(cmd);
40861+ break;
40862+ case SERVICE_ACTION_IN:
40863+ if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) {
40864+ vdisk_exec_read_capacity16(cmd);
40865+ break;
40866+ }
40867+ /* else go through */
40868+ case REPORT_LUNS:
40869+ default:
40870+ TRACE_DBG("Invalid opcode %d", opcode);
40871+ scst_set_cmd_error(cmd,
40872+ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
40873+ }
40874+
40875+out_compl:
40876+ cmd->completed = 1;
40877+
40878+out_done:
40879+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
40880+
40881+out_thr:
40882+ if (likely(thr != NULL))
40883+ scst_thr_data_put(&thr->hdr);
40884+
40885+ res = SCST_EXEC_COMPLETED;
40886+
40887+ TRACE_EXIT_RES(res);
40888+ return res;
40889+}
40890+
40891+static int vdisk_get_block_shift(struct scst_cmd *cmd)
40892+{
40893+ struct scst_vdisk_dev *virt_dev =
40894+ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
40895+ return virt_dev->block_shift;
40896+}
40897+
40898+static int vdisk_parse(struct scst_cmd *cmd)
40899+{
40900+ scst_sbc_generic_parse(cmd, vdisk_get_block_shift);
40901+ return SCST_CMD_STATE_DEFAULT;
40902+}
40903+
40904+static int vcdrom_parse(struct scst_cmd *cmd)
40905+{
40906+ scst_cdrom_generic_parse(cmd, vdisk_get_block_shift);
40907+ return SCST_CMD_STATE_DEFAULT;
40908+}
40909+
40910+static int vcdrom_exec(struct scst_cmd *cmd)
40911+{
40912+ int res = SCST_EXEC_COMPLETED;
40913+ int opcode = cmd->cdb[0];
40914+ struct scst_vdisk_dev *virt_dev =
40915+ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
40916+
40917+ TRACE_ENTRY();
40918+
40919+ cmd->status = 0;
40920+ cmd->msg_status = 0;
40921+ cmd->host_status = DID_OK;
40922+ cmd->driver_status = 0;
40923+
40924+ if (virt_dev->cdrom_empty && (opcode != INQUIRY)) {
40925+ TRACE_DBG("%s", "CDROM empty");
40926+ scst_set_cmd_error(cmd,
40927+ SCST_LOAD_SENSE(scst_sense_not_ready));
40928+ goto out_done;
40929+ }
40930+
40931+ if (virt_dev->media_changed && scst_is_ua_command(cmd)) {
40932+ spin_lock(&virt_dev->flags_lock);
40933+ if (virt_dev->media_changed) {
40934+ virt_dev->media_changed = 0;
40935+ TRACE_DBG("%s", "Reporting media changed");
40936+ scst_set_cmd_error(cmd,
40937+ SCST_LOAD_SENSE(scst_sense_medium_changed_UA));
40938+ spin_unlock(&virt_dev->flags_lock);
40939+ goto out_done;
40940+ }
40941+ spin_unlock(&virt_dev->flags_lock);
40942+ }
40943+
40944+ res = vdisk_do_job(cmd);
40945+
40946+out:
40947+ TRACE_EXIT_RES(res);
40948+ return res;
40949+
40950+out_done:
40951+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
40952+ goto out;
40953+}
40954+
40955+static uint64_t vdisk_gen_dev_id_num(const char *virt_dev_name)
40956+{
40957+ unsigned int dev_id_num, i;
40958+
40959+ for (dev_id_num = 0, i = 0; i < strlen(virt_dev_name); i++) {
40960+ unsigned int rv = random_values[(int)(virt_dev_name[i])];
40961+ /* Do some rotating of the bits */
40962+ dev_id_num ^= ((rv << i) | (rv >> (32 - i)));
40963+ }
40964+
40965+ return ((uint64_t)scst_get_setup_id() << 32) | dev_id_num;
40966+}
40967+
40968+static void vdisk_exec_inquiry(struct scst_cmd *cmd)
40969+{
40970+ int32_t length, i, resp_len = 0;
40971+ uint8_t *address;
40972+ uint8_t *buf;
40973+ struct scst_vdisk_dev *virt_dev =
40974+ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
40975+
40976+ /* ToDo: Performance Boost:
40977+ * 1. remove kzalloc, buf
40978+ * 2. do all checks before touching *address
40979+ * 3. zero *address
40980+ * 4. write directly to *address
40981+ */
40982+
40983+ TRACE_ENTRY();
40984+
40985+ buf = kzalloc(INQ_BUF_SZ, GFP_KERNEL);
40986+ if (buf == NULL) {
40987+ scst_set_busy(cmd);
40988+ goto out;
40989+ }
40990+
40991+ length = scst_get_buf_first(cmd, &address);
40992+ TRACE_DBG("length %d", length);
40993+ if (unlikely(length <= 0)) {
40994+ if (length < 0) {
40995+ PRINT_ERROR("scst_get_buf_first() failed: %d", length);
40996+ scst_set_cmd_error(cmd,
40997+ SCST_LOAD_SENSE(scst_sense_hardw_error));
40998+ }
40999+ goto out_free;
41000+ }
41001+
41002+ if (cmd->cdb[1] & CMDDT) {
41003+ TRACE_DBG("%s", "INQUIRY: CMDDT is unsupported");
41004+ scst_set_cmd_error(cmd,
41005+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
41006+ goto out_put;
41007+ }
41008+
41009+ buf[0] = cmd->dev->type; /* type dev */
41010+ if (virt_dev->removable)
41011+ buf[1] = 0x80; /* removable */
41012+ /* Vital Product */
41013+ if (cmd->cdb[1] & EVPD) {
41014+ if (0 == cmd->cdb[2]) {
41015+ /* supported vital product data pages */
41016+ buf[3] = 3;
41017+ buf[4] = 0x0; /* this page */
41018+ buf[5] = 0x80; /* unit serial number */
41019+ buf[6] = 0x83; /* device identification */
41020+ if (virt_dev->dev->type == TYPE_DISK) {
41021+ buf[3] += 1;
41022+ buf[7] = 0xB0; /* block limits */
41023+ }
41024+ resp_len = buf[3] + 4;
41025+ } else if (0x80 == cmd->cdb[2]) {
41026+ /* unit serial number */
41027+ int usn_len = strlen(virt_dev->usn);
41028+ buf[1] = 0x80;
41029+ buf[3] = usn_len;
41030+ strncpy(&buf[4], virt_dev->usn, usn_len);
41031+ resp_len = buf[3] + 4;
41032+ } else if (0x83 == cmd->cdb[2]) {
41033+ /* device identification */
41034+ int num = 4;
41035+
41036+ buf[1] = 0x83;
41037+ /* T10 vendor identifier field format (faked) */
41038+ buf[num + 0] = 0x2; /* ASCII */
41039+ buf[num + 1] = 0x1; /* Vendor ID */
41040+ if (virt_dev->blockio)
41041+ memcpy(&buf[num + 4], SCST_BIO_VENDOR, 8);
41042+ else
41043+ memcpy(&buf[num + 4], SCST_FIO_VENDOR, 8);
41044+
41045+ read_lock_bh(&vdisk_t10_dev_id_rwlock);
41046+ i = strlen(virt_dev->t10_dev_id);
41047+ memcpy(&buf[num + 12], virt_dev->t10_dev_id, i);
41048+ read_unlock_bh(&vdisk_t10_dev_id_rwlock);
41049+
41050+ buf[num + 3] = 8 + i;
41051+ num += buf[num + 3];
41052+
41053+ num += 4;
41054+
41055+ /*
41056+ * Relative target port identifier
41057+ */
41058+ buf[num + 0] = 0x01; /* binary */
41059+ /* Relative target port id */
41060+ buf[num + 1] = 0x10 | 0x04;
41061+
41062+ put_unaligned(cpu_to_be16(cmd->tgt->rel_tgt_id),
41063+ (__be16 *)&buf[num + 4 + 2]);
41064+
41065+ buf[num + 3] = 4;
41066+ num += buf[num + 3];
41067+
41068+ num += 4;
41069+
41070+ /*
41071+ * IEEE id
41072+ */
41073+ buf[num + 0] = 0x01; /* binary */
41074+
41075+ /* EUI-64 */
41076+ buf[num + 1] = 0x02;
41077+ buf[num + 2] = 0x00;
41078+ buf[num + 3] = 0x08;
41079+
41080+ /* IEEE id */
41081+ buf[num + 4] = virt_dev->t10_dev_id[0];
41082+ buf[num + 5] = virt_dev->t10_dev_id[1];
41083+ buf[num + 6] = virt_dev->t10_dev_id[2];
41084+
41085+ /* IEEE ext id */
41086+ buf[num + 7] = virt_dev->t10_dev_id[3];
41087+ buf[num + 8] = virt_dev->t10_dev_id[4];
41088+ buf[num + 9] = virt_dev->t10_dev_id[5];
41089+ buf[num + 10] = virt_dev->t10_dev_id[6];
41090+ buf[num + 11] = virt_dev->t10_dev_id[7];
41091+ num += buf[num + 3];
41092+
41093+ resp_len = num;
41094+ buf[2] = (resp_len >> 8) & 0xFF;
41095+ buf[3] = resp_len & 0xFF;
41096+ resp_len += 4;
41097+ } else if ((0xB0 == cmd->cdb[2]) &&
41098+ (virt_dev->dev->type == TYPE_DISK)) {
41099+ /* block limits */
41100+ int max_transfer;
41101+ buf[1] = 0xB0;
41102+ buf[3] = 0x1C;
41103+ /* Optimal transfer granuality is PAGE_SIZE */
41104+ put_unaligned(cpu_to_be16(max_t(int,
41105+ PAGE_SIZE/virt_dev->block_size, 1)),
41106+ (uint16_t *)&buf[6]);
41107+ /* Max transfer len is min of sg limit and 8M */
41108+ max_transfer = min_t(int,
41109+ cmd->tgt_dev->max_sg_cnt << PAGE_SHIFT,
41110+ 8*1024*1024) / virt_dev->block_size;
41111+ put_unaligned(cpu_to_be32(max_transfer),
41112+ (uint32_t *)&buf[8]);
41113+ /*
41114+ * Let's have optimal transfer len 1MB. Better to not
41115+ * set it at all, because we don't have such limit,
41116+ * but some initiators may not understand that (?).
41117+ * From other side, too big transfers are not optimal,
41118+ * because SGV cache supports only <4M buffers.
41119+ */
41120+ put_unaligned(cpu_to_be32(min_t(int,
41121+ max_transfer,
41122+ 1*1024*1024 / virt_dev->block_size)),
41123+ (uint32_t *)&buf[12]);
41124+ resp_len = buf[3] + 4;
41125+ } else {
41126+ TRACE_DBG("INQUIRY: Unsupported EVPD page %x",
41127+ cmd->cdb[2]);
41128+ scst_set_cmd_error(cmd,
41129+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
41130+ goto out_put;
41131+ }
41132+ } else {
41133+ int len, num;
41134+
41135+ if (cmd->cdb[2] != 0) {
41136+ TRACE_DBG("INQUIRY: Unsupported page %x", cmd->cdb[2]);
41137+ scst_set_cmd_error(cmd,
41138+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
41139+ goto out_put;
41140+ }
41141+
41142+ buf[2] = 5; /* Device complies to SPC-3 */
41143+ buf[3] = 0x12; /* HiSup + data in format specified in SPC */
41144+ buf[4] = 31;/* n - 4 = 35 - 4 = 31 for full 36 byte data */
41145+ buf[6] = 1; /* MultiP 1 */
41146+ buf[7] = 2; /* CMDQUE 1, BQue 0 => commands queuing supported */
41147+
41148+ /*
41149+ * 8 byte ASCII Vendor Identification of the target
41150+ * - left aligned.
41151+ */
41152+ if (virt_dev->blockio)
41153+ memcpy(&buf[8], SCST_BIO_VENDOR, 8);
41154+ else
41155+ memcpy(&buf[8], SCST_FIO_VENDOR, 8);
41156+
41157+ /*
41158+ * 16 byte ASCII Product Identification of the target - left
41159+ * aligned.
41160+ */
41161+ memset(&buf[16], ' ', 16);
41162+ len = min(strlen(virt_dev->name), (size_t)16);
41163+ memcpy(&buf[16], virt_dev->name, len);
41164+
41165+ /*
41166+ * 4 byte ASCII Product Revision Level of the target - left
41167+ * aligned.
41168+ */
41169+ memcpy(&buf[32], SCST_FIO_REV, 4);
41170+
41171+ /** Version descriptors **/
41172+
41173+ buf[4] += 58 - 36;
41174+ num = 0;
41175+
41176+ /* SAM-3 T10/1561-D revision 14 */
41177+ buf[58 + num] = 0x0;
41178+ buf[58 + num + 1] = 0x76;
41179+ num += 2;
41180+
41181+ /* Physical transport */
41182+ if (cmd->tgtt->get_phys_transport_version != NULL) {
41183+ uint16_t v = cmd->tgtt->get_phys_transport_version(cmd->tgt);
41184+ if (v != 0) {
41185+ *((__be16 *)&buf[58 + num]) = cpu_to_be16(v);
41186+ num += 2;
41187+ }
41188+ }
41189+
41190+ /* SCSI transport */
41191+ if (cmd->tgtt->get_scsi_transport_version != NULL) {
41192+ *((__be16 *)&buf[58 + num]) =
41193+ cpu_to_be16(cmd->tgtt->get_scsi_transport_version(cmd->tgt));
41194+ num += 2;
41195+ }
41196+
41197+ /* SPC-3 T10/1416-D revision 23 */
41198+ buf[58 + num] = 0x3;
41199+ buf[58 + num + 1] = 0x12;
41200+ num += 2;
41201+
41202+ /* Device command set */
41203+ if (virt_dev->command_set_version != 0) {
41204+ *((__be16 *)&buf[58 + num]) =
41205+ cpu_to_be16(virt_dev->command_set_version);
41206+ num += 2;
41207+ }
41208+
41209+ buf[4] += num;
41210+ resp_len = buf[4] + 5;
41211+ }
41212+
41213+ BUG_ON(resp_len >= INQ_BUF_SZ);
41214+
41215+ if (length > resp_len)
41216+ length = resp_len;
41217+ memcpy(address, buf, length);
41218+
41219+out_put:
41220+ scst_put_buf(cmd, address);
41221+ if (length < cmd->resp_data_len)
41222+ scst_set_resp_data_len(cmd, length);
41223+
41224+out_free:
41225+ kfree(buf);
41226+
41227+out:
41228+ TRACE_EXIT();
41229+ return;
41230+}
41231+
41232+static void vdisk_exec_request_sense(struct scst_cmd *cmd)
41233+{
41234+ int32_t length, sl;
41235+ uint8_t *address;
41236+ uint8_t b[SCST_STANDARD_SENSE_LEN];
41237+
41238+ TRACE_ENTRY();
41239+
41240+ sl = scst_set_sense(b, sizeof(b), cmd->dev->d_sense,
41241+ SCST_LOAD_SENSE(scst_sense_no_sense));
41242+
41243+ length = scst_get_buf_first(cmd, &address);
41244+ TRACE_DBG("length %d", length);
41245+ if (length < 0) {
41246+ PRINT_ERROR("scst_get_buf_first() failed: %d)", length);
41247+ scst_set_cmd_error(cmd,
41248+ SCST_LOAD_SENSE(scst_sense_hardw_error));
41249+ goto out;
41250+ }
41251+
41252+ length = min(sl, length);
41253+ memcpy(address, b, length);
41254+ scst_set_resp_data_len(cmd, length);
41255+
41256+ scst_put_buf(cmd, address);
41257+
41258+out:
41259+ TRACE_EXIT();
41260+ return;
41261+}
41262+
41263+/*
41264+ * <<Following mode pages info copied from ST318451LW with some corrections>>
41265+ *
41266+ * ToDo: revise them
41267+ */
41268+static int vdisk_err_recov_pg(unsigned char *p, int pcontrol,
41269+ struct scst_vdisk_dev *virt_dev)
41270+{ /* Read-Write Error Recovery page for mode_sense */
41271+ const unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0,
41272+ 5, 0, 0xff, 0xff};
41273+
41274+ memcpy(p, err_recov_pg, sizeof(err_recov_pg));
41275+ if (1 == pcontrol)
41276+ memset(p + 2, 0, sizeof(err_recov_pg) - 2);
41277+ return sizeof(err_recov_pg);
41278+}
41279+
41280+static int vdisk_disconnect_pg(unsigned char *p, int pcontrol,
41281+ struct scst_vdisk_dev *virt_dev)
41282+{ /* Disconnect-Reconnect page for mode_sense */
41283+ const unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0,
41284+ 0, 0, 0, 0, 0, 0, 0, 0};
41285+
41286+ memcpy(p, disconnect_pg, sizeof(disconnect_pg));
41287+ if (1 == pcontrol)
41288+ memset(p + 2, 0, sizeof(disconnect_pg) - 2);
41289+ return sizeof(disconnect_pg);
41290+}
41291+
41292+static int vdisk_rigid_geo_pg(unsigned char *p, int pcontrol,
41293+ struct scst_vdisk_dev *virt_dev)
41294+{
41295+ unsigned char geo_m_pg[] = {0x04, 0x16, 0, 0, 0, DEF_HEADS, 0, 0,
41296+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
41297+ 0x3a, 0x98/* 15K RPM */, 0, 0};
41298+ int32_t ncyl, n, rem;
41299+ uint64_t dividend;
41300+
41301+ memcpy(p, geo_m_pg, sizeof(geo_m_pg));
41302+ /*
41303+ * Divide virt_dev->nblocks by (DEF_HEADS * DEF_SECTORS) and store
41304+ * the quotient in ncyl and the remainder in rem.
41305+ */
41306+ dividend = virt_dev->nblocks;
41307+ rem = do_div(dividend, DEF_HEADS * DEF_SECTORS);
41308+ ncyl = dividend;
41309+ if (rem != 0)
41310+ ncyl++;
41311+ memcpy(&n, p + 2, sizeof(u32));
41312+ n = n | ((__force u32)cpu_to_be32(ncyl) >> 8);
41313+ memcpy(p + 2, &n, sizeof(u32));
41314+ if (1 == pcontrol)
41315+ memset(p + 2, 0, sizeof(geo_m_pg) - 2);
41316+ return sizeof(geo_m_pg);
41317+}
41318+
41319+static int vdisk_format_pg(unsigned char *p, int pcontrol,
41320+ struct scst_vdisk_dev *virt_dev)
41321+{ /* Format device page for mode_sense */
41322+ const unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0,
41323+ 0, 0, 0, 0, 0, 0, 0, 0,
41324+ 0, 0, 0, 0, 0x40, 0, 0, 0};
41325+
41326+ memcpy(p, format_pg, sizeof(format_pg));
41327+ p[10] = (DEF_SECTORS >> 8) & 0xff;
41328+ p[11] = DEF_SECTORS & 0xff;
41329+ p[12] = (virt_dev->block_size >> 8) & 0xff;
41330+ p[13] = virt_dev->block_size & 0xff;
41331+ if (1 == pcontrol)
41332+ memset(p + 2, 0, sizeof(format_pg) - 2);
41333+ return sizeof(format_pg);
41334+}
41335+
41336+static int vdisk_caching_pg(unsigned char *p, int pcontrol,
41337+ struct scst_vdisk_dev *virt_dev)
41338+{ /* Caching page for mode_sense */
41339+ const unsigned char caching_pg[] = {0x8, 18, 0x10, 0, 0xff, 0xff, 0, 0,
41340+ 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0};
41341+
41342+ memcpy(p, caching_pg, sizeof(caching_pg));
41343+ p[2] |= !(virt_dev->wt_flag || virt_dev->nv_cache) ? WCE : 0;
41344+ if (1 == pcontrol)
41345+ memset(p + 2, 0, sizeof(caching_pg) - 2);
41346+ return sizeof(caching_pg);
41347+}
41348+
41349+static int vdisk_ctrl_m_pg(unsigned char *p, int pcontrol,
41350+ struct scst_vdisk_dev *virt_dev)
41351+{ /* Control mode page for mode_sense */
41352+ const unsigned char ctrl_m_pg[] = {0xa, 0xa, 0, 0, 0, 0, 0, 0,
41353+ 0, 0, 0x2, 0x4b};
41354+
41355+ memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
41356+ switch (pcontrol) {
41357+ case 0:
41358+ p[2] |= virt_dev->dev->tst << 5;
41359+ p[2] |= virt_dev->dev->d_sense << 2;
41360+ p[3] |= virt_dev->dev->queue_alg << 4;
41361+ p[4] |= virt_dev->dev->swp << 3;
41362+ p[5] |= virt_dev->dev->tas << 6;
41363+ break;
41364+ case 1:
41365+ memset(p + 2, 0, sizeof(ctrl_m_pg) - 2);
41366+#if 0 /*
41367+ * It's too early to implement it, since we can't control the
41368+ * backstorage device parameters. ToDo
41369+ */
41370+ p[2] |= 7 << 5; /* TST */
41371+ p[3] |= 0xF << 4; /* QUEUE ALGORITHM MODIFIER */
41372+#endif
41373+ p[2] |= 1 << 2; /* D_SENSE */
41374+ p[4] |= 1 << 3; /* SWP */
41375+ p[5] |= 1 << 6; /* TAS */
41376+ break;
41377+ case 2:
41378+ p[2] |= DEF_TST << 5;
41379+ p[2] |= DEF_DSENSE << 2;
41380+ if (virt_dev->wt_flag || virt_dev->nv_cache)
41381+ p[3] |= DEF_QUEUE_ALG_WT << 4;
41382+ else
41383+ p[3] |= DEF_QUEUE_ALG << 4;
41384+ p[4] |= DEF_SWP << 3;
41385+ p[5] |= DEF_TAS << 6;
41386+ break;
41387+ default:
41388+ BUG();
41389+ }
41390+ return sizeof(ctrl_m_pg);
41391+}
41392+
41393+static int vdisk_iec_m_pg(unsigned char *p, int pcontrol,
41394+ struct scst_vdisk_dev *virt_dev)
41395+{ /* Informational Exceptions control mode page for mode_sense */
41396+ const unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
41397+ 0, 0, 0x0, 0x0};
41398+ memcpy(p, iec_m_pg, sizeof(iec_m_pg));
41399+ if (1 == pcontrol)
41400+ memset(p + 2, 0, sizeof(iec_m_pg) - 2);
41401+ return sizeof(iec_m_pg);
41402+}
41403+
41404+static void vdisk_exec_mode_sense(struct scst_cmd *cmd)
41405+{
41406+ int32_t length;
41407+ uint8_t *address;
41408+ uint8_t *buf;
41409+ struct scst_vdisk_dev *virt_dev;
41410+ uint32_t blocksize;
41411+ uint64_t nblocks;
41412+ unsigned char dbd, type;
41413+ int pcontrol, pcode, subpcode;
41414+ unsigned char dev_spec;
41415+ int msense_6, offset = 0, len;
41416+ unsigned char *bp;
41417+
41418+ TRACE_ENTRY();
41419+
41420+ buf = kzalloc(MSENSE_BUF_SZ, GFP_KERNEL);
41421+ if (buf == NULL) {
41422+ scst_set_busy(cmd);
41423+ goto out;
41424+ }
41425+
41426+ virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
41427+ blocksize = virt_dev->block_size;
41428+ nblocks = virt_dev->nblocks;
41429+
41430+ type = cmd->dev->type; /* type dev */
41431+ dbd = cmd->cdb[1] & DBD;
41432+ pcontrol = (cmd->cdb[2] & 0xc0) >> 6;
41433+ pcode = cmd->cdb[2] & 0x3f;
41434+ subpcode = cmd->cdb[3];
41435+ msense_6 = (MODE_SENSE == cmd->cdb[0]);
41436+ dev_spec = (virt_dev->dev->rd_only ||
41437+ cmd->tgt_dev->acg_dev->rd_only) ? WP : 0;
41438+
41439+ if (!virt_dev->blockio)
41440+ dev_spec |= DPOFUA;
41441+
41442+ length = scst_get_buf_first(cmd, &address);
41443+ if (unlikely(length <= 0)) {
41444+ if (length < 0) {
41445+ PRINT_ERROR("scst_get_buf_first() failed: %d", length);
41446+ scst_set_cmd_error(cmd,
41447+ SCST_LOAD_SENSE(scst_sense_hardw_error));
41448+ }
41449+ goto out_free;
41450+ }
41451+
41452+ if (0x3 == pcontrol) {
41453+ TRACE_DBG("%s", "MODE SENSE: Saving values not supported");
41454+ scst_set_cmd_error(cmd,
41455+ SCST_LOAD_SENSE(scst_sense_saving_params_unsup));
41456+ goto out_put;
41457+ }
41458+
41459+ if (msense_6) {
41460+ buf[1] = type;
41461+ buf[2] = dev_spec;
41462+ offset = 4;
41463+ } else {
41464+ buf[2] = type;
41465+ buf[3] = dev_spec;
41466+ offset = 8;
41467+ }
41468+
41469+ if (0 != subpcode) {
41470+ /* TODO: Control Extension page */
41471+ TRACE_DBG("%s", "MODE SENSE: Only subpage 0 is supported");
41472+ scst_set_cmd_error(cmd,
41473+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
41474+ goto out_put;
41475+ }
41476+
41477+ if (!dbd) {
41478+ /* Create block descriptor */
41479+ buf[offset - 1] = 0x08; /* block descriptor length */
41480+ if (nblocks >> 32) {
41481+ buf[offset + 0] = 0xFF;
41482+ buf[offset + 1] = 0xFF;
41483+ buf[offset + 2] = 0xFF;
41484+ buf[offset + 3] = 0xFF;
41485+ } else {
41486+ /* num blks */
41487+ buf[offset + 0] = (nblocks >> (BYTE * 3)) & 0xFF;
41488+ buf[offset + 1] = (nblocks >> (BYTE * 2)) & 0xFF;
41489+ buf[offset + 2] = (nblocks >> (BYTE * 1)) & 0xFF;
41490+ buf[offset + 3] = (nblocks >> (BYTE * 0)) & 0xFF;
41491+ }
41492+ buf[offset + 4] = 0; /* density code */
41493+ buf[offset + 5] = (blocksize >> (BYTE * 2)) & 0xFF;/* blklen */
41494+ buf[offset + 6] = (blocksize >> (BYTE * 1)) & 0xFF;
41495+ buf[offset + 7] = (blocksize >> (BYTE * 0)) & 0xFF;
41496+
41497+ offset += 8; /* increment offset */
41498+ }
41499+
41500+ bp = buf + offset;
41501+
41502+ switch (pcode) {
41503+ case 0x1: /* Read-Write error recovery page, direct access */
41504+ len = vdisk_err_recov_pg(bp, pcontrol, virt_dev);
41505+ break;
41506+ case 0x2: /* Disconnect-Reconnect page, all devices */
41507+ len = vdisk_disconnect_pg(bp, pcontrol, virt_dev);
41508+ break;
41509+ case 0x3: /* Format device page, direct access */
41510+ len = vdisk_format_pg(bp, pcontrol, virt_dev);
41511+ break;
41512+ case 0x4: /* Rigid disk geometry */
41513+ len = vdisk_rigid_geo_pg(bp, pcontrol, virt_dev);
41514+ break;
41515+ case 0x8: /* Caching page, direct access */
41516+ len = vdisk_caching_pg(bp, pcontrol, virt_dev);
41517+ break;
41518+ case 0xa: /* Control Mode page, all devices */
41519+ len = vdisk_ctrl_m_pg(bp, pcontrol, virt_dev);
41520+ break;
41521+ case 0x1c: /* Informational Exceptions Mode page, all devices */
41522+ len = vdisk_iec_m_pg(bp, pcontrol, virt_dev);
41523+ break;
41524+ case 0x3f: /* Read all Mode pages */
41525+ len = vdisk_err_recov_pg(bp, pcontrol, virt_dev);
41526+ len += vdisk_disconnect_pg(bp + len, pcontrol, virt_dev);
41527+ len += vdisk_format_pg(bp + len, pcontrol, virt_dev);
41528+ len += vdisk_caching_pg(bp + len, pcontrol, virt_dev);
41529+ len += vdisk_ctrl_m_pg(bp + len, pcontrol, virt_dev);
41530+ len += vdisk_iec_m_pg(bp + len, pcontrol, virt_dev);
41531+ len += vdisk_rigid_geo_pg(bp + len, pcontrol, virt_dev);
41532+ break;
41533+ default:
41534+ TRACE_DBG("MODE SENSE: Unsupported page %x", pcode);
41535+ scst_set_cmd_error(cmd,
41536+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
41537+ goto out_put;
41538+ }
41539+
41540+ offset += len;
41541+
41542+ if (msense_6)
41543+ buf[0] = offset - 1;
41544+ else {
41545+ buf[0] = ((offset - 2) >> 8) & 0xff;
41546+ buf[1] = (offset - 2) & 0xff;
41547+ }
41548+
41549+ if (offset > length)
41550+ offset = length;
41551+ memcpy(address, buf, offset);
41552+
41553+out_put:
41554+ scst_put_buf(cmd, address);
41555+ if (offset < cmd->resp_data_len)
41556+ scst_set_resp_data_len(cmd, offset);
41557+
41558+out_free:
41559+ kfree(buf);
41560+
41561+out:
41562+ TRACE_EXIT();
41563+ return;
41564+}
41565+
41566+static int vdisk_set_wt(struct scst_vdisk_dev *virt_dev, int wt)
41567+{
41568+ int res = 0;
41569+
41570+ TRACE_ENTRY();
41571+
41572+ if ((virt_dev->wt_flag == wt) || virt_dev->nullio || virt_dev->nv_cache)
41573+ goto out;
41574+
41575+ spin_lock(&virt_dev->flags_lock);
41576+ virt_dev->wt_flag = wt;
41577+ spin_unlock(&virt_dev->flags_lock);
41578+
41579+ scst_dev_del_all_thr_data(virt_dev->dev);
41580+
41581+out:
41582+ TRACE_EXIT_RES(res);
41583+ return res;
41584+}
41585+
41586+static void vdisk_ctrl_m_pg_select(unsigned char *p,
41587+ struct scst_vdisk_dev *virt_dev)
41588+{
41589+ struct scst_device *dev = virt_dev->dev;
41590+ int old_swp = dev->swp, old_tas = dev->tas, old_dsense = dev->d_sense;
41591+
41592+#if 0
41593+ /* Not implemented yet, see comment in vdisk_ctrl_m_pg() */
41594+ dev->tst = p[2] >> 5;
41595+ dev->queue_alg = p[3] >> 4;
41596+#endif
41597+ dev->swp = (p[4] & 0x8) >> 3;
41598+ dev->tas = (p[5] & 0x40) >> 6;
41599+ dev->d_sense = (p[2] & 0x4) >> 2;
41600+
41601+ PRINT_INFO("Device %s: new control mode page parameters: SWP %x "
41602+ "(was %x), TAS %x (was %x), D_SENSE %d (was %d)",
41603+ virt_dev->name, dev->swp, old_swp, dev->tas, old_tas,
41604+ dev->d_sense, old_dsense);
41605+ return;
41606+}
41607+
41608+static void vdisk_exec_mode_select(struct scst_cmd *cmd)
41609+{
41610+ int32_t length;
41611+ uint8_t *address;
41612+ struct scst_vdisk_dev *virt_dev;
41613+ int mselect_6, offset;
41614+
41615+ TRACE_ENTRY();
41616+
41617+ virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
41618+ mselect_6 = (MODE_SELECT == cmd->cdb[0]);
41619+
41620+ length = scst_get_buf_first(cmd, &address);
41621+ if (unlikely(length <= 0)) {
41622+ if (length < 0) {
41623+ PRINT_ERROR("scst_get_buf_first() failed: %d", length);
41624+ scst_set_cmd_error(cmd,
41625+ SCST_LOAD_SENSE(scst_sense_hardw_error));
41626+ }
41627+ goto out;
41628+ }
41629+
41630+ if (!(cmd->cdb[1] & PF) || (cmd->cdb[1] & SP)) {
41631+ TRACE(TRACE_MINOR|TRACE_SCSI, "MODE SELECT: Unsupported "
41632+ "value(s) of PF and/or SP bits (cdb[1]=%x)",
41633+ cmd->cdb[1]);
41634+ scst_set_cmd_error(cmd,
41635+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
41636+ goto out_put;
41637+ }
41638+
41639+ if (mselect_6)
41640+ offset = 4;
41641+ else
41642+ offset = 8;
41643+
41644+ if (address[offset - 1] == 8) {
41645+ offset += 8;
41646+ } else if (address[offset - 1] != 0) {
41647+ PRINT_ERROR("%s", "MODE SELECT: Wrong parameters list "
41648+ "lenght");
41649+ scst_set_cmd_error(cmd,
41650+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
41651+ goto out_put;
41652+ }
41653+
41654+ while (length > offset + 2) {
41655+ if (address[offset] & PS) {
41656+ PRINT_ERROR("%s", "MODE SELECT: Illegal PS bit");
41657+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
41658+ scst_sense_invalid_field_in_parm_list));
41659+ goto out_put;
41660+ }
41661+ if ((address[offset] & 0x3f) == 0x8) {
41662+ /* Caching page */
41663+ if (address[offset + 1] != 18) {
41664+ PRINT_ERROR("%s", "MODE SELECT: Invalid "
41665+ "caching page request");
41666+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
41667+ scst_sense_invalid_field_in_parm_list));
41668+ goto out_put;
41669+ }
41670+ if (vdisk_set_wt(virt_dev,
41671+ (address[offset + 2] & WCE) ? 0 : 1) != 0) {
41672+ scst_set_cmd_error(cmd,
41673+ SCST_LOAD_SENSE(scst_sense_hardw_error));
41674+ goto out_put;
41675+ }
41676+ break;
41677+ } else if ((address[offset] & 0x3f) == 0xA) {
41678+ /* Control page */
41679+ if (address[offset + 1] != 0xA) {
41680+ PRINT_ERROR("%s", "MODE SELECT: Invalid "
41681+ "control page request");
41682+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
41683+ scst_sense_invalid_field_in_parm_list));
41684+ goto out_put;
41685+ }
41686+ vdisk_ctrl_m_pg_select(&address[offset], virt_dev);
41687+ } else {
41688+ PRINT_ERROR("MODE SELECT: Invalid request %x",
41689+ address[offset] & 0x3f);
41690+ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
41691+ scst_sense_invalid_field_in_parm_list));
41692+ goto out_put;
41693+ }
41694+ offset += address[offset + 1];
41695+ }
41696+
41697+out_put:
41698+ scst_put_buf(cmd, address);
41699+
41700+out:
41701+ TRACE_EXIT();
41702+ return;
41703+}
41704+
41705+static void vdisk_exec_log(struct scst_cmd *cmd)
41706+{
41707+ TRACE_ENTRY();
41708+
41709+ /* No log pages are supported */
41710+ scst_set_cmd_error(cmd,
41711+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
41712+
41713+ TRACE_EXIT();
41714+ return;
41715+}
41716+
41717+static void vdisk_exec_read_capacity(struct scst_cmd *cmd)
41718+{
41719+ int32_t length;
41720+ uint8_t *address;
41721+ struct scst_vdisk_dev *virt_dev;
41722+ uint32_t blocksize;
41723+ uint64_t nblocks;
41724+ uint8_t buffer[8];
41725+
41726+ TRACE_ENTRY();
41727+
41728+ virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
41729+ blocksize = virt_dev->block_size;
41730+ nblocks = virt_dev->nblocks;
41731+
41732+ if ((cmd->cdb[8] & 1) == 0) {
41733+ uint64_t lba = be64_to_cpu(get_unaligned((__be64 *)&cmd->cdb[2]));
41734+ if (lba != 0) {
41735+ TRACE_DBG("PMI zero and LBA not zero (cmd %p)", cmd);
41736+ scst_set_cmd_error(cmd,
41737+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
41738+ goto out;
41739+ }
41740+ }
41741+
41742+ /* Last block on the virt_dev is (nblocks-1) */
41743+ memset(buffer, 0, sizeof(buffer));
41744+ if (nblocks >> 32) {
41745+ buffer[0] = 0xFF;
41746+ buffer[1] = 0xFF;
41747+ buffer[2] = 0xFF;
41748+ buffer[3] = 0xFF;
41749+ } else {
41750+ buffer[0] = ((nblocks - 1) >> (BYTE * 3)) & 0xFF;
41751+ buffer[1] = ((nblocks - 1) >> (BYTE * 2)) & 0xFF;
41752+ buffer[2] = ((nblocks - 1) >> (BYTE * 1)) & 0xFF;
41753+ buffer[3] = ((nblocks - 1) >> (BYTE * 0)) & 0xFF;
41754+ }
41755+ buffer[4] = (blocksize >> (BYTE * 3)) & 0xFF;
41756+ buffer[5] = (blocksize >> (BYTE * 2)) & 0xFF;
41757+ buffer[6] = (blocksize >> (BYTE * 1)) & 0xFF;
41758+ buffer[7] = (blocksize >> (BYTE * 0)) & 0xFF;
41759+
41760+ length = scst_get_buf_first(cmd, &address);
41761+ if (unlikely(length <= 0)) {
41762+ if (length < 0) {
41763+ PRINT_ERROR("scst_get_buf_first() failed: %d", length);
41764+ scst_set_cmd_error(cmd,
41765+ SCST_LOAD_SENSE(scst_sense_hardw_error));
41766+ }
41767+ goto out;
41768+ }
41769+
41770+ length = min_t(int, length, sizeof(buffer));
41771+
41772+ memcpy(address, buffer, length);
41773+
41774+ scst_put_buf(cmd, address);
41775+
41776+ if (length < cmd->resp_data_len)
41777+ scst_set_resp_data_len(cmd, length);
41778+
41779+out:
41780+ TRACE_EXIT();
41781+ return;
41782+}
41783+
41784+static void vdisk_exec_read_capacity16(struct scst_cmd *cmd)
41785+{
41786+ int32_t length;
41787+ uint8_t *address;
41788+ struct scst_vdisk_dev *virt_dev;
41789+ uint32_t blocksize;
41790+ uint64_t nblocks;
41791+ uint8_t buffer[32];
41792+
41793+ TRACE_ENTRY();
41794+
41795+ virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
41796+ blocksize = virt_dev->block_size;
41797+ nblocks = virt_dev->nblocks - 1;
41798+
41799+ if ((cmd->cdb[14] & 1) == 0) {
41800+ uint64_t lba = be64_to_cpu(get_unaligned((__be64 *)&cmd->cdb[2]));
41801+ if (lba != 0) {
41802+ TRACE_DBG("PMI zero and LBA not zero (cmd %p)", cmd);
41803+ scst_set_cmd_error(cmd,
41804+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
41805+ goto out;
41806+ }
41807+ }
41808+
41809+ memset(buffer, 0, sizeof(buffer));
41810+
41811+ buffer[0] = nblocks >> 56;
41812+ buffer[1] = (nblocks >> 48) & 0xFF;
41813+ buffer[2] = (nblocks >> 40) & 0xFF;
41814+ buffer[3] = (nblocks >> 32) & 0xFF;
41815+ buffer[4] = (nblocks >> 24) & 0xFF;
41816+ buffer[5] = (nblocks >> 16) & 0xFF;
41817+ buffer[6] = (nblocks >> 8) & 0xFF;
41818+ buffer[7] = nblocks & 0xFF;
41819+
41820+ buffer[8] = (blocksize >> (BYTE * 3)) & 0xFF;
41821+ buffer[9] = (blocksize >> (BYTE * 2)) & 0xFF;
41822+ buffer[10] = (blocksize >> (BYTE * 1)) & 0xFF;
41823+ buffer[11] = (blocksize >> (BYTE * 0)) & 0xFF;
41824+
41825+ switch (blocksize) {
41826+ case 512:
41827+ buffer[13] = 3;
41828+ break;
41829+ case 1024:
41830+ buffer[13] = 2;
41831+ break;
41832+ case 2048:
41833+ buffer[13] = 1;
41834+ break;
41835+ case 4096:
41836+ default:
41837+ buffer[13] = 0;
41838+ break;
41839+ }
41840+
41841+ length = scst_get_buf_first(cmd, &address);
41842+ if (unlikely(length <= 0)) {
41843+ if (length < 0) {
41844+ PRINT_ERROR("scst_get_buf_first() failed: %d", length);
41845+ scst_set_cmd_error(cmd,
41846+ SCST_LOAD_SENSE(scst_sense_hardw_error));
41847+ }
41848+ goto out;
41849+ }
41850+
41851+ length = min_t(int, length, sizeof(buffer));
41852+
41853+ memcpy(address, buffer, length);
41854+
41855+ scst_put_buf(cmd, address);
41856+
41857+ if (length < cmd->resp_data_len)
41858+ scst_set_resp_data_len(cmd, length);
41859+
41860+out:
41861+ TRACE_EXIT();
41862+ return;
41863+}
41864+
41865+static void vdisk_exec_read_toc(struct scst_cmd *cmd)
41866+{
41867+ int32_t length, off = 0;
41868+ uint8_t *address;
41869+ struct scst_vdisk_dev *virt_dev;
41870+ uint32_t nblocks;
41871+ uint8_t buffer[4+8+8] = { 0x00, 0x0a, 0x01, 0x01, 0x00, 0x14,
41872+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
41873+
41874+ TRACE_ENTRY();
41875+
41876+ if (cmd->dev->type != TYPE_ROM) {
41877+ PRINT_ERROR("%s", "READ TOC for non-CDROM device");
41878+ scst_set_cmd_error(cmd,
41879+ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
41880+ goto out;
41881+ }
41882+
41883+ if (cmd->cdb[2] & 0x0e/*Format*/) {
41884+ PRINT_ERROR("%s", "READ TOC: invalid requested data format");
41885+ scst_set_cmd_error(cmd,
41886+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
41887+ goto out;
41888+ }
41889+
41890+ if ((cmd->cdb[6] != 0 && (cmd->cdb[2] & 0x01)) ||
41891+ (cmd->cdb[6] > 1 && cmd->cdb[6] != 0xAA)) {
41892+ PRINT_ERROR("READ TOC: invalid requested track number %x",
41893+ cmd->cdb[6]);
41894+ scst_set_cmd_error(cmd,
41895+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
41896+ goto out;
41897+ }
41898+
41899+ length = scst_get_buf_first(cmd, &address);
41900+ if (unlikely(length <= 0)) {
41901+ if (length < 0) {
41902+ PRINT_ERROR("scst_get_buf_first() failed: %d", length);
41903+ scst_set_cmd_error(cmd,
41904+ SCST_LOAD_SENSE(scst_sense_hardw_error));
41905+ }
41906+ goto out;
41907+ }
41908+
41909+ virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
41910+ /* ToDo when you have > 8TB ROM device. */
41911+ nblocks = (uint32_t)virt_dev->nblocks;
41912+
41913+ /* Header */
41914+ memset(buffer, 0, sizeof(buffer));
41915+ buffer[2] = 0x01; /* First Track/Session */
41916+ buffer[3] = 0x01; /* Last Track/Session */
41917+ off = 4;
41918+ if (cmd->cdb[6] <= 1) {
41919+ /* Fistr TOC Track Descriptor */
41920+ /* ADDR 0x10 - Q Sub-channel encodes current position data
41921+ CONTROL 0x04 - Data track, recoreded uninterrupted */
41922+ buffer[off+1] = 0x14;
41923+ /* Track Number */
41924+ buffer[off+2] = 0x01;
41925+ off += 8;
41926+ }
41927+ if (!(cmd->cdb[2] & 0x01)) {
41928+ /* Lead-out area TOC Track Descriptor */
41929+ buffer[off+1] = 0x14;
41930+ /* Track Number */
41931+ buffer[off+2] = 0xAA;
41932+ /* Track Start Address */
41933+ buffer[off+4] = (nblocks >> (BYTE * 3)) & 0xFF;
41934+ buffer[off+5] = (nblocks >> (BYTE * 2)) & 0xFF;
41935+ buffer[off+6] = (nblocks >> (BYTE * 1)) & 0xFF;
41936+ buffer[off+7] = (nblocks >> (BYTE * 0)) & 0xFF;
41937+ off += 8;
41938+ }
41939+
41940+ buffer[1] = off - 2; /* Data Length */
41941+
41942+ if (off > length)
41943+ off = length;
41944+ memcpy(address, buffer, off);
41945+
41946+ scst_put_buf(cmd, address);
41947+
41948+ if (off < cmd->resp_data_len)
41949+ scst_set_resp_data_len(cmd, off);
41950+
41951+out:
41952+ TRACE_EXIT();
41953+ return;
41954+}
41955+
41956+static void vdisk_exec_prevent_allow_medium_removal(struct scst_cmd *cmd)
41957+{
41958+ struct scst_vdisk_dev *virt_dev =
41959+ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
41960+
41961+ TRACE_DBG("PERSIST/PREVENT 0x%02x", cmd->cdb[4]);
41962+
41963+ spin_lock(&virt_dev->flags_lock);
41964+ virt_dev->prevent_allow_medium_removal = cmd->cdb[4] & 0x01 ? 1 : 0;
41965+ spin_unlock(&virt_dev->flags_lock);
41966+
41967+ return;
41968+}
41969+
41970+static int vdisk_fsync(struct scst_vdisk_thr *thr, loff_t loff,
41971+ loff_t len, struct scst_cmd *cmd, struct scst_device *dev)
41972+{
41973+ int res = 0;
41974+ struct scst_vdisk_dev *virt_dev =
41975+ (struct scst_vdisk_dev *)dev->dh_priv;
41976+ struct file *file;
41977+
41978+ TRACE_ENTRY();
41979+
41980+ /* Hopefully, the compiler will generate the single comparison */
41981+ if (virt_dev->nv_cache || virt_dev->wt_flag ||
41982+ virt_dev->o_direct_flag || virt_dev->nullio)
41983+ goto out;
41984+
41985+ if (virt_dev->blockio) {
41986+ res = blockio_flush(thr->bdev);
41987+ goto out;
41988+ }
41989+
41990+ file = thr->fd;
41991+
41992+#if 0 /* For sparse files we might need to sync metadata as well */
41993+ res = generic_write_sync(file, loff, len);
41994+#else
41995+ res = filemap_write_and_wait_range(file->f_mapping, loff, len);
41996+#endif
41997+ if (unlikely(res != 0)) {
41998+ PRINT_ERROR("sync range failed (%d)", res);
41999+ if (cmd != NULL) {
42000+ scst_set_cmd_error(cmd,
42001+ SCST_LOAD_SENSE(scst_sense_write_error));
42002+ }
42003+ }
42004+
42005+out:
42006+ TRACE_EXIT_RES(res);
42007+ return res;
42008+}
42009+
42010+static struct iovec *vdisk_alloc_iv(struct scst_cmd *cmd,
42011+ struct scst_vdisk_thr *thr)
42012+{
42013+ int iv_count;
42014+
42015+ iv_count = min_t(int, scst_get_buf_count(cmd), UIO_MAXIOV);
42016+ if (iv_count > thr->iv_count) {
42017+ kfree(thr->iv);
42018+ /* It can't be called in atomic context */
42019+ thr->iv = kmalloc(sizeof(*thr->iv) * iv_count, GFP_KERNEL);
42020+ if (thr->iv == NULL) {
42021+ PRINT_ERROR("Unable to allocate iv (%d)", iv_count);
42022+ scst_set_busy(cmd);
42023+ goto out;
42024+ }
42025+ thr->iv_count = iv_count;
42026+ }
42027+
42028+out:
42029+ return thr->iv;
42030+}
42031+
42032+static void vdisk_exec_read(struct scst_cmd *cmd,
42033+ struct scst_vdisk_thr *thr, loff_t loff)
42034+{
42035+ mm_segment_t old_fs;
42036+ loff_t err;
42037+ ssize_t length, full_len;
42038+ uint8_t __user *address;
42039+ struct scst_vdisk_dev *virt_dev =
42040+ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
42041+ struct file *fd = thr->fd;
42042+ struct iovec *iv;
42043+ int iv_count, i;
42044+ bool finished = false;
42045+
42046+ TRACE_ENTRY();
42047+
42048+ if (virt_dev->nullio)
42049+ goto out;
42050+
42051+ iv = vdisk_alloc_iv(cmd, thr);
42052+ if (iv == NULL)
42053+ goto out;
42054+
42055+ length = scst_get_buf_first(cmd, (uint8_t __force **)&address);
42056+ if (unlikely(length < 0)) {
42057+ PRINT_ERROR("scst_get_buf_first() failed: %zd", length);
42058+ scst_set_cmd_error(cmd,
42059+ SCST_LOAD_SENSE(scst_sense_hardw_error));
42060+ goto out;
42061+ }
42062+
42063+ old_fs = get_fs();
42064+ set_fs(get_ds());
42065+
42066+ while (1) {
42067+ iv_count = 0;
42068+ full_len = 0;
42069+ i = -1;
42070+ while (length > 0) {
42071+ full_len += length;
42072+ i++;
42073+ iv_count++;
42074+ iv[i].iov_base = address;
42075+ iv[i].iov_len = length;
42076+ if (iv_count == UIO_MAXIOV)
42077+ break;
42078+ length = scst_get_buf_next(cmd,
42079+ (uint8_t __force **)&address);
42080+ }
42081+ if (length == 0) {
42082+ finished = true;
42083+ if (unlikely(iv_count == 0))
42084+ break;
42085+ } else if (unlikely(length < 0)) {
42086+ PRINT_ERROR("scst_get_buf_next() failed: %zd", length);
42087+ scst_set_cmd_error(cmd,
42088+ SCST_LOAD_SENSE(scst_sense_hardw_error));
42089+ goto out_set_fs;
42090+ }
42091+
42092+ TRACE_DBG("(iv_count %d, full_len %zd)", iv_count, full_len);
42093+ /* SEEK */
42094+ if (fd->f_op->llseek)
42095+ err = fd->f_op->llseek(fd, loff, 0/*SEEK_SET*/);
42096+ else
42097+ err = default_llseek(fd, loff, 0/*SEEK_SET*/);
42098+ if (err != loff) {
42099+ PRINT_ERROR("lseek trouble %lld != %lld",
42100+ (long long unsigned int)err,
42101+ (long long unsigned int)loff);
42102+ scst_set_cmd_error(cmd,
42103+ SCST_LOAD_SENSE(scst_sense_hardw_error));
42104+ goto out_set_fs;
42105+ }
42106+
42107+ /* READ */
42108+ err = vfs_readv(fd, (struct iovec __force __user *)iv, iv_count,
42109+ &fd->f_pos);
42110+
42111+ if ((err < 0) || (err < full_len)) {
42112+ PRINT_ERROR("readv() returned %lld from %zd",
42113+ (long long unsigned int)err,
42114+ full_len);
42115+ if (err == -EAGAIN)
42116+ scst_set_busy(cmd);
42117+ else {
42118+ scst_set_cmd_error(cmd,
42119+ SCST_LOAD_SENSE(scst_sense_read_error));
42120+ }
42121+ goto out_set_fs;
42122+ }
42123+
42124+ for (i = 0; i < iv_count; i++)
42125+ scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
42126+
42127+ if (finished)
42128+ break;
42129+
42130+ loff += full_len;
42131+ length = scst_get_buf_next(cmd, (uint8_t __force **)&address);
42132+ };
42133+
42134+ set_fs(old_fs);
42135+
42136+out:
42137+ TRACE_EXIT();
42138+ return;
42139+
42140+out_set_fs:
42141+ set_fs(old_fs);
42142+ for (i = 0; i < iv_count; i++)
42143+ scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
42144+ goto out;
42145+}
42146+
42147+static void vdisk_exec_write(struct scst_cmd *cmd,
42148+ struct scst_vdisk_thr *thr, loff_t loff)
42149+{
42150+ mm_segment_t old_fs;
42151+ loff_t err;
42152+ ssize_t length, full_len, saved_full_len;
42153+ uint8_t __user *address;
42154+ struct scst_vdisk_dev *virt_dev =
42155+ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
42156+ struct file *fd = thr->fd;
42157+ struct iovec *iv, *eiv;
42158+ int i, iv_count, eiv_count;
42159+ bool finished = false;
42160+
42161+ TRACE_ENTRY();
42162+
42163+ if (virt_dev->nullio)
42164+ goto out;
42165+
42166+ iv = vdisk_alloc_iv(cmd, thr);
42167+ if (iv == NULL)
42168+ goto out;
42169+
42170+ length = scst_get_buf_first(cmd, (uint8_t __force **)&address);
42171+ if (unlikely(length < 0)) {
42172+ PRINT_ERROR("scst_get_buf_first() failed: %zd", length);
42173+ scst_set_cmd_error(cmd,
42174+ SCST_LOAD_SENSE(scst_sense_hardw_error));
42175+ goto out;
42176+ }
42177+
42178+ old_fs = get_fs();
42179+ set_fs(get_ds());
42180+
42181+ while (1) {
42182+ iv_count = 0;
42183+ full_len = 0;
42184+ i = -1;
42185+ while (length > 0) {
42186+ full_len += length;
42187+ i++;
42188+ iv_count++;
42189+ iv[i].iov_base = address;
42190+ iv[i].iov_len = length;
42191+ if (iv_count == UIO_MAXIOV)
42192+ break;
42193+ length = scst_get_buf_next(cmd,
42194+ (uint8_t __force **)&address);
42195+ }
42196+ if (length == 0) {
42197+ finished = true;
42198+ if (unlikely(iv_count == 0))
42199+ break;
42200+ } else if (unlikely(length < 0)) {
42201+ PRINT_ERROR("scst_get_buf_next() failed: %zd", length);
42202+ scst_set_cmd_error(cmd,
42203+ SCST_LOAD_SENSE(scst_sense_hardw_error));
42204+ goto out_set_fs;
42205+ }
42206+
42207+ saved_full_len = full_len;
42208+ eiv = iv;
42209+ eiv_count = iv_count;
42210+restart:
42211+ TRACE_DBG("writing(eiv_count %d, full_len %zd)", eiv_count, full_len);
42212+
42213+ /* SEEK */
42214+ if (fd->f_op->llseek)
42215+ err = fd->f_op->llseek(fd, loff, 0 /*SEEK_SET */);
42216+ else
42217+ err = default_llseek(fd, loff, 0 /*SEEK_SET */);
42218+ if (err != loff) {
42219+ PRINT_ERROR("lseek trouble %lld != %lld",
42220+ (long long unsigned int)err,
42221+ (long long unsigned int)loff);
42222+ scst_set_cmd_error(cmd,
42223+ SCST_LOAD_SENSE(scst_sense_hardw_error));
42224+ goto out_set_fs;
42225+ }
42226+
42227+ /* WRITE */
42228+ err = vfs_writev(fd, (struct iovec __force __user *)eiv, eiv_count,
42229+ &fd->f_pos);
42230+
42231+ if (err < 0) {
42232+ PRINT_ERROR("write() returned %lld from %zd",
42233+ (long long unsigned int)err,
42234+ full_len);
42235+ if (err == -EAGAIN)
42236+ scst_set_busy(cmd);
42237+ else {
42238+ scst_set_cmd_error(cmd,
42239+ SCST_LOAD_SENSE(scst_sense_write_error));
42240+ }
42241+ goto out_set_fs;
42242+ } else if (err < full_len) {
42243+ /*
42244+ * Probably that's wrong, but sometimes write() returns
42245+ * value less, than requested. Let's restart.
42246+ */
42247+ int e = eiv_count;
42248+ TRACE_MGMT_DBG("write() returned %d from %zd "
42249+ "(iv_count=%d)", (int)err, full_len,
42250+ eiv_count);
42251+ if (err == 0) {
42252+ PRINT_INFO("Suspicious: write() returned 0 from "
42253+ "%zd (iv_count=%d)", full_len, eiv_count);
42254+ }
42255+ full_len -= err;
42256+ for (i = 0; i < e; i++) {
42257+ if ((long long)eiv->iov_len < err) {
42258+ err -= eiv->iov_len;
42259+ eiv++;
42260+ eiv_count--;
42261+ } else {
42262+ eiv->iov_base =
42263+ (uint8_t __force __user *)eiv->iov_base + err;
42264+ eiv->iov_len -= err;
42265+ break;
42266+ }
42267+ }
42268+ goto restart;
42269+ }
42270+
42271+ for (i = 0; i < iv_count; i++)
42272+ scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
42273+
42274+ if (finished)
42275+ break;
42276+
42277+ loff += saved_full_len;
42278+ length = scst_get_buf_next(cmd, (uint8_t __force **)&address);
42279+ }
42280+
42281+ set_fs(old_fs);
42282+
42283+out:
42284+ TRACE_EXIT();
42285+ return;
42286+
42287+out_set_fs:
42288+ set_fs(old_fs);
42289+ for (i = 0; i < iv_count; i++)
42290+ scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
42291+ goto out;
42292+}
42293+
42294+struct scst_blockio_work {
42295+ atomic_t bios_inflight;
42296+ struct scst_cmd *cmd;
42297+};
42298+
42299+static inline void blockio_check_finish(struct scst_blockio_work *blockio_work)
42300+{
42301+ /* Decrement the bios in processing, and if zero signal completion */
42302+ if (atomic_dec_and_test(&blockio_work->bios_inflight)) {
42303+ blockio_work->cmd->completed = 1;
42304+ blockio_work->cmd->scst_cmd_done(blockio_work->cmd,
42305+ SCST_CMD_STATE_DEFAULT, scst_estimate_context());
42306+ kmem_cache_free(blockio_work_cachep, blockio_work);
42307+ }
42308+ return;
42309+}
42310+
42311+static void blockio_endio(struct bio *bio, int error)
42312+{
42313+ struct scst_blockio_work *blockio_work = bio->bi_private;
42314+
42315+ if (unlikely(!bio_flagged(bio, BIO_UPTODATE))) {
42316+ if (error == 0) {
42317+ PRINT_ERROR("Not up to date bio with error 0 for "
42318+ "cmd %p, returning -EIO", blockio_work->cmd);
42319+ error = -EIO;
42320+ }
42321+ }
42322+
42323+ if (unlikely(error != 0)) {
42324+ static DEFINE_SPINLOCK(blockio_endio_lock);
42325+ unsigned long flags;
42326+
42327+ PRINT_ERROR("cmd %p returned error %d", blockio_work->cmd,
42328+ error);
42329+
42330+ /* To protect from several bios finishing simultaneously */
42331+ spin_lock_irqsave(&blockio_endio_lock, flags);
42332+
42333+ if (bio->bi_rw & (1 << BIO_RW))
42334+ scst_set_cmd_error(blockio_work->cmd,
42335+ SCST_LOAD_SENSE(scst_sense_write_error));
42336+ else
42337+ scst_set_cmd_error(blockio_work->cmd,
42338+ SCST_LOAD_SENSE(scst_sense_read_error));
42339+
42340+ spin_unlock_irqrestore(&blockio_endio_lock, flags);
42341+ }
42342+
42343+ blockio_check_finish(blockio_work);
42344+
42345+ bio_put(bio);
42346+ return;
42347+}
42348+
42349+static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
42350+ u64 lba_start, int write)
42351+{
42352+ struct scst_vdisk_dev *virt_dev =
42353+ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
42354+ struct block_device *bdev = thr->bdev;
42355+ struct request_queue *q = bdev_get_queue(bdev);
42356+ int length, max_nr_vecs = 0;
42357+ uint8_t *address;
42358+ struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
42359+ int need_new_bio;
42360+ struct scst_blockio_work *blockio_work;
42361+ int bios = 0;
42362+
42363+ TRACE_ENTRY();
42364+
42365+ if (virt_dev->nullio)
42366+ goto out;
42367+
42368+ /* Allocate and initialize blockio_work struct */
42369+ blockio_work = kmem_cache_alloc(blockio_work_cachep, GFP_KERNEL);
42370+ if (blockio_work == NULL)
42371+ goto out_no_mem;
42372+
42373+ blockio_work->cmd = cmd;
42374+
42375+ if (q)
42376+ max_nr_vecs = min(bio_get_nr_vecs(bdev), BIO_MAX_PAGES);
42377+ else
42378+ max_nr_vecs = 1;
42379+
42380+ need_new_bio = 1;
42381+
42382+ length = scst_get_buf_first(cmd, &address);
42383+ while (length > 0) {
42384+ int len, bytes, off, thislen;
42385+ uint8_t *addr;
42386+ u64 lba_start0;
42387+
42388+ addr = address;
42389+ off = offset_in_page(addr);
42390+ len = length;
42391+ thislen = 0;
42392+ lba_start0 = lba_start;
42393+
42394+ while (len > 0) {
42395+ int rc;
42396+ struct page *page = virt_to_page(addr);
42397+
42398+ if (need_new_bio) {
42399+ bio = bio_kmalloc(GFP_KERNEL, max_nr_vecs);
42400+ if (!bio) {
42401+ PRINT_ERROR("Failed to create bio "
42402+ "for data segment %d (cmd %p)",
42403+ cmd->get_sg_buf_entry_num, cmd);
42404+ goto out_no_bio;
42405+ }
42406+
42407+ bios++;
42408+ need_new_bio = 0;
42409+ bio->bi_end_io = blockio_endio;
42410+ bio->bi_sector = lba_start0 <<
42411+ (virt_dev->block_shift - 9);
42412+ bio->bi_bdev = bdev;
42413+ bio->bi_private = blockio_work;
42414+ /*
42415+ * Better to fail fast w/o any local recovery
42416+ * and retries.
42417+ */
42418+ bio->bi_rw |= (1 << BIO_RW_FAILFAST_DEV) |
42419+ (1 << BIO_RW_FAILFAST_TRANSPORT) |
42420+ (1 << BIO_RW_FAILFAST_DRIVER);
42421+#if 0 /* It could be win, but could be not, so a performance study is needed */
42422+ bio->bi_rw |= REQ_SYNC;
42423+#endif
42424+ if (!hbio)
42425+ hbio = tbio = bio;
42426+ else
42427+ tbio = tbio->bi_next = bio;
42428+ }
42429+
42430+ bytes = min_t(unsigned int, len, PAGE_SIZE - off);
42431+
42432+ rc = bio_add_page(bio, page, bytes, off);
42433+ if (rc < bytes) {
42434+ BUG_ON(rc != 0);
42435+ need_new_bio = 1;
42436+ lba_start0 += thislen >> virt_dev->block_shift;
42437+ thislen = 0;
42438+ continue;
42439+ }
42440+
42441+ addr += PAGE_SIZE;
42442+ thislen += bytes;
42443+ len -= bytes;
42444+ off = 0;
42445+ }
42446+
42447+ lba_start += length >> virt_dev->block_shift;
42448+
42449+ scst_put_buf(cmd, address);
42450+ length = scst_get_buf_next(cmd, &address);
42451+ }
42452+
42453+ /* +1 to prevent erroneous too early command completion */
42454+ atomic_set(&blockio_work->bios_inflight, bios+1);
42455+
42456+ while (hbio) {
42457+ bio = hbio;
42458+ hbio = hbio->bi_next;
42459+ bio->bi_next = NULL;
42460+ submit_bio((write != 0), bio);
42461+ }
42462+
42463+ if (q && q->unplug_fn)
42464+ q->unplug_fn(q);
42465+
42466+ blockio_check_finish(blockio_work);
42467+
42468+out:
42469+ TRACE_EXIT();
42470+ return;
42471+
42472+out_no_bio:
42473+ while (hbio) {
42474+ bio = hbio;
42475+ hbio = hbio->bi_next;
42476+ bio_put(bio);
42477+ }
42478+ kmem_cache_free(blockio_work_cachep, blockio_work);
42479+
42480+out_no_mem:
42481+ scst_set_busy(cmd);
42482+ goto out;
42483+}
42484+
42485+static int blockio_flush(struct block_device *bdev)
42486+{
42487+ int res = 0;
42488+
42489+ TRACE_ENTRY();
42490+
42491+ res = blkdev_issue_flush(bdev, GFP_KERNEL, NULL, BLKDEV_IFL_WAIT);
42492+ if (res != 0)
42493+ PRINT_ERROR("blkdev_issue_flush() failed: %d", res);
42494+
42495+ TRACE_EXIT_RES(res);
42496+ return res;
42497+}
42498+
42499+static void vdisk_exec_verify(struct scst_cmd *cmd,
42500+ struct scst_vdisk_thr *thr, loff_t loff)
42501+{
42502+ mm_segment_t old_fs;
42503+ loff_t err;
42504+ ssize_t length, len_mem = 0;
42505+ uint8_t *address_sav, *address;
42506+ int compare;
42507+ struct scst_vdisk_dev *virt_dev =
42508+ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
42509+ struct file *fd = thr->fd;
42510+ uint8_t *mem_verify = NULL;
42511+
42512+ TRACE_ENTRY();
42513+
42514+ if (vdisk_fsync(thr, loff, cmd->bufflen, cmd, cmd->dev) != 0)
42515+ goto out;
42516+
42517+ /*
42518+ * Until the cache is cleared prior the verifying, there is not
42519+ * much point in this code. ToDo.
42520+ *
42521+ * Nevertherless, this code is valuable if the data have not read
42522+ * from the file/disk yet.
42523+ */
42524+
42525+ /* SEEK */
42526+ old_fs = get_fs();
42527+ set_fs(get_ds());
42528+
42529+ if (!virt_dev->nullio) {
42530+ if (fd->f_op->llseek)
42531+ err = fd->f_op->llseek(fd, loff, 0/*SEEK_SET*/);
42532+ else
42533+ err = default_llseek(fd, loff, 0/*SEEK_SET*/);
42534+ if (err != loff) {
42535+ PRINT_ERROR("lseek trouble %lld != %lld",
42536+ (long long unsigned int)err,
42537+ (long long unsigned int)loff);
42538+ scst_set_cmd_error(cmd,
42539+ SCST_LOAD_SENSE(scst_sense_hardw_error));
42540+ goto out_set_fs;
42541+ }
42542+ }
42543+
42544+ mem_verify = vmalloc(LEN_MEM);
42545+ if (mem_verify == NULL) {
42546+ PRINT_ERROR("Unable to allocate memory %d for verify",
42547+ LEN_MEM);
42548+ scst_set_cmd_error(cmd,
42549+ SCST_LOAD_SENSE(scst_sense_hardw_error));
42550+ goto out_set_fs;
42551+ }
42552+
42553+ length = scst_get_buf_first(cmd, &address);
42554+ address_sav = address;
42555+ if (!length && cmd->data_len) {
42556+ length = cmd->data_len;
42557+ compare = 0;
42558+ } else
42559+ compare = 1;
42560+
42561+ while (length > 0) {
42562+ len_mem = (length > LEN_MEM) ? LEN_MEM : length;
42563+ TRACE_DBG("Verify: length %zd - len_mem %zd", length, len_mem);
42564+
42565+ if (!virt_dev->nullio)
42566+ err = vfs_read(fd, (char __force __user *)mem_verify,
42567+ len_mem, &fd->f_pos);
42568+ else
42569+ err = len_mem;
42570+ if ((err < 0) || (err < len_mem)) {
42571+ PRINT_ERROR("verify() returned %lld from %zd",
42572+ (long long unsigned int)err, len_mem);
42573+ if (err == -EAGAIN)
42574+ scst_set_busy(cmd);
42575+ else {
42576+ scst_set_cmd_error(cmd,
42577+ SCST_LOAD_SENSE(scst_sense_read_error));
42578+ }
42579+ if (compare)
42580+ scst_put_buf(cmd, address_sav);
42581+ goto out_set_fs;
42582+ }
42583+ if (compare && memcmp(address, mem_verify, len_mem) != 0) {
42584+ TRACE_DBG("Verify: error memcmp length %zd", length);
42585+ scst_set_cmd_error(cmd,
42586+ SCST_LOAD_SENSE(scst_sense_miscompare_error));
42587+ scst_put_buf(cmd, address_sav);
42588+ goto out_set_fs;
42589+ }
42590+ length -= len_mem;
42591+ address += len_mem;
42592+ if (compare && length <= 0) {
42593+ scst_put_buf(cmd, address_sav);
42594+ length = scst_get_buf_next(cmd, &address);
42595+ address_sav = address;
42596+ }
42597+ }
42598+
42599+ if (length < 0) {
42600+ PRINT_ERROR("scst_get_buf_() failed: %zd", length);
42601+ scst_set_cmd_error(cmd,
42602+ SCST_LOAD_SENSE(scst_sense_hardw_error));
42603+ }
42604+
42605+out_set_fs:
42606+ set_fs(old_fs);
42607+ if (mem_verify)
42608+ vfree(mem_verify);
42609+
42610+out:
42611+ TRACE_EXIT();
42612+ return;
42613+}
42614+
42615+static int vdisk_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
42616+ struct scst_tgt_dev *tgt_dev)
42617+{
42618+ TRACE_ENTRY();
42619+
42620+ if ((mcmd->fn == SCST_LUN_RESET) || (mcmd->fn == SCST_TARGET_RESET)) {
42621+ /* Restore default values */
42622+ struct scst_device *dev = tgt_dev->dev;
42623+ struct scst_vdisk_dev *virt_dev =
42624+ (struct scst_vdisk_dev *)dev->dh_priv;
42625+
42626+ dev->tst = DEF_TST;
42627+ dev->d_sense = DEF_DSENSE;
42628+ if (virt_dev->wt_flag && !virt_dev->nv_cache)
42629+ dev->queue_alg = DEF_QUEUE_ALG_WT;
42630+ else
42631+ dev->queue_alg = DEF_QUEUE_ALG;
42632+ dev->swp = DEF_SWP;
42633+ dev->tas = DEF_TAS;
42634+
42635+ spin_lock(&virt_dev->flags_lock);
42636+ virt_dev->prevent_allow_medium_removal = 0;
42637+ spin_unlock(&virt_dev->flags_lock);
42638+ } else if (mcmd->fn == SCST_PR_ABORT_ALL) {
42639+ struct scst_device *dev = tgt_dev->dev;
42640+ struct scst_vdisk_dev *virt_dev =
42641+ (struct scst_vdisk_dev *)dev->dh_priv;
42642+ spin_lock(&virt_dev->flags_lock);
42643+ virt_dev->prevent_allow_medium_removal = 0;
42644+ spin_unlock(&virt_dev->flags_lock);
42645+ }
42646+
42647+ TRACE_EXIT();
42648+ return SCST_DEV_TM_NOT_COMPLETED;
42649+}
42650+
42651+static void vdisk_report_registering(const struct scst_vdisk_dev *virt_dev)
42652+{
42653+ char buf[128];
42654+ int i, j;
42655+
42656+ i = snprintf(buf, sizeof(buf), "Registering virtual %s device %s ",
42657+ virt_dev->vdev_devt->name, virt_dev->name);
42658+ j = i;
42659+
42660+ if (virt_dev->wt_flag)
42661+ i += snprintf(&buf[i], sizeof(buf) - i, "(WRITE_THROUGH");
42662+
42663+ if (virt_dev->nv_cache)
42664+ i += snprintf(&buf[i], sizeof(buf) - i, "%sNV_CACHE",
42665+ (j == i) ? "(" : ", ");
42666+
42667+ if (virt_dev->rd_only)
42668+ i += snprintf(&buf[i], sizeof(buf) - i, "%sREAD_ONLY",
42669+ (j == i) ? "(" : ", ");
42670+
42671+ if (virt_dev->o_direct_flag)
42672+ i += snprintf(&buf[i], sizeof(buf) - i, "%sO_DIRECT",
42673+ (j == i) ? "(" : ", ");
42674+
42675+ if (virt_dev->nullio)
42676+ i += snprintf(&buf[i], sizeof(buf) - i, "%sNULLIO",
42677+ (j == i) ? "(" : ", ");
42678+
42679+ if (virt_dev->blockio)
42680+ i += snprintf(&buf[i], sizeof(buf) - i, "%sBLOCKIO",
42681+ (j == i) ? "(" : ", ");
42682+
42683+ if (virt_dev->removable)
42684+ i += snprintf(&buf[i], sizeof(buf) - i, "%sREMOVABLE",
42685+ (j == i) ? "(" : ", ");
42686+
42687+ if (j == i)
42688+ PRINT_INFO("%s", buf);
42689+ else
42690+ PRINT_INFO("%s)", buf);
42691+
42692+ return;
42693+}
42694+
42695+static int vdisk_resync_size(struct scst_vdisk_dev *virt_dev)
42696+{
42697+ loff_t file_size;
42698+ int res = 0;
42699+
42700+ BUG_ON(virt_dev->nullio);
42701+
42702+ res = vdisk_get_file_size(virt_dev->filename,
42703+ virt_dev->blockio, &file_size);
42704+ if (res != 0)
42705+ goto out;
42706+
42707+ if (file_size == virt_dev->file_size) {
42708+ PRINT_INFO("Size of virtual disk %s remained the same",
42709+ virt_dev->name);
42710+ goto out;
42711+ }
42712+
42713+ res = scst_suspend_activity(true);
42714+ if (res != 0)
42715+ goto out;
42716+
42717+ virt_dev->file_size = file_size;
42718+ virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift;
42719+
42720+ scst_dev_del_all_thr_data(virt_dev->dev);
42721+
42722+ PRINT_INFO("New size of SCSI target virtual disk %s "
42723+ "(fs=%lldMB, bs=%d, nblocks=%lld, cyln=%lld%s)",
42724+ virt_dev->name, virt_dev->file_size >> 20,
42725+ virt_dev->block_size,
42726+ (long long unsigned int)virt_dev->nblocks,
42727+ (long long unsigned int)virt_dev->nblocks/64/32,
42728+ virt_dev->nblocks < 64*32 ? " !WARNING! cyln less "
42729+ "than 1" : "");
42730+
42731+ scst_capacity_data_changed(virt_dev->dev);
42732+
42733+ scst_resume_activity();
42734+
42735+out:
42736+ return res;
42737+}
42738+
42739+static int vdev_create(struct scst_dev_type *devt,
42740+ const char *name, struct scst_vdisk_dev **res_virt_dev)
42741+{
42742+ int res = 0;
42743+ struct scst_vdisk_dev *virt_dev;
42744+ uint64_t dev_id_num;
42745+ int dev_id_len;
42746+ char dev_id_str[17];
42747+ int32_t i;
42748+
42749+ virt_dev = kzalloc(sizeof(*virt_dev), GFP_KERNEL);
42750+ if (virt_dev == NULL) {
42751+ PRINT_ERROR("Allocation of virtual device %s failed",
42752+ devt->name);
42753+ res = -ENOMEM;
42754+ goto out;
42755+ }
42756+
42757+ spin_lock_init(&virt_dev->flags_lock);
42758+ virt_dev->vdev_devt = devt;
42759+
42760+ virt_dev->rd_only = DEF_RD_ONLY;
42761+ virt_dev->removable = DEF_REMOVABLE;
42762+
42763+ virt_dev->block_size = DEF_DISK_BLOCKSIZE;
42764+ virt_dev->block_shift = DEF_DISK_BLOCKSIZE_SHIFT;
42765+
42766+ if (strlen(name) >= sizeof(virt_dev->name)) {
42767+ PRINT_ERROR("Name %s is too long (max allowed %zd)", name,
42768+ sizeof(virt_dev->name)-1);
42769+ res = -EINVAL;
42770+ goto out_free;
42771+ }
42772+ strcpy(virt_dev->name, name);
42773+
42774+ dev_id_num = vdisk_gen_dev_id_num(virt_dev->name);
42775+ dev_id_len = scnprintf(dev_id_str, sizeof(dev_id_str), "%llx",
42776+ dev_id_num);
42777+
42778+ i = strlen(virt_dev->name) + 1; /* for ' ' */
42779+ memset(virt_dev->t10_dev_id, ' ', i + dev_id_len);
42780+ memcpy(virt_dev->t10_dev_id, virt_dev->name, i-1);
42781+ memcpy(virt_dev->t10_dev_id + i, dev_id_str, dev_id_len);
42782+ TRACE_DBG("t10_dev_id %s", virt_dev->t10_dev_id);
42783+
42784+ scnprintf(virt_dev->usn, sizeof(virt_dev->usn), "%llx", dev_id_num);
42785+ TRACE_DBG("usn %s", virt_dev->usn);
42786+
42787+ *res_virt_dev = virt_dev;
42788+
42789+out:
42790+ return res;
42791+
42792+out_free:
42793+ kfree(virt_dev);
42794+ goto out;
42795+}
42796+
42797+static void vdev_destroy(struct scst_vdisk_dev *virt_dev)
42798+{
42799+ kfree(virt_dev->filename);
42800+ kfree(virt_dev);
42801+ return;
42802+}
42803+
42804+/* scst_vdisk_mutex supposed to be held */
42805+static struct scst_vdisk_dev *vdev_find(const char *name)
42806+{
42807+ struct scst_vdisk_dev *res, *vv;
42808+
42809+ TRACE_ENTRY();
42810+
42811+ res = NULL;
42812+ list_for_each_entry(vv, &vdev_list, vdev_list_entry) {
42813+ if (strcmp(vv->name, name) == 0) {
42814+ res = vv;
42815+ break;
42816+ }
42817+ }
42818+
42819+ TRACE_EXIT_HRES((unsigned long)res);
42820+ return res;
42821+}
42822+
42823+static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev,
42824+ char *params, const char *allowed_params[])
42825+{
42826+ int res = 0;
42827+ unsigned long val;
42828+ char *param, *p, *pp;
42829+
42830+ TRACE_ENTRY();
42831+
42832+ while (1) {
42833+ param = scst_get_next_token_str(&params);
42834+ if (param == NULL)
42835+ break;
42836+
42837+ p = scst_get_next_lexem(&param);
42838+ if (*p == '\0') {
42839+ PRINT_ERROR("Syntax error at %s (device %s)",
42840+ param, virt_dev->name);
42841+ res = -EINVAL;
42842+ goto out;
42843+ }
42844+
42845+ if (allowed_params != NULL) {
42846+ const char **a = allowed_params;
42847+ bool allowed = false;
42848+
42849+ while (*a != NULL) {
42850+ if (!strcasecmp(*a, p)) {
42851+ allowed = true;
42852+ break;
42853+ }
42854+ a++;
42855+ }
42856+
42857+ if (!allowed) {
42858+ PRINT_ERROR("Unknown parameter %s (device %s)", p,
42859+ virt_dev->name);
42860+ res = -EINVAL;
42861+ goto out;
42862+ }
42863+ }
42864+
42865+ pp = scst_get_next_lexem(&param);
42866+ if (*pp == '\0') {
42867+ PRINT_ERROR("Parameter %s value missed for device %s",
42868+ p, virt_dev->name);
42869+ res = -EINVAL;
42870+ goto out;
42871+ }
42872+
42873+ if (scst_get_next_lexem(&param)[0] != '\0') {
42874+ PRINT_ERROR("Too many parameter's %s values (device %s)",
42875+ p, virt_dev->name);
42876+ res = -EINVAL;
42877+ goto out;
42878+ }
42879+
42880+ if (!strcasecmp("filename", p)) {
42881+ if (*pp != '/') {
42882+ PRINT_ERROR("Filename %s must be global "
42883+ "(device %s)", pp, virt_dev->name);
42884+ res = -EINVAL;
42885+ goto out;
42886+ }
42887+
42888+ virt_dev->filename = kstrdup(pp, GFP_KERNEL);
42889+ if (virt_dev->filename == NULL) {
42890+ PRINT_ERROR("Unable to duplicate file name %s "
42891+ "(device %s)", pp, virt_dev->name);
42892+ res = -ENOMEM;
42893+ goto out;
42894+ }
42895+ continue;
42896+ }
42897+
42898+ res = strict_strtoul(pp, 0, &val);
42899+ if (res != 0) {
42900+ PRINT_ERROR("strict_strtoul() for %s failed: %d "
42901+ "(device %s)", pp, res, virt_dev->name);
42902+ goto out;
42903+ }
42904+
42905+ if (!strcasecmp("write_through", p)) {
42906+ virt_dev->wt_flag = val;
42907+ TRACE_DBG("WRITE THROUGH %d", virt_dev->wt_flag);
42908+ } else if (!strcasecmp("nv_cache", p)) {
42909+ virt_dev->nv_cache = val;
42910+ TRACE_DBG("NON-VOLATILE CACHE %d", virt_dev->nv_cache);
42911+ } else if (!strcasecmp("o_direct", p)) {
42912+#if 0
42913+ virt_dev->o_direct_flag = val;
42914+ TRACE_DBG("O_DIRECT %d", virt_dev->o_direct_flag);
42915+#else
42916+ PRINT_INFO("O_DIRECT flag doesn't currently"
42917+ " work, ignoring it, use fileio_tgt "
42918+ "in O_DIRECT mode instead (device %s)", virt_dev->name);
42919+#endif
42920+ } else if (!strcasecmp("read_only", p)) {
42921+ virt_dev->rd_only = val;
42922+ TRACE_DBG("READ ONLY %d", virt_dev->rd_only);
42923+ } else if (!strcasecmp("removable", p)) {
42924+ virt_dev->removable = val;
42925+ TRACE_DBG("REMOVABLE %d", virt_dev->removable);
42926+ } else if (!strcasecmp("blocksize", p)) {
42927+ virt_dev->block_size = val;
42928+ virt_dev->block_shift = scst_calc_block_shift(
42929+ virt_dev->block_size);
42930+ if (virt_dev->block_shift < 9) {
42931+ res = -EINVAL;
42932+ goto out;
42933+ }
42934+ TRACE_DBG("block_size %d, block_shift %d",
42935+ virt_dev->block_size,
42936+ virt_dev->block_shift);
42937+ } else {
42938+ PRINT_ERROR("Unknown parameter %s (device %s)", p,
42939+ virt_dev->name);
42940+ res = -EINVAL;
42941+ goto out;
42942+ }
42943+ }
42944+
42945+out:
42946+ TRACE_EXIT_RES(res);
42947+ return res;
42948+}
42949+
42950+/* scst_vdisk_mutex supposed to be held */
42951+static int vdev_fileio_add_device(const char *device_name, char *params)
42952+{
42953+ int res = 0;
42954+ struct scst_vdisk_dev *virt_dev;
42955+
42956+ TRACE_ENTRY();
42957+
42958+ res = vdev_create(&vdisk_file_devtype, device_name, &virt_dev);
42959+ if (res != 0)
42960+ goto out;
42961+
42962+ virt_dev->command_set_version = 0x04C0; /* SBC-3 */
42963+
42964+ virt_dev->wt_flag = DEF_WRITE_THROUGH;
42965+ virt_dev->nv_cache = DEF_NV_CACHE;
42966+ virt_dev->o_direct_flag = DEF_O_DIRECT;
42967+
42968+ res = vdev_parse_add_dev_params(virt_dev, params, NULL);
42969+ if (res != 0)
42970+ goto out_destroy;
42971+
42972+ if (virt_dev->rd_only && (virt_dev->wt_flag || virt_dev->nv_cache)) {
42973+ PRINT_ERROR("Write options on read only device %s",
42974+ virt_dev->name);
42975+ res = -EINVAL;
42976+ goto out_destroy;
42977+ }
42978+
42979+ if (virt_dev->filename == NULL) {
42980+ PRINT_ERROR("File name required (device %s)", virt_dev->name);
42981+ res = -EINVAL;
42982+ goto out_destroy;
42983+ }
42984+
42985+ list_add_tail(&virt_dev->vdev_list_entry, &vdev_list);
42986+
42987+ vdisk_report_registering(virt_dev);
42988+
42989+ virt_dev->virt_id = scst_register_virtual_device(virt_dev->vdev_devt,
42990+ virt_dev->name);
42991+ if (virt_dev->virt_id < 0) {
42992+ res = virt_dev->virt_id;
42993+ goto out_del;
42994+ }
42995+
42996+ TRACE_DBG("Registered virt_dev %s with id %d", virt_dev->name,
42997+ virt_dev->virt_id);
42998+
42999+out:
43000+ TRACE_EXIT_RES(res);
43001+ return res;
43002+
43003+out_del:
43004+ list_del(&virt_dev->vdev_list_entry);
43005+
43006+out_destroy:
43007+ vdev_destroy(virt_dev);
43008+ goto out;
43009+}
43010+
43011+/* scst_vdisk_mutex supposed to be held */
43012+static int vdev_blockio_add_device(const char *device_name, char *params)
43013+{
43014+ int res = 0;
43015+ const char *allowed_params[] = { "filename", "read_only", "removable",
43016+ "blocksize", "nv_cache", NULL };
43017+ struct scst_vdisk_dev *virt_dev;
43018+
43019+ TRACE_ENTRY();
43020+
43021+ res = vdev_create(&vdisk_blk_devtype, device_name, &virt_dev);
43022+ if (res != 0)
43023+ goto out;
43024+
43025+ virt_dev->command_set_version = 0x04C0; /* SBC-3 */
43026+
43027+ virt_dev->blockio = 1;
43028+
43029+ res = vdev_parse_add_dev_params(virt_dev, params, allowed_params);
43030+ if (res != 0)
43031+ goto out_destroy;
43032+
43033+ if (virt_dev->filename == NULL) {
43034+ PRINT_ERROR("File name required (device %s)", virt_dev->name);
43035+ res = -EINVAL;
43036+ goto out_destroy;
43037+ }
43038+
43039+ list_add_tail(&virt_dev->vdev_list_entry, &vdev_list);
43040+
43041+ vdisk_report_registering(virt_dev);
43042+
43043+ virt_dev->virt_id = scst_register_virtual_device(virt_dev->vdev_devt,
43044+ virt_dev->name);
43045+ if (virt_dev->virt_id < 0) {
43046+ res = virt_dev->virt_id;
43047+ goto out_del;
43048+ }
43049+
43050+ TRACE_DBG("Registered virt_dev %s with id %d", virt_dev->name,
43051+ virt_dev->virt_id);
43052+
43053+out:
43054+ TRACE_EXIT_RES(res);
43055+ return res;
43056+
43057+out_del:
43058+ list_del(&virt_dev->vdev_list_entry);
43059+
43060+out_destroy:
43061+ vdev_destroy(virt_dev);
43062+ goto out;
43063+}
43064+
43065+/* scst_vdisk_mutex supposed to be held */
43066+static int vdev_nullio_add_device(const char *device_name, char *params)
43067+{
43068+ int res = 0;
43069+ const char *allowed_params[] = { "read_only", "removable",
43070+ "blocksize", NULL };
43071+ struct scst_vdisk_dev *virt_dev;
43072+
43073+ TRACE_ENTRY();
43074+
43075+ res = vdev_create(&vdisk_null_devtype, device_name, &virt_dev);
43076+ if (res != 0)
43077+ goto out;
43078+
43079+ virt_dev->command_set_version = 0x04C0; /* SBC-3 */
43080+
43081+ virt_dev->nullio = 1;
43082+
43083+ res = vdev_parse_add_dev_params(virt_dev, params, allowed_params);
43084+ if (res != 0)
43085+ goto out_destroy;
43086+
43087+ list_add_tail(&virt_dev->vdev_list_entry, &vdev_list);
43088+
43089+ vdisk_report_registering(virt_dev);
43090+
43091+ virt_dev->virt_id = scst_register_virtual_device(virt_dev->vdev_devt,
43092+ virt_dev->name);
43093+ if (virt_dev->virt_id < 0) {
43094+ res = virt_dev->virt_id;
43095+ goto out_del;
43096+ }
43097+
43098+ TRACE_DBG("Registered virt_dev %s with id %d", virt_dev->name,
43099+ virt_dev->virt_id);
43100+
43101+out:
43102+ TRACE_EXIT_RES(res);
43103+ return res;
43104+
43105+out_del:
43106+ list_del(&virt_dev->vdev_list_entry);
43107+
43108+out_destroy:
43109+ vdev_destroy(virt_dev);
43110+ goto out;
43111+}
43112+
43113+static ssize_t vdisk_add_fileio_device(const char *device_name, char *params)
43114+{
43115+ int res;
43116+
43117+ TRACE_ENTRY();
43118+
43119+ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
43120+ res = -EINTR;
43121+ goto out;
43122+ }
43123+
43124+ res = vdev_fileio_add_device(device_name, params);
43125+
43126+ mutex_unlock(&scst_vdisk_mutex);
43127+
43128+out:
43129+ TRACE_EXIT_RES(res);
43130+ return res;
43131+}
43132+
43133+static ssize_t vdisk_add_blockio_device(const char *device_name, char *params)
43134+{
43135+ int res;
43136+
43137+ TRACE_ENTRY();
43138+
43139+ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
43140+ res = -EINTR;
43141+ goto out;
43142+ }
43143+
43144+ res = vdev_blockio_add_device(device_name, params);
43145+
43146+ mutex_unlock(&scst_vdisk_mutex);
43147+
43148+out:
43149+ TRACE_EXIT_RES(res);
43150+ return res;
43151+
43152+}
43153+
43154+static ssize_t vdisk_add_nullio_device(const char *device_name, char *params)
43155+{
43156+ int res;
43157+
43158+ TRACE_ENTRY();
43159+
43160+ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
43161+ res = -EINTR;
43162+ goto out;
43163+ }
43164+
43165+ res = vdev_nullio_add_device(device_name, params);
43166+
43167+ mutex_unlock(&scst_vdisk_mutex);
43168+
43169+out:
43170+ TRACE_EXIT_RES(res);
43171+ return res;
43172+
43173+}
43174+
43175+/* scst_vdisk_mutex supposed to be held */
43176+static void vdev_del_device(struct scst_vdisk_dev *virt_dev)
43177+{
43178+ TRACE_ENTRY();
43179+
43180+ scst_unregister_virtual_device(virt_dev->virt_id);
43181+
43182+ list_del(&virt_dev->vdev_list_entry);
43183+
43184+ PRINT_INFO("Virtual device %s unregistered", virt_dev->name);
43185+ TRACE_DBG("virt_id %d unregistered", virt_dev->virt_id);
43186+
43187+ vdev_destroy(virt_dev);
43188+
43189+ return;
43190+}
43191+
43192+static ssize_t vdisk_del_device(const char *device_name)
43193+{
43194+ int res = 0;
43195+ struct scst_vdisk_dev *virt_dev;
43196+
43197+ TRACE_ENTRY();
43198+
43199+ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
43200+ res = -EINTR;
43201+ goto out;
43202+ }
43203+
43204+ virt_dev = vdev_find(device_name);
43205+ if (virt_dev == NULL) {
43206+ PRINT_ERROR("Device %s not found", device_name);
43207+ res = -EINVAL;
43208+ goto out_unlock;
43209+ }
43210+
43211+ vdev_del_device(virt_dev);
43212+
43213+out_unlock:
43214+ mutex_unlock(&scst_vdisk_mutex);
43215+
43216+out:
43217+ TRACE_EXIT_RES(res);
43218+ return res;
43219+}
43220+
43221+/* scst_vdisk_mutex supposed to be held */
43222+static ssize_t __vcdrom_add_device(const char *device_name, char *params)
43223+{
43224+ int res = 0;
43225+ const char *allowed_params[] = { NULL }; /* no params */
43226+ struct scst_vdisk_dev *virt_dev;
43227+
43228+ TRACE_ENTRY();
43229+
43230+ res = vdev_create(&vcdrom_devtype, device_name, &virt_dev);
43231+ if (res != 0)
43232+ goto out;
43233+
43234+ virt_dev->command_set_version = 0x02A0; /* MMC-3 */
43235+
43236+ virt_dev->rd_only = 1;
43237+ virt_dev->removable = 1;
43238+ virt_dev->cdrom_empty = 1;
43239+
43240+ virt_dev->block_size = DEF_CDROM_BLOCKSIZE;
43241+ virt_dev->block_shift = DEF_CDROM_BLOCKSIZE_SHIFT;
43242+
43243+ res = vdev_parse_add_dev_params(virt_dev, params, allowed_params);
43244+ if (res != 0)
43245+ goto out_destroy;
43246+
43247+ list_add_tail(&virt_dev->vdev_list_entry, &vdev_list);
43248+
43249+ vdisk_report_registering(virt_dev);
43250+
43251+ virt_dev->virt_id = scst_register_virtual_device(virt_dev->vdev_devt,
43252+ virt_dev->name);
43253+ if (virt_dev->virt_id < 0) {
43254+ res = virt_dev->virt_id;
43255+ goto out_del;
43256+ }
43257+
43258+ TRACE_DBG("Registered virt_dev %s with id %d", virt_dev->name,
43259+ virt_dev->virt_id);
43260+
43261+out:
43262+ TRACE_EXIT_RES(res);
43263+ return res;
43264+
43265+out_del:
43266+ list_del(&virt_dev->vdev_list_entry);
43267+
43268+out_destroy:
43269+ vdev_destroy(virt_dev);
43270+ goto out;
43271+}
43272+
43273+static ssize_t vcdrom_add_device(const char *device_name, char *params)
43274+{
43275+ int res;
43276+
43277+ TRACE_ENTRY();
43278+
43279+ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
43280+ res = -EINTR;
43281+ goto out;
43282+ }
43283+
43284+ res = __vcdrom_add_device(device_name, params);
43285+
43286+ mutex_unlock(&scst_vdisk_mutex);
43287+
43288+out:
43289+ TRACE_EXIT_RES(res);
43290+ return res;
43291+
43292+}
43293+
43294+static ssize_t vcdrom_del_device(const char *device_name)
43295+{
43296+ int res = 0;
43297+ struct scst_vdisk_dev *virt_dev;
43298+
43299+ TRACE_ENTRY();
43300+
43301+ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
43302+ res = -EINTR;
43303+ goto out;
43304+ }
43305+
43306+ virt_dev = vdev_find(device_name);
43307+ if (virt_dev == NULL) {
43308+ PRINT_ERROR("Device %s not found", device_name);
43309+ res = -EINVAL;
43310+ goto out_unlock;
43311+ }
43312+
43313+ vdev_del_device(virt_dev);
43314+
43315+out_unlock:
43316+ mutex_unlock(&scst_vdisk_mutex);
43317+
43318+out:
43319+ TRACE_EXIT_RES(res);
43320+ return res;
43321+}
43322+
43323+static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
43324+ char *buffer)
43325+{
43326+ loff_t err;
43327+ char *old_fn, *p, *pp;
43328+ const char *filename = NULL;
43329+ int length = strlen(buffer);
43330+ int res = 0;
43331+
43332+ TRACE_ENTRY();
43333+
43334+ p = buffer;
43335+
43336+ while (isspace(*p) && *p != '\0')
43337+ p++;
43338+ filename = p;
43339+ p = &buffer[length-1];
43340+ pp = &buffer[length];
43341+ while (isspace(*p) && (*p != '\0')) {
43342+ pp = p;
43343+ p--;
43344+ }
43345+ *pp = '\0';
43346+
43347+ res = scst_suspend_activity(true);
43348+ if (res != 0)
43349+ goto out;
43350+
43351+ /* To sync with detach*() functions */
43352+ mutex_lock(&scst_mutex);
43353+
43354+ if (*filename == '\0') {
43355+ virt_dev->cdrom_empty = 1;
43356+ TRACE_DBG("%s", "No media");
43357+ } else if (*filename != '/') {
43358+ PRINT_ERROR("File path \"%s\" is not absolute", filename);
43359+ res = -EINVAL;
43360+ goto out_unlock;
43361+ } else
43362+ virt_dev->cdrom_empty = 0;
43363+
43364+ old_fn = virt_dev->filename;
43365+
43366+ if (!virt_dev->cdrom_empty) {
43367+ int len = strlen(filename) + 1;
43368+ char *fn = kmalloc(len, GFP_KERNEL);
43369+ if (fn == NULL) {
43370+ TRACE(TRACE_OUT_OF_MEM, "%s",
43371+ "Allocation of filename failed");
43372+ res = -ENOMEM;
43373+ goto out_unlock;
43374+ }
43375+
43376+ strlcpy(fn, filename, len);
43377+ virt_dev->filename = fn;
43378+
43379+ res = vdisk_get_file_size(virt_dev->filename,
43380+ virt_dev->blockio, &err);
43381+ if (res != 0)
43382+ goto out_free_fn;
43383+ } else {
43384+ err = 0;
43385+ virt_dev->filename = NULL;
43386+ }
43387+
43388+ if (virt_dev->prevent_allow_medium_removal) {
43389+ PRINT_ERROR("Prevent medium removal for "
43390+ "virtual device with name %s", virt_dev->name);
43391+ res = -EINVAL;
43392+ goto out_free_fn;
43393+ }
43394+
43395+ virt_dev->file_size = err;
43396+ virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift;
43397+ if (!virt_dev->cdrom_empty)
43398+ virt_dev->media_changed = 1;
43399+
43400+ mutex_unlock(&scst_mutex);
43401+
43402+ scst_dev_del_all_thr_data(virt_dev->dev);
43403+
43404+ if (!virt_dev->cdrom_empty) {
43405+ PRINT_INFO("Changed SCSI target virtual cdrom %s "
43406+ "(file=\"%s\", fs=%lldMB, bs=%d, nblocks=%lld,"
43407+ " cyln=%lld%s)", virt_dev->name,
43408+ vdev_get_filename(virt_dev),
43409+ virt_dev->file_size >> 20, virt_dev->block_size,
43410+ (long long unsigned int)virt_dev->nblocks,
43411+ (long long unsigned int)virt_dev->nblocks/64/32,
43412+ virt_dev->nblocks < 64*32 ? " !WARNING! cyln less "
43413+ "than 1" : "");
43414+ } else {
43415+ PRINT_INFO("Removed media from SCSI target virtual cdrom %s",
43416+ virt_dev->name);
43417+ }
43418+
43419+ kfree(old_fn);
43420+
43421+out_resume:
43422+ scst_resume_activity();
43423+
43424+out:
43425+ TRACE_EXIT_RES(res);
43426+ return res;
43427+
43428+out_free_fn:
43429+ kfree(virt_dev->filename);
43430+ virt_dev->filename = old_fn;
43431+
43432+out_unlock:
43433+ mutex_unlock(&scst_mutex);
43434+ goto out_resume;
43435+}
43436+
43437+static int vcdrom_sysfs_process_filename_store(struct scst_sysfs_work_item *work)
43438+{
43439+ int res;
43440+ struct scst_device *dev = work->dev;
43441+ struct scst_vdisk_dev *virt_dev;
43442+
43443+ TRACE_ENTRY();
43444+
43445+ /* It's safe, since we taken dev_kobj and dh_priv NULLed in attach() */
43446+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43447+
43448+ res = vcdrom_change(virt_dev, work->buf);
43449+
43450+ kobject_put(&dev->dev_kobj);
43451+
43452+ TRACE_EXIT_RES(res);
43453+ return res;
43454+}
43455+
43456+static ssize_t vcdrom_sysfs_filename_store(struct kobject *kobj,
43457+ struct kobj_attribute *attr, const char *buf, size_t count)
43458+{
43459+ int res;
43460+ char *i_buf;
43461+ struct scst_sysfs_work_item *work;
43462+ struct scst_device *dev;
43463+
43464+ TRACE_ENTRY();
43465+
43466+ dev = container_of(kobj, struct scst_device, dev_kobj);
43467+
43468+ i_buf = kmalloc(count+1, GFP_KERNEL);
43469+ if (i_buf == NULL) {
43470+ PRINT_ERROR("Unable to alloc intermediate buffer with size %zd",
43471+ count+1);
43472+ res = -ENOMEM;
43473+ goto out;
43474+ }
43475+ memcpy(i_buf, buf, count);
43476+ i_buf[count] = '\0';
43477+
43478+ res = scst_alloc_sysfs_work(vcdrom_sysfs_process_filename_store,
43479+ false, &work);
43480+ if (res != 0)
43481+ goto out_free;
43482+
43483+ work->buf = i_buf;
43484+ work->dev = dev;
43485+
43486+ kobject_get(&dev->dev_kobj);
43487+
43488+ res = scst_sysfs_queue_wait_work(work);
43489+ if (res == 0)
43490+ res = count;
43491+
43492+out:
43493+ TRACE_EXIT_RES(res);
43494+ return res;
43495+
43496+out_free:
43497+ kfree(i_buf);
43498+ goto out;
43499+}
43500+
43501+static ssize_t vdev_sysfs_size_show(struct kobject *kobj,
43502+ struct kobj_attribute *attr, char *buf)
43503+{
43504+ int pos = 0;
43505+ struct scst_device *dev;
43506+ struct scst_vdisk_dev *virt_dev;
43507+
43508+ TRACE_ENTRY();
43509+
43510+ dev = container_of(kobj, struct scst_device, dev_kobj);
43511+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43512+
43513+ pos = sprintf(buf, "%lld\n", virt_dev->file_size / 1024 / 1024);
43514+
43515+ TRACE_EXIT_RES(pos);
43516+ return pos;
43517+}
43518+
43519+static ssize_t vdisk_sysfs_blocksize_show(struct kobject *kobj,
43520+ struct kobj_attribute *attr, char *buf)
43521+{
43522+ int pos = 0;
43523+ struct scst_device *dev;
43524+ struct scst_vdisk_dev *virt_dev;
43525+
43526+ TRACE_ENTRY();
43527+
43528+ dev = container_of(kobj, struct scst_device, dev_kobj);
43529+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43530+
43531+ pos = sprintf(buf, "%d\n%s", (int)virt_dev->block_size,
43532+ (virt_dev->block_size == DEF_DISK_BLOCKSIZE) ? "" :
43533+ SCST_SYSFS_KEY_MARK "\n");
43534+
43535+ TRACE_EXIT_RES(pos);
43536+ return pos;
43537+}
43538+
43539+static ssize_t vdisk_sysfs_rd_only_show(struct kobject *kobj,
43540+ struct kobj_attribute *attr, char *buf)
43541+{
43542+ int pos = 0;
43543+ struct scst_device *dev;
43544+ struct scst_vdisk_dev *virt_dev;
43545+
43546+ TRACE_ENTRY();
43547+
43548+ dev = container_of(kobj, struct scst_device, dev_kobj);
43549+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43550+
43551+ pos = sprintf(buf, "%d\n%s", virt_dev->rd_only ? 1 : 0,
43552+ (virt_dev->rd_only == DEF_RD_ONLY) ? "" :
43553+ SCST_SYSFS_KEY_MARK "");
43554+
43555+ TRACE_EXIT_RES(pos);
43556+ return pos;
43557+}
43558+
43559+static ssize_t vdisk_sysfs_wt_show(struct kobject *kobj,
43560+ struct kobj_attribute *attr, char *buf)
43561+{
43562+ int pos = 0;
43563+ struct scst_device *dev;
43564+ struct scst_vdisk_dev *virt_dev;
43565+
43566+ TRACE_ENTRY();
43567+
43568+ dev = container_of(kobj, struct scst_device, dev_kobj);
43569+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43570+
43571+ pos = sprintf(buf, "%d\n%s", virt_dev->wt_flag ? 1 : 0,
43572+ (virt_dev->wt_flag == DEF_WRITE_THROUGH) ? "" :
43573+ SCST_SYSFS_KEY_MARK "");
43574+
43575+ TRACE_EXIT_RES(pos);
43576+ return pos;
43577+}
43578+
43579+static ssize_t vdisk_sysfs_nv_cache_show(struct kobject *kobj,
43580+ struct kobj_attribute *attr, char *buf)
43581+{
43582+ int pos = 0;
43583+ struct scst_device *dev;
43584+ struct scst_vdisk_dev *virt_dev;
43585+
43586+ TRACE_ENTRY();
43587+
43588+ dev = container_of(kobj, struct scst_device, dev_kobj);
43589+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43590+
43591+ pos = sprintf(buf, "%d\n%s", virt_dev->nv_cache ? 1 : 0,
43592+ (virt_dev->nv_cache == DEF_NV_CACHE) ? "" :
43593+ SCST_SYSFS_KEY_MARK "");
43594+
43595+ TRACE_EXIT_RES(pos);
43596+ return pos;
43597+}
43598+
43599+static ssize_t vdisk_sysfs_o_direct_show(struct kobject *kobj,
43600+ struct kobj_attribute *attr, char *buf)
43601+{
43602+ int pos = 0;
43603+ struct scst_device *dev;
43604+ struct scst_vdisk_dev *virt_dev;
43605+
43606+ TRACE_ENTRY();
43607+
43608+ dev = container_of(kobj, struct scst_device, dev_kobj);
43609+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43610+
43611+ pos = sprintf(buf, "%d\n%s", virt_dev->o_direct_flag ? 1 : 0,
43612+ (virt_dev->o_direct_flag == DEF_O_DIRECT) ? "" :
43613+ SCST_SYSFS_KEY_MARK "");
43614+
43615+ TRACE_EXIT_RES(pos);
43616+ return pos;
43617+}
43618+
43619+static ssize_t vdisk_sysfs_removable_show(struct kobject *kobj,
43620+ struct kobj_attribute *attr, char *buf)
43621+{
43622+ int pos = 0;
43623+ struct scst_device *dev;
43624+ struct scst_vdisk_dev *virt_dev;
43625+
43626+ TRACE_ENTRY();
43627+
43628+ dev = container_of(kobj, struct scst_device, dev_kobj);
43629+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43630+
43631+ pos = sprintf(buf, "%d\n", virt_dev->removable ? 1 : 0);
43632+
43633+ if ((virt_dev->dev->type != TYPE_ROM) &&
43634+ (virt_dev->removable != DEF_REMOVABLE))
43635+ pos += sprintf(&buf[pos], "%s\n", SCST_SYSFS_KEY_MARK);
43636+
43637+ TRACE_EXIT_RES(pos);
43638+ return pos;
43639+}
43640+
43641+static int vdev_sysfs_process_get_filename(struct scst_sysfs_work_item *work)
43642+{
43643+ int res = 0;
43644+ struct scst_device *dev;
43645+ struct scst_vdisk_dev *virt_dev;
43646+
43647+ TRACE_ENTRY();
43648+
43649+ dev = work->dev;
43650+
43651+ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
43652+ res = -EINTR;
43653+ goto out_put;
43654+ }
43655+
43656+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43657+
43658+ if (virt_dev == NULL)
43659+ goto out_unlock;
43660+
43661+ if (virt_dev->filename != NULL)
43662+ work->res_buf = kasprintf(GFP_KERNEL, "%s\n%s\n",
43663+ vdev_get_filename(virt_dev), SCST_SYSFS_KEY_MARK);
43664+ else
43665+ work->res_buf = kasprintf(GFP_KERNEL, "%s\n",
43666+ vdev_get_filename(virt_dev));
43667+
43668+out_unlock:
43669+ mutex_unlock(&scst_vdisk_mutex);
43670+
43671+out_put:
43672+ kobject_put(&dev->dev_kobj);
43673+
43674+ TRACE_EXIT_RES(res);
43675+ return res;
43676+}
43677+
43678+static ssize_t vdev_sysfs_filename_show(struct kobject *kobj,
43679+ struct kobj_attribute *attr, char *buf)
43680+{
43681+ int res = 0;
43682+ struct scst_device *dev;
43683+ struct scst_sysfs_work_item *work;
43684+
43685+ TRACE_ENTRY();
43686+
43687+ dev = container_of(kobj, struct scst_device, dev_kobj);
43688+
43689+ res = scst_alloc_sysfs_work(vdev_sysfs_process_get_filename,
43690+ true, &work);
43691+ if (res != 0)
43692+ goto out;
43693+
43694+ work->dev = dev;
43695+
43696+ kobject_get(&dev->dev_kobj);
43697+
43698+ scst_sysfs_work_get(work);
43699+
43700+ res = scst_sysfs_queue_wait_work(work);
43701+ if (res != 0)
43702+ goto out_put;
43703+
43704+ res = snprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n", work->res_buf);
43705+
43706+out_put:
43707+ scst_sysfs_work_put(work);
43708+
43709+out:
43710+ TRACE_EXIT_RES(res);
43711+ return res;
43712+}
43713+
43714+static int vdisk_sysfs_process_resync_size_store(
43715+ struct scst_sysfs_work_item *work)
43716+{
43717+ int res;
43718+ struct scst_device *dev = work->dev;
43719+ struct scst_vdisk_dev *virt_dev;
43720+
43721+ TRACE_ENTRY();
43722+
43723+ /* It's safe, since we taken dev_kobj and dh_priv NULLed in attach() */
43724+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43725+
43726+ res = vdisk_resync_size(virt_dev);
43727+
43728+ kobject_put(&dev->dev_kobj);
43729+
43730+ TRACE_EXIT_RES(res);
43731+ return res;
43732+}
43733+
43734+static ssize_t vdisk_sysfs_resync_size_store(struct kobject *kobj,
43735+ struct kobj_attribute *attr, const char *buf, size_t count)
43736+{
43737+ int res;
43738+ struct scst_device *dev;
43739+ struct scst_sysfs_work_item *work;
43740+
43741+ TRACE_ENTRY();
43742+
43743+ dev = container_of(kobj, struct scst_device, dev_kobj);
43744+
43745+ res = scst_alloc_sysfs_work(vdisk_sysfs_process_resync_size_store,
43746+ false, &work);
43747+ if (res != 0)
43748+ goto out;
43749+
43750+ work->dev = dev;
43751+
43752+ kobject_get(&dev->dev_kobj);
43753+
43754+ res = scst_sysfs_queue_wait_work(work);
43755+ if (res == 0)
43756+ res = count;
43757+
43758+out:
43759+ TRACE_EXIT_RES(res);
43760+ return res;
43761+}
43762+
43763+static ssize_t vdev_sysfs_t10_dev_id_store(struct kobject *kobj,
43764+ struct kobj_attribute *attr, const char *buf, size_t count)
43765+{
43766+ int res, i;
43767+ struct scst_device *dev;
43768+ struct scst_vdisk_dev *virt_dev;
43769+
43770+ TRACE_ENTRY();
43771+
43772+ dev = container_of(kobj, struct scst_device, dev_kobj);
43773+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43774+
43775+ write_lock_bh(&vdisk_t10_dev_id_rwlock);
43776+
43777+ if ((count > sizeof(virt_dev->t10_dev_id)) ||
43778+ ((count == sizeof(virt_dev->t10_dev_id)) &&
43779+ (buf[count-1] != '\n'))) {
43780+ PRINT_ERROR("T10 device id is too long (max %zd "
43781+ "characters)", sizeof(virt_dev->t10_dev_id)-1);
43782+ res = -EINVAL;
43783+ goto out_unlock;
43784+ }
43785+
43786+ memset(virt_dev->t10_dev_id, 0, sizeof(virt_dev->t10_dev_id));
43787+ memcpy(virt_dev->t10_dev_id, buf, count);
43788+
43789+ i = 0;
43790+ while (i < sizeof(virt_dev->t10_dev_id)) {
43791+ if (virt_dev->t10_dev_id[i] == '\n') {
43792+ virt_dev->t10_dev_id[i] = '\0';
43793+ break;
43794+ }
43795+ i++;
43796+ }
43797+
43798+ virt_dev->t10_dev_id_set = 1;
43799+
43800+ res = count;
43801+
43802+ PRINT_INFO("T10 device id for device %s changed to %s", virt_dev->name,
43803+ virt_dev->t10_dev_id);
43804+
43805+out_unlock:
43806+ write_unlock_bh(&vdisk_t10_dev_id_rwlock);
43807+
43808+ TRACE_EXIT_RES(res);
43809+ return res;
43810+}
43811+
43812+static ssize_t vdev_sysfs_t10_dev_id_show(struct kobject *kobj,
43813+ struct kobj_attribute *attr, char *buf)
43814+{
43815+ int pos = 0;
43816+ struct scst_device *dev;
43817+ struct scst_vdisk_dev *virt_dev;
43818+
43819+ TRACE_ENTRY();
43820+
43821+ dev = container_of(kobj, struct scst_device, dev_kobj);
43822+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43823+
43824+ read_lock_bh(&vdisk_t10_dev_id_rwlock);
43825+ pos = sprintf(buf, "%s\n%s", virt_dev->t10_dev_id,
43826+ virt_dev->t10_dev_id_set ? SCST_SYSFS_KEY_MARK "\n" : "");
43827+ read_unlock_bh(&vdisk_t10_dev_id_rwlock);
43828+
43829+ TRACE_EXIT_RES(pos);
43830+ return pos;
43831+}
43832+
43833+static ssize_t vdev_sysfs_usn_show(struct kobject *kobj,
43834+ struct kobj_attribute *attr, char *buf)
43835+{
43836+ int pos = 0;
43837+ struct scst_device *dev;
43838+ struct scst_vdisk_dev *virt_dev;
43839+
43840+ TRACE_ENTRY();
43841+
43842+ dev = container_of(kobj, struct scst_device, dev_kobj);
43843+ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
43844+
43845+ pos = sprintf(buf, "%s\n", virt_dev->usn);
43846+
43847+ TRACE_EXIT_RES(pos);
43848+ return pos;
43849+}
43850+
43851+static int __init init_scst_vdisk(struct scst_dev_type *devtype)
43852+{
43853+ int res = 0;
43854+
43855+ TRACE_ENTRY();
43856+
43857+ devtype->module = THIS_MODULE;
43858+
43859+ res = scst_register_virtual_dev_driver(devtype);
43860+ if (res < 0)
43861+ goto out;
43862+
43863+out:
43864+ TRACE_EXIT_RES(res);
43865+ return res;
43866+
43867+}
43868+
43869+static void exit_scst_vdisk(struct scst_dev_type *devtype)
43870+{
43871+ TRACE_ENTRY();
43872+
43873+ mutex_lock(&scst_vdisk_mutex);
43874+ while (1) {
43875+ struct scst_vdisk_dev *virt_dev;
43876+
43877+ if (list_empty(&vdev_list))
43878+ break;
43879+
43880+ virt_dev = list_entry(vdev_list.next, typeof(*virt_dev),
43881+ vdev_list_entry);
43882+
43883+ vdev_del_device(virt_dev);
43884+ }
43885+ mutex_unlock(&scst_vdisk_mutex);
43886+
43887+ scst_unregister_virtual_dev_driver(devtype);
43888+
43889+ TRACE_EXIT();
43890+ return;
43891+}
43892+
43893+static int __init init_scst_vdisk_driver(void)
43894+{
43895+ int res;
43896+
43897+ vdisk_thr_cachep = KMEM_CACHE(scst_vdisk_thr, SCST_SLAB_FLAGS);
43898+ if (vdisk_thr_cachep == NULL) {
43899+ res = -ENOMEM;
43900+ goto out;
43901+ }
43902+
43903+ blockio_work_cachep = KMEM_CACHE(scst_blockio_work, SCST_SLAB_FLAGS);
43904+ if (blockio_work_cachep == NULL) {
43905+ res = -ENOMEM;
43906+ goto out_free_vdisk_cache;
43907+ }
43908+
43909+ if (num_threads < 1) {
43910+ PRINT_ERROR("num_threads can not be less than 1, use "
43911+ "default %d", DEF_NUM_THREADS);
43912+ num_threads = DEF_NUM_THREADS;
43913+ }
43914+
43915+ vdisk_file_devtype.threads_num = num_threads;
43916+ vcdrom_devtype.threads_num = num_threads;
43917+
43918+ atomic_set(&nullio_thr_data.hdr.ref, 1); /* never destroy it */
43919+
43920+ res = init_scst_vdisk(&vdisk_file_devtype);
43921+ if (res != 0)
43922+ goto out_free_slab;
43923+
43924+ res = init_scst_vdisk(&vdisk_blk_devtype);
43925+ if (res != 0)
43926+ goto out_free_vdisk;
43927+
43928+ res = init_scst_vdisk(&vdisk_null_devtype);
43929+ if (res != 0)
43930+ goto out_free_blk;
43931+
43932+ res = init_scst_vdisk(&vcdrom_devtype);
43933+ if (res != 0)
43934+ goto out_free_null;
43935+
43936+out:
43937+ return res;
43938+
43939+out_free_null:
43940+ exit_scst_vdisk(&vdisk_null_devtype);
43941+
43942+out_free_blk:
43943+ exit_scst_vdisk(&vdisk_blk_devtype);
43944+
43945+out_free_vdisk:
43946+ exit_scst_vdisk(&vdisk_file_devtype);
43947+
43948+out_free_slab:
43949+ kmem_cache_destroy(blockio_work_cachep);
43950+
43951+out_free_vdisk_cache:
43952+ kmem_cache_destroy(vdisk_thr_cachep);
43953+ goto out;
43954+}
43955+
43956+static void __exit exit_scst_vdisk_driver(void)
43957+{
43958+ exit_scst_vdisk(&vdisk_null_devtype);
43959+ exit_scst_vdisk(&vdisk_blk_devtype);
43960+ exit_scst_vdisk(&vdisk_file_devtype);
43961+ exit_scst_vdisk(&vcdrom_devtype);
43962+
43963+ kmem_cache_destroy(blockio_work_cachep);
43964+ kmem_cache_destroy(vdisk_thr_cachep);
43965+}
43966+
43967+module_init(init_scst_vdisk_driver);
43968+module_exit(exit_scst_vdisk_driver);
43969+
43970+MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
43971+MODULE_LICENSE("GPL");
43972+MODULE_DESCRIPTION("SCSI disk (type 0) and CDROM (type 5) dev handler for "
43973+ "SCST using files on file systems or block devices");
43974+MODULE_VERSION(SCST_VERSION_STRING);
43975diff -uprN orig/linux-2.6.35/Documentation/scst/README.scst linux-2.6.35/Documentation/scst/README.scst
43976--- orig/linux-2.6.35/Documentation/scst/README.scst
43977+++ linux-2.6.35/Documentation/scst/README.scst
43978@@ -0,0 +1,1445 @@
43979+Generic SCSI target mid-level for Linux (SCST)
43980+==============================================
43981+
43982+SCST is designed to provide unified, consistent interface between SCSI
43983+target drivers and Linux kernel and simplify target drivers development
43984+as much as possible. Detail description of SCST's features and internals
43985+could be found on its Internet page http://scst.sourceforge.net.
43986+
43987+SCST supports the following I/O modes:
43988+
43989+ * Pass-through mode with one to many relationship, i.e. when multiple
43990+ initiators can connect to the exported pass-through devices, for
43991+ the following SCSI devices types: disks (type 0), tapes (type 1),
43992+ processors (type 3), CDROMs (type 5), MO disks (type 7), medium
43993+ changers (type 8) and RAID controllers (type 0xC).
43994+
43995+ * FILEIO mode, which allows to use files on file systems or block
43996+ devices as virtual remotely available SCSI disks or CDROMs with
43997+ benefits of the Linux page cache.
43998+
43999+ * BLOCKIO mode, which performs direct block IO with a block device,
44000+ bypassing page-cache for all operations. This mode works ideally with
44001+ high-end storage HBAs and for applications that either do not need
44002+ caching between application and disk or need the large block
44003+ throughput.
44004+
44005+ * "Performance" device handlers, which provide in pseudo pass-through
44006+ mode a way for direct performance measurements without overhead of
44007+ actual data transferring from/to underlying SCSI device.
44008+
44009+In addition, SCST supports advanced per-initiator access and devices
44010+visibility management, so different initiators could see different set
44011+of devices with different access permissions. See below for details.
44012+
44013+Full list of SCST features and comparison with other Linux targets you
44014+can find on http://scst.sourceforge.net/comparison.html.
44015+
44016+Installation
44017+------------
44018+
44019+To see your devices remotely, you need to add a corresponding LUN for
44020+them (see below how). By default, no local devices are seen remotely.
44021+There must be LUN 0 in each LUNs set (security group), i.e. LUs
44022+numeration must not start from, e.g., 1. Otherwise you will see no
44023+devices on remote initiators and SCST core will write into the kernel
44024+log message: "tgt_dev for LUN 0 not found, command to unexisting LU?"
44025+
44026+It is highly recommended to use scstadmin utility for configuring
44027+devices and security groups.
44028+
44029+The flow of SCST inialization should be as the following:
44030+
44031+1. Load of SCST modules with necessary module parameters, if needed.
44032+
44033+2. Configure targets, devices, LUNs, etc. using either scstadmin
44034+(recommended), or the sysfs interface directly as described below.
44035+
44036+If you experience problems during modules load or running, check your
44037+kernel logs (or run dmesg command for the few most recent messages).
44038+
44039+IMPORTANT: Without loading appropriate device handler, corresponding devices
44040+========= will be invisible for remote initiators, which could lead to holes
44041+ in the LUN addressing, so automatic device scanning by remote SCSI
44042+ mid-level could not notice the devices. Therefore you will have
44043+ to add them manually via
44044+ 'echo "- - -" >/sys/class/scsi_host/hostX/scan',
44045+ where X - is the host number.
44046+
44047+IMPORTANT: Working of target and initiator on the same host is
44048+========= supported, except the following 2 cases: swap over target exported
44049+ device and using a writable mmap over a file from target
44050+ exported device. The latter means you can't mount a file
44051+ system over target exported device. In other words, you can
44052+ freely use any sg, sd, st, etc. devices imported from target
44053+ on the same host, but you can't mount file systems or put
44054+ swap on them. This is a limitation of Linux memory/cache
44055+ manager, because in this case an OOM deadlock like: system
44056+ needs some memory -> it decides to clear some cache -> cache
44057+ needs to write on target exported device -> initiator sends
44058+ request to the target -> target needs memory -> system needs
44059+ even more memory -> deadlock.
44060+
44061+IMPORTANT: In the current version simultaneous access to local SCSI devices
44062+========= via standard high-level SCSI drivers (sd, st, sg, etc.) and
44063+ SCST's target drivers is unsupported. Especially it is
44064+ important for execution via sg and st commands that change
44065+ the state of devices and their parameters, because that could
44066+ lead to data corruption. If any such command is done, at
44067+ least related device handler(s) must be restarted. For block
44068+ devices READ/WRITE commands using direct disk handler are
44069+ generally safe.
44070+
44071+Usage in failover mode
44072+----------------------
44073+
44074+It is recommended to use TEST UNIT READY ("tur") command to check if
44075+SCST target is alive in MPIO configurations.
44076+
44077+Device handlers
44078+---------------
44079+
44080+Device specific drivers (device handlers) are plugins for SCST, which
44081+help SCST to analyze incoming requests and determine parameters,
44082+specific to various types of devices. If an appropriate device handler
44083+for a SCSI device type isn't loaded, SCST doesn't know how to handle
44084+devices of this type, so they will be invisible for remote initiators
44085+(more precisely, "LUN not supported" sense code will be returned).
44086+
44087+In addition to device handlers for real devices, there are VDISK, user
44088+space and "performance" device handlers.
44089+
44090+VDISK device handler works over files on file systems and makes from
44091+them virtual remotely available SCSI disks or CDROM's. In addition, it
44092+allows to work directly over a block device, e.g. local IDE or SCSI disk
44093+or ever disk partition, where there is no file systems overhead. Using
44094+block devices comparing to sending SCSI commands directly to SCSI
44095+mid-level via scsi_do_req()/scsi_execute_async() has advantage that data
44096+are transferred via system cache, so it is possible to fully benefit from
44097+caching and read ahead performed by Linux's VM subsystem. The only
44098+disadvantage here that in the FILEIO mode there is superfluous data
44099+copying between the cache and SCST's buffers. This issue is going to be
44100+addressed in the next release. Virtual CDROM's are useful for remote
44101+installation. See below for details how to setup and use VDISK device
44102+handler.
44103+
44104+"Performance" device handlers for disks, MO disks and tapes in their
44105+exec() method skip (pretend to execute) all READ and WRITE operations
44106+and thus provide a way for direct link performance measurements without
44107+overhead of actual data transferring from/to underlying SCSI device.
44108+
44109+NOTE: Since "perf" device handlers on READ operations don't touch the
44110+==== commands' data buffer, it is returned to remote initiators as it
44111+ was allocated, without even being zeroed. Thus, "perf" device
44112+ handlers impose some security risk, so use them with caution.
44113+
44114+Compilation options
44115+-------------------
44116+
44117+There are the following compilation options, that could be change using
44118+your favorite kernel configuration Makefile target, e.g. "make xconfig":
44119+
44120+ - CONFIG_SCST_DEBUG - if defined, turns on some debugging code,
44121+ including some logging. Makes the driver considerably bigger and slower,
44122+ producing large amount of log data.
44123+
44124+ - CONFIG_SCST_TRACING - if defined, turns on ability to log events. Makes the
44125+ driver considerably bigger and leads to some performance loss.
44126+
44127+ - CONFIG_SCST_EXTRACHECKS - if defined, adds extra validity checks in
44128+ the various places.
44129+
44130+ - CONFIG_SCST_USE_EXPECTED_VALUES - if not defined (default), initiator
44131+ supplied expected data transfer length and direction will be used
44132+ only for verification purposes to return error or warn in case if one
44133+ of them is invalid. Instead, locally decoded from SCSI command values
44134+ will be used. This is necessary for security reasons, because
44135+ otherwise a faulty initiator can crash target by supplying invalid
44136+ value in one of those parameters. This is especially important in
44137+ case of pass-through mode. If CONFIG_SCST_USE_EXPECTED_VALUES is
44138+ defined, initiator supplied expected data transfer length and
44139+ direction will override the locally decoded values. This might be
44140+ necessary if internal SCST commands translation table doesn't contain
44141+ SCSI command, which is used in your environment. You can know that if
44142+ you enable "minor" trace level and have messages like "Unknown
44143+ opcode XX for YY. Should you update scst_scsi_op_table?" in your
44144+ kernel log and your initiator returns an error. Also report those
44145+ messages in the SCST mailing list scst-devel@lists.sourceforge.net.
44146+ Note, that not all SCSI transports support supplying expected values.
44147+
44148+ - CONFIG_SCST_DEBUG_TM - if defined, turns on task management functions
44149+ debugging, when on LUN 6 some of the commands will be delayed for
44150+ about 60 sec., so making the remote initiator send TM functions, eg
44151+ ABORT TASK and TARGET RESET. Also define
44152+ CONFIG_SCST_TM_DBG_GO_OFFLINE symbol in the Makefile if you want that
44153+ the device eventually become completely unresponsive, or otherwise to
44154+ circle around ABORTs and RESETs code. Needs CONFIG_SCST_DEBUG turned
44155+ on.
44156+
44157+ - CONFIG_SCST_STRICT_SERIALIZING - if defined, makes SCST send all commands to
44158+ underlying SCSI device synchronously, one after one. This makes task
44159+ management more reliable, with cost of some performance penalty. This
44160+ is mostly actual for stateful SCSI devices like tapes, where the
44161+ result of command's execution depends from device's settings defined
44162+ by previous commands. Disk and RAID devices are stateless in the most
44163+ cases. The current SCSI core in Linux doesn't allow to abort all
44164+ commands reliably if they sent asynchronously to a stateful device.
44165+ Turned off by default, turn it on if you use stateful device(s) and
44166+ need as much error recovery reliability as possible. As a side effect
44167+ of CONFIG_SCST_STRICT_SERIALIZING, on kernels below 2.6.30 no kernel
44168+ patching is necessary for pass-through device handlers (scst_disk,
44169+ etc.).
44170+
44171+ - CONFIG_SCST_TEST_IO_IN_SIRQ - if defined, allows SCST to submit selected
44172+ SCSI commands (TUR and READ/WRITE) from soft-IRQ context (tasklets).
44173+ Enabling it will decrease amount of context switches and slightly
44174+ improve performance. The goal of this option is to be able to measure
44175+ overhead of the context switches. If after enabling this option you
44176+ don't see under load in vmstat output on the target significant
44177+ decrease of amount of context switches, then your target driver
44178+ doesn't submit commands to SCST in IRQ context. For instance,
44179+ iSCSI-SCST doesn't do that, but qla2x00t with
44180+ CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD disabled - does. This option is
44181+ designed to be used with vdisk NULLIO backend.
44182+
44183+ WARNING! Using this option enabled with other backend than vdisk
44184+ NULLIO is unsafe and can lead you to a kernel crash!
44185+
44186+ - CONFIG_SCST_STRICT_SECURITY - if defined, makes SCST zero allocated data
44187+ buffers. Undefining it (default) considerably improves performance
44188+ and eases CPU load, but could create a security hole (information
44189+ leakage), so enable it, if you have strict security requirements.
44190+
44191+ - CONFIG_SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING - if defined,
44192+ in case when TASK MANAGEMENT function ABORT TASK is trying to abort a
44193+ command, which has already finished, remote initiator, which sent the
44194+ ABORT TASK request, will receive TASK NOT EXIST (or ABORT FAILED)
44195+ response for the ABORT TASK request. This is more logical response,
44196+ since, because the command finished, attempt to abort it failed, but
44197+ some initiators, particularly VMware iSCSI initiator, consider TASK
44198+ NOT EXIST response as if the target got crazy and try to RESET it.
44199+ Then sometimes get crazy itself. So, this option is disabled by
44200+ default.
44201+
44202+ - CONFIG_SCST_MEASURE_LATENCY - if defined, provides in "latency" files
44203+ global and per-LUN average commands processing latency statistic. You
44204+ can clear already measured results by writing 0 in each file. Note,
44205+ you need a non-preemptible kernel to have correct results.
44206+
44207+HIGHMEM kernel configurations are fully supported, but not recommended
44208+for performance reasons.
44209+
44210+Module parameters
44211+-----------------
44212+
44213+Module scst supports the following parameters:
44214+
44215+ - scst_threads - allows to set count of SCST's threads. By default it
44216+ is CPU count.
44217+
44218+ - scst_max_cmd_mem - sets maximum amount of memory in MB allowed to be
44219+ consumed by the SCST commands for data buffers at any given time. By
44220+ default it is approximately TotalMem/4.
44221+
44222+SCST sysfs interface
44223+--------------------
44224+
44225+Root of SCST sysfs interface is /sys/kernel/scst_tgt. It has the
44226+following entries:
44227+
44228+ - devices - this is a root subdirectory for all SCST devices
44229+
44230+ - handlers - this is a root subdirectory for all SCST dev handlers
44231+
44232+ - sgv - this is a root subdirectory for all SCST SGV caches
44233+
44234+ - targets - this is a root subdirectory for all SCST targets
44235+
44236+ - setup_id - allows to read and write SCST setup ID. This ID can be
44237+ used in cases, when the same SCST configuration should be installed
44238+ on several targets, but exported from those targets devices should
44239+ have different IDs and SNs. For instance, VDISK dev handler uses this
44240+ ID to generate T10 vendor specific identifier and SN of the devices.
44241+
44242+ - threads - allows to read and set number of global SCST I/O threads.
44243+ Those threads used with async. dev handlers, for instance, vdisk
44244+ BLOCKIO or NULLIO.
44245+
44246+ - trace_level - allows to enable and disable various tracing
44247+ facilities. See content of this file for help how to use it.
44248+
44249+ - version - read-only attribute, which allows to see version of
44250+ SCST and enabled optional features.
44251+
44252+ - last_sysfs_mgmt_res - read-only attribute returning completion status
44253+ of the last management command. In the sysfs implementation there are
44254+ some problems between internal sysfs and internal SCST locking. To
44255+ avoid them in some cases sysfs calls can return error with errno
44256+ EAGAIN. This doesn't mean the operation failed. It only means that
44257+ the operation queued and not yet completed. To wait for it to
44258+ complete, an management tool should poll this file. If the operation
44259+ hasn't yet completed, it will also return EAGAIN. But after it's
44260+ completed, it will return the result of this operation (0 for success
44261+ or -errno for error).
44262+
44263+Each SCST sysfs file (attribute) can contain in the last line mark
44264+"[key]". It is automatically added mark used to allow scstadmin to see
44265+which attributes it should save in the config file. You can ignore it.
44266+
44267+"Devices" subdirectory contains subdirectories for each SCST devices.
44268+
44269+Content of each device's subdirectory is dev handler specific. See
44270+documentation for your dev handlers for more info about it as well as
44271+SysfsRules file for more info about common to all dev handlers rules.
44272+SCST dev handlers can have the following common entries:
44273+
44274+ - exported - subdirectory containing links to all LUNs where this
44275+ device was exported.
44276+
44277+ - handler - if dev handler determined for this device, this link points
44278+ to it. The handler can be not set for pass-through devices.
44279+
44280+ - threads_num - shows and allows to set number of threads in this device's
44281+ threads pool. If 0 - no threads will be created, and global SCST
44282+ threads pool will be used. If <0 - creation of the threads pool is
44283+ prohibited.
44284+
44285+ - threads_pool_type - shows and allows to sets threads pool type.
44286+ Possible values: "per_initiator" and "shared". When the value is
44287+ "per_initiator" (default), each session from each initiator will use
44288+ separate dedicated pool of threads. When the value is "shared", all
44289+ sessions from all initiators will share the same per-device pool of
44290+ threads. Valid only if threads_num attribute >0.
44291+
44292+ - dump_prs - allows to dump persistent reservations information in the
44293+ kernel log.
44294+
44295+ - type - SCSI type of this device
44296+
44297+See below for more information about other entries of this subdirectory
44298+of the standard SCST dev handlers.
44299+
44300+"Handlers" subdirectory contains subdirectories for each SCST dev
44301+handler.
44302+
44303+Content of each handler's subdirectory is dev handler specific. See
44304+documentation for your dev handlers for more info about it as well as
44305+SysfsRules file for more info about common to all dev handlers rules.
44306+SCST dev handlers can have the following common entries:
44307+
44308+ - mgmt - this entry allows to create virtual devices and their
44309+ attributes (for virtual devices dev handlers) or assign/unassign real
44310+ SCSI devices to/from this dev handler (for pass-through dev
44311+ handlers).
44312+
44313+ - trace_level - allows to enable and disable various tracing
44314+ facilities. See content of this file for help how to use it.
44315+
44316+ - type - SCSI type of devices served by this dev handler.
44317+
44318+See below for more information about other entries of this subdirectory
44319+of the standard SCST dev handlers.
44320+
44321+"Sgv" subdirectory contains statistic information of SCST SGV caches. It
44322+has the following entries:
44323+
44324+ - None, one or more subdirectories for each existing SGV cache.
44325+
44326+ - global_stats - file containing global SGV caches statistics.
44327+
44328+Each SGV cache's subdirectory has the following item:
44329+
44330+ - stats - file containing statistics for this SGV caches.
44331+
44332+"Targets" subdirectory contains subdirectories for each SCST target.
44333+
44334+Content of each target's subdirectory is target specific. See
44335+documentation for your target for more info about it as well as
44336+SysfsRules file for more info about common to all targets rules.
44337+Every target should have at least the following entries:
44338+
44339+ - ini_groups - subdirectory, which contains and allows to define
44340+ initiator-oriented access control information, see below.
44341+
44342+ - luns - subdirectory, which contains list of available LUNs in the
44343+ target-oriented access control and allows to define it, see below.
44344+
44345+ - sessions - subdirectory containing connected to this target sessions.
44346+
44347+ - enabled - using this attribute you can enable or disable this target/
44348+ It allows to finish configuring it before it starts accepting new
44349+ connections. 0 by default.
44350+
44351+ - addr_method - used LUNs addressing method. Possible values:
44352+ "Peripheral" and "Flat". Most initiators work well with Peripheral
44353+ addressing method (default), but some (HP-UX, for instance) may
44354+ require Flat method. This attribute is also available in the
44355+ initiators security groups, so you can assign the addressing method
44356+ on per-initiator basis.
44357+
44358+ - io_grouping_type - defines how I/O from sessions to this target are
44359+ grouped together. This I/O grouping is very important for
44360+ performance. By setting this attribute in a right value, you can
44361+ considerably increase performance of your setup. This grouping is
44362+ performed only if you use CFQ I/O scheduler on the target and for
44363+ devices with threads_num >= 0 and, if threads_num > 0, with
44364+ threads_pool_type "per_initiator". Possible values:
44365+ "this_group_only", "never", "auto", or I/O group number >0. When the
44366+ value is "this_group_only" all I/O from all sessions in this target
44367+ will be grouped together. When the value is "never", I/O from
44368+ different sessions will not be grouped together, i.e. all sessions in
44369+ this target will have separate dedicated I/O groups. When the value
44370+ is "auto" (default), all I/O from initiators with the same name
44371+ (iSCSI initiator name, for instance) in all targets will be grouped
44372+ together with a separate dedicated I/O group for each initiator name.
44373+ For iSCSI this mode works well, but other transports usually use
44374+ different initiator names for different sessions, so using such
44375+ transports in MPIO configurations you should either use value
44376+ "this_group_only", or an explicit I/O group number. This attribute is
44377+ also available in the initiators security groups, so you can assign
44378+ the I/O grouping on per-initiator basis. See below for more info how
44379+ to use this attribute.
44380+
44381+ - rel_tgt_id - allows to read or write SCSI Relative Target Port
44382+ Identifier attribute. This identifier is used to identify SCSI Target
44383+ Ports by some SCSI commands, mainly by Persistent Reservations
44384+ commands. This identifier must be unique among all SCST targets, but
44385+ for convenience SCST allows disabled targets to have not unique
44386+ rel_tgt_id. In this case SCST will not allow to enable this target
44387+ until rel_tgt_id becomes unique. This attribute initialized unique by
44388+ SCST by default.
44389+
44390+A target driver may have also the following entries:
44391+
44392+ - "hw_target" - if the target driver supports both hardware and virtual
44393+ targets (for instance, an FC adapter supporting NPIV, which has
44394+ hardware targets for its physical ports as well as virtual NPIV
44395+ targets), this read only attribute for all hardware targets will
44396+ exist and contain value 1.
44397+
44398+Subdirectory "sessions" contains one subdirectory for each connected
44399+session with name equal to name of the connected initiator.
44400+
44401+Each session subdirectory contains the following entries:
44402+
44403+ - initiator_name - contains initiator name
44404+
44405+ - force_close - optional write-only attribute, which allows to force
44406+ close this session.
44407+
44408+ - active_commands - contains number of active, i.e. not yet or being
44409+ executed, SCSI commands in this session.
44410+
44411+ - commands - contains overall number of SCSI commands in this session.
44412+
44413+ - latency - if CONFIG_SCST_MEASURE_LATENCY enabled, contains latency
44414+ statistics for this session.
44415+
44416+ - luns - a link pointing out to the corresponding LUNs set (security
44417+ group) where this session was attached to.
44418+
44419+ - One or more "lunX" subdirectories, where 'X' is a number, for each LUN
44420+ this session has (see below).
44421+
44422+ - other target driver specific attributes and subdirectories.
44423+
44424+See below description of the VDISK's sysfs interface for samples.
44425+
44426+Access and devices visibility management (LUN masking)
44427+------------------------------------------------------
44428+
44429+Access and devices visibility management allows for an initiator or
44430+group of initiators to see different devices with different LUNs
44431+with necessary access permissions.
44432+
44433+SCST supports two modes of access control:
44434+
44435+1. Target-oriented. In this mode you define for each target a default
44436+set of LUNs, which are accessible to all initiators, connected to that
44437+target. This is a regular access control mode, which people usually mean
44438+thinking about access control in general. For instance, in IET this is
44439+the only supported mode.
44440+
44441+2. Initiator-oriented. In this mode you define which LUNs are accessible
44442+for each initiator. In this mode you should create for each set of one
44443+or more initiators, which should access to the same set of devices with
44444+the same LUNs, a separate security group, then add to it devices and
44445+names of allowed initiator(s).
44446+
44447+Both modes can be used simultaneously. In this case the
44448+initiator-oriented mode has higher priority, than the target-oriented,
44449+i.e. initiators are at first searched in all defined security groups for
44450+this target and, if none matches, the default target's set of LUNs is
44451+used. This set of LUNs might be empty, then the initiator will not see
44452+any LUNs from the target.
44453+
44454+You can at any time find out which set of LUNs each session is assigned
44455+to by looking where link
44456+/sys/kernel/scst_tgt/targets/target_driver/target_name/sessions/initiator_name/luns
44457+points to.
44458+
44459+To configure the target-oriented access control SCST provides the
44460+following interface. Each target's sysfs subdirectory
44461+(/sys/kernel/scst_tgt/targets/target_driver/target_name) has "luns"
44462+subdirectory. This subdirectory contains the list of already defined
44463+target-oriented access control LUNs for this target as well as file
44464+"mgmt". This file has the following commands, which you can send to it,
44465+for instance, using "echo" shell command. You can always get a small
44466+help about supported commands by looking inside this file. "Parameters"
44467+are one or more param_name=value pairs separated by ';'.
44468+
44469+ - "add H:C:I:L lun [parameters]" - adds a pass-through device with
44470+ host:channel:id:lun with LUN "lun". Optionally, the device could be
44471+ marked as read only by using parameter "read_only". The recommended
44472+ way to find out H:C:I:L numbers is use of lsscsi utility.
44473+
44474+ - "replace H:C:I:L lun [parameters]" - replaces by pass-through device
44475+ with host:channel:id:lun existing with LUN "lun" device with
44476+ generation of INQUIRY DATA HAS CHANGED Unit Attention. If the old
44477+ device doesn't exist, this command acts as the "add" command.
44478+ Optionally, the device could be marked as read only by using
44479+ parameter "read_only". The recommended way to find out H:C:I:L
44480+ numbers is use of lsscsi utility.
44481+
44482+ - "add VNAME lun [parameters]" - adds a virtual device with name VNAME
44483+ with LUN "lun". Optionally, the device could be marked as read only
44484+ by using parameter "read_only".
44485+
44486+ - "replace VNAME lun [parameters]" - replaces by virtual device
44487+ with name VNAME existing with LUN "lun" device with generation of
44488+ INQUIRY DATA HAS CHANGED Unit Attention. If the old device doesn't
44489+ exist, this command acts as the "add" command. Optionally, the device
44490+ could be marked as read only by using parameter "read_only".
44491+
44492+ - "del lun" - deletes LUN lun
44493+
44494+ - "clear" - clears the list of devices
44495+
44496+To configure the initiator-oriented access control SCST provides the
44497+following interface. Each target's sysfs subdirectory
44498+(/sys/kernel/scst_tgt/targets/target_driver/target_name) has "ini_groups"
44499+subdirectory. This subdirectory contains the list of already defined
44500+security groups for this target as well as file "mgmt". This file has
44501+the following commands, which you can send to it, for instance, using
44502+"echo" shell command. You can always get a small help about supported
44503+commands by looking inside this file.
44504+
44505+ - "create GROUP_NAME" - creates a new security group.
44506+
44507+ - "del GROUP_NAME" - deletes a new security group.
44508+
44509+Each security group's subdirectory contains 2 subdirectories: initiators
44510+and luns.
44511+
44512+Each "initiators" subdirectory contains list of added to this groups
44513+initiator as well as as well as file "mgmt". This file has the following
44514+commands, which you can send to it, for instance, using "echo" shell
44515+command. You can always get a small help about supported commands by
44516+looking inside this file.
44517+
44518+ - "add INITIATOR_NAME" - adds initiator with name INITIATOR_NAME to the
44519+ group.
44520+
44521+ - "del INITIATOR_NAME" - deletes initiator with name INITIATOR_NAME
44522+ from the group.
44523+
44524+ - "move INITIATOR_NAME DEST_GROUP_NAME" moves initiator with name
44525+ INITIATOR_NAME from the current group to group with name
44526+ DEST_GROUP_NAME.
44527+
44528+ - "clear" - deletes all initiators from this group.
44529+
44530+For "add" and "del" commands INITIATOR_NAME can be a simple DOS-type
44531+patterns, containing '*' and '?' symbols. '*' means match all any
44532+symbols, '?' means match only any single symbol. For instance,
44533+"blah.xxx" will match "bl?h.*". Additionally, you can use negative sign
44534+'!' to revert the value of the pattern. For instance, "ah.xxx" will
44535+match "!bl?h.*".
44536+
44537+Each "luns" subdirectory contains the list of already defined LUNs for
44538+this group as well as file "mgmt". Content of this file as well as list
44539+of available in it commands is fully identical to the "luns"
44540+subdirectory of the target-oriented access control.
44541+
44542+Examples:
44543+
44544+ - echo "create INI" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/mgmt -
44545+ creates security group INI for target iqn.2006-10.net.vlnb:tgt1.
44546+
44547+ - echo "add 2:0:1:0 11" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/INI/luns/mgmt -
44548+ adds a pass-through device sitting on host 2, channel 0, ID 1, LUN 0
44549+ to group with name INI as LUN 11.
44550+
44551+ - echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/INI/luns/mgmt -
44552+ adds a virtual disk with name disk1 to group with name INI as LUN 0.
44553+
44554+ - echo "add 21:*:e0:?b:83:*" >/sys/kernel/scst_tgt/targets/21:00:00:a0:8c:54:52:12/ini_groups/INI/initiators/mgmt -
44555+ adds a pattern to group with name INI to Fibre Channel target with
44556+ WWN 21:00:00:a0:8c:54:52:12, which matches WWNs of Fibre Channel
44557+ initiator ports.
44558+
44559+Consider you need to have an iSCSI target with name
44560+"iqn.2007-05.com.example:storage.disk1.sys1.xyz", which should export
44561+virtual device "dev1" with LUN 0 and virtual device "dev2" with LUN 1,
44562+but initiator with name
44563+"iqn.2007-05.com.example:storage.disk1.spec_ini.xyz" should see only
44564+virtual device "dev2" read only with LUN 0. To achieve that you should
44565+do the following commands:
44566+
44567+# echo "iqn.2007-05.com.example:storage.disk1.sys1.xyz" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
44568+# echo "add dev1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/luns/mgmt
44569+# echo "add dev2 1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/luns/mgmt
44570+# echo "create SPEC_INI" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_groups/mgmt
44571+# echo "add dev2 0 read_only=1" \
44572+ >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_groups/SPEC_INI/luns/mgmt
44573+# echo "iqn.2007-05.com.example:storage.disk1.spec_ini.xyz" \
44574+ >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_groups/SPEC_INI/initiators/mgmt
44575+
44576+For Fibre Channel or SAS in the above example you should use target's
44577+and initiator ports WWNs instead of iSCSI names.
44578+
44579+It is highly recommended to use scstadmin utility instead of described
44580+in this section low level interface.
44581+
44582+IMPORTANT
44583+=========
44584+
44585+There must be LUN 0 in each set of LUNs, i.e. LUs numeration must not
44586+start from, e.g., 1. Otherwise you will see no devices on remote
44587+initiators and SCST core will write into the kernel log message: "tgt_dev
44588+for LUN 0 not found, command to unexisting LU?"
44589+
44590+IMPORTANT
44591+=========
44592+
44593+All the access control must be fully configured BEFORE the corresponding
44594+target is enabled. When you enable a target, it will immediately start
44595+accepting new connections, hence creating new sessions, and those new
44596+sessions will be assigned to security groups according to the
44597+*currently* configured access control settings. For instance, to
44598+the default target's set of LUNs, instead of "HOST004" group as you may
44599+need, because "HOST004" doesn't exist yet. So, you must configure all
44600+the security groups before new connections from the initiators are
44601+created, i.e. before the target enabled.
44602+
44603+VDISK device handler
44604+--------------------
44605+
44606+VDISK has 4 built-in dev handlers: vdisk_fileio, vdisk_blockio,
44607+vdisk_nullio and vcdrom. Roots of their sysfs interface are
44608+/sys/kernel/scst_tgt/handlers/handler_name, e.g. for vdisk_fileio:
44609+/sys/kernel/scst_tgt/handlers/vdisk_fileio. Each root has the following
44610+entries:
44611+
44612+ - None, one or more links to devices with name equal to names
44613+ of the corresponding devices.
44614+
44615+ - trace_level - allows to enable and disable various tracing
44616+ facilities. See content of this file for help how to use it.
44617+
44618+ - mgmt - main management entry, which allows to add/delete VDISK
44619+ devices with the corresponding type.
44620+
44621+The "mgmt" file has the following commands, which you can send to it,
44622+for instance, using "echo" shell command. You can always get a small
44623+help about supported commands by looking inside this file. "Parameters"
44624+are one or more param_name=value pairs separated by ';'.
44625+
44626+ - echo "add_device device_name [parameters]" - adds a virtual device
44627+ with name device_name and specified parameters (see below)
44628+
44629+ - echo "del_device device_name" - deletes a virtual device with name
44630+ device_name.
44631+
44632+Handler vdisk_fileio provides FILEIO mode to create virtual devices.
44633+This mode uses as backend files and accesses to them using regular
44634+read()/write() file calls. This allows to use full power of Linux page
44635+cache. The following parameters possible for vdisk_fileio:
44636+
44637+ - filename - specifies path and file name of the backend file. The path
44638+ must be absolute.
44639+
44640+ - blocksize - specifies block size used by this virtual device. The
44641+ block size must be power of 2 and >= 512 bytes. Default is 512.
44642+
44643+ - write_through - disables write back caching. Note, this option
44644+ has sense only if you also *manually* disable write-back cache in
44645+ *all* your backstorage devices and make sure it's actually disabled,
44646+ since many devices are known to lie about this mode to get better
44647+ benchmark results. Default is 0.
44648+
44649+ - read_only - read only. Default is 0.
44650+
44651+ - o_direct - disables both read and write caching. This mode isn't
44652+ currently fully implemented, you should use user space fileio_tgt
44653+ program in O_DIRECT mode instead (see below).
44654+
44655+ - nv_cache - enables "non-volatile cache" mode. In this mode it is
44656+ assumed that the target has a GOOD UPS with ability to cleanly
44657+ shutdown target in case of power failure and it is software/hardware
44658+ bugs free, i.e. all data from the target's cache are guaranteed
44659+ sooner or later to go to the media. Hence all data synchronization
44660+ with media operations, like SYNCHRONIZE_CACHE, are ignored in order
44661+ to bring more performance. Also in this mode target reports to
44662+ initiators that the corresponding device has write-through cache to
44663+ disable all write-back cache workarounds used by initiators. Use with
44664+ extreme caution, since in this mode after a crash of the target
44665+ journaled file systems don't guarantee the consistency after journal
44666+ recovery, therefore manual fsck MUST be ran. Note, that since usually
44667+ the journal barrier protection (see "IMPORTANT" note below) turned
44668+ off, enabling NV_CACHE could change nothing from data protection
44669+ point of view, since no data synchronization with media operations
44670+ will go from the initiator. This option overrides "write_through"
44671+ option. Disabled by default.
44672+
44673+ - removable - with this flag set the device is reported to remote
44674+ initiators as removable.
44675+
44676+Handler vdisk_blockio provides BLOCKIO mode to create virtual devices.
44677+This mode performs direct block I/O with a block device, bypassing the
44678+page cache for all operations. This mode works ideally with high-end
44679+storage HBAs and for applications that either do not need caching
44680+between application and disk or need the large block throughput. See
44681+below for more info.
44682+
44683+The following parameters possible for vdisk_blockio: filename,
44684+blocksize, nv_cache, read_only, removable. See vdisk_fileio above for
44685+description of those parameters.
44686+
44687+Handler vdisk_nullio provides NULLIO mode to create virtual devices. In
44688+this mode no real I/O is done, but success returned to initiators.
44689+Intended to be used for performance measurements at the same way as
44690+"*_perf" handlers. The following parameters possible for vdisk_nullio:
44691+blocksize, read_only, removable. See vdisk_fileio above for description
44692+of those parameters.
44693+
44694+Handler vcdrom allows emulation of a virtual CDROM device using an ISO
44695+file as backend. It doesn't have any parameters.
44696+
44697+For example:
44698+
44699+echo "add_device disk1 filename=/disk1; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
44700+
44701+will create a FILEIO virtual device disk1 with backend file /disk1
44702+with block size 4K and NV_CACHE enabled.
44703+
44704+Each vdisk_fileio's device has the following attributes in
44705+/sys/kernel/scst_tgt/devices/device_name:
44706+
44707+ - filename - contains path and file name of the backend file.
44708+
44709+ - blocksize - contains block size used by this virtual device.
44710+
44711+ - write_through - contains status of write back caching of this virtual
44712+ device.
44713+
44714+ - read_only - contains read only status of this virtual device.
44715+
44716+ - o_direct - contains O_DIRECT status of this virtual device.
44717+
44718+ - nv_cache - contains NV_CACHE status of this virtual device.
44719+
44720+ - removable - contains removable status of this virtual device.
44721+
44722+ - size_mb - contains size of this virtual device in MB.
44723+
44724+ - t10_dev_id - contains and allows to set T10 vendor specific
44725+ identifier for Device Identification VPD page (0x83) of INQUIRY data.
44726+ By default VDISK handler always generates t10_dev_id for every new
44727+ created device at creation time based on the device name and
44728+ scst_vdisk_ID scst_vdisk.ko module parameter (see below).
44729+
44730+ - usn - contains the virtual device's serial number of INQUIRY data. It
44731+ is created at the device creation time based on the device name and
44732+ scst_vdisk_ID scst_vdisk.ko module parameter (see below).
44733+
44734+ - type - contains SCSI type of this virtual device.
44735+
44736+ - resync_size - write only attribute, which makes vdisk_fileio to
44737+ rescan size of the backend file. It is useful if you changed it, for
44738+ instance, if you resized it.
44739+
44740+For example:
44741+
44742+/sys/kernel/scst_tgt/devices/disk1
44743+|-- blocksize
44744+|-- exported
44745+| |-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/0
44746+| |-- export1 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/INI/luns/0
44747+| |-- export2 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/0
44748+| |-- export3 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/INI1/luns/0
44749+| |-- export4 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/INI2/luns/0
44750+|-- filename
44751+|-- handler -> ../../handlers/vdisk_fileio
44752+|-- nv_cache
44753+|-- o_direct
44754+|-- read_only
44755+|-- removable
44756+|-- resync_size
44757+|-- size_mb
44758+|-- t10_dev_id
44759+|-- threads_num
44760+|-- threads_pool_type
44761+|-- type
44762+|-- usn
44763+`-- write_through
44764+
44765+Each vdisk_blockio's device has the following attributes in
44766+/sys/kernel/scst_tgt/devices/device_name: blocksize, filename, nv_cache,
44767+read_only, removable, resync_size, size_mb, t10_dev_id, threads_num,
44768+threads_pool_type, type, usn. See above description of those parameters.
44769+
44770+Each vdisk_nullio's device has the following attributes in
44771+/sys/kernel/scst_tgt/devices/device_name: blocksize, read_only,
44772+removable, size_mb, t10_dev_id, threads_num, threads_pool_type, type,
44773+usn. See above description of those parameters.
44774+
44775+Each vcdrom's device has the following attributes in
44776+/sys/kernel/scst_tgt/devices/device_name: filename, size_mb,
44777+t10_dev_id, threads_num, threads_pool_type, type, usn. See above
44778+description of those parameters. Exception is filename attribute. For
44779+vcdrom it is writable. Writing to it allows to virtually insert or
44780+change virtual CD media in the virtual CDROM device. For example:
44781+
44782+ - echo "/image.iso" >/sys/kernel/scst_tgt/devices/cdrom/filename - will
44783+ insert file /image.iso as virtual media to the virtual CDROM cdrom.
44784+
44785+ - echo "" >/sys/kernel/scst_tgt/devices/cdrom/filename - will remove
44786+ "media" from the virtual CDROM cdrom.
44787+
44788+Additionally VDISK handler has module parameter "num_threads", which
44789+specifies count of I/O threads for each FILEIO VDISK's or VCDROM device.
44790+If you have a workload, which tends to produce rather random accesses
44791+(e.g. DB-like), you should increase this count to a bigger value, like
44792+32. If you have a rather sequential workload, you should decrease it to
44793+a lower value, like number of CPUs on the target or even 1. Due to some
44794+limitations of Linux I/O subsystem, increasing number of I/O threads too
44795+much leads to sequential performance drop, especially with deadline
44796+scheduler, so decreasing it can improve sequential performance. The
44797+default provides a good compromise between random and sequential
44798+accesses.
44799+
44800+You shouldn't be afraid to have too many VDISK I/O threads if you have
44801+many VDISK devices. Kernel threads consume very little amount of
44802+resources (several KBs) and only necessary threads will be used by SCST,
44803+so the threads will not trash your system.
44804+
44805+CAUTION: If you partitioned/formatted your device with block size X, *NEVER*
44806+======== ever try to export and then mount it (even accidentally) with another
44807+ block size. Otherwise you can *instantly* damage it pretty
44808+ badly as well as all your data on it. Messages on initiator
44809+ like: "attempt to access beyond end of device" is the sign of
44810+ such damage.
44811+
44812+ Moreover, if you want to compare how well different block sizes
44813+ work for you, you **MUST** EVERY TIME AFTER CHANGING BLOCK SIZE
44814+ **COMPLETELY** **WIPE OFF** ALL THE DATA FROM THE DEVICE. In
44815+ other words, THE **WHOLE** DEVICE **MUST** HAVE ONLY **ZEROS**
44816+ AS THE DATA AFTER YOU SWITCH TO NEW BLOCK SIZE. Switching block
44817+ sizes isn't like switching between FILEIO and BLOCKIO, after
44818+ changing block size all previously written with another block
44819+ size data MUST BE ERASED. Otherwise you will have a full set of
44820+ very weird behaviors, because blocks addressing will be
44821+ changed, but initiators in most cases will not have a
44822+ possibility to detect that old addresses written on the device
44823+ in, e.g., partition table, don't refer anymore to what they are
44824+ intended to refer.
44825+
44826+IMPORTANT: Some disk and partition table management utilities don't support
44827+========= block sizes >512 bytes, therefore make sure that your favorite one
44828+ supports it. Currently only cfdisk is known to work only with
44829+ 512 bytes blocks, other utilities like fdisk on Linux or
44830+ standard disk manager on Windows are proved to work well with
44831+ non-512 bytes blocks. Note, if you export a disk file or
44832+ device with some block size, different from one, with which
44833+ it was already partitioned, you could get various weird
44834+ things like utilities hang up or other unexpected behavior.
44835+ Hence, to be sure, zero the exported file or device before
44836+ the first access to it from the remote initiator with another
44837+ block size. On Window initiator make sure you "Set Signature"
44838+ in the disk manager on the imported from the target drive
44839+ before doing any other partitioning on it. After you
44840+ successfully mounted a file system over non-512 bytes block
44841+ size device, the block size stops matter, any program will
44842+ work with files on such file system.
44843+
44844+Persistent Reservations
44845+-----------------------
44846+
44847+SCST implements Persistent Reservations with full set of capabilities,
44848+including "Persistence Through Power Loss".
44849+
44850+The "Persistence Through Power Loss" data are saved in /var/lib/scst/pr
44851+with files with names the same as the names of the corresponding
44852+devices. Also this directory contains backup versions of those files
44853+with suffix ".1". Those backup files are used in case of power or other
44854+failure to prevent Persistent Reservation information from corruption
44855+during update.
44856+
44857+The Persistent Reservations available on all transports implementing
44858+get_initiator_port_transport_id() callback. Transports not implementing
44859+this callback will act in one of 2 possible scenarios ("all or
44860+nothing"):
44861+
44862+1. If a device has such transport connected and doesn't have persistent
44863+reservations, it will refuse Persistent Reservations commands as if it
44864+doesn't support them.
44865+
44866+2. If a device has persistent reservations, all initiators newly
44867+connecting via such transports will not see this device. After all
44868+persistent reservations from this device are released, upon reconnect
44869+the initiators will see it.
44870+
44871+Caching
44872+-------
44873+
44874+By default for performance reasons VDISK FILEIO devices use write back
44875+caching policy.
44876+
44877+Generally, write back caching is safe for use and danger of it is
44878+greatly overestimated, because most modern (especially, Enterprise
44879+level) applications are well prepared to work with write back cached
44880+storage. Particularly, such are all transactions-based applications.
44881+Those applications flush cache to completely avoid ANY data loss on a
44882+crash or power failure. For instance, journaled file systems flush cache
44883+on each meta data update, so they survive power/hardware/software
44884+failures pretty well.
44885+
44886+Since locally on initiators write back caching is always on, if an
44887+application cares about its data consistency, it does flush the cache
44888+when necessary or on any write, if open files with O_SYNC. If it doesn't
44889+care, it doesn't flush the cache. As soon as the cache flushes
44890+propagated to the storage, write back caching on it doesn't make any
44891+difference. If application doesn't flush the cache, it's doomed to loose
44892+data in case of a crash or power failure doesn't matter where this cache
44893+located, locally or on the storage.
44894+
44895+To illustrate that consider, for example, a user who wants to copy /src
44896+directory to /dst directory reliably, i.e. after the copy finished no
44897+power failure or software/hardware crash could lead to a loss of the
44898+data in /dst. There are 2 ways to achieve this. Let's suppose for
44899+simplicity cp opens files for writing with O_SYNC flag, hence bypassing
44900+the local cache.
44901+
44902+1. Slow. Make the device behind /dst working in write through caching
44903+mode and then run "cp -a /src /dst".
44904+
44905+2. Fast. Let the device behind /dst working in write back caching mode
44906+and then run "cp -a /src /dst; sync". The reliability of the result is
44907+the same, but it's much faster than (1). Nobody would care if a crash
44908+happens during the copy, because after recovery simply leftovers from
44909+the not completed attempt would be deleted and the operation would be
44910+restarted from the very beginning.
44911+
44912+So, you can see in (2) there is no danger of ANY data loss from the
44913+write back caching. Moreover, since on practice cp doesn't open files
44914+for writing with O_SYNC flag, to get the copy done reliably, sync
44915+command must be called after cp anyway, so enabling write back caching
44916+wouldn't make any difference for reliability.
44917+
44918+Also you can consider it from another side. Modern HDDs have at least
44919+16MB of cache working in write back mode by default, so for a 10 drives
44920+RAID it is 160MB of a write back cache. How many people are happy with
44921+it and how many disabled write back cache of their HDDs? Almost all and
44922+almost nobody correspondingly? Moreover, many HDDs lie about state of
44923+their cache and report write through while working in write back mode.
44924+They are also successfully used.
44925+
44926+Note, Linux I/O subsystem guarantees to propagated cache flushes to the
44927+storage only using data protection barriers, which usually turned off by
44928+default (see http://lwn.net/Articles/283161). Without barriers enabled
44929+Linux doesn't provide a guarantee that after sync()/fsync() all written
44930+data really hit permanent storage. They can be stored in the cache of
44931+your backstorage devices and, hence, lost on a power failure event.
44932+Thus, ever with write-through cache mode, you still either need to
44933+enable barriers on your backend file system on the target (for direct
44934+/dev/sdX devices this is, indeed, impossible), or need a good UPS to
44935+protect yourself from not committed data loss. Some info about barriers
44936+from the XFS point of view could be found at
44937+http://oss.sgi.com/projects/xfs/faq.html#wcache. On Linux initiators for
44938+Ext3 and ReiserFS file systems the barrier protection could be turned on
44939+using "barrier=1" and "barrier=flush" mount options correspondingly. You
44940+can check if the barriers turn on or off by looking in /proc/mounts.
44941+Windows and, AFAIK, other UNIX'es don't need any special explicit
44942+options and do necessary barrier actions on write-back caching devices
44943+by default.
44944+
44945+To limit this data loss with write back caching you can use files in
44946+/proc/sys/vm to limit amount of unflushed data in the system cache.
44947+
44948+If you for some reason have to use VDISK FILEIO devices in write through
44949+caching mode, don't forget to disable internal caching on their backend
44950+devices or make sure they have additional battery or supercapacitors
44951+power supply on board. Otherwise, you still on a power failure would
44952+loose all the unsaved yet data in the devices internal cache.
44953+
44954+Note, on some real-life workloads write through caching might perform
44955+better, than write back one with the barrier protection turned on.
44956+
44957+BLOCKIO VDISK mode
44958+------------------
44959+
44960+This module works best for these types of scenarios:
44961+
44962+1) Data that are not aligned to 4K sector boundaries and <4K block sizes
44963+are used, which is normally found in virtualization environments where
44964+operating systems start partitions on odd sectors (Windows and it's
44965+sector 63).
44966+
44967+2) Large block data transfers normally found in database loads/dumps and
44968+streaming media.
44969+
44970+3) Advanced relational database systems that perform their own caching
44971+which prefer or demand direct IO access and, because of the nature of
44972+their data access, can actually see worse performance with
44973+non-discriminate caching.
44974+
44975+4) Multiple layers of targets were the secondary and above layers need
44976+to have a consistent view of the primary targets in order to preserve
44977+data integrity which a page cache backed IO type might not provide
44978+reliably.
44979+
44980+Also it has an advantage over FILEIO that it doesn't copy data between
44981+the system cache and the commands data buffers, so it saves a
44982+considerable amount of CPU power and memory bandwidth.
44983+
44984+IMPORTANT: Since data in BLOCKIO and FILEIO modes are not consistent between
44985+========= each other, if you try to use a device in both those modes
44986+ simultaneously, you will almost instantly corrupt your data
44987+ on that device.
44988+
44989+IMPORTANT: If SCST 1.x BLOCKIO worked by default in NV_CACHE mode, when
44990+========= each device reported to remote initiators as having write through
44991+ caching. But if your backend block device has internal write
44992+ back caching it might create a possibility for data loss of
44993+ the cached in the internal cache data in case of a power
44994+ failure. Starting from SCST 2.0 BLOCKIO works by default in
44995+ non-NV_CACHE mode, when each device reported to remote
44996+ initiators as having write back caching, and synchronizes the
44997+ internal device's cache on each SYNCHRONIZE_CACHE command
44998+ from the initiators. It might lead to some PERFORMANCE LOSS,
44999+ so if you are are sure in your power supply and want to
45000+ restore 1.x behavior, your should recreate your BLOCKIO
45001+ devices in NV_CACHE mode.
45002+
45003+Pass-through mode
45004+-----------------
45005+
45006+In the pass-through mode (i.e. using the pass-through device handlers
45007+scst_disk, scst_tape, etc) SCSI commands, coming from remote initiators,
45008+are passed to local SCSI devices on target as is, without any
45009+modifications.
45010+
45011+SCST supports 1 to many pass-through, when several initiators can safely
45012+connect a single pass-through device (a tape, for instance). For such
45013+cases SCST emulates all the necessary functionality.
45014+
45015+In the sysfs interface all real SCSI devices are listed in
45016+/sys/kernel/scst_tgt/devices in form host:channel:id:lun numbers, for
45017+instance 1:0:0:0. The recommended way to match those numbers to your
45018+devices is use of lsscsi utility.
45019+
45020+Each pass-through dev handler has in its root subdirectory
45021+/sys/kernel/scst_tgt/handlers/handler_name, e.g.
45022+/sys/kernel/scst_tgt/handlers/dev_disk, "mgmt" file. It allows the
45023+following commands. They can be sent to it using, e.g., echo command.
45024+
45025+ - "add_device" - this command assigns SCSI device with
45026+host:channel:id:lun numbers to this dev handler.
45027+
45028+echo "add_device 1:0:0:0" >/sys/kernel/scst_tgt/handlers/dev_disk/mgmt
45029+
45030+will assign SCSI device 1:0:0:0 to this dev handler.
45031+
45032+ - "del_device" - this command unassigns SCSI device with
45033+host:channel:id:lun numbers from this dev handler.
45034+
45035+As usually, on read the "mgmt" file returns small help about available
45036+commands.
45037+
45038+You need to manually assign each your real SCSI device to the
45039+corresponding pass-through dev handler using the "add_device" command,
45040+otherwise the real SCSI devices will not be visible remotely. The
45041+assignment isn't done automatically, because it could lead to the
45042+pass-through dev handlers load and initialization problems if any of the
45043+local real SCSI devices are malfunctioning.
45044+
45045+As any other hardware, the local SCSI hardware can not handle commands
45046+with amount of data and/or segments count in scatter-gather array bigger
45047+some values. Therefore, when using the pass-through mode you should note
45048+that values for maximum number of segments and maximum amount of
45049+transferred data (max_sectors) for each SCSI command on devices on
45050+initiators can not be bigger, than corresponding values of the
45051+corresponding SCSI devices on the target. Otherwise you will see
45052+symptoms like small transfers work well, but large ones stall and
45053+messages like: "Unable to complete command due to SG IO count
45054+limitation" are printed in the kernel logs.
45055+
45056+You can't control from the user space limit of the scatter-gather
45057+segments, but for block devices usually it is sufficient if you set on
45058+the initiators /sys/block/DEVICE_NAME/queue/max_sectors_kb in the same
45059+or lower value as in /sys/block/DEVICE_NAME/queue/max_hw_sectors_kb for
45060+the corresponding devices on the target.
45061+
45062+For not-block devices SCSI commands are usually generated directly by
45063+applications, so, if you experience large transfers stalls, you should
45064+check documentation for your application how to limit the transfer
45065+sizes.
45066+
45067+Another way to solve this issue is to build SG entries with more than 1
45068+page each. See the following patch as an example:
45069+http://scst.sourceforge.net/sgv_big_order_alloc.diff
45070+
45071+Performance
45072+-----------
45073+
45074+SCST from the very beginning has been designed and implemented to
45075+provide the best possible performance. Since there is no "one fit all"
45076+the best performance configuration for different setups and loads, SCST
45077+provides extensive set of settings to allow to tune it for the best
45078+performance in each particular case. You don't have to necessary use
45079+those settings. If you don't, SCST will do very good job to autotune for
45080+you, so the resulting performance will, in average, be better
45081+(sometimes, much better) than with other SCSI targets. But in some cases
45082+you can by manual tuning improve it even more.
45083+
45084+Before doing any performance measurements note that performance results
45085+are very much dependent from your type of load, so it is crucial that
45086+you choose access mode (FILEIO, BLOCKIO, O_DIRECT, pass-through), which
45087+suits your needs the best.
45088+
45089+In order to get the maximum performance you should:
45090+
45091+1. For SCST:
45092+
45093+ - Disable in Makefile CONFIG_SCST_STRICT_SERIALIZING, CONFIG_SCST_EXTRACHECKS,
45094+ CONFIG_SCST_TRACING, CONFIG_SCST_DEBUG*, CONFIG_SCST_STRICT_SECURITY,
45095+ CONFIG_SCST_MEASURE_LATENCY
45096+
45097+2. For target drivers:
45098+
45099+ - Disable in Makefiles CONFIG_SCST_EXTRACHECKS, CONFIG_SCST_TRACING,
45100+ CONFIG_SCST_DEBUG*
45101+
45102+3. For device handlers, including VDISK:
45103+
45104+ - Disable in Makefile CONFIG_SCST_TRACING and CONFIG_SCST_DEBUG.
45105+
45106+4. Make sure you have io_grouping_type option set correctly, especially
45107+in the following cases:
45108+
45109+ - Several initiators share your target's backstorage. It can be a
45110+ shared LU using some cluster FS, like VMFS, as well as can be
45111+ different LUs located on the same backstorage (RAID array). For
45112+ instance, if you have 3 initiators and each of them using its own
45113+ dedicated FILEIO device file from the same RAID-6 array on the
45114+ target.
45115+
45116+ In this case for the best performance you should have
45117+ io_grouping_type option set in value "never" in all the LUNs' targets
45118+ and security groups.
45119+
45120+ - Your initiator connected to your target in MPIO mode. In this case for
45121+ the best performance you should:
45122+
45123+ * Either connect all the sessions from the initiator to a single
45124+ target or security group and have io_grouping_type option set in
45125+ value "this_group_only" in the target or security group,
45126+
45127+ * Or, if it isn't possible to connect all the sessions from the
45128+ initiator to a single target or security group, assign the same
45129+ numeric io_grouping_type value for each target/security group this
45130+ initiator connected to. The exact value itself doesn't matter,
45131+ important only that all the targets/security groups use the same
45132+ value.
45133+
45134+Don't forget, io_grouping_type makes sense only if you use CFQ I/O
45135+scheduler on the target and for devices with threads_num >= 0 and, if
45136+threads_num > 0, with threads_pool_type "per_initiator".
45137+
45138+You can check if in your setup io_grouping_type set correctly as well as
45139+if the "auto" io_grouping_type value works for you by tests like the
45140+following:
45141+
45142+ - For not MPIO case you can run single thread sequential reading, e.g.
45143+ using buffered dd, from one initiator, then run the same single
45144+ thread sequential reading from the second initiator in parallel. If
45145+ io_grouping_type is set correctly the aggregate throughput measured
45146+ on the target should only slightly decrease as well as all initiators
45147+ should have nearly equal share of it. If io_grouping_type is not set
45148+ correctly, the aggregate throughput and/or throughput on any
45149+ initiator will decrease significantly, in 2 times or even more. For
45150+ instance, you have 80MB/s single thread sequential reading from the
45151+ target on any initiator. When then both initiators are reading in
45152+ parallel you should see on the target aggregate throughput something
45153+ like 70-75MB/s with correct io_grouping_type and something like
45154+ 35-40MB/s or 8-10MB/s on any initiator with incorrect.
45155+
45156+ - For the MPIO case it's quite easier. With incorrect io_grouping_type
45157+ you simply won't see performance increase from adding the second
45158+ session (assuming your hardware is capable to transfer data through
45159+ both sessions in parallel), or can even see a performance decrease.
45160+
45161+5. If you are going to use your target in an VM environment, for
45162+instance as a shared storage with VMware, make sure all your VMs
45163+connected to the target via *separate* sessions. For instance, for iSCSI
45164+it means that each VM has own connection to the target, not all VMs
45165+connected using a single connection. You can check it using SCST sysfs
45166+interface. For other transports you should use available facilities,
45167+like NPIV for Fibre Channel, to make separate sessions for each VM. If
45168+you miss it, you can greatly loose performance of parallel access to
45169+your target from different VMs. This isn't related to the case if your
45170+VMs are using the same shared storage, like with VMFS, for instance. In
45171+this case all your VM hosts will be connected to the target via separate
45172+sessions, which is enough.
45173+
45174+6. For other target and initiator software parts:
45175+
45176+ - Make sure you applied on your kernel all available SCST patches.
45177+ If for your kernel version this patch doesn't exist, it is strongly
45178+ recommended to upgrade your kernel to version, for which this patch
45179+ exists.
45180+
45181+ - Don't enable debug/hacking features in the kernel, i.e. use them as
45182+ they are by default.
45183+
45184+ - The default kernel read-ahead and queuing settings are optimized
45185+ for locally attached disks, therefore they are not optimal if they
45186+ attached remotely (SCSI target case), which sometimes could lead to
45187+ unexpectedly low throughput. You should increase read-ahead size to at
45188+ least 512KB or even more on all initiators and the target.
45189+
45190+ You should also limit on all initiators maximum amount of sectors per
45191+ SCSI command. This tuning is also recommended on targets with large
45192+ read-ahead values. To do it on Linux, run:
45193+
45194+ echo “64” > /sys/block/sdX/queue/max_sectors_kb
45195+
45196+ where specify instead of X your imported from target device letter,
45197+ like 'b', i.e. sdb.
45198+
45199+ To increase read-ahead size on Linux, run:
45200+
45201+ blockdev --setra N /dev/sdX
45202+
45203+ where N is a read-ahead number in 512-byte sectors and X is a device
45204+ letter like above.
45205+
45206+ Note: you need to set read-ahead setting for device sdX again after
45207+ you changed the maximum amount of sectors per SCSI command for that
45208+ device.
45209+
45210+ Note2: you need to restart SCST after you changed read-ahead settings
45211+ on the target.
45212+
45213+ - You may need to increase amount of requests that OS on initiator
45214+ sends to the target device. To do it on Linux initiators, run
45215+
45216+ echo “64” > /sys/block/sdX/queue/nr_requests
45217+
45218+ where X is a device letter like above.
45219+
45220+ You may also experiment with other parameters in /sys/block/sdX
45221+ directory, they also affect performance. If you find the best values,
45222+ please share them with us.
45223+
45224+ - On the target use CFQ IO scheduler. In most cases it has performance
45225+ advantage over other IO schedulers, sometimes huge (2+ times
45226+ aggregate throughput increase).
45227+
45228+ - It is recommended to turn the kernel preemption off, i.e. set
45229+ the kernel preemption model to "No Forced Preemption (Server)".
45230+
45231+ - Looks like XFS is the best filesystem on the target to store device
45232+ files, because it allows considerably better linear write throughput,
45233+ than ext3.
45234+
45235+7. For hardware on target.
45236+
45237+ - Make sure that your target hardware (e.g. target FC or network card)
45238+ and underlaying IO hardware (e.g. IO card, like SATA, SCSI or RAID to
45239+ which your disks connected) don't share the same PCI bus. You can
45240+ check it using lspci utility. They have to work in parallel, so it
45241+ will be better if they don't compete for the bus. The problem is not
45242+ only in the bandwidth, which they have to share, but also in the
45243+ interaction between cards during that competition. This is very
45244+ important, because in some cases if target and backend storage
45245+ controllers share the same PCI bus, it could lead up to 5-10 times
45246+ less performance, than expected. Moreover, some motherboard (by
45247+ Supermicro, particularly) have serious stability issues if there are
45248+ several high speed devices on the same bus working in parallel. If
45249+ you have no choice, but PCI bus sharing, set in the BIOS PCI latency
45250+ as low as possible.
45251+
45252+8. If you use VDISK IO module in FILEIO mode, NV_CACHE option will
45253+provide you the best performance. But using it make sure you use a good
45254+UPS with ability to shutdown the target on the power failure.
45255+
45256+Baseline performance numbers you can find in those measurements:
45257+http://lkml.org/lkml/2009/3/30/283.
45258+
45259+IMPORTANT: If you use on initiator some versions of Windows (at least W2K)
45260+========= you can't get good write performance for VDISK FILEIO devices with
45261+ default 512 bytes block sizes. You could get about 10% of the
45262+ expected one. This is because of the partition alignment, which
45263+ is (simplifying) incompatible with how Linux page cache
45264+ works, so for each write the corresponding block must be read
45265+ first. Use 4096 bytes block sizes for VDISK devices and you
45266+ will have the expected write performance. Actually, any OS on
45267+ initiators, not only Windows, will benefit from block size
45268+ max(PAGE_SIZE, BLOCK_SIZE_ON_UNDERLYING_FS), where PAGE_SIZE
45269+ is the page size, BLOCK_SIZE_ON_UNDERLYING_FS is block size
45270+ on the underlying FS, on which the device file located, or 0,
45271+ if a device node is used. Both values are from the target.
45272+ See also important notes about setting block sizes >512 bytes
45273+ for VDISK FILEIO devices above.
45274+
45275+9. In some cases, for instance working with SSD devices, which consume 100%
45276+of a single CPU load for data transfers in their internal threads, to
45277+maximize IOPS it can be needed to assign for those threads dedicated
45278+CPUs using Linux CPU affinity facilities. No IRQ processing should be
45279+done on those CPUs. Check that using /proc/interrupts. See taskset
45280+command and Documentation/IRQ-affinity.txt in your kernel's source tree
45281+for how to assign IRQ affinity to tasks and IRQs.
45282+
45283+The reason for that is that processing of coming commands in SIRQ
45284+context might be done on the same CPUs as SSD devices' threads doing data
45285+transfers. As the result, those threads won't receive all the processing
45286+power of those CPUs and perform worse.
45287+
45288+Work if target's backstorage or link is too slow
45289+------------------------------------------------
45290+
45291+Under high I/O load, when your target's backstorage gets overloaded, or
45292+working over a slow link between initiator and target, when the link
45293+can't serve all the queued commands on time, you can experience I/O
45294+stalls or see in the kernel log abort or reset messages.
45295+
45296+At first, consider the case of too slow target's backstorage. On some
45297+seek intensive workloads even fast disks or RAIDs, which able to serve
45298+continuous data stream on 500+ MB/s speed, can be as slow as 0.3 MB/s.
45299+Another possible cause for that can be MD/LVM/RAID on your target as in
45300+http://lkml.org/lkml/2008/2/27/96 (check the whole thread as well).
45301+
45302+Thus, in such situations simply processing of one or more commands takes
45303+too long time, hence initiator decides that they are stuck on the target
45304+and tries to recover. Particularly, it is known that the default amount
45305+of simultaneously queued commands (48) is sometimes too high if you do
45306+intensive writes from VMware on a target disk, which uses LVM in the
45307+snapshot mode. In this case value like 16 or even 8-10 depending of your
45308+backstorage speed could be more appropriate.
45309+
45310+Unfortunately, currently SCST lacks dynamic I/O flow control, when the
45311+queue depth on the target is dynamically decreased/increased based on
45312+how slow/fast the backstorage speed comparing to the target link. So,
45313+there are 6 possible actions, which you can do to workaround or fix this
45314+issue in this case:
45315+
45316+1. Ignore incoming task management (TM) commands. It's fine if there are
45317+not too many of them, so average performance isn't hurt and the
45318+corresponding device isn't getting put offline, i.e. if the backstorage
45319+isn't too slow.
45320+
45321+2. Decrease /sys/block/sdX/device/queue_depth on the initiator in case
45322+if it's Linux (see below how) or/and SCST_MAX_TGT_DEV_COMMANDS constant
45323+in scst_priv.h file until you stop seeing incoming TM commands.
45324+ISCSI-SCST driver also has its own iSCSI specific parameter for that,
45325+see its README file.
45326+
45327+To decrease device queue depth on Linux initiators you can run command:
45328+
45329+# echo Y >/sys/block/sdX/device/queue_depth
45330+
45331+where Y is the new number of simultaneously queued commands, X - your
45332+imported device letter, like 'a' for sda device. There are no special
45333+limitations for Y value, it can be any value from 1 to possible maximum
45334+(usually, 32), so start from dividing the current value on 2, i.e. set
45335+16, if /sys/block/sdX/device/queue_depth contains 32.
45336+
45337+3. Increase the corresponding timeout on the initiator. For Linux it is
45338+located in
45339+/sys/devices/platform/host*/session*/target*:0:0/*:0:0:1/timeout. It can
45340+be done automatically by an udev rule. For instance, the following
45341+rule will increase it to 300 seconds:
45342+
45343+SUBSYSTEM=="scsi", KERNEL=="[0-9]*:[0-9]*", ACTION=="add", ATTR{type}=="0|7|14", ATTR{timeout}="300"
45344+
45345+By default, this timeout is 30 or 60 seconds, depending on your distribution.
45346+
45347+4. Try to avoid such seek intensive workloads.
45348+
45349+5. Increase speed of the target's backstorage.
45350+
45351+6. Implement in SCST dynamic I/O flow control. This will be an ultimate
45352+solution. See "Dynamic I/O flow control" section on
45353+http://scst.sourceforge.net/contributing.html page for possible
45354+implementation idea.
45355+
45356+Next, consider the case of too slow link between initiator and target,
45357+when the initiator tries to simultaneously push N commands to the target
45358+over it. In this case time to serve those commands, i.e. send or receive
45359+data for them over the link, can be more, than timeout for any single
45360+command, hence one or more commands in the tail of the queue can not be
45361+served on time less than the timeout, so the initiator will decide that
45362+they are stuck on the target and will try to recover.
45363+
45364+To workaround/fix this issue in this case you can use ways 1, 2, 3, 6
45365+above or (7): increase speed of the link between target and initiator.
45366+But for some initiators implementations for WRITE commands there might
45367+be cases when target has no way to detect the issue, so dynamic I/O flow
45368+control will not be able to help. In those cases you could also need on
45369+the initiator(s) to either decrease the queue depth (way 2), or increase
45370+the corresponding timeout (way 3).
45371+
45372+Note, that logged messages about QUEUE_FULL status are quite different
45373+by nature. This is a normal work, just SCSI flow control in action.
45374+Simply don't enable "mgmt_minor" logging level, or, alternatively, if
45375+you are confident in the worst case performance of your back-end storage
45376+or initiator-target link, you can increase SCST_MAX_TGT_DEV_COMMANDS in
45377+scst_priv.h to 64. Usually initiators don't try to push more commands on
45378+the target.
45379+
45380+Credits
45381+-------
45382+
45383+Thanks to:
45384+
45385+ * Mark Buechler <mark.buechler@gmail.com> for a lot of useful
45386+ suggestions, bug reports and help in debugging.
45387+
45388+ * Ming Zhang <mingz@ele.uri.edu> for fixes and comments.
45389+
45390+ * Nathaniel Clark <nate@misrule.us> for fixes and comments.
45391+
45392+ * Calvin Morrow <calvin.morrow@comcast.net> for testing and useful
45393+ suggestions.
45394+
45395+ * Hu Gang <hugang@soulinfo.com> for the original version of the
45396+ LSI target driver.
45397+
45398+ * Erik Habbinga <erikhabbinga@inphase-tech.com> for fixes and support
45399+ of the LSI target driver.
45400+
45401+ * Ross S. W. Walker <rswwalker@hotmail.com> for the original block IO
45402+ code and Vu Pham <huongvp@yahoo.com> who updated it for the VDISK dev
45403+ handler.
45404+
45405+ * Michael G. Byrnes <michael.byrnes@hp.com> for fixes.
45406+
45407+ * Alessandro Premoli <a.premoli@andxor.it> for fixes
45408+
45409+ * Nathan Bullock <nbullock@yottayotta.com> for fixes.
45410+
45411+ * Terry Greeniaus <tgreeniaus@yottayotta.com> for fixes.
45412+
45413+ * Krzysztof Blaszkowski <kb@sysmikro.com.pl> for many fixes and bug reports.
45414+
45415+ * Jianxi Chen <pacers@users.sourceforge.net> for fixing problem with
45416+ devices >2TB in size
45417+
45418+ * Bart Van Assche <bart.vanassche@gmail.com> for a lot of help
45419+
45420+ * Daniel Debonzi <debonzi@linux.vnet.ibm.com> for a big part of the
45421+ initial SCST sysfs tree implementation
45422+
45423+Vladislav Bolkhovitin <vst@vlnb.net>, http://scst.sourceforge.net
45424diff -uprN orig/linux-2.6.35/Documentation/scst/SysfsRules linux-2.6.35/Documentation/scst/SysfsRules
45425--- orig/linux-2.6.35/Documentation/scst/SysfsRules
45426+++ linux-2.6.35/Documentation/scst/SysfsRules
45427@@ -0,0 +1,933 @@
45428+ SCST SYSFS interface rules
45429+ ==========================
45430+
45431+This file describes SYSFS interface rules, which all SCST target
45432+drivers, dev handlers and management utilities MUST follow. This allows
45433+to have a simple, self-documented, target drivers and dev handlers
45434+independent management interface.
45435+
45436+Words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
45437+"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
45438+document are to be interpreted as described in RFC 2119.
45439+
45440+In this document "key attribute" means a configuration attribute with
45441+not default value, which must be configured during the target driver's
45442+initialization. A key attribute MUST have in the last line keyword
45443+"[key]". If a default value set to a key attribute, it becomes a regular
45444+none-key attribute. For instance, iSCSI target has attribute DataDigest.
45445+Default value for this attribute is "None". It value "CRC32C" is set to
45446+this attribute, it will become a key attribute. If value "None" is again
45447+set, this attribute will become back to a none-key attribute.
45448+
45449+Each user configurable attribute with a not default value MUST be marked
45450+as key attribute.
45451+
45452+Key attributes SHOULD NOT have sysfs names finished on digits, because
45453+such names SHOULD be used to store several attributes with the same name
45454+on the sysfs tree where duplicated names are not allowed. For instance,
45455+iSCSI targets can have several incoming user names, so the corresponding
45456+attribute should have sysfs name "IncomingUser". If there are 2 user
45457+names, they should have sysfs names "IncomingUser" and "IncomingUser1".
45458+In other words, all "IncomingUser[0-9]*" names should be considered as
45459+different instances of the same "IncomingUser" attribute.
45460+
45461+I. Rules for target drivers
45462+===========================
45463+
45464+SCST core for each target driver (struct scst_tgt_template) creates a
45465+root subdirectory in /sys/kernel/scst_tgt/targets with name
45466+scst_tgt_template.name (called "target_driver_name" further in this
45467+document).
45468+
45469+For each target (struct scst_tgt) SCST core creates a root subdirectory
45470+in /sys/kernel/scst_tgt/targets/target_driver_name with name
45471+scst_tgt.tgt_name (called "target_name" further in this document).
45472+
45473+There are 2 type of targets possible: hardware and virtual targets.
45474+Hardware targets are targets corresponding to real hardware, for
45475+instance, a Fibre Channel adapter's port. Virtual targets are hardware
45476+independent targets, which can be dynamically added or removed, for
45477+instance, an iSCSI target, or NPIV Fibre Channel target.
45478+
45479+A target driver supporting virtual targets MUST support "mgmt" attribute
45480+and "add_target"/"del_target" commands.
45481+
45482+If target driver supports both hardware and virtual targets (for
45483+instance, an FC adapter supporting NPIV, which has hardware targets for
45484+its physical ports as well as virtual NPIV targets), it MUST create each
45485+hardware target with hw_target mark to make SCST core create "hw_target"
45486+attribute (see below).
45487+
45488+Attributes for target drivers
45489+-----------------------------
45490+
45491+A target driver MAY support in its root subdirectory the following
45492+optional attributes. Target drivers MAY also support there other
45493+read-only or read-writable attributes.
45494+
45495+1. "enabled" - this attribute MUST allow to enable and disable target
45496+driver as a whole, i.e. if disabled, the target driver MUST NOT accept
45497+new connections. The goal of this attribute is to allow the target
45498+driver's initial configuration. For instance, iSCSI target may need to
45499+have discovery user names and passwords set before it starts serving
45500+discovery connections.
45501+
45502+This attribute MUST have read and write permissions for superuser and be
45503+read-only for other users.
45504+
45505+On read it MUST return 0, if the target driver is disabled, and 1, if it
45506+is enabled.
45507+
45508+On write it MUST accept '0' character as request to disable and '1' as
45509+request to enable, but MAY also accept other driver specific commands.
45510+
45511+During disabling the target driver MAY close already connected sessions
45512+in all targets, but this is OPTIONAL.
45513+
45514+MUST be 0 by default.
45515+
45516+2. "trace_level" - this attribute SHOULD allow to change log level of this
45517+driver.
45518+
45519+This attribute SHOULD have read and write permissions for superuser and be
45520+read-only for other users.
45521+
45522+On read it SHOULD return a help text about available command and log levels.
45523+
45524+On write it SHOULD accept commands to change log levels according to the
45525+help text.
45526+
45527+For example:
45528+
45529+out_of_mem | minor | pid | line | function | special | mgmt | mgmt_dbg | flow_control | conn
45530+
45531+Usage:
45532+ echo "all|none|default" >trace_level
45533+ echo "value DEC|0xHEX|0OCT" >trace_level
45534+ echo "add|del TOKEN" >trace_level
45535+
45536+where TOKEN is one of [debug, function, line, pid,
45537+ entryexit, buff, mem, sg, out_of_mem,
45538+ special, scsi, mgmt, minor,
45539+ mgmt_dbg, scsi_serializing,
45540+ retry, recv_bot, send_bot, recv_top,
45541+ send_top, d_read, d_write, conn, conn_dbg, iov, pdu, net_page]
45542+
45543+3. "version" - this read-only for all attribute SHOULD return version of
45544+the target driver and some info about its enabled compile time facilities.
45545+
45546+For example:
45547+
45548+2.0.0
45549+EXTRACHECKS
45550+DEBUG
45551+
45552+4. "mgmt" - if supported this attribute MUST allow to add and delete
45553+targets, if virtual targets are supported by this driver, as well as it
45554+MAY allow to add and delete the target driver's or its targets'
45555+attributes.
45556+
45557+This attribute MUST have read and write permissions for superuser and be
45558+read-only for other users.
45559+
45560+On read it MUST return a help string describing available commands,
45561+parameters and attributes.
45562+
45563+To achieve that the target driver should just set in its struct
45564+scst_tgt_template correctly the following fields: mgmt_cmd_help,
45565+add_target_parameters, tgtt_optional_attributes and
45566+tgt_optional_attributes.
45567+
45568+For example:
45569+
45570+Usage: echo "add_target target_name [parameters]" >mgmt
45571+ echo "del_target target_name" >mgmt
45572+ echo "add_attribute <attribute> <value>" >mgmt
45573+ echo "del_attribute <attribute> <value>" >mgmt
45574+ echo "add_target_attribute target_name <attribute> <value>" >mgmt
45575+ echo "del_target_attribute target_name <attribute> <value>" >mgmt
45576+
45577+where parameters are one or more param_name=value pairs separated by ';'
45578+
45579+The following target driver attributes available: IncomingUser, OutgoingUser
45580+The following target attributes available: IncomingUser, OutgoingUser, allowed_portal
45581+
45582+4.1. "add_target" - if supported, this command MUST add new target with
45583+name "target_name" and specified optional or required parameters. Each
45584+parameter MUST be in form "parameter=value". All parameters MUST be
45585+separated by ';' symbol.
45586+
45587+All target drivers supporting creation of virtual targets MUST support
45588+this command.
45589+
45590+All target drivers supporting "add_target" command MUST support all
45591+read-only targets' key attributes as parameters to "add_target" command
45592+with the attributes' names as parameters' names and the attributes'
45593+values as parameters' values.
45594+
45595+For example:
45596+
45597+echo "add_target TARGET1 parameter1=1; parameter2=2" >mgmt
45598+
45599+will add target with name "TARGET1" and parameters with names
45600+"parameter1" and "parameter2" with values 1 and 2 correspondingly.
45601+
45602+4.2. "del_target" - if supported, this command MUST delete target with
45603+name "target_name". If "add_target" command is supported "del_target"
45604+MUST also be supported.
45605+
45606+4.3. "add_attribute" - if supported, this command MUST add a target
45607+driver's attribute with the specified name and one or more values.
45608+
45609+All target drivers supporting run time creation of the target driver's
45610+key attributes MUST support this command.
45611+
45612+For example, for iSCSI target:
45613+
45614+echo "add_attribute IncomingUser name password" >mgmt
45615+
45616+will add for discovery sessions an incoming user (attribute
45617+/sys/kernel/scst_tgt/targets/iscsi/IncomingUser) with name "name" and
45618+password "password".
45619+
45620+4.4. "del_attribute" - if supported, this command MUST delete target
45621+driver's attribute with the specified name and values. The values MUST
45622+be specified, because in some cases attributes MAY internally be
45623+distinguished by values. For instance, iSCSI target might have several
45624+incoming users. If not needed, target driver might ignore the values.
45625+
45626+If "add_attribute" command is supported "del_attribute" MUST
45627+also be supported.
45628+
45629+4.5. "add_target_attribute" - if supported, this command MUST add new
45630+attribute for the specified target with the specified name and one or
45631+more values.
45632+
45633+All target drivers supporting run time creation of targets' key
45634+attributes MUST support this command.
45635+
45636+For example:
45637+
45638+echo "add_target_attribute iqn.2006-10.net.vlnb:tgt IncomingUser name password" >mgmt
45639+
45640+will add for target with name "iqn.2006-10.net.vlnb:tgt" an incoming
45641+user (attribute
45642+/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/IncomingUser)
45643+with name "name" and password "password".
45644+
45645+4.6. "del_target_attribute" - if supported, this command MUST delete
45646+target's attribute with the specified name and values. The values MUST
45647+be specified, because in some cases attributes MAY internally be
45648+distinguished by values. For instance, iSCSI target might have several
45649+incoming users. If not needed, target driver might ignore the values.
45650+
45651+If "add_target_attribute" command is supported "del_target_attribute"
45652+MUST also be supported.
45653+
45654+Attributes for targets
45655+----------------------
45656+
45657+Each target MAY support in its root subdirectory the following optional
45658+attributes. Target drivers MAY also support there other read-only or
45659+read-writable attributes.
45660+
45661+1. "enabled" - this attribute MUST allow to enable and disable the
45662+corresponding target, i.e. if disabled, the target MUST NOT accept new
45663+connections. The goal of this attribute is to allow the target's initial
45664+configuration. For instance, each target needs to have its LUNs setup
45665+before it starts serving initiators. Another example is iSCSI target,
45666+which may need to have initialized a number of iSCSI parameters before
45667+it starts accepting new iSCSI connections.
45668+
45669+This attribute MUST have read and write permissions for superuser and be
45670+read-only for other users.
45671+
45672+On read it MUST return 0, if the target is disabled, and 1, if it is
45673+enabled.
45674+
45675+On write it MUST accept '0' character as request to disable and '1' as
45676+request to enable. Other requests MUST be rejected.
45677+
45678+SCST core provides some facilities, which MUST be used to implement this
45679+attribute.
45680+
45681+During disabling the target driver MAY close already connected sessions
45682+to the target, but this is OPTIONAL.
45683+
45684+MUST be 0 by default.
45685+
45686+SCST core will automatically create for all targets the following
45687+attributes:
45688+
45689+1. "rel_tgt_id" - allows to read or write SCSI Relative Target Port
45690+Identifier attribute.
45691+
45692+2. "hw_target" - allows to distinguish hardware and virtual targets, if
45693+the target driver supports both.
45694+
45695+To provide OPTIONAL force close session functionality target drivers
45696+MUST implement it using "force_close" write only session's attribute,
45697+which on write to it MUST close the corresponding session.
45698+
45699+See SCST core's README for more info about those attributes.
45700+
45701+II. Rules for dev handlers
45702+==========================
45703+
45704+There are 2 types of dev handlers: parent dev handlers and children dev
45705+handlers. The children dev handlers depend from the parent dev handlers.
45706+
45707+SCST core for each parent dev handler (struct scst_dev_type with
45708+parent member with value NULL) creates a root subdirectory in
45709+/sys/kernel/scst_tgt/handlers with name scst_dev_type.name (called
45710+"dev_handler_name" further in this document).
45711+
45712+Parent dev handlers can have one or more subdirectories for children dev
45713+handlers with names scst_dev_type.name of them.
45714+
45715+Only one level of the dev handlers' parent/children hierarchy is
45716+allowed. Parent dev handlers, which support children dev handlers, MUST
45717+NOT handle devices and MUST be only placeholders for the children dev
45718+handlers.
45719+
45720+Further in this document children dev handlers or parent dev handlers,
45721+which don't support children, will be called "end level dev handlers".
45722+
45723+End level dev handlers can be recognized by existence of the "mgmt"
45724+attribute.
45725+
45726+For each device (struct scst_device) SCST core creates a root
45727+subdirectory in /sys/kernel/scst_tgt/devices/device_name with name
45728+scst_device.virt_name (called "device_name" further in this document).
45729+
45730+Attributes for dev handlers
45731+---------------------------
45732+
45733+Each dev handler MUST have it in its root subdirectory "mgmt" attribute,
45734+which MUST support "add_device" and "del_device" attributes as described
45735+below.
45736+
45737+Parent dev handlers and end level dev handlers without parents MAY
45738+support in its root subdirectory the following optional attributes. They
45739+MAY also support there other read-only or read-writable attributes.
45740+
45741+1. "trace_level" - this attribute SHOULD allow to change log level of this
45742+driver.
45743+
45744+This attribute SHOULD have read and write permissions for superuser and be
45745+read-only for other users.
45746+
45747+On read it SHOULD return a help text about available command and log levels.
45748+
45749+On write it SHOULD accept commands to change log levels according to the
45750+help text.
45751+
45752+For example:
45753+
45754+out_of_mem | minor | pid | line | function | special | mgmt | mgmt_dbg
45755+
45756+Usage:
45757+ echo "all|none|default" >trace_level
45758+ echo "value DEC|0xHEX|0OCT" >trace_level
45759+ echo "add|del TOKEN" >trace_level
45760+
45761+where TOKEN is one of [debug, function, line, pid,
45762+ entryexit, buff, mem, sg, out_of_mem,
45763+ special, scsi, mgmt, minor,
45764+ mgmt_dbg, scsi_serializing,
45765+ retry, recv_bot, send_bot, recv_top,
45766+ send_top]
45767+
45768+2. "version" - this read-only for all attribute SHOULD return version of
45769+the dev handler and some info about its enabled compile time facilities.
45770+
45771+For example:
45772+
45773+2.0.0
45774+EXTRACHECKS
45775+DEBUG
45776+
45777+End level dev handlers in their root subdirectories MUST support "mgmt"
45778+attribute and MAY support other read-only or read-writable attributes.
45779+This attribute MUST have read and write permissions for superuser and be
45780+read-only for other users.
45781+
45782+Attribute "mgmt" for virtual devices dev handlers
45783+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45784+
45785+For virtual devices dev handlers "mgmt" attribute MUST allow to add and
45786+delete devices as well as it MAY allow to add and delete the dev
45787+handler's or its devices' attributes.
45788+
45789+On read it MUST return a help string describing available commands and
45790+parameters.
45791+
45792+To achieve that the dev handler should just set in its struct
45793+scst_dev_type correctly the following fields: mgmt_cmd_help,
45794+add_device_parameters, devt_optional_attributes and
45795+dev_optional_attributes.
45796+
45797+For example:
45798+
45799+Usage: echo "add_device device_name [parameters]" >mgmt
45800+ echo "del_device device_name" >mgmt
45801+ echo "add_attribute <attribute> <value>" >mgmt
45802+ echo "del_attribute <attribute> <value>" >mgmt
45803+ echo "add_device_attribute device_name <attribute> <value>" >mgmt
45804+ echo "del_device_attribute device_name <attribute> <value>" >mgmt
45805+
45806+where parameters are one or more param_name=value pairs separated by ';'
45807+
45808+The following parameters available: filename, blocksize, write_through, nv_cache, o_direct, read_only, removable
45809+The following device driver attributes available: AttributeX, AttributeY
45810+The following device attributes available: AttributeDX, AttributeDY
45811+
45812+1. "add_device" - this command MUST add new device with name
45813+"device_name" and specified optional or required parameters. Each
45814+parameter MUST be in form "parameter=value". All parameters MUST be
45815+separated by ';' symbol.
45816+
45817+All dev handlers supporting "add_device" command MUST support all
45818+read-only devices' key attributes as parameters to "add_device" command
45819+with the attributes' names as parameters' names and the attributes'
45820+values as parameters' values.
45821+
45822+For example:
45823+
45824+echo "add_device device1 parameter1=1; parameter2=2" >mgmt
45825+
45826+will add device with name "device1" and parameters with names
45827+"parameter1" and "parameter2" with values 1 and 2 correspondingly.
45828+
45829+2. "del_device" - this command MUST delete device with name
45830+"device_name".
45831+
45832+3. "add_attribute" - if supported, this command MUST add a device
45833+driver's attribute with the specified name and one or more values.
45834+
45835+All dev handlers supporting run time creation of the dev handler's
45836+key attributes MUST support this command.
45837+
45838+For example:
45839+
45840+echo "add_attribute AttributeX ValueX" >mgmt
45841+
45842+will add attribute
45843+/sys/kernel/scst_tgt/handlers/dev_handler_name/AttributeX with value ValueX.
45844+
45845+4. "del_attribute" - if supported, this command MUST delete device
45846+driver's attribute with the specified name and values. The values MUST
45847+be specified, because in some cases attributes MAY internally be
45848+distinguished by values. If not needed, dev handler might ignore the
45849+values.
45850+
45851+If "add_attribute" command is supported "del_attribute" MUST also be
45852+supported.
45853+
45854+5. "add_device_attribute" - if supported, this command MUST add new
45855+attribute for the specified device with the specified name and one or
45856+more values.
45857+
45858+All dev handlers supporting run time creation of devices' key attributes
45859+MUST support this command.
45860+
45861+For example:
45862+
45863+echo "add_device_attribute device1 AttributeDX ValueDX" >mgmt
45864+
45865+will add for device with name "device1" attribute
45866+/sys/kernel/scst_tgt/devices/device_name/AttributeDX) with value
45867+ValueDX.
45868+
45869+6. "del_device_attribute" - if supported, this command MUST delete
45870+device's attribute with the specified name and values. The values MUST
45871+be specified, because in some cases attributes MAY internally be
45872+distinguished by values. If not needed, dev handler might ignore the
45873+values.
45874+
45875+If "add_device_attribute" command is supported "del_device_attribute"
45876+MUST also be supported.
45877+
45878+Attribute "mgmt" for pass-through devices dev handlers
45879+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45880+
45881+For pass-through devices dev handlers "mgmt" attribute MUST allow to
45882+assign and unassign this dev handler to existing SCSI devices via
45883+"add_device" and "del_device" commands correspondingly.
45884+
45885+On read it MUST return a help string describing available commands and
45886+parameters.
45887+
45888+For example:
45889+
45890+Usage: echo "add_device H:C:I:L" >mgmt
45891+ echo "del_device H:C:I:L" >mgmt
45892+
45893+1. "add_device" - this command MUST assign SCSI device with
45894+host:channel:id:lun numbers to this dev handler.
45895+
45896+All pass-through dev handlers MUST support this command.
45897+
45898+For example:
45899+
45900+echo "add_device 1:0:0:0" >mgmt
45901+
45902+will assign SCSI device 1:0:0:0 to this dev handler.
45903+
45904+2. "del_device" - this command MUST unassign SCSI device with
45905+host:channel:id:lun numbers from this dev handler.
45906+
45907+SCST core will automatically create for all dev handlers the following
45908+attributes:
45909+
45910+1. "type" - SCSI type of device this dev handler can handle.
45911+
45912+See SCST core's README for more info about those attributes.
45913+
45914+Attributes for devices
45915+----------------------
45916+
45917+Each device MAY support in its root subdirectory any read-only or
45918+read-writable attributes.
45919+
45920+SCST core will automatically create for all devices the following
45921+attributes:
45922+
45923+1. "type" - SCSI type of this device
45924+
45925+See SCST core's README for more info about those attributes.
45926+
45927+III. Rules for management utilities
45928+===================================
45929+
45930+Rules summary
45931+-------------
45932+
45933+A management utility (scstadmin) SHOULD NOT keep any knowledge specific
45934+to any device, dev handler, target or target driver. It SHOULD only know
45935+the common SCST SYSFS rules, which all dev handlers and target drivers
45936+MUST follow. Namely:
45937+
45938+Common rules:
45939+~~~~~~~~~~~~~
45940+
45941+1. All key attributes MUST be marked by mark "[key]" in the last line of
45942+the attribute.
45943+
45944+2. All not key attributes don't matter and SHOULD be ignored.
45945+
45946+For target drivers and targets:
45947+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45948+
45949+1. If target driver supports adding new targets, it MUST have "mgmt"
45950+attribute, which MUST support "add_target" and "del_target" commands as
45951+specified above.
45952+
45953+2. If target driver supports run time adding new key attributes, it MUST
45954+have "mgmt" attribute, which MUST support "add_attribute" and
45955+"del_attribute" commands as specified above.
45956+
45957+3. If target driver supports both hardware and virtual targets, all its
45958+hardware targets MUST have "hw_target" attribute with value 1.
45959+
45960+4. If target has read-only key attributes, the add_target command MUST
45961+support them as parameters.
45962+
45963+5. If target supports run time adding new key attributes, the target
45964+driver MUST have "mgmt" attribute, which MUST support
45965+"add_target_attribute" and "del_target_attribute" commands as specified
45966+above.
45967+
45968+6. Both target drivers and targets MAY support "enable" attribute. If
45969+supported, after configuring the corresponding target driver or target
45970+"1" MUST be written to this attribute in the following order: at first,
45971+for all targets of the target driver, then for the target driver.
45972+
45973+For devices and dev handlers:
45974+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45975+
45976+1. Each dev handler in its root subdirectory MUST have "mgmt" attribute.
45977+
45978+2. Each dev handler MUST support "add_device" and "del_device" commands
45979+to the "mgmt" attribute as specified above.
45980+
45981+3. If dev handler driver supports run time adding new key attributes, it
45982+MUST support "add_attribute" and "del_attribute" commands to the "mgmt"
45983+attribute as specified above.
45984+
45985+4. All device handlers have links in the root subdirectory pointing to
45986+their devices.
45987+
45988+5. If device has read-only key attributes, the "add_device" command MUST
45989+support them as parameters.
45990+
45991+6. If device supports run time adding new key attributes, its dev
45992+handler MUST support "add_device_attribute" and "del_device_attribute"
45993+commands to the "mgmt" attribute as specified above.
45994+
45995+7. Each device has "handler" link to its dev handler's root
45996+subdirectory.
45997+
45998+How to distinguish and process different types of attributes
45999+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
46000+
46001+Since management utilities only interested in key attributes, they
46002+should simply ignore all non-key attributes, like
46003+devices/device_name/type or targets/target_driver/target_name/version
46004+doesn't matter if they are read-only or writable. So, the word "key"
46005+will be omitted later in this section.
46006+
46007+At first, any attribute can be a key attribute, doesn't matter how it's
46008+created.
46009+
46010+All the existing on the configuration save time attributes should be
46011+treated the same. Management utilities shouldn't try to separate anyhow
46012+them in config files.
46013+
46014+1. Always existing attributes
46015+-----------------------------
46016+
46017+There are 2 type of them:
46018+
46019+1.1. Writable, like devices/device_name/t10_dev_id or
46020+targets/qla2x00tgt/target_name/explicit_confirmation. They are the
46021+simplest and all the values can just be read and written from/to them.
46022+
46023+On the configuration save time they can be distinguished as existing.
46024+
46025+On the write configuration time they can be distinguished as existing
46026+and writable.
46027+
46028+1.2. Read-only, like devices/fileio_device_name/filename or
46029+devices/fileio_device_name/block_size. They are also easy to distinguish
46030+looking at the permissions.
46031+
46032+On the configuration save time they can be distinguished the same as for
46033+(1.1) as existing.
46034+
46035+On the write configuration time they can be distinguished as existing
46036+and read-only. They all should be passed to "add_target" or
46037+"add_device" commands for virtual targets and devices correspondingly.
46038+To apply changes to them, the whole corresponding object
46039+(fileio_device_name in this example) should be removed then recreated.
46040+
46041+2. Optional
46042+-----------
46043+
46044+For instance, targets/iscsi/IncomingUser or
46045+targets/iscsi/target_name/IncomingUser. There are 4 types of them:
46046+
46047+2.1. Global for target drivers and dev handlers
46048+-----------------------------------------------
46049+
46050+For instance, targets/iscsi/IncomingUser or handlers/vdisk_fileio/XX
46051+(none at the moment).
46052+
46053+On the configuration save time they can be distinguished the same as for
46054+(1.1).
46055+
46056+On the write configuration time they can be distinguished as one of 4
46057+choices:
46058+
46059+2.1.1. Existing and writable. In this case they should be treated as
46060+(1.1)
46061+
46062+2.1.2. Existing and read-only. In this case they should be treated as
46063+(1.2).
46064+
46065+2.1.3. Not existing. In this case they should be added using
46066+"add_attribute" command.
46067+
46068+2.1.4. Existing in the sysfs tree and not existing in the config file.
46069+In this case they should be deleted using "del_attribute" command.
46070+
46071+2.2. Global for targets
46072+-----------------------
46073+
46074+For instance, targets/iscsi/target_name/IncomingUser.
46075+
46076+On the configuration save time they can be distinguished the same as (1.1).
46077+
46078+On the write configuration time they can be distinguished as one of 4
46079+choices:
46080+
46081+2.2.1. Existing and writable. In this case they should be treated as
46082+(1.1).
46083+
46084+2.2.2. Existing and read-only. In this case they should be treated as
46085+(1.2).
46086+
46087+2.2.3. Not existing. In this case they should be added using
46088+"add_target_attribute" command.
46089+
46090+2.2.4. Existing in the sysfs tree and not existing in the config file.
46091+In this case they should be deleted using "del_target_attribute"
46092+command.
46093+
46094+2.3. Global for devices
46095+-----------------------
46096+
46097+For instance, devices/nullio/t10_dev_id.
46098+
46099+On the configuration save time they can be distinguished the same as (1.1).
46100+
46101+On the write configuration time they can be distinguished as one of 4
46102+choices:
46103+
46104+2.3.1. Existing and writable. In this case they should be treated as
46105+(1.1)
46106+
46107+2.3.2. Existing and read-only. In this case they should be treated as
46108+(1.2).
46109+
46110+2.3.3. Not existing. In this case they should be added using
46111+"add_device_attribute" command for the corresponding handler, e.g.
46112+devices/nullio/handler/.
46113+
46114+2.3.4. Existing in the sysfs tree and not existing in the config file.
46115+In this case they should be deleted using "del_device_attribute"
46116+command for the corresponding handler, e.g. devices/nullio/handler/.
46117+
46118+Thus, management utility should implement only 8 procedures: (1.1),
46119+(1.2), (2.1.3), (2.1.4), (2.2.3), (2.2.4), (2.3.3), (2.3.4).
46120+
46121+How to distinguish hardware and virtual targets
46122+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
46123+
46124+A target is hardware:
46125+
46126+ * if exist both "hw_target" attribute and "mgmt" management file
46127+
46128+ * or if both don't exist
46129+
46130+A target is virtual if there is "mgmt" file and "hw_target" attribute
46131+doesn't exist.
46132+
46133+Algorithm to convert current SCST configuration to config file
46134+--------------------------------------------------------------
46135+
46136+A management utility SHOULD use the following algorithm when converting
46137+current SCST configuration to a config file.
46138+
46139+For all attributes with digits at the end the name, the digits part
46140+should be omitted from the attributes' names during the store. For
46141+instance, "IncomingUser1" should be stored as "IncomingUser".
46142+
46143+1. Scan all attributes in /sys/kernel/scst_tgt (not recursive) and store
46144+all found key attributes.
46145+
46146+2. Scan all subdirectories of /sys/kernel/scst_tgt/handlers. Each
46147+subdirectory with "mgmt" attribute is a root subdirectory of a dev
46148+handler with name the name of the subdirectory. For each found dev
46149+handler do the following:
46150+
46151+2.1. Store the dev handler's name. Store also its path to the root
46152+subdirectory, if it isn't default (/sys/kernel/scst_tgt/handlers/handler_name).
46153+
46154+2.2. Store all dev handler's key attributes.
46155+
46156+2.3. Go through all links in the root subdirectory pointing to
46157+/sys/kernel/scst_tgt/devices and for each device:
46158+
46159+2.3.1. For virtual devices dev handlers:
46160+
46161+2.3.1.1. Store the name of the device.
46162+
46163+2.3.1.2. Store all key attributes. Mark all read only key attributes
46164+during storing, they will be parameters for the device's creation.
46165+
46166+2.3.2. For pass-through devices dev handlers:
46167+
46168+2.3.2.1. Store the H:C:I:L name of the device. Optionally, instead of
46169+the name unique T10 vendor device ID found using command:
46170+
46171+sg_inq -p 0x83 /dev/sdX
46172+
46173+can be stored. It will allow to reliably find out this device if on the
46174+next reboot it will have another host:channel:id:lin numbers. The sdX
46175+device can be found as the last letters after ':' in
46176+/sys/kernel/scst_tgt/devices/H:C:I:L/scsi_device/device/block:sdX.
46177+
46178+3. Go through all subdirectories in /sys/kernel/scst_tgt/targets. For
46179+each target driver:
46180+
46181+3.1. Store the name of the target driver.
46182+
46183+3.2. Store all its key attributes.
46184+
46185+3.3. Go through all target's subdirectories. For each target:
46186+
46187+3.3.1. Store the name of the target.
46188+
46189+3.3.2. Mark if the target is hardware or virtual target. The target is a
46190+hardware target if it has "hw_target" attribute or its target driver
46191+doesn't have "mgmt" attribute.
46192+
46193+3.3.3. Store all key attributes. Mark all read only key attributes
46194+during storing, they will be parameters for the target's creation.
46195+
46196+3.3.4. Scan all "luns" subdirectory and store:
46197+
46198+ - LUN.
46199+
46200+ - LU's device name.
46201+
46202+ - Key attributes.
46203+
46204+3.3.5. Scan all "ini_groups" subdirectories. For each group store the following:
46205+
46206+ - The group's name.
46207+
46208+ - The group's LUNs (the same info as for 3.3.4).
46209+
46210+ - The group's initiators.
46211+
46212+3.3.6. Store value of "enabled" attribute, if it exists.
46213+
46214+3.4. Store value of "enabled" attribute, if it exists.
46215+
46216+Algorithm to initialize SCST from config file
46217+---------------------------------------------
46218+
46219+A management utility SHOULD use the following algorithm when doing
46220+initial SCST configuration from a config file. All necessary kernel
46221+modules and user space programs supposed to be already loaded, hence all
46222+dev handlers' entries in /sys/kernel/scst_tgt/handlers as well as all
46223+entries for hardware targets already created.
46224+
46225+1. Set stored values for all stored global (/sys/kernel/scst_tgt)
46226+attributes.
46227+
46228+2. For each dev driver:
46229+
46230+2.1. Set stored values for all already existing stored attributes.
46231+
46232+2.2. Create not existing stored attributes using "add_attribute" command.
46233+
46234+2.3. For virtual devices dev handlers for each stored device:
46235+
46236+2.3.1. Create the device using "add_device" command using marked read
46237+only attributes as parameters.
46238+
46239+2.3.2. Set stored values for all already existing stored attributes.
46240+
46241+2.3.3. Create not existing stored attributes using
46242+"add_device_attribute" command.
46243+
46244+2.4. For pass-through dev handlers for each stores device:
46245+
46246+2.4.1. Assign the corresponding pass-through device to this dev handler
46247+using "add_device" command.
46248+
46249+3. For each target driver:
46250+
46251+3.1. Set stored values for all already existing stored attributes.
46252+
46253+3.2. Create not existing stored attributes using "add_attribute" command.
46254+
46255+3.3. For each target:
46256+
46257+3.3.1. For virtual targets:
46258+
46259+3.3.1.1. Create the target using "add_target" command using marked read
46260+only attributes as parameters.
46261+
46262+3.3.1.2. Set stored values for all already existing stored attributes.
46263+
46264+3.3.1.3. Create not existing stored attributes using
46265+"add_target_attribute" command.
46266+
46267+3.3.2. For hardware targets for each target:
46268+
46269+3.3.2.1. Set stored values for all already existing stored attributes.
46270+
46271+3.3.2.2. Create not existing stored attributes using
46272+"add_target_attribute" command.
46273+
46274+3.3.3. Setup LUNs
46275+
46276+3.3.4. Setup ini_groups, their LUNs and initiators' names.
46277+
46278+3.3.5. If this target supports enabling, enable it.
46279+
46280+3.4. If this target driver supports enabling, enable it.
46281+
46282+Algorithm to apply changes in config file to currently running SCST
46283+-------------------------------------------------------------------
46284+
46285+A management utility SHOULD use the following algorithm when applying
46286+changes in config file to currently running SCST.
46287+
46288+Not all changes can be applied on enabled targets or enabled target
46289+drivers. From other side, for some target drivers enabling/disabling is
46290+a very long and disruptive operation, which should be performed as rare
46291+as possible. Thus, the management utility SHOULD support additional
46292+option, which, if set, will make it to disable all affected targets
46293+before doing any change with them.
46294+
46295+1. Scan all attributes in /sys/kernel/scst_tgt (not recursive) and
46296+compare stored and actual key attributes. Apply all changes.
46297+
46298+2. Scan all subdirectories of /sys/kernel/scst_tgt/handlers. Each
46299+subdirectory with "mgmt" attribute is a root subdirectory of a dev
46300+handler with name the name of the subdirectory. For each found dev
46301+handler do the following:
46302+
46303+2.1. Compare stored and actual key attributes. Apply all changes. Create
46304+new attributes using "add_attribute" commands and delete not needed any
46305+more attributes using "del_attribute" command.
46306+
46307+2.2. Compare existing devices (links in the root subdirectory pointing
46308+to /sys/kernel/scst_tgt/devices) and stored devices in the config file.
46309+Delete all not needed devices and create new devices.
46310+
46311+2.3. For all existing devices:
46312+
46313+2.3.1. Compare stored and actual key attributes. Apply all changes.
46314+Create new attributes using "add_device_attribute" commands and delete
46315+not needed any more attributes using "del_device_attribute" command.
46316+
46317+2.3.2. If any read only key attribute for virtual device should be
46318+changed, delete the devices and recreate it.
46319+
46320+3. Go through all subdirectories in /sys/kernel/scst_tgt/targets. For
46321+each target driver:
46322+
46323+3.1. If this target driver should be disabled, disable it.
46324+
46325+3.2. Compare stored and actual key attributes. Apply all changes. Create
46326+new attributes using "add_attribute" commands and delete not needed any
46327+more attributes using "del_attribute" command.
46328+
46329+3.3. Go through all target's subdirectories. Compare existing and stored
46330+targets. Delete all not needed targets and create new targets.
46331+
46332+3.4. For all existing targets:
46333+
46334+3.4.1. If this target should be disabled, disable it.
46335+
46336+3.4.2. Compare stored and actual key attributes. Apply all changes.
46337+Create new attributes using "add_target_attribute" commands and delete
46338+not needed any more attributes using "del_target_attribute" command.
46339+
46340+3.4.3. If any read only key attribute for virtual target should be
46341+changed, delete the target and recreate it.
46342+
46343+3.4.4. Scan all "luns" subdirectory and apply necessary changes, using
46344+"replace" commands to replace one LUN by another, if needed.
46345+
46346+3.4.5. Scan all "ini_groups" subdirectories and apply necessary changes,
46347+using "replace" commands to replace one LUN by another and "move"
46348+command to move initiator from one group to another, if needed. It MUST
46349+be done in the following order:
46350+
46351+ - Necessary initiators deleted, if they aren't going to be moved
46352+
46353+ - LUNs updated
46354+
46355+ - Necessary initiators added or moved
46356+
46357+3.4.6. If this target should be enabled, enable it.
46358+
46359+3.5. If this target driver should be enabled, enable it.
46360+
46361diff -uprN orig/linux-2.6.35/drivers/scst/dev_handlers/Makefile linux-2.6.35/drivers/scst/dev_handlers/Makefile
46362--- orig/linux-2.6.35/drivers/scst/dev_handlers/Makefile
46363+++ linux-2.6.35/drivers/scst/dev_handlers/Makefile
46364@@ -0,0 +1,14 @@
46365+ccflags-y += -Wno-unused-parameter
46366+
46367+obj-m := scst_cdrom.o scst_changer.o scst_disk.o scst_modisk.o scst_tape.o \
46368+ scst_vdisk.o scst_raid.o scst_processor.o scst_user.o
46369+
46370+obj-$(CONFIG_SCST_DISK) += scst_disk.o
46371+obj-$(CONFIG_SCST_TAPE) += scst_tape.o
46372+obj-$(CONFIG_SCST_CDROM) += scst_cdrom.o
46373+obj-$(CONFIG_SCST_MODISK) += scst_modisk.o
46374+obj-$(CONFIG_SCST_CHANGER) += scst_changer.o
46375+obj-$(CONFIG_SCST_RAID) += scst_raid.o
46376+obj-$(CONFIG_SCST_PROCESSOR) += scst_processor.o
46377+obj-$(CONFIG_SCST_VDISK) += scst_vdisk.o
46378+obj-$(CONFIG_SCST_USER) += scst_user.o
46379diff -uprN orig/linux-2.6.35/drivers/scst/dev_handlers/scst_cdrom.c linux-2.6.35/drivers/scst/dev_handlers/scst_cdrom.c
46380--- orig/linux-2.6.35/drivers/scst/dev_handlers/scst_cdrom.c
46381+++ linux-2.6.35/drivers/scst/dev_handlers/scst_cdrom.c
46382@@ -0,0 +1,301 @@
46383+/*
46384+ * scst_cdrom.c
46385+ *
46386+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
46387+ * Copyright (C) 2004 - 2005 Leonid Stoljar
46388+ * Copyright (C) 2007 - 2010 ID7 Ltd.
46389+ *
46390+ * SCSI CDROM (type 5) dev handler
46391+ *
46392+ * This program is free software; you can redistribute it and/or
46393+ * modify it under the terms of the GNU General Public License
46394+ * as published by the Free Software Foundation, version 2
46395+ * of the License.
46396+ *
46397+ * This program is distributed in the hope that it will be useful,
46398+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
46399+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46400+ * GNU General Public License for more details.
46401+ */
46402+
46403+#include <linux/cdrom.h>
46404+#include <scsi/scsi_host.h>
46405+#include <linux/slab.h>
46406+
46407+#define LOG_PREFIX "dev_cdrom"
46408+
46409+#include <scst/scst.h>
46410+#include "scst_dev_handler.h"
46411+
46412+#define CDROM_NAME "dev_cdrom"
46413+
46414+#define CDROM_DEF_BLOCK_SHIFT 11
46415+
46416+struct cdrom_params {
46417+ int block_shift;
46418+};
46419+
46420+static int cdrom_attach(struct scst_device *);
46421+static void cdrom_detach(struct scst_device *);
46422+static int cdrom_parse(struct scst_cmd *);
46423+static int cdrom_done(struct scst_cmd *);
46424+
46425+static struct scst_dev_type cdrom_devtype = {
46426+ .name = CDROM_NAME,
46427+ .type = TYPE_ROM,
46428+ .threads_num = 1,
46429+ .parse_atomic = 1,
46430+ .dev_done_atomic = 1,
46431+ .attach = cdrom_attach,
46432+ .detach = cdrom_detach,
46433+ .parse = cdrom_parse,
46434+ .dev_done = cdrom_done,
46435+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
46436+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
46437+ .trace_flags = &trace_flag,
46438+#endif
46439+};
46440+
46441+/**************************************************************
46442+ * Function: cdrom_attach
46443+ *
46444+ * Argument:
46445+ *
46446+ * Returns : 1 if attached, error code otherwise
46447+ *
46448+ * Description:
46449+ *************************************************************/
46450+static int cdrom_attach(struct scst_device *dev)
46451+{
46452+ int res, rc;
46453+ uint8_t cmd[10];
46454+ const int buffer_size = 512;
46455+ uint8_t *buffer = NULL;
46456+ int retries;
46457+ unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
46458+ enum dma_data_direction data_dir;
46459+ struct cdrom_params *params;
46460+
46461+ TRACE_ENTRY();
46462+
46463+ if (dev->scsi_dev == NULL ||
46464+ dev->scsi_dev->type != dev->type) {
46465+ PRINT_ERROR("%s", "SCSI device not define or illegal type");
46466+ res = -ENODEV;
46467+ goto out;
46468+ }
46469+
46470+ params = kzalloc(sizeof(*params), GFP_KERNEL);
46471+ if (params == NULL) {
46472+ TRACE(TRACE_OUT_OF_MEM, "%s",
46473+ "Unable to allocate struct cdrom_params");
46474+ res = -ENOMEM;
46475+ goto out;
46476+ }
46477+
46478+ buffer = kmalloc(buffer_size, GFP_KERNEL);
46479+ if (!buffer) {
46480+ TRACE(TRACE_OUT_OF_MEM, "%s", "Memory allocation failure");
46481+ res = -ENOMEM;
46482+ goto out_free_params;
46483+ }
46484+
46485+ /* Clear any existing UA's and get cdrom capacity (cdrom block size) */
46486+ memset(cmd, 0, sizeof(cmd));
46487+ cmd[0] = READ_CAPACITY;
46488+ cmd[1] = (dev->scsi_dev->scsi_level <= SCSI_2) ?
46489+ ((dev->scsi_dev->lun << 5) & 0xe0) : 0;
46490+ retries = SCST_DEV_UA_RETRIES;
46491+ while (1) {
46492+ memset(buffer, 0, buffer_size);
46493+ memset(sense_buffer, 0, sizeof(sense_buffer));
46494+ data_dir = SCST_DATA_READ;
46495+
46496+ TRACE_DBG("%s", "Doing READ_CAPACITY");
46497+ rc = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
46498+ buffer_size, sense_buffer,
46499+ SCST_GENERIC_CDROM_REG_TIMEOUT, 3, 0
46500+ , NULL
46501+ );
46502+
46503+ TRACE_DBG("READ_CAPACITY done: %x", rc);
46504+
46505+ if ((rc == 0) ||
46506+ !scst_analyze_sense(sense_buffer,
46507+ sizeof(sense_buffer), SCST_SENSE_KEY_VALID,
46508+ UNIT_ATTENTION, 0, 0))
46509+ break;
46510+
46511+ if (!--retries) {
46512+ PRINT_ERROR("UA not cleared after %d retries",
46513+ SCST_DEV_UA_RETRIES);
46514+ params->block_shift = CDROM_DEF_BLOCK_SHIFT;
46515+ res = -ENODEV;
46516+ goto out_free_buf;
46517+ }
46518+ }
46519+
46520+ if (rc == 0) {
46521+ int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
46522+ (buffer[6] << 8) | (buffer[7] << 0));
46523+ if (sector_size == 0)
46524+ params->block_shift = CDROM_DEF_BLOCK_SHIFT;
46525+ else
46526+ params->block_shift =
46527+ scst_calc_block_shift(sector_size);
46528+ TRACE_DBG("Sector size is %i scsi_level %d(SCSI_2 %d)",
46529+ sector_size, dev->scsi_dev->scsi_level, SCSI_2);
46530+ } else {
46531+ params->block_shift = CDROM_DEF_BLOCK_SHIFT;
46532+ TRACE(TRACE_MINOR, "Read capacity failed: %x, using default "
46533+ "sector size %d", rc, params->block_shift);
46534+ PRINT_BUFF_FLAG(TRACE_MINOR, "Returned sense", sense_buffer,
46535+ sizeof(sense_buffer));
46536+ }
46537+
46538+ res = scst_obtain_device_parameters(dev);
46539+ if (res != 0) {
46540+ PRINT_ERROR("Failed to obtain control parameters for device "
46541+ "%s", dev->virt_name);
46542+ goto out_free_buf;
46543+ }
46544+
46545+out_free_buf:
46546+ kfree(buffer);
46547+
46548+out_free_params:
46549+ if (res == 0)
46550+ dev->dh_priv = params;
46551+ else
46552+ kfree(params);
46553+
46554+out:
46555+ TRACE_EXIT();
46556+ return res;
46557+}
46558+
46559+/************************************************************
46560+ * Function: cdrom_detach
46561+ *
46562+ * Argument:
46563+ *
46564+ * Returns : None
46565+ *
46566+ * Description: Called to detach this device type driver
46567+ ************************************************************/
46568+static void cdrom_detach(struct scst_device *dev)
46569+{
46570+ struct cdrom_params *params =
46571+ (struct cdrom_params *)dev->dh_priv;
46572+
46573+ TRACE_ENTRY();
46574+
46575+ kfree(params);
46576+ dev->dh_priv = NULL;
46577+
46578+ TRACE_EXIT();
46579+ return;
46580+}
46581+
46582+static int cdrom_get_block_shift(struct scst_cmd *cmd)
46583+{
46584+ struct cdrom_params *params = (struct cdrom_params *)cmd->dev->dh_priv;
46585+ /*
46586+ * No need for locks here, since *_detach() can not be
46587+ * called, when there are existing commands.
46588+ */
46589+ return params->block_shift;
46590+}
46591+
46592+/********************************************************************
46593+ * Function: cdrom_parse
46594+ *
46595+ * Argument:
46596+ *
46597+ * Returns : The state of the command
46598+ *
46599+ * Description: This does the parsing of the command
46600+ *
46601+ * Note: Not all states are allowed on return
46602+ ********************************************************************/
46603+static int cdrom_parse(struct scst_cmd *cmd)
46604+{
46605+ int res = SCST_CMD_STATE_DEFAULT;
46606+
46607+ scst_cdrom_generic_parse(cmd, cdrom_get_block_shift);
46608+
46609+ cmd->retries = SCST_PASSTHROUGH_RETRIES;
46610+
46611+ return res;
46612+}
46613+
46614+static void cdrom_set_block_shift(struct scst_cmd *cmd, int block_shift)
46615+{
46616+ struct cdrom_params *params = (struct cdrom_params *)cmd->dev->dh_priv;
46617+ /*
46618+ * No need for locks here, since *_detach() can not be
46619+ * called, when there are existing commands.
46620+ */
46621+ if (block_shift != 0)
46622+ params->block_shift = block_shift;
46623+ else
46624+ params->block_shift = CDROM_DEF_BLOCK_SHIFT;
46625+ return;
46626+}
46627+
46628+/********************************************************************
46629+ * Function: cdrom_done
46630+ *
46631+ * Argument:
46632+ *
46633+ * Returns :
46634+ *
46635+ * Description: This is the completion routine for the command,
46636+ * it is used to extract any necessary information
46637+ * about a command.
46638+ ********************************************************************/
46639+static int cdrom_done(struct scst_cmd *cmd)
46640+{
46641+ int res = SCST_CMD_STATE_DEFAULT;
46642+
46643+ TRACE_ENTRY();
46644+
46645+ res = scst_block_generic_dev_done(cmd, cdrom_set_block_shift);
46646+
46647+ TRACE_EXIT_RES(res);
46648+ return res;
46649+}
46650+
46651+static int __init cdrom_init(void)
46652+{
46653+ int res = 0;
46654+
46655+ TRACE_ENTRY();
46656+
46657+ cdrom_devtype.module = THIS_MODULE;
46658+
46659+ res = scst_register_dev_driver(&cdrom_devtype);
46660+ if (res < 0)
46661+ goto out;
46662+
46663+out:
46664+ TRACE_EXIT();
46665+ return res;
46666+
46667+}
46668+
46669+static void __exit cdrom_exit(void)
46670+{
46671+ TRACE_ENTRY();
46672+ scst_unregister_dev_driver(&cdrom_devtype);
46673+ TRACE_EXIT();
46674+ return;
46675+}
46676+
46677+module_init(cdrom_init);
46678+module_exit(cdrom_exit);
46679+
46680+MODULE_LICENSE("GPL");
46681+MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
46682+MODULE_DESCRIPTION("SCSI CDROM (type 5) dev handler for SCST");
46683+MODULE_VERSION(SCST_VERSION_STRING);
46684diff -uprN orig/linux-2.6.35/drivers/scst/dev_handlers/scst_changer.c linux-2.6.35/drivers/scst/dev_handlers/scst_changer.c
46685--- orig/linux-2.6.35/drivers/scst/dev_handlers/scst_changer.c
46686+++ linux-2.6.35/drivers/scst/dev_handlers/scst_changer.c
46687@@ -0,0 +1,222 @@
46688+/*
46689+ * scst_changer.c
46690+ *
46691+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
46692+ * Copyright (C) 2004 - 2005 Leonid Stoljar
46693+ * Copyright (C) 2007 - 2010 ID7 Ltd.
46694+ *
46695+ * SCSI medium changer (type 8) dev handler
46696+ *
46697+ * This program is free software; you can redistribute it and/or
46698+ * modify it under the terms of the GNU General Public License
46699+ * as published by the Free Software Foundation, version 2
46700+ * of the License.
46701+ *
46702+ * This program is distributed in the hope that it will be useful,
46703+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
46704+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46705+ * GNU General Public License for more details.
46706+ */
46707+
46708+#include <scsi/scsi_host.h>
46709+#include <linux/slab.h>
46710+
46711+#define LOG_PREFIX "dev_changer"
46712+
46713+#include <scst/scst.h>
46714+#include "scst_dev_handler.h"
46715+
46716+#define CHANGER_NAME "dev_changer"
46717+
46718+#define CHANGER_RETRIES 2
46719+
46720+static int changer_attach(struct scst_device *);
46721+/* static void changer_detach(struct scst_device *); */
46722+static int changer_parse(struct scst_cmd *);
46723+/* static int changer_done(struct scst_cmd *); */
46724+
46725+static struct scst_dev_type changer_devtype = {
46726+ .name = CHANGER_NAME,
46727+ .type = TYPE_MEDIUM_CHANGER,
46728+ .threads_num = 1,
46729+ .parse_atomic = 1,
46730+/* .dev_done_atomic = 1, */
46731+ .attach = changer_attach,
46732+/* .detach = changer_detach, */
46733+ .parse = changer_parse,
46734+/* .dev_done = changer_done */
46735+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
46736+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
46737+ .trace_flags = &trace_flag,
46738+#endif
46739+};
46740+
46741+/**************************************************************
46742+ * Function: changer_attach
46743+ *
46744+ * Argument:
46745+ *
46746+ * Returns : 1 if attached, error code otherwise
46747+ *
46748+ * Description:
46749+ *************************************************************/
46750+static int changer_attach(struct scst_device *dev)
46751+{
46752+ int res, rc;
46753+ int retries;
46754+
46755+ TRACE_ENTRY();
46756+
46757+ if (dev->scsi_dev == NULL ||
46758+ dev->scsi_dev->type != dev->type) {
46759+ PRINT_ERROR("%s", "SCSI device not define or illegal type");
46760+ res = -ENODEV;
46761+ goto out;
46762+ }
46763+
46764+ /*
46765+ * If the device is offline, don't try to read capacity or any
46766+ * of the other stuff
46767+ */
46768+ if (dev->scsi_dev->sdev_state == SDEV_OFFLINE) {
46769+ TRACE_DBG("%s", "Device is offline");
46770+ res = -ENODEV;
46771+ goto out;
46772+ }
46773+
46774+ retries = SCST_DEV_UA_RETRIES;
46775+ do {
46776+ TRACE_DBG("%s", "Doing TEST_UNIT_READY");
46777+ rc = scsi_test_unit_ready(dev->scsi_dev,
46778+ SCST_GENERIC_CHANGER_TIMEOUT, CHANGER_RETRIES
46779+ , NULL);
46780+ TRACE_DBG("TEST_UNIT_READY done: %x", rc);
46781+ } while ((--retries > 0) && rc);
46782+
46783+ if (rc) {
46784+ PRINT_WARNING("Unit not ready: %x", rc);
46785+ /* Let's try not to be too smart and continue processing */
46786+ }
46787+
46788+ res = scst_obtain_device_parameters(dev);
46789+ if (res != 0) {
46790+ PRINT_ERROR("Failed to obtain control parameters for device "
46791+ "%s", dev->virt_name);
46792+ goto out;
46793+ }
46794+
46795+out:
46796+ TRACE_EXIT_HRES(res);
46797+ return res;
46798+}
46799+
46800+/************************************************************
46801+ * Function: changer_detach
46802+ *
46803+ * Argument:
46804+ *
46805+ * Returns : None
46806+ *
46807+ * Description: Called to detach this device type driver
46808+ ************************************************************/
46809+#if 0
46810+void changer_detach(struct scst_device *dev)
46811+{
46812+ TRACE_ENTRY();
46813+
46814+ TRACE_EXIT();
46815+ return;
46816+}
46817+#endif
46818+
46819+/********************************************************************
46820+ * Function: changer_parse
46821+ *
46822+ * Argument:
46823+ *
46824+ * Returns : The state of the command
46825+ *
46826+ * Description: This does the parsing of the command
46827+ *
46828+ * Note: Not all states are allowed on return
46829+ ********************************************************************/
46830+static int changer_parse(struct scst_cmd *cmd)
46831+{
46832+ int res = SCST_CMD_STATE_DEFAULT;
46833+
46834+ scst_changer_generic_parse(cmd, NULL);
46835+
46836+ cmd->retries = SCST_PASSTHROUGH_RETRIES;
46837+
46838+ return res;
46839+}
46840+
46841+/********************************************************************
46842+ * Function: changer_done
46843+ *
46844+ * Argument:
46845+ *
46846+ * Returns :
46847+ *
46848+ * Description: This is the completion routine for the command,
46849+ * it is used to extract any necessary information
46850+ * about a command.
46851+ ********************************************************************/
46852+#if 0
46853+int changer_done(struct scst_cmd *cmd)
46854+{
46855+ int res = SCST_CMD_STATE_DEFAULT;
46856+
46857+ TRACE_ENTRY();
46858+
46859+ /*
46860+ * SCST sets good defaults for cmd->is_send_status and
46861+ * cmd->resp_data_len based on cmd->status and cmd->data_direction,
46862+ * therefore change them only if necessary
46863+ */
46864+
46865+#if 0
46866+ switch (cmd->cdb[0]) {
46867+ default:
46868+ /* It's all good */
46869+ break;
46870+ }
46871+#endif
46872+
46873+ TRACE_EXIT();
46874+ return res;
46875+}
46876+#endif
46877+
46878+static int __init changer_init(void)
46879+{
46880+ int res = 0;
46881+
46882+ TRACE_ENTRY();
46883+
46884+ changer_devtype.module = THIS_MODULE;
46885+
46886+ res = scst_register_dev_driver(&changer_devtype);
46887+ if (res < 0)
46888+ goto out;
46889+
46890+out:
46891+ TRACE_EXIT_RES(res);
46892+ return res;
46893+}
46894+
46895+static void __exit changer_exit(void)
46896+{
46897+ TRACE_ENTRY();
46898+ scst_unregister_dev_driver(&changer_devtype);
46899+ TRACE_EXIT();
46900+ return;
46901+}
46902+
46903+module_init(changer_init);
46904+module_exit(changer_exit);
46905+
46906+MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
46907+MODULE_LICENSE("GPL");
46908+MODULE_DESCRIPTION("SCSI medium changer (type 8) dev handler for SCST");
46909+MODULE_VERSION(SCST_VERSION_STRING);
46910diff -uprN orig/linux-2.6.35/drivers/scst/dev_handlers/scst_dev_handler.h linux-2.6.35/drivers/scst/dev_handlers/scst_dev_handler.h
46911--- orig/linux-2.6.35/drivers/scst/dev_handlers/scst_dev_handler.h
46912+++ linux-2.6.35/drivers/scst/dev_handlers/scst_dev_handler.h
46913@@ -0,0 +1,27 @@
46914+#ifndef __SCST_DEV_HANDLER_H
46915+#define __SCST_DEV_HANDLER_H
46916+
46917+#include <linux/module.h>
46918+#include <scsi/scsi_eh.h>
46919+#include <scst/scst_debug.h>
46920+
46921+#define SCST_DEV_UA_RETRIES 5
46922+#define SCST_PASSTHROUGH_RETRIES 0
46923+
46924+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
46925+
46926+#ifdef CONFIG_SCST_DEBUG
46927+#define SCST_DEFAULT_DEV_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_PID | \
46928+ TRACE_LINE | TRACE_FUNCTION | TRACE_MGMT | TRACE_MINOR | \
46929+ TRACE_MGMT_DEBUG | TRACE_SPECIAL)
46930+#else
46931+#define SCST_DEFAULT_DEV_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
46932+ TRACE_SPECIAL)
46933+#endif
46934+
46935+static unsigned long dh_trace_flag = SCST_DEFAULT_DEV_LOG_FLAGS;
46936+#define trace_flag dh_trace_flag
46937+
46938+#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
46939+
46940+#endif /* __SCST_DEV_HANDLER_H */
46941diff -uprN orig/linux-2.6.35/drivers/scst/dev_handlers/scst_disk.c linux-2.6.35/drivers/scst/dev_handlers/scst_disk.c
46942--- orig/linux-2.6.35/drivers/scst/dev_handlers/scst_disk.c
46943+++ linux-2.6.35/drivers/scst/dev_handlers/scst_disk.c
46944@@ -0,0 +1,379 @@
46945+/*
46946+ * scst_disk.c
46947+ *
46948+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
46949+ * Copyright (C) 2004 - 2005 Leonid Stoljar
46950+ * Copyright (C) 2007 - 2010 ID7 Ltd.
46951+ *
46952+ * SCSI disk (type 0) dev handler
46953+ * &
46954+ * SCSI disk (type 0) "performance" device handler (skip all READ and WRITE
46955+ * operations).
46956+ *
46957+ * This program is free software; you can redistribute it and/or
46958+ * modify it under the terms of the GNU General Public License
46959+ * as published by the Free Software Foundation, version 2
46960+ * of the License.
46961+ *
46962+ * This program is distributed in the hope that it will be useful,
46963+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
46964+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46965+ * GNU General Public License for more details.
46966+ */
46967+
46968+#include <linux/module.h>
46969+#include <linux/init.h>
46970+#include <scsi/scsi_host.h>
46971+#include <linux/slab.h>
46972+
46973+#define LOG_PREFIX "dev_disk"
46974+
46975+#include <scst/scst.h>
46976+#include "scst_dev_handler.h"
46977+
46978+# define DISK_NAME "dev_disk"
46979+# define DISK_PERF_NAME "dev_disk_perf"
46980+
46981+#define DISK_DEF_BLOCK_SHIFT 9
46982+
46983+struct disk_params {
46984+ int block_shift;
46985+};
46986+
46987+static int disk_attach(struct scst_device *dev);
46988+static void disk_detach(struct scst_device *dev);
46989+static int disk_parse(struct scst_cmd *cmd);
46990+static int disk_done(struct scst_cmd *cmd);
46991+static int disk_exec(struct scst_cmd *cmd);
46992+
46993+static struct scst_dev_type disk_devtype = {
46994+ .name = DISK_NAME,
46995+ .type = TYPE_DISK,
46996+ .threads_num = 1,
46997+ .parse_atomic = 1,
46998+ .dev_done_atomic = 1,
46999+ .attach = disk_attach,
47000+ .detach = disk_detach,
47001+ .parse = disk_parse,
47002+ .dev_done = disk_done,
47003+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
47004+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
47005+ .trace_flags = &trace_flag,
47006+#endif
47007+};
47008+
47009+static struct scst_dev_type disk_devtype_perf = {
47010+ .name = DISK_PERF_NAME,
47011+ .type = TYPE_DISK,
47012+ .parse_atomic = 1,
47013+ .dev_done_atomic = 1,
47014+ .attach = disk_attach,
47015+ .detach = disk_detach,
47016+ .parse = disk_parse,
47017+ .dev_done = disk_done,
47018+ .exec = disk_exec,
47019+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
47020+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
47021+ .trace_flags = &trace_flag,
47022+#endif
47023+};
47024+
47025+static int __init init_scst_disk_driver(void)
47026+{
47027+ int res = 0;
47028+
47029+ TRACE_ENTRY();
47030+
47031+ disk_devtype.module = THIS_MODULE;
47032+
47033+ res = scst_register_dev_driver(&disk_devtype);
47034+ if (res < 0)
47035+ goto out;
47036+
47037+ disk_devtype_perf.module = THIS_MODULE;
47038+
47039+ res = scst_register_dev_driver(&disk_devtype_perf);
47040+ if (res < 0)
47041+ goto out_unreg;
47042+
47043+out:
47044+ TRACE_EXIT_RES(res);
47045+ return res;
47046+
47047+out_unreg:
47048+ scst_unregister_dev_driver(&disk_devtype);
47049+ goto out;
47050+}
47051+
47052+static void __exit exit_scst_disk_driver(void)
47053+{
47054+ TRACE_ENTRY();
47055+
47056+ scst_unregister_dev_driver(&disk_devtype_perf);
47057+ scst_unregister_dev_driver(&disk_devtype);
47058+
47059+ TRACE_EXIT();
47060+ return;
47061+}
47062+
47063+module_init(init_scst_disk_driver);
47064+module_exit(exit_scst_disk_driver);
47065+
47066+/**************************************************************
47067+ * Function: disk_attach
47068+ *
47069+ * Argument:
47070+ *
47071+ * Returns : 1 if attached, error code otherwise
47072+ *
47073+ * Description:
47074+ *************************************************************/
47075+static int disk_attach(struct scst_device *dev)
47076+{
47077+ int res, rc;
47078+ uint8_t cmd[10];
47079+ const int buffer_size = 512;
47080+ uint8_t *buffer = NULL;
47081+ int retries;
47082+ unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
47083+ enum dma_data_direction data_dir;
47084+ struct disk_params *params;
47085+
47086+ TRACE_ENTRY();
47087+
47088+ if (dev->scsi_dev == NULL ||
47089+ dev->scsi_dev->type != dev->type) {
47090+ PRINT_ERROR("%s", "SCSI device not define or illegal type");
47091+ res = -ENODEV;
47092+ goto out;
47093+ }
47094+
47095+ params = kzalloc(sizeof(*params), GFP_KERNEL);
47096+ if (params == NULL) {
47097+ TRACE(TRACE_OUT_OF_MEM, "%s",
47098+ "Unable to allocate struct disk_params");
47099+ res = -ENOMEM;
47100+ goto out;
47101+ }
47102+
47103+ buffer = kmalloc(buffer_size, GFP_KERNEL);
47104+ if (!buffer) {
47105+ TRACE(TRACE_OUT_OF_MEM, "%s", "Memory allocation failure");
47106+ res = -ENOMEM;
47107+ goto out_free_params;
47108+ }
47109+
47110+ /* Clear any existing UA's and get disk capacity (disk block size) */
47111+ memset(cmd, 0, sizeof(cmd));
47112+ cmd[0] = READ_CAPACITY;
47113+ cmd[1] = (dev->scsi_dev->scsi_level <= SCSI_2) ?
47114+ ((dev->scsi_dev->lun << 5) & 0xe0) : 0;
47115+ retries = SCST_DEV_UA_RETRIES;
47116+ while (1) {
47117+ memset(buffer, 0, buffer_size);
47118+ memset(sense_buffer, 0, sizeof(sense_buffer));
47119+ data_dir = SCST_DATA_READ;
47120+
47121+ TRACE_DBG("%s", "Doing READ_CAPACITY");
47122+ rc = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
47123+ buffer_size, sense_buffer,
47124+ SCST_GENERIC_DISK_REG_TIMEOUT, 3, 0
47125+ , NULL
47126+ );
47127+
47128+ TRACE_DBG("READ_CAPACITY done: %x", rc);
47129+
47130+ if ((rc == 0) ||
47131+ !scst_analyze_sense(sense_buffer,
47132+ sizeof(sense_buffer), SCST_SENSE_KEY_VALID,
47133+ UNIT_ATTENTION, 0, 0))
47134+ break;
47135+ if (!--retries) {
47136+ PRINT_ERROR("UA not clear after %d retries",
47137+ SCST_DEV_UA_RETRIES);
47138+ res = -ENODEV;
47139+ goto out_free_buf;
47140+ }
47141+ }
47142+ if (rc == 0) {
47143+ int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
47144+ (buffer[6] << 8) | (buffer[7] << 0));
47145+ if (sector_size == 0)
47146+ params->block_shift = DISK_DEF_BLOCK_SHIFT;
47147+ else
47148+ params->block_shift =
47149+ scst_calc_block_shift(sector_size);
47150+ } else {
47151+ params->block_shift = DISK_DEF_BLOCK_SHIFT;
47152+ TRACE(TRACE_MINOR, "Read capacity failed: %x, using default "
47153+ "sector size %d", rc, params->block_shift);
47154+ PRINT_BUFF_FLAG(TRACE_MINOR, "Returned sense", sense_buffer,
47155+ sizeof(sense_buffer));
47156+ }
47157+
47158+ res = scst_obtain_device_parameters(dev);
47159+ if (res != 0) {
47160+ PRINT_ERROR("Failed to obtain control parameters for device "
47161+ "%s", dev->virt_name);
47162+ goto out_free_buf;
47163+ }
47164+
47165+out_free_buf:
47166+ kfree(buffer);
47167+
47168+out_free_params:
47169+ if (res == 0)
47170+ dev->dh_priv = params;
47171+ else
47172+ kfree(params);
47173+
47174+out:
47175+ TRACE_EXIT_RES(res);
47176+ return res;
47177+}
47178+
47179+/************************************************************
47180+ * Function: disk_detach
47181+ *
47182+ * Argument:
47183+ *
47184+ * Returns : None
47185+ *
47186+ * Description: Called to detach this device type driver
47187+ ************************************************************/
47188+static void disk_detach(struct scst_device *dev)
47189+{
47190+ struct disk_params *params =
47191+ (struct disk_params *)dev->dh_priv;
47192+
47193+ TRACE_ENTRY();
47194+
47195+ kfree(params);
47196+ dev->dh_priv = NULL;
47197+
47198+ TRACE_EXIT();
47199+ return;
47200+}
47201+
47202+static int disk_get_block_shift(struct scst_cmd *cmd)
47203+{
47204+ struct disk_params *params = (struct disk_params *)cmd->dev->dh_priv;
47205+ /*
47206+ * No need for locks here, since *_detach() can not be
47207+ * called, when there are existing commands.
47208+ */
47209+ return params->block_shift;
47210+}
47211+
47212+/********************************************************************
47213+ * Function: disk_parse
47214+ *
47215+ * Argument:
47216+ *
47217+ * Returns : The state of the command
47218+ *
47219+ * Description: This does the parsing of the command
47220+ *
47221+ * Note: Not all states are allowed on return
47222+ ********************************************************************/
47223+static int disk_parse(struct scst_cmd *cmd)
47224+{
47225+ int res = SCST_CMD_STATE_DEFAULT;
47226+
47227+ scst_sbc_generic_parse(cmd, disk_get_block_shift);
47228+
47229+ cmd->retries = SCST_PASSTHROUGH_RETRIES;
47230+
47231+ return res;
47232+}
47233+
47234+static void disk_set_block_shift(struct scst_cmd *cmd, int block_shift)
47235+{
47236+ struct disk_params *params = (struct disk_params *)cmd->dev->dh_priv;
47237+ /*
47238+ * No need for locks here, since *_detach() can not be
47239+ * called, when there are existing commands.
47240+ */
47241+ if (block_shift != 0)
47242+ params->block_shift = block_shift;
47243+ else
47244+ params->block_shift = DISK_DEF_BLOCK_SHIFT;
47245+ return;
47246+}
47247+
47248+/********************************************************************
47249+ * Function: disk_done
47250+ *
47251+ * Argument:
47252+ *
47253+ * Returns :
47254+ *
47255+ * Description: This is the completion routine for the command,
47256+ * it is used to extract any necessary information
47257+ * about a command.
47258+ ********************************************************************/
47259+static int disk_done(struct scst_cmd *cmd)
47260+{
47261+ int res = SCST_CMD_STATE_DEFAULT;
47262+
47263+ TRACE_ENTRY();
47264+
47265+ res = scst_block_generic_dev_done(cmd, disk_set_block_shift);
47266+
47267+ TRACE_EXIT_RES(res);
47268+ return res;
47269+}
47270+
47271+/********************************************************************
47272+ * Function: disk_exec
47273+ *
47274+ * Argument:
47275+ *
47276+ * Returns :
47277+ *
47278+ * Description: Make SCST do nothing for data READs and WRITES.
47279+ * Intended for raw line performance testing
47280+ ********************************************************************/
47281+static int disk_exec(struct scst_cmd *cmd)
47282+{
47283+ int res = SCST_EXEC_NOT_COMPLETED, rc;
47284+ int opcode = cmd->cdb[0];
47285+
47286+ TRACE_ENTRY();
47287+
47288+ rc = scst_check_local_events(cmd);
47289+ if (unlikely(rc != 0))
47290+ goto out_done;
47291+
47292+ cmd->status = 0;
47293+ cmd->msg_status = 0;
47294+ cmd->host_status = DID_OK;
47295+ cmd->driver_status = 0;
47296+
47297+ switch (opcode) {
47298+ case WRITE_6:
47299+ case WRITE_10:
47300+ case WRITE_12:
47301+ case WRITE_16:
47302+ case READ_6:
47303+ case READ_10:
47304+ case READ_12:
47305+ case READ_16:
47306+ cmd->completed = 1;
47307+ goto out_done;
47308+ }
47309+
47310+out:
47311+ TRACE_EXIT_RES(res);
47312+ return res;
47313+
47314+out_done:
47315+ res = SCST_EXEC_COMPLETED;
47316+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
47317+ goto out;
47318+}
47319+
47320+MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
47321+MODULE_LICENSE("GPL");
47322+MODULE_DESCRIPTION("SCSI disk (type 0) dev handler for SCST");
47323+MODULE_VERSION(SCST_VERSION_STRING);
47324diff -uprN orig/linux-2.6.35/drivers/scst/dev_handlers/scst_modisk.c linux-2.6.35/drivers/scst/dev_handlers/scst_modisk.c
47325--- orig/linux-2.6.35/drivers/scst/dev_handlers/scst_modisk.c
47326+++ linux-2.6.35/drivers/scst/dev_handlers/scst_modisk.c
47327@@ -0,0 +1,398 @@
47328+/*
47329+ * scst_modisk.c
47330+ *
47331+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
47332+ * Copyright (C) 2004 - 2005 Leonid Stoljar
47333+ * Copyright (C) 2007 - 2010 ID7 Ltd.
47334+ *
47335+ * SCSI MO disk (type 7) dev handler
47336+ * &
47337+ * SCSI MO disk (type 7) "performance" device handler (skip all READ and WRITE
47338+ * operations).
47339+ *
47340+ * This program is free software; you can redistribute it and/or
47341+ * modify it under the terms of the GNU General Public License
47342+ * as published by the Free Software Foundation, version 2
47343+ * of the License.
47344+ *
47345+ * This program is distributed in the hope that it will be useful,
47346+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
47347+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47348+ * GNU General Public License for more details.
47349+ */
47350+
47351+#include <linux/module.h>
47352+#include <linux/init.h>
47353+#include <scsi/scsi_host.h>
47354+#include <linux/slab.h>
47355+
47356+#define LOG_PREFIX "dev_modisk"
47357+
47358+#include <scst/scst.h>
47359+#include "scst_dev_handler.h"
47360+
47361+# define MODISK_NAME "dev_modisk"
47362+# define MODISK_PERF_NAME "dev_modisk_perf"
47363+
47364+#define MODISK_DEF_BLOCK_SHIFT 10
47365+
47366+struct modisk_params {
47367+ int block_shift;
47368+};
47369+
47370+static int modisk_attach(struct scst_device *);
47371+static void modisk_detach(struct scst_device *);
47372+static int modisk_parse(struct scst_cmd *);
47373+static int modisk_done(struct scst_cmd *);
47374+static int modisk_exec(struct scst_cmd *);
47375+
47376+static struct scst_dev_type modisk_devtype = {
47377+ .name = MODISK_NAME,
47378+ .type = TYPE_MOD,
47379+ .threads_num = 1,
47380+ .parse_atomic = 1,
47381+ .dev_done_atomic = 1,
47382+ .attach = modisk_attach,
47383+ .detach = modisk_detach,
47384+ .parse = modisk_parse,
47385+ .dev_done = modisk_done,
47386+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
47387+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
47388+ .trace_flags = &trace_flag,
47389+#endif
47390+};
47391+
47392+static struct scst_dev_type modisk_devtype_perf = {
47393+ .name = MODISK_PERF_NAME,
47394+ .type = TYPE_MOD,
47395+ .parse_atomic = 1,
47396+ .dev_done_atomic = 1,
47397+ .attach = modisk_attach,
47398+ .detach = modisk_detach,
47399+ .parse = modisk_parse,
47400+ .dev_done = modisk_done,
47401+ .exec = modisk_exec,
47402+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
47403+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
47404+ .trace_flags = &trace_flag,
47405+#endif
47406+};
47407+
47408+static int __init init_scst_modisk_driver(void)
47409+{
47410+ int res = 0;
47411+
47412+ TRACE_ENTRY();
47413+
47414+ modisk_devtype.module = THIS_MODULE;
47415+
47416+ res = scst_register_dev_driver(&modisk_devtype);
47417+ if (res < 0)
47418+ goto out;
47419+
47420+ modisk_devtype_perf.module = THIS_MODULE;
47421+
47422+ res = scst_register_dev_driver(&modisk_devtype_perf);
47423+ if (res < 0)
47424+ goto out_unreg;
47425+
47426+out:
47427+ TRACE_EXIT_RES(res);
47428+ return res;
47429+
47430+out_unreg:
47431+ scst_unregister_dev_driver(&modisk_devtype);
47432+ goto out;
47433+}
47434+
47435+static void __exit exit_scst_modisk_driver(void)
47436+{
47437+ TRACE_ENTRY();
47438+
47439+ scst_unregister_dev_driver(&modisk_devtype_perf);
47440+ scst_unregister_dev_driver(&modisk_devtype);
47441+
47442+ TRACE_EXIT();
47443+ return;
47444+}
47445+
47446+module_init(init_scst_modisk_driver);
47447+module_exit(exit_scst_modisk_driver);
47448+
47449+/**************************************************************
47450+ * Function: modisk_attach
47451+ *
47452+ * Argument:
47453+ *
47454+ * Returns : 1 if attached, error code otherwise
47455+ *
47456+ * Description:
47457+ *************************************************************/
47458+static int modisk_attach(struct scst_device *dev)
47459+{
47460+ int res, rc;
47461+ uint8_t cmd[10];
47462+ const int buffer_size = 512;
47463+ uint8_t *buffer = NULL;
47464+ int retries;
47465+ unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
47466+ enum dma_data_direction data_dir;
47467+ struct modisk_params *params;
47468+
47469+ TRACE_ENTRY();
47470+
47471+ if (dev->scsi_dev == NULL ||
47472+ dev->scsi_dev->type != dev->type) {
47473+ PRINT_ERROR("%s", "SCSI device not define or illegal type");
47474+ res = -ENODEV;
47475+ goto out;
47476+ }
47477+
47478+ params = kzalloc(sizeof(*params), GFP_KERNEL);
47479+ if (params == NULL) {
47480+ TRACE(TRACE_OUT_OF_MEM, "%s",
47481+ "Unable to allocate struct modisk_params");
47482+ res = -ENOMEM;
47483+ goto out;
47484+ }
47485+ params->block_shift = MODISK_DEF_BLOCK_SHIFT;
47486+
47487+ /*
47488+ * If the device is offline, don't try to read capacity or any
47489+ * of the other stuff
47490+ */
47491+ if (dev->scsi_dev->sdev_state == SDEV_OFFLINE) {
47492+ TRACE_DBG("%s", "Device is offline");
47493+ res = -ENODEV;
47494+ goto out_free_params;
47495+ }
47496+
47497+ buffer = kmalloc(buffer_size, GFP_KERNEL);
47498+ if (!buffer) {
47499+ TRACE(TRACE_OUT_OF_MEM, "%s", "Memory allocation failure");
47500+ res = -ENOMEM;
47501+ goto out_free_params;
47502+ }
47503+
47504+ /*
47505+ * Clear any existing UA's and get modisk capacity (modisk block
47506+ * size).
47507+ */
47508+ memset(cmd, 0, sizeof(cmd));
47509+ cmd[0] = READ_CAPACITY;
47510+ cmd[1] = (dev->scsi_dev->scsi_level <= SCSI_2) ?
47511+ ((dev->scsi_dev->lun << 5) & 0xe0) : 0;
47512+ retries = SCST_DEV_UA_RETRIES;
47513+ while (1) {
47514+ memset(buffer, 0, buffer_size);
47515+ memset(sense_buffer, 0, sizeof(sense_buffer));
47516+ data_dir = SCST_DATA_READ;
47517+
47518+ TRACE_DBG("%s", "Doing READ_CAPACITY");
47519+ rc = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
47520+ buffer_size, sense_buffer,
47521+ SCST_GENERIC_MODISK_REG_TIMEOUT, 3, 0
47522+ , NULL
47523+ );
47524+
47525+ TRACE_DBG("READ_CAPACITY done: %x", rc);
47526+
47527+ if (!rc || !scst_analyze_sense(sense_buffer,
47528+ sizeof(sense_buffer), SCST_SENSE_KEY_VALID,
47529+ UNIT_ATTENTION, 0, 0))
47530+ break;
47531+
47532+ if (!--retries) {
47533+ PRINT_ERROR("UA not cleared after %d retries",
47534+ SCST_DEV_UA_RETRIES);
47535+ res = -ENODEV;
47536+ goto out_free_buf;
47537+ }
47538+ }
47539+
47540+ if (rc == 0) {
47541+ int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
47542+ (buffer[6] << 8) | (buffer[7] << 0));
47543+ if (sector_size == 0)
47544+ params->block_shift = MODISK_DEF_BLOCK_SHIFT;
47545+ else
47546+ params->block_shift =
47547+ scst_calc_block_shift(sector_size);
47548+ TRACE_DBG("Sector size is %i scsi_level %d(SCSI_2 %d)",
47549+ sector_size, dev->scsi_dev->scsi_level, SCSI_2);
47550+ } else {
47551+ params->block_shift = MODISK_DEF_BLOCK_SHIFT;
47552+ TRACE(TRACE_MINOR, "Read capacity failed: %x, using default "
47553+ "sector size %d", rc, params->block_shift);
47554+ PRINT_BUFF_FLAG(TRACE_MINOR, "Returned sense", sense_buffer,
47555+ sizeof(sense_buffer));
47556+ }
47557+
47558+ res = scst_obtain_device_parameters(dev);
47559+ if (res != 0) {
47560+ PRINT_ERROR("Failed to obtain control parameters for device "
47561+ "%s: %x", dev->virt_name, res);
47562+ goto out_free_buf;
47563+ }
47564+
47565+out_free_buf:
47566+ kfree(buffer);
47567+
47568+out_free_params:
47569+ if (res == 0)
47570+ dev->dh_priv = params;
47571+ else
47572+ kfree(params);
47573+
47574+out:
47575+ TRACE_EXIT_RES(res);
47576+ return res;
47577+}
47578+
47579+/************************************************************
47580+ * Function: modisk_detach
47581+ *
47582+ * Argument:
47583+ *
47584+ * Returns : None
47585+ *
47586+ * Description: Called to detach this device type driver
47587+ ************************************************************/
47588+static void modisk_detach(struct scst_device *dev)
47589+{
47590+ struct modisk_params *params =
47591+ (struct modisk_params *)dev->dh_priv;
47592+
47593+ TRACE_ENTRY();
47594+
47595+ kfree(params);
47596+ dev->dh_priv = NULL;
47597+
47598+ TRACE_EXIT();
47599+ return;
47600+}
47601+
47602+static int modisk_get_block_shift(struct scst_cmd *cmd)
47603+{
47604+ struct modisk_params *params =
47605+ (struct modisk_params *)cmd->dev->dh_priv;
47606+ /*
47607+ * No need for locks here, since *_detach() can not be
47608+ * called, when there are existing commands.
47609+ */
47610+ return params->block_shift;
47611+}
47612+
47613+/********************************************************************
47614+ * Function: modisk_parse
47615+ *
47616+ * Argument:
47617+ *
47618+ * Returns : The state of the command
47619+ *
47620+ * Description: This does the parsing of the command
47621+ *
47622+ * Note: Not all states are allowed on return
47623+ ********************************************************************/
47624+static int modisk_parse(struct scst_cmd *cmd)
47625+{
47626+ int res = SCST_CMD_STATE_DEFAULT;
47627+
47628+ scst_modisk_generic_parse(cmd, modisk_get_block_shift);
47629+
47630+ cmd->retries = SCST_PASSTHROUGH_RETRIES;
47631+
47632+ return res;
47633+}
47634+
47635+static void modisk_set_block_shift(struct scst_cmd *cmd, int block_shift)
47636+{
47637+ struct modisk_params *params =
47638+ (struct modisk_params *)cmd->dev->dh_priv;
47639+ /*
47640+ * No need for locks here, since *_detach() can not be
47641+ * called, when there are existing commands.
47642+ */
47643+ if (block_shift != 0)
47644+ params->block_shift = block_shift;
47645+ else
47646+ params->block_shift = MODISK_DEF_BLOCK_SHIFT;
47647+ return;
47648+}
47649+
47650+/********************************************************************
47651+ * Function: modisk_done
47652+ *
47653+ * Argument:
47654+ *
47655+ * Returns :
47656+ *
47657+ * Description: This is the completion routine for the command,
47658+ * it is used to extract any necessary information
47659+ * about a command.
47660+ ********************************************************************/
47661+static int modisk_done(struct scst_cmd *cmd)
47662+{
47663+ int res;
47664+
47665+ TRACE_ENTRY();
47666+
47667+ res = scst_block_generic_dev_done(cmd, modisk_set_block_shift);
47668+
47669+ TRACE_EXIT_RES(res);
47670+ return res;
47671+}
47672+
47673+/********************************************************************
47674+ * Function: modisk_exec
47675+ *
47676+ * Argument:
47677+ *
47678+ * Returns :
47679+ *
47680+ * Description: Make SCST do nothing for data READs and WRITES.
47681+ * Intended for raw line performance testing
47682+ ********************************************************************/
47683+static int modisk_exec(struct scst_cmd *cmd)
47684+{
47685+ int res = SCST_EXEC_NOT_COMPLETED, rc;
47686+ int opcode = cmd->cdb[0];
47687+
47688+ TRACE_ENTRY();
47689+
47690+ rc = scst_check_local_events(cmd);
47691+ if (unlikely(rc != 0))
47692+ goto out_done;
47693+
47694+ cmd->status = 0;
47695+ cmd->msg_status = 0;
47696+ cmd->host_status = DID_OK;
47697+ cmd->driver_status = 0;
47698+
47699+ switch (opcode) {
47700+ case WRITE_6:
47701+ case WRITE_10:
47702+ case WRITE_12:
47703+ case WRITE_16:
47704+ case READ_6:
47705+ case READ_10:
47706+ case READ_12:
47707+ case READ_16:
47708+ cmd->completed = 1;
47709+ goto out_done;
47710+ }
47711+
47712+out:
47713+ TRACE_EXIT_RES(res);
47714+ return res;
47715+
47716+out_done:
47717+ res = SCST_EXEC_COMPLETED;
47718+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
47719+ goto out;
47720+}
47721+
47722+MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
47723+MODULE_LICENSE("GPL");
47724+MODULE_DESCRIPTION("SCSI MO disk (type 7) dev handler for SCST");
47725+MODULE_VERSION(SCST_VERSION_STRING);
47726diff -uprN orig/linux-2.6.35/drivers/scst/dev_handlers/scst_processor.c linux-2.6.35/drivers/scst/dev_handlers/scst_processor.c
47727--- orig/linux-2.6.35/drivers/scst/dev_handlers/scst_processor.c
47728+++ linux-2.6.35/drivers/scst/dev_handlers/scst_processor.c
47729@@ -0,0 +1,222 @@
47730+/*
47731+ * scst_processor.c
47732+ *
47733+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
47734+ * Copyright (C) 2004 - 2005 Leonid Stoljar
47735+ * Copyright (C) 2007 - 2010 ID7 Ltd.
47736+ *
47737+ * SCSI medium processor (type 3) dev handler
47738+ *
47739+ * This program is free software; you can redistribute it and/or
47740+ * modify it under the terms of the GNU General Public License
47741+ * as published by the Free Software Foundation, version 2
47742+ * of the License.
47743+ *
47744+ * This program is distributed in the hope that it will be useful,
47745+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
47746+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47747+ * GNU General Public License for more details.
47748+ */
47749+
47750+#include <scsi/scsi_host.h>
47751+#include <linux/slab.h>
47752+
47753+#define LOG_PREFIX "dev_processor"
47754+
47755+#include <scst/scst.h>
47756+#include "scst_dev_handler.h"
47757+
47758+#define PROCESSOR_NAME "dev_processor"
47759+
47760+#define PROCESSOR_RETRIES 2
47761+
47762+static int processor_attach(struct scst_device *);
47763+/*static void processor_detach(struct scst_device *);*/
47764+static int processor_parse(struct scst_cmd *);
47765+/*static int processor_done(struct scst_cmd *);*/
47766+
47767+static struct scst_dev_type processor_devtype = {
47768+ .name = PROCESSOR_NAME,
47769+ .type = TYPE_PROCESSOR,
47770+ .threads_num = 1,
47771+ .parse_atomic = 1,
47772+/* .dev_done_atomic = 1,*/
47773+ .attach = processor_attach,
47774+/* .detach = processor_detach,*/
47775+ .parse = processor_parse,
47776+/* .dev_done = processor_done*/
47777+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
47778+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
47779+ .trace_flags = &trace_flag,
47780+#endif
47781+};
47782+
47783+/**************************************************************
47784+ * Function: processor_attach
47785+ *
47786+ * Argument:
47787+ *
47788+ * Returns : 1 if attached, error code otherwise
47789+ *
47790+ * Description:
47791+ *************************************************************/
47792+static int processor_attach(struct scst_device *dev)
47793+{
47794+ int res, rc;
47795+ int retries;
47796+
47797+ TRACE_ENTRY();
47798+
47799+ if (dev->scsi_dev == NULL ||
47800+ dev->scsi_dev->type != dev->type) {
47801+ PRINT_ERROR("%s", "SCSI device not define or illegal type");
47802+ res = -ENODEV;
47803+ goto out;
47804+ }
47805+
47806+ /*
47807+ * If the device is offline, don't try to read capacity or any
47808+ * of the other stuff
47809+ */
47810+ if (dev->scsi_dev->sdev_state == SDEV_OFFLINE) {
47811+ TRACE_DBG("%s", "Device is offline");
47812+ res = -ENODEV;
47813+ goto out;
47814+ }
47815+
47816+ retries = SCST_DEV_UA_RETRIES;
47817+ do {
47818+ TRACE_DBG("%s", "Doing TEST_UNIT_READY");
47819+ rc = scsi_test_unit_ready(dev->scsi_dev,
47820+ SCST_GENERIC_PROCESSOR_TIMEOUT, PROCESSOR_RETRIES
47821+ , NULL);
47822+ TRACE_DBG("TEST_UNIT_READY done: %x", rc);
47823+ } while ((--retries > 0) && rc);
47824+
47825+ if (rc) {
47826+ PRINT_WARNING("Unit not ready: %x", rc);
47827+ /* Let's try not to be too smart and continue processing */
47828+ }
47829+
47830+ res = scst_obtain_device_parameters(dev);
47831+ if (res != 0) {
47832+ PRINT_ERROR("Failed to obtain control parameters for device "
47833+ "%s", dev->virt_name);
47834+ goto out;
47835+ }
47836+
47837+out:
47838+ TRACE_EXIT();
47839+ return res;
47840+}
47841+
47842+/************************************************************
47843+ * Function: processor_detach
47844+ *
47845+ * Argument:
47846+ *
47847+ * Returns : None
47848+ *
47849+ * Description: Called to detach this device type driver
47850+ ************************************************************/
47851+#if 0
47852+void processor_detach(struct scst_device *dev)
47853+{
47854+ TRACE_ENTRY();
47855+
47856+ TRACE_EXIT();
47857+ return;
47858+}
47859+#endif
47860+
47861+/********************************************************************
47862+ * Function: processor_parse
47863+ *
47864+ * Argument:
47865+ *
47866+ * Returns : The state of the command
47867+ *
47868+ * Description: This does the parsing of the command
47869+ *
47870+ * Note: Not all states are allowed on return
47871+ ********************************************************************/
47872+static int processor_parse(struct scst_cmd *cmd)
47873+{
47874+ int res = SCST_CMD_STATE_DEFAULT;
47875+
47876+ scst_processor_generic_parse(cmd, NULL);
47877+
47878+ cmd->retries = SCST_PASSTHROUGH_RETRIES;
47879+
47880+ return res;
47881+}
47882+
47883+/********************************************************************
47884+ * Function: processor_done
47885+ *
47886+ * Argument:
47887+ *
47888+ * Returns :
47889+ *
47890+ * Description: This is the completion routine for the command,
47891+ * it is used to extract any necessary information
47892+ * about a command.
47893+ ********************************************************************/
47894+#if 0
47895+int processor_done(struct scst_cmd *cmd)
47896+{
47897+ int res = SCST_CMD_STATE_DEFAULT;
47898+
47899+ TRACE_ENTRY();
47900+
47901+ /*
47902+ * SCST sets good defaults for cmd->is_send_status and
47903+ * cmd->resp_data_len based on cmd->status and cmd->data_direction,
47904+ * therefore change them only if necessary.
47905+ */
47906+
47907+#if 0
47908+ switch (cmd->cdb[0]) {
47909+ default:
47910+ /* It's all good */
47911+ break;
47912+ }
47913+#endif
47914+
47915+ TRACE_EXIT();
47916+ return res;
47917+}
47918+#endif
47919+
47920+static int __init processor_init(void)
47921+{
47922+ int res = 0;
47923+
47924+ TRACE_ENTRY();
47925+
47926+ processor_devtype.module = THIS_MODULE;
47927+
47928+ res = scst_register_dev_driver(&processor_devtype);
47929+ if (res < 0)
47930+ goto out;
47931+
47932+out:
47933+ TRACE_EXIT_RES(res);
47934+ return res;
47935+}
47936+
47937+static void __exit processor_exit(void)
47938+{
47939+ TRACE_ENTRY();
47940+ scst_unregister_dev_driver(&processor_devtype);
47941+ TRACE_EXIT();
47942+ return;
47943+}
47944+
47945+module_init(processor_init);
47946+module_exit(processor_exit);
47947+
47948+MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
47949+MODULE_LICENSE("GPL");
47950+MODULE_DESCRIPTION("SCSI medium processor (type 3) dev handler for SCST");
47951+MODULE_VERSION(SCST_VERSION_STRING);
47952diff -uprN orig/linux-2.6.35/drivers/scst/dev_handlers/scst_raid.c linux-2.6.35/drivers/scst/dev_handlers/scst_raid.c
47953--- orig/linux-2.6.35/drivers/scst/dev_handlers/scst_raid.c
47954+++ linux-2.6.35/drivers/scst/dev_handlers/scst_raid.c
47955@@ -0,0 +1,223 @@
47956+/*
47957+ * scst_raid.c
47958+ *
47959+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
47960+ * Copyright (C) 2004 - 2005 Leonid Stoljar
47961+ * Copyright (C) 2007 - 2010 ID7 Ltd.
47962+ *
47963+ * SCSI raid(controller) (type 0xC) dev handler
47964+ *
47965+ * This program is free software; you can redistribute it and/or
47966+ * modify it under the terms of the GNU General Public License
47967+ * as published by the Free Software Foundation, version 2
47968+ * of the License.
47969+ *
47970+ * This program is distributed in the hope that it will be useful,
47971+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
47972+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47973+ * GNU General Public License for more details.
47974+ */
47975+
47976+#define LOG_PREFIX "dev_raid"
47977+
47978+#include <scsi/scsi_host.h>
47979+#include <linux/slab.h>
47980+
47981+#include <scst/scst.h>
47982+#include "scst_dev_handler.h"
47983+
47984+#define RAID_NAME "dev_raid"
47985+
47986+#define RAID_RETRIES 2
47987+
47988+static int raid_attach(struct scst_device *);
47989+/* static void raid_detach(struct scst_device *); */
47990+static int raid_parse(struct scst_cmd *);
47991+/* static int raid_done(struct scst_cmd *); */
47992+
47993+static struct scst_dev_type raid_devtype = {
47994+ .name = RAID_NAME,
47995+ .type = TYPE_RAID,
47996+ .threads_num = 1,
47997+ .parse_atomic = 1,
47998+/* .dev_done_atomic = 1,*/
47999+ .attach = raid_attach,
48000+/* .detach = raid_detach,*/
48001+ .parse = raid_parse,
48002+/* .dev_done = raid_done,*/
48003+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
48004+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
48005+ .trace_flags = &trace_flag,
48006+#endif
48007+};
48008+
48009+/**************************************************************
48010+ * Function: raid_attach
48011+ *
48012+ * Argument:
48013+ *
48014+ * Returns : 1 if attached, error code otherwise
48015+ *
48016+ * Description:
48017+ *************************************************************/
48018+static int raid_attach(struct scst_device *dev)
48019+{
48020+ int res, rc;
48021+ int retries;
48022+
48023+ TRACE_ENTRY();
48024+
48025+ if (dev->scsi_dev == NULL ||
48026+ dev->scsi_dev->type != dev->type) {
48027+ PRINT_ERROR("%s", "SCSI device not define or illegal type");
48028+ res = -ENODEV;
48029+ goto out;
48030+ }
48031+
48032+ /*
48033+ * If the device is offline, don't try to read capacity or any
48034+ * of the other stuff
48035+ */
48036+ if (dev->scsi_dev->sdev_state == SDEV_OFFLINE) {
48037+ TRACE_DBG("%s", "Device is offline");
48038+ res = -ENODEV;
48039+ goto out;
48040+ }
48041+
48042+ retries = SCST_DEV_UA_RETRIES;
48043+ do {
48044+ TRACE_DBG("%s", "Doing TEST_UNIT_READY");
48045+ rc = scsi_test_unit_ready(dev->scsi_dev,
48046+ SCST_GENERIC_RAID_TIMEOUT, RAID_RETRIES
48047+ , NULL);
48048+ TRACE_DBG("TEST_UNIT_READY done: %x", rc);
48049+ } while ((--retries > 0) && rc);
48050+
48051+ if (rc) {
48052+ PRINT_WARNING("Unit not ready: %x", rc);
48053+ /* Let's try not to be too smart and continue processing */
48054+ }
48055+
48056+ res = scst_obtain_device_parameters(dev);
48057+ if (res != 0) {
48058+ PRINT_ERROR("Failed to obtain control parameters for device "
48059+ "%s", dev->virt_name);
48060+ goto out;
48061+ }
48062+
48063+out:
48064+ TRACE_EXIT();
48065+ return res;
48066+}
48067+
48068+/************************************************************
48069+ * Function: raid_detach
48070+ *
48071+ * Argument:
48072+ *
48073+ * Returns : None
48074+ *
48075+ * Description: Called to detach this device type driver
48076+ ************************************************************/
48077+#if 0
48078+void raid_detach(struct scst_device *dev)
48079+{
48080+ TRACE_ENTRY();
48081+
48082+ TRACE_EXIT();
48083+ return;
48084+}
48085+#endif
48086+
48087+/********************************************************************
48088+ * Function: raid_parse
48089+ *
48090+ * Argument:
48091+ *
48092+ * Returns : The state of the command
48093+ *
48094+ * Description: This does the parsing of the command
48095+ *
48096+ * Note: Not all states are allowed on return
48097+ ********************************************************************/
48098+static int raid_parse(struct scst_cmd *cmd)
48099+{
48100+ int res = SCST_CMD_STATE_DEFAULT;
48101+
48102+ scst_raid_generic_parse(cmd, NULL);
48103+
48104+ cmd->retries = SCST_PASSTHROUGH_RETRIES;
48105+
48106+ return res;
48107+}
48108+
48109+/********************************************************************
48110+ * Function: raid_done
48111+ *
48112+ * Argument:
48113+ *
48114+ * Returns :
48115+ *
48116+ * Description: This is the completion routine for the command,
48117+ * it is used to extract any necessary information
48118+ * about a command.
48119+ ********************************************************************/
48120+#if 0
48121+int raid_done(struct scst_cmd *cmd)
48122+{
48123+ int res = SCST_CMD_STATE_DEFAULT;
48124+
48125+ TRACE_ENTRY();
48126+
48127+ /*
48128+ * SCST sets good defaults for cmd->is_send_status and
48129+ * cmd->resp_data_len based on cmd->status and cmd->data_direction,
48130+ * therefore change them only if necessary.
48131+ */
48132+
48133+#if 0
48134+ switch (cmd->cdb[0]) {
48135+ default:
48136+ /* It's all good */
48137+ break;
48138+ }
48139+#endif
48140+
48141+ TRACE_EXIT();
48142+ return res;
48143+}
48144+#endif
48145+
48146+static int __init raid_init(void)
48147+{
48148+ int res = 0;
48149+
48150+ TRACE_ENTRY();
48151+
48152+ raid_devtype.module = THIS_MODULE;
48153+
48154+ res = scst_register_dev_driver(&raid_devtype);
48155+ if (res < 0)
48156+ goto out;
48157+
48158+out:
48159+ TRACE_EXIT_RES(res);
48160+ return res;
48161+
48162+}
48163+
48164+static void __exit raid_exit(void)
48165+{
48166+ TRACE_ENTRY();
48167+ scst_unregister_dev_driver(&raid_devtype);
48168+ TRACE_EXIT();
48169+ return;
48170+}
48171+
48172+module_init(raid_init);
48173+module_exit(raid_exit);
48174+
48175+MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
48176+MODULE_LICENSE("GPL");
48177+MODULE_DESCRIPTION("SCSI raid(controller) (type 0xC) dev handler for SCST");
48178+MODULE_VERSION(SCST_VERSION_STRING);
48179diff -uprN orig/linux-2.6.35/drivers/scst/dev_handlers/scst_tape.c linux-2.6.35/drivers/scst/dev_handlers/scst_tape.c
48180--- orig/linux-2.6.35/drivers/scst/dev_handlers/scst_tape.c
48181+++ linux-2.6.35/drivers/scst/dev_handlers/scst_tape.c
48182@@ -0,0 +1,431 @@
48183+/*
48184+ * scst_tape.c
48185+ *
48186+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
48187+ * Copyright (C) 2004 - 2005 Leonid Stoljar
48188+ * Copyright (C) 2007 - 2010 ID7 Ltd.
48189+ *
48190+ * SCSI tape (type 1) dev handler
48191+ * &
48192+ * SCSI tape (type 1) "performance" device handler (skip all READ and WRITE
48193+ * operations).
48194+ *
48195+ * This program is free software; you can redistribute it and/or
48196+ * modify it under the terms of the GNU General Public License
48197+ * as published by the Free Software Foundation, version 2
48198+ * of the License.
48199+ *
48200+ * This program is distributed in the hope that it will be useful,
48201+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
48202+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48203+ * GNU General Public License for more details.
48204+ */
48205+
48206+#include <linux/module.h>
48207+#include <linux/init.h>
48208+#include <scsi/scsi_host.h>
48209+#include <linux/slab.h>
48210+
48211+#define LOG_PREFIX "dev_tape"
48212+
48213+#include <scst/scst.h>
48214+#include "scst_dev_handler.h"
48215+
48216+# define TAPE_NAME "dev_tape"
48217+# define TAPE_PERF_NAME "dev_tape_perf"
48218+
48219+#define TAPE_RETRIES 2
48220+
48221+#define TAPE_DEF_BLOCK_SIZE 512
48222+
48223+/* The fixed bit in READ/WRITE/VERIFY */
48224+#define SILI_BIT 2
48225+
48226+struct tape_params {
48227+ int block_size;
48228+};
48229+
48230+static int tape_attach(struct scst_device *);
48231+static void tape_detach(struct scst_device *);
48232+static int tape_parse(struct scst_cmd *);
48233+static int tape_done(struct scst_cmd *);
48234+static int tape_exec(struct scst_cmd *);
48235+
48236+static struct scst_dev_type tape_devtype = {
48237+ .name = TAPE_NAME,
48238+ .type = TYPE_TAPE,
48239+ .threads_num = 1,
48240+ .parse_atomic = 1,
48241+ .dev_done_atomic = 1,
48242+ .attach = tape_attach,
48243+ .detach = tape_detach,
48244+ .parse = tape_parse,
48245+ .dev_done = tape_done,
48246+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
48247+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
48248+ .trace_flags = &trace_flag,
48249+#endif
48250+};
48251+
48252+static struct scst_dev_type tape_devtype_perf = {
48253+ .name = TAPE_PERF_NAME,
48254+ .type = TYPE_TAPE,
48255+ .parse_atomic = 1,
48256+ .dev_done_atomic = 1,
48257+ .attach = tape_attach,
48258+ .detach = tape_detach,
48259+ .parse = tape_parse,
48260+ .dev_done = tape_done,
48261+ .exec = tape_exec,
48262+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
48263+ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
48264+ .trace_flags = &trace_flag,
48265+#endif
48266+};
48267+
48268+static int __init init_scst_tape_driver(void)
48269+{
48270+ int res = 0;
48271+
48272+ TRACE_ENTRY();
48273+
48274+ tape_devtype.module = THIS_MODULE;
48275+
48276+ res = scst_register_dev_driver(&tape_devtype);
48277+ if (res < 0)
48278+ goto out;
48279+
48280+ tape_devtype_perf.module = THIS_MODULE;
48281+
48282+ res = scst_register_dev_driver(&tape_devtype_perf);
48283+ if (res < 0)
48284+ goto out_unreg;
48285+
48286+out:
48287+ TRACE_EXIT_RES(res);
48288+ return res;
48289+
48290+out_unreg:
48291+ scst_unregister_dev_driver(&tape_devtype);
48292+ goto out;
48293+}
48294+
48295+static void __exit exit_scst_tape_driver(void)
48296+{
48297+ TRACE_ENTRY();
48298+
48299+ scst_unregister_dev_driver(&tape_devtype_perf);
48300+ scst_unregister_dev_driver(&tape_devtype);
48301+
48302+ TRACE_EXIT();
48303+ return;
48304+}
48305+
48306+module_init(init_scst_tape_driver);
48307+module_exit(exit_scst_tape_driver);
48308+
48309+/**************************************************************
48310+ * Function: tape_attach
48311+ *
48312+ * Argument:
48313+ *
48314+ * Returns : 1 if attached, error code otherwise
48315+ *
48316+ * Description:
48317+ *************************************************************/
48318+static int tape_attach(struct scst_device *dev)
48319+{
48320+ int res, rc;
48321+ int retries;
48322+ struct scsi_mode_data data;
48323+ const int buffer_size = 512;
48324+ uint8_t *buffer = NULL;
48325+ struct tape_params *params;
48326+
48327+ TRACE_ENTRY();
48328+
48329+ if (dev->scsi_dev == NULL ||
48330+ dev->scsi_dev->type != dev->type) {
48331+ PRINT_ERROR("%s", "SCSI device not define or illegal type");
48332+ res = -ENODEV;
48333+ goto out;
48334+ }
48335+
48336+ params = kzalloc(sizeof(*params), GFP_KERNEL);
48337+ if (params == NULL) {
48338+ TRACE(TRACE_OUT_OF_MEM, "%s",
48339+ "Unable to allocate struct tape_params");
48340+ res = -ENOMEM;
48341+ goto out;
48342+ }
48343+
48344+ params->block_size = TAPE_DEF_BLOCK_SIZE;
48345+
48346+ buffer = kmalloc(buffer_size, GFP_KERNEL);
48347+ if (!buffer) {
48348+ TRACE(TRACE_OUT_OF_MEM, "%s", "Memory allocation failure");
48349+ res = -ENOMEM;
48350+ goto out_free_req;
48351+ }
48352+
48353+ retries = SCST_DEV_UA_RETRIES;
48354+ do {
48355+ TRACE_DBG("%s", "Doing TEST_UNIT_READY");
48356+ rc = scsi_test_unit_ready(dev->scsi_dev,
48357+ SCST_GENERIC_TAPE_SMALL_TIMEOUT, TAPE_RETRIES
48358+ , NULL);
48359+ TRACE_DBG("TEST_UNIT_READY done: %x", rc);
48360+ } while ((--retries > 0) && rc);
48361+
48362+ if (rc) {
48363+ PRINT_WARNING("Unit not ready: %x", rc);
48364+ /* Let's try not to be too smart and continue processing */
48365+ goto obtain;
48366+ }
48367+
48368+ TRACE_DBG("%s", "Doing MODE_SENSE");
48369+ rc = scsi_mode_sense(dev->scsi_dev,
48370+ ((dev->scsi_dev->scsi_level <= SCSI_2) ?
48371+ ((dev->scsi_dev->lun << 5) & 0xe0) : 0),
48372+ 0 /* Mode Page 0 */,
48373+ buffer, buffer_size,
48374+ SCST_GENERIC_TAPE_SMALL_TIMEOUT, TAPE_RETRIES,
48375+ &data, NULL);
48376+ TRACE_DBG("MODE_SENSE done: %x", rc);
48377+
48378+ if (rc == 0) {
48379+ int medium_type, mode, speed, density;
48380+ if (buffer[3] == 8) {
48381+ params->block_size = ((buffer[9] << 16) |
48382+ (buffer[10] << 8) |
48383+ (buffer[11] << 0));
48384+ } else
48385+ params->block_size = TAPE_DEF_BLOCK_SIZE;
48386+ medium_type = buffer[1];
48387+ mode = (buffer[2] & 0x70) >> 4;
48388+ speed = buffer[2] & 0x0f;
48389+ density = buffer[4];
48390+ TRACE_DBG("Tape: lun %d. bs %d. type 0x%02x mode 0x%02x "
48391+ "speed 0x%02x dens 0x%02x", dev->scsi_dev->lun,
48392+ params->block_size, medium_type, mode, speed, density);
48393+ } else {
48394+ PRINT_ERROR("MODE_SENSE failed: %x", rc);
48395+ res = -ENODEV;
48396+ goto out_free_buf;
48397+ }
48398+
48399+obtain:
48400+ res = scst_obtain_device_parameters(dev);
48401+ if (res != 0) {
48402+ PRINT_ERROR("Failed to obtain control parameters for device "
48403+ "%s", dev->virt_name);
48404+ goto out_free_buf;
48405+ }
48406+
48407+out_free_buf:
48408+ kfree(buffer);
48409+
48410+out_free_req:
48411+ if (res == 0)
48412+ dev->dh_priv = params;
48413+ else
48414+ kfree(params);
48415+
48416+out:
48417+ TRACE_EXIT_RES(res);
48418+ return res;
48419+}
48420+
48421+/************************************************************
48422+ * Function: tape_detach
48423+ *
48424+ * Argument:
48425+ *
48426+ * Returns : None
48427+ *
48428+ * Description: Called to detach this device type driver
48429+ ************************************************************/
48430+static void tape_detach(struct scst_device *dev)
48431+{
48432+ struct tape_params *params =
48433+ (struct tape_params *)dev->dh_priv;
48434+
48435+ TRACE_ENTRY();
48436+
48437+ kfree(params);
48438+ dev->dh_priv = NULL;
48439+
48440+ TRACE_EXIT();
48441+ return;
48442+}
48443+
48444+static int tape_get_block_size(struct scst_cmd *cmd)
48445+{
48446+ struct tape_params *params = (struct tape_params *)cmd->dev->dh_priv;
48447+ /*
48448+ * No need for locks here, since *_detach() can not be called,
48449+ * when there are existing commands.
48450+ */
48451+ return params->block_size;
48452+}
48453+
48454+/********************************************************************
48455+ * Function: tape_parse
48456+ *
48457+ * Argument:
48458+ *
48459+ * Returns : The state of the command
48460+ *
48461+ * Description: This does the parsing of the command
48462+ *
48463+ * Note: Not all states are allowed on return
48464+ ********************************************************************/
48465+static int tape_parse(struct scst_cmd *cmd)
48466+{
48467+ int res = SCST_CMD_STATE_DEFAULT;
48468+
48469+ scst_tape_generic_parse(cmd, tape_get_block_size);
48470+
48471+ cmd->retries = SCST_PASSTHROUGH_RETRIES;
48472+
48473+ return res;
48474+}
48475+
48476+static void tape_set_block_size(struct scst_cmd *cmd, int block_size)
48477+{
48478+ struct tape_params *params = (struct tape_params *)cmd->dev->dh_priv;
48479+ /*
48480+ * No need for locks here, since *_detach() can not be called, when
48481+ * there are existing commands.
48482+ */
48483+ params->block_size = block_size;
48484+ return;
48485+}
48486+
48487+/********************************************************************
48488+ * Function: tape_done
48489+ *
48490+ * Argument:
48491+ *
48492+ * Returns :
48493+ *
48494+ * Description: This is the completion routine for the command,
48495+ * it is used to extract any necessary information
48496+ * about a command.
48497+ ********************************************************************/
48498+static int tape_done(struct scst_cmd *cmd)
48499+{
48500+ int opcode = cmd->cdb[0];
48501+ int status = cmd->status;
48502+ int res = SCST_CMD_STATE_DEFAULT;
48503+
48504+ TRACE_ENTRY();
48505+
48506+ if ((status == SAM_STAT_GOOD) || (status == SAM_STAT_CONDITION_MET))
48507+ res = scst_tape_generic_dev_done(cmd, tape_set_block_size);
48508+ else if ((status == SAM_STAT_CHECK_CONDITION) &&
48509+ SCST_SENSE_VALID(cmd->sense)) {
48510+ struct tape_params *params;
48511+
48512+ TRACE_DBG("Extended sense %x", cmd->sense[0] & 0x7F);
48513+
48514+ if ((cmd->sense[0] & 0x7F) != 0x70) {
48515+ PRINT_ERROR("Sense format 0x%x is not supported",
48516+ cmd->sense[0] & 0x7F);
48517+ scst_set_cmd_error(cmd,
48518+ SCST_LOAD_SENSE(scst_sense_hardw_error));
48519+ goto out;
48520+ }
48521+
48522+ if (opcode == READ_6 && !(cmd->cdb[1] & SILI_BIT) &&
48523+ (cmd->sense[2] & 0xe0)) {
48524+ /* EOF, EOM, or ILI */
48525+ int TransferLength, Residue = 0;
48526+ if ((cmd->sense[2] & 0x0f) == BLANK_CHECK)
48527+ /* No need for EOM in this case */
48528+ cmd->sense[2] &= 0xcf;
48529+ TransferLength = ((cmd->cdb[2] << 16) |
48530+ (cmd->cdb[3] << 8) | cmd->cdb[4]);
48531+ /* Compute the residual count */
48532+ if ((cmd->sense[0] & 0x80) != 0) {
48533+ Residue = ((cmd->sense[3] << 24) |
48534+ (cmd->sense[4] << 16) |
48535+ (cmd->sense[5] << 8) |
48536+ cmd->sense[6]);
48537+ }
48538+ TRACE_DBG("Checking the sense key "
48539+ "sn[2]=%x cmd->cdb[0,1]=%x,%x TransLen/Resid"
48540+ " %d/%d", (int)cmd->sense[2], cmd->cdb[0],
48541+ cmd->cdb[1], TransferLength, Residue);
48542+ if (TransferLength > Residue) {
48543+ int resp_data_len = TransferLength - Residue;
48544+ if (cmd->cdb[1] & SCST_TRANSFER_LEN_TYPE_FIXED) {
48545+ /*
48546+ * No need for locks here, since
48547+ * *_detach() can not be called, when
48548+ * there are existing commands.
48549+ */
48550+ params = (struct tape_params *)
48551+ cmd->dev->dh_priv;
48552+ resp_data_len *= params->block_size;
48553+ }
48554+ scst_set_resp_data_len(cmd, resp_data_len);
48555+ }
48556+ }
48557+ }
48558+
48559+out:
48560+ TRACE_DBG("cmd->is_send_status=%x, cmd->resp_data_len=%d, "
48561+ "res=%d", cmd->is_send_status, cmd->resp_data_len, res);
48562+
48563+ TRACE_EXIT_RES(res);
48564+ return res;
48565+}
48566+
48567+/********************************************************************
48568+ * Function: tape_exec
48569+ *
48570+ * Argument:
48571+ *
48572+ * Returns :
48573+ *
48574+ * Description: Make SCST do nothing for data READs and WRITES.
48575+ * Intended for raw line performance testing
48576+ ********************************************************************/
48577+static int tape_exec(struct scst_cmd *cmd)
48578+{
48579+ int res = SCST_EXEC_NOT_COMPLETED, rc;
48580+ int opcode = cmd->cdb[0];
48581+
48582+ TRACE_ENTRY();
48583+
48584+ rc = scst_check_local_events(cmd);
48585+ if (unlikely(rc != 0))
48586+ goto out_done;
48587+
48588+ cmd->status = 0;
48589+ cmd->msg_status = 0;
48590+ cmd->host_status = DID_OK;
48591+ cmd->driver_status = 0;
48592+
48593+ switch (opcode) {
48594+ case WRITE_6:
48595+ case READ_6:
48596+ cmd->completed = 1;
48597+ goto out_done;
48598+ }
48599+
48600+out:
48601+ TRACE_EXIT_RES(res);
48602+ return res;
48603+
48604+out_done:
48605+ res = SCST_EXEC_COMPLETED;
48606+ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
48607+ goto out;
48608+}
48609+
48610+MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
48611+MODULE_LICENSE("GPL");
48612+MODULE_DESCRIPTION("SCSI tape (type 1) dev handler for SCST");
48613+MODULE_VERSION(SCST_VERSION_STRING);
48614libfc: add hook for FC-4 provider registration
48615
48616Allow FC-4 provider modules to hook into libfc, mostly for targets.
48617This should allow any FC-4 module to handle PRLI requests and maintain
48618process-association states.
48619
48620Each provider registers its ops with libfc and then will be called for
48621any incoming PRLI for that FC-4 type on any instance. The provider
48622can decide whether to handle that particular instance using any method
48623it likes, such as ACLs or other configuration information.
48624
48625A count is kept of the number of successful PRLIs from the remote port.
48626Providers are called back with an implicit PRLO when the remote port
48627is about to be deleted or has been reset.
48628
48629fc_lport_recv_req() now sends incoming FC-4 requests to FC-4 providers,
48630and there is a built-in provider always registered for handling
48631incoming ELS requests.
48632
48633The call to provider recv() routines uses rcu_read_lock()
48634so that providers aren't removed during the call. That lock is very
48635cheap and shouldn't affect any performance on ELS requests.
48636Providers can rely on the RCU lock to protect a session lookup as well.
48637
48638Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
48639
48640---
48641 drivers/scsi/libfc/fc_libfc.c | 60 ++++++++++++++++++
48642 drivers/scsi/libfc/fc_libfc.h | 11 +++
48643 drivers/scsi/libfc/fc_lport.c | 63 ++++++++++++++++---
48644 drivers/scsi/libfc/fc_rport.c | 133 +++++++++++++++++++++++++++++++++--------
48645 include/scsi/libfc.h | 26 ++++++++
48646 5 files changed, 255 insertions(+), 38 deletions(-)
48647
48648
48649---
48650diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c
48651index 39f4b6a..ce0de44 100644
48652--- a/drivers/scsi/libfc/fc_libfc.c
48653+++ b/drivers/scsi/libfc/fc_libfc.c
48654@@ -34,6 +34,23 @@ unsigned int fc_debug_logging;
48655 module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR);
48656 MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
48657
48658+DEFINE_MUTEX(fc_prov_mutex);
48659+
48660+/*
48661+ * Providers which primarily send requests and PRLIs.
48662+ */
48663+struct fc4_prov *fc_active_prov[FC_FC4_PROV_SIZE] = {
48664+ [0] = &fc_rport_t0_prov,
48665+ [FC_TYPE_FCP] = &fc_rport_fcp_init,
48666+};
48667+
48668+/*
48669+ * Providers which receive requests.
48670+ */
48671+struct fc4_prov *fc_passive_prov[FC_FC4_PROV_SIZE] = {
48672+ [FC_TYPE_ELS] = &fc_lport_els_prov,
48673+};
48674+
48675 /**
48676 * libfc_init() - Initialize libfc.ko
48677 */
48678@@ -132,3 +149,46 @@ u32 fc_copy_buffer_to_sglist(void *buf, size_t len,
48679 }
48680 return copy_len;
48681 }
48682+
48683+/**
48684+ * fc_fc4_register_provider() - register FC-4 upper-level provider.
48685+ * @type: FC-4 type, such as FC_TYPE_FCP
48686+ * @prov: structure describing provider including ops vector.
48687+ *
48688+ * Returns 0 on success, negative error otherwise.
48689+ */
48690+int fc_fc4_register_provider(enum fc_fh_type type, struct fc4_prov *prov)
48691+{
48692+ struct fc4_prov **prov_entry;
48693+ int ret = 0;
48694+
48695+ if (type >= FC_FC4_PROV_SIZE)
48696+ return -EINVAL;
48697+ mutex_lock(&fc_prov_mutex);
48698+ prov_entry = (prov->recv ? fc_passive_prov : fc_active_prov) + type;
48699+ if (*prov_entry)
48700+ ret = -EBUSY;
48701+ else
48702+ *prov_entry = prov;
48703+ mutex_unlock(&fc_prov_mutex);
48704+ return ret;
48705+}
48706+EXPORT_SYMBOL(fc_fc4_register_provider);
48707+
48708+/**
48709+ * fc_fc4_deregister_provider() - deregister FC-4 upper-level provider.
48710+ * @type: FC-4 type, such as FC_TYPE_FCP
48711+ * @prov: structure describing provider including ops vector.
48712+ */
48713+void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *prov)
48714+{
48715+ BUG_ON(type >= FC_FC4_PROV_SIZE);
48716+ mutex_lock(&fc_prov_mutex);
48717+ if (prov->recv)
48718+ rcu_assign_pointer(fc_passive_prov[type], NULL);
48719+ else
48720+ rcu_assign_pointer(fc_active_prov[type], NULL);
48721+ mutex_unlock(&fc_prov_mutex);
48722+ synchronize_rcu();
48723+}
48724+EXPORT_SYMBOL(fc_fc4_deregister_provider);
48725diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h
48726index f5c0ca4..2323c80 100644
48727--- a/drivers/scsi/libfc/fc_libfc.h
48728+++ b/drivers/scsi/libfc/fc_libfc.h
48729@@ -82,6 +82,17 @@ extern unsigned int fc_debug_logging;
48730 (lport)->host->host_no, ##args))
48731
48732 /*
48733+ * FC-4 Providers.
48734+ */
48735+extern struct fc4_prov *fc_active_prov[]; /* providers without recv */
48736+extern struct fc4_prov *fc_passive_prov[]; /* providers with recv */
48737+extern struct mutex fc_prov_mutex; /* lock over table changes */
48738+
48739+extern struct fc4_prov fc_rport_t0_prov; /* type 0 provider */
48740+extern struct fc4_prov fc_lport_els_prov; /* ELS provider */
48741+extern struct fc4_prov fc_rport_fcp_init; /* FCP initiator provider */
48742+
48743+/*
48744 * Set up direct-data placement for this I/O request
48745 */
48746 void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid);
48747diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
48748index 79c9e3c..b05329c 100644
48749--- a/drivers/scsi/libfc/fc_lport.c
48750+++ b/drivers/scsi/libfc/fc_lport.c
48751@@ -844,7 +844,7 @@ out:
48752 }
48753
48754 /**
48755- * fc_lport_recv_req() - The generic lport request handler
48756+ * fc_lport_recv_els_req() - The generic lport ELS request handler
48757 * @lport: The local port that received the request
48758 * @sp: The sequence the request is on
48759 * @fp: The request frame
48760@@ -855,8 +855,8 @@ out:
48761 * Locking Note: This function should not be called with the lport
48762 * lock held becuase it will grab the lock.
48763 */
48764-static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
48765- struct fc_frame *fp)
48766+static void fc_lport_recv_els_req(struct fc_lport *lport, struct fc_seq *sp,
48767+ struct fc_frame *fp)
48768 {
48769 struct fc_frame_header *fh = fc_frame_header_get(fp);
48770 void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *);
48771@@ -870,8 +870,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
48772 */
48773 if (!lport->link_up)
48774 fc_frame_free(fp);
48775- else if (fh->fh_type == FC_TYPE_ELS &&
48776- fh->fh_r_ctl == FC_RCTL_ELS_REQ) {
48777+ else {
48778 /*
48779 * Check opcode.
48780 */
48781@@ -900,17 +899,59 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
48782 }
48783
48784 recv(sp, fp, lport);
48785- } else {
48786- FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n",
48787- fr_eof(fp));
48788- fc_frame_free(fp);
48789 }
48790 mutex_unlock(&lport->lp_mutex);
48791+ lport->tt.exch_done(sp);
48792+}
48793+
48794+static int fc_lport_els_prli(struct fc_rport_priv *rdata, u32 spp_len,
48795+ const struct fc_els_spp *spp_in,
48796+ struct fc_els_spp *spp_out)
48797+{
48798+ return FC_SPP_RESP_INVL;
48799+}
48800+
48801+struct fc4_prov fc_lport_els_prov = {
48802+ .prli = fc_lport_els_prli,
48803+ .recv = fc_lport_recv_els_req,
48804+};
48805+
48806+/**
48807+ * fc_lport_recv_req() - The generic lport request handler
48808+ * @lport: The lport that received the request
48809+ * @sp: The sequence the request is on
48810+ * @fp: The frame the request is in
48811+ *
48812+ * Locking Note: This function should not be called with the lport
48813+ * lock held becuase it may grab the lock.
48814+ */
48815+static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
48816+ struct fc_frame *fp)
48817+{
48818+ struct fc_frame_header *fh = fc_frame_header_get(fp);
48819+ struct fc4_prov *prov;
48820
48821 /*
48822- * The common exch_done for all request may not be good
48823- * if any request requires longer hold on exhange. XXX
48824+ * Use RCU read lock and module_lock to be sure module doesn't
48825+ * deregister and get unloaded while we're calling it.
48826+ * try_module_get() is inlined and accepts a NULL parameter.
48827+ * Only ELSes and FCP target ops should come through here.
48828+ * The locking is unfortunate, and a better scheme is being sought.
48829 */
48830+ rcu_read_lock();
48831+ if (fh->fh_type >= FC_FC4_PROV_SIZE)
48832+ goto drop;
48833+ prov = rcu_dereference(fc_passive_prov[fh->fh_type]);
48834+ if (!prov || !try_module_get(prov->module))
48835+ goto drop;
48836+ rcu_read_unlock();
48837+ prov->recv(lport, sp, fp);
48838+ module_put(prov->module);
48839+ return;
48840+drop:
48841+ rcu_read_unlock();
48842+ FC_LPORT_DBG(lport, "dropping unexpected frame type %x\n", fh->fh_type);
48843+ fc_frame_free(fp);
48844 lport->tt.exch_done(sp);
48845 }
48846
48847diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
48848index 39e440f..3ec4aa5 100644
48849--- a/drivers/scsi/libfc/fc_rport.c
48850+++ b/drivers/scsi/libfc/fc_rport.c
48851@@ -246,6 +246,8 @@ static void fc_rport_work(struct work_struct *work)
48852 struct fc_rport_operations *rport_ops;
48853 struct fc_rport_identifiers ids;
48854 struct fc_rport *rport;
48855+ struct fc4_prov *prov;
48856+ u8 type;
48857 int restart = 0;
48858
48859 mutex_lock(&rdata->rp_mutex);
48860@@ -295,6 +297,15 @@ static void fc_rport_work(struct work_struct *work)
48861 case RPORT_EV_FAILED:
48862 case RPORT_EV_LOGO:
48863 case RPORT_EV_STOP:
48864+ if (rdata->prli_count) {
48865+ mutex_lock(&fc_prov_mutex);
48866+ for (type = 1; type < FC_FC4_PROV_SIZE; type++) {
48867+ prov = fc_passive_prov[type];
48868+ if (prov && prov->prlo)
48869+ prov->prlo(rdata);
48870+ }
48871+ mutex_unlock(&fc_prov_mutex);
48872+ }
48873 port_id = rdata->ids.port_id;
48874 mutex_unlock(&rdata->rp_mutex);
48875
48876@@ -1434,6 +1445,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
48877 struct fc_exch *ep;
48878 struct fc_frame *fp;
48879 struct fc_frame_header *fh;
48880+ struct fc4_prov *prov;
48881 struct {
48882 struct fc_els_prli prli;
48883 struct fc_els_spp spp;
48884@@ -1443,10 +1455,9 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
48885 unsigned int len;
48886 unsigned int plen;
48887 enum fc_els_spp_resp resp;
48888+ enum fc_els_spp_resp passive;
48889 struct fc_seq_els_data rjt_data;
48890 u32 f_ctl;
48891- u32 fcp_parm;
48892- u32 roles = FC_RPORT_ROLE_UNKNOWN;
48893
48894 rjt_data.fp = NULL;
48895 fh = fc_frame_header_get(rx_fp);
48896@@ -1485,46 +1496,41 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
48897 pp->prli.prli_len = htons(len);
48898 len -= sizeof(struct fc_els_prli);
48899
48900- /* reinitialize remote port roles */
48901- rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;
48902-
48903 /*
48904 * Go through all the service parameter pages and build
48905 * response. If plen indicates longer SPP than standard,
48906 * use that. The entire response has been pre-cleared above.
48907 */
48908 spp = &pp->spp;
48909+ mutex_lock(&fc_prov_mutex);
48910 while (len >= plen) {
48911 spp->spp_type = rspp->spp_type;
48912 spp->spp_type_ext = rspp->spp_type_ext;
48913- spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR;
48914- resp = FC_SPP_RESP_ACK;
48915-
48916- switch (rspp->spp_type) {
48917- case 0: /* common to all FC-4 types */
48918- break;
48919- case FC_TYPE_FCP:
48920- fcp_parm = ntohl(rspp->spp_params);
48921- if (fcp_parm & FCP_SPPF_RETRY)
48922- rdata->flags |= FC_RP_FLAGS_RETRY;
48923- rdata->supported_classes = FC_COS_CLASS3;
48924- if (fcp_parm & FCP_SPPF_INIT_FCN)
48925- roles |= FC_RPORT_ROLE_FCP_INITIATOR;
48926- if (fcp_parm & FCP_SPPF_TARG_FCN)
48927- roles |= FC_RPORT_ROLE_FCP_TARGET;
48928- rdata->ids.roles = roles;
48929-
48930- spp->spp_params = htonl(lport->service_params);
48931- break;
48932- default:
48933- resp = FC_SPP_RESP_INVL;
48934- break;
48935+ resp = 0;
48936+
48937+ if (rspp->spp_type < FC_FC4_PROV_SIZE) {
48938+ prov = fc_active_prov[rspp->spp_type];
48939+ if (prov)
48940+ resp = prov->prli(rdata, plen, rspp, spp);
48941+ prov = fc_passive_prov[rspp->spp_type];
48942+ if (prov) {
48943+ passive = prov->prli(rdata, plen, rspp, spp);
48944+ if (!resp || passive == FC_SPP_RESP_ACK)
48945+ resp = passive;
48946+ }
48947+ }
48948+ if (!resp) {
48949+ if (spp->spp_flags & FC_SPP_EST_IMG_PAIR)
48950+ resp |= FC_SPP_RESP_CONF;
48951+ else
48952+ resp |= FC_SPP_RESP_INVL;
48953 }
48954 spp->spp_flags |= resp;
48955 len -= plen;
48956 rspp = (struct fc_els_spp *)((char *)rspp + plen);
48957 spp = (struct fc_els_spp *)((char *)spp + plen);
48958 }
48959+ mutex_unlock(&fc_prov_mutex);
48960
48961 /*
48962 * Send LS_ACC. If this fails, the originator should retry.
48963@@ -1669,6 +1675,79 @@ int fc_rport_init(struct fc_lport *lport)
48964 EXPORT_SYMBOL(fc_rport_init);
48965
48966 /**
48967+ * fc_rport_fcp_prli() - Handle incoming PRLI for the FCP initiator.
48968+ * @rdata: remote port private
48969+ * @spp_len: service parameter page length
48970+ * @rspp: received service parameter page
48971+ * @spp: response service parameter page
48972+ *
48973+ * Returns the value for the response code to be placed in spp_flags;
48974+ * Returns 0 if not an initiator.
48975+ */
48976+static int fc_rport_fcp_prli(struct fc_rport_priv *rdata, u32 spp_len,
48977+ const struct fc_els_spp *rspp,
48978+ struct fc_els_spp *spp)
48979+{
48980+ struct fc_lport *lport = rdata->local_port;
48981+ u32 fcp_parm;
48982+
48983+ fcp_parm = ntohl(rspp->spp_params);
48984+ rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;
48985+ if (fcp_parm & FCP_SPPF_INIT_FCN)
48986+ rdata->ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
48987+ if (fcp_parm & FCP_SPPF_TARG_FCN)
48988+ rdata->ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
48989+ if (fcp_parm & FCP_SPPF_RETRY)
48990+ rdata->flags |= FC_RP_FLAGS_RETRY;
48991+ rdata->supported_classes = FC_COS_CLASS3;
48992+
48993+ if (!(lport->service_params & FC_RPORT_ROLE_FCP_INITIATOR))
48994+ return 0;
48995+
48996+ spp->spp_flags |= rspp->spp_flags & FC_SPP_EST_IMG_PAIR;
48997+
48998+ /*
48999+ * OR in our service parameters with other providers (target), if any.
49000+ */
49001+ fcp_parm = ntohl(spp->spp_params);
49002+ spp->spp_params = htonl(fcp_parm | lport->service_params);
49003+ return FC_SPP_RESP_ACK;
49004+}
49005+
49006+/*
49007+ * FC-4 provider ops for FCP initiator.
49008+ */
49009+struct fc4_prov fc_rport_fcp_init = {
49010+ .prli = fc_rport_fcp_prli,
49011+};
49012+
49013+/**
49014+ * fc_rport_t0_prli() - Handle incoming PRLI parameters for type 0
49015+ * @rdata: remote port private
49016+ * @spp_len: service parameter page length
49017+ * @rspp: received service parameter page
49018+ * @spp: response service parameter page
49019+ */
49020+static int fc_rport_t0_prli(struct fc_rport_priv *rdata, u32 spp_len,
49021+ const struct fc_els_spp *rspp,
49022+ struct fc_els_spp *spp)
49023+{
49024+ if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR)
49025+ return FC_SPP_RESP_INVL;
49026+ return FC_SPP_RESP_ACK;
49027+}
49028+
49029+/*
49030+ * FC-4 provider ops for type 0 service parameters.
49031+ *
49032+ * This handles the special case of type 0 which is always successful
49033+ * but doesn't do anything otherwise.
49034+ */
49035+struct fc4_prov fc_rport_t0_prov = {
49036+ .prli = fc_rport_t0_prli,
49037+};
49038+
49039+/**
49040 * fc_setup_rport() - Initialize the rport_event_queue
49041 */
49042 int fc_setup_rport()
49043diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
49044index 7495c0b..4ac290f 100644
49045--- a/include/scsi/libfc.h
49046+++ b/include/scsi/libfc.h
49047@@ -35,6 +35,8 @@
49048
49049 #include <scsi/fc_frame.h>
49050
49051+#define FC_FC4_PROV_SIZE (FC_TYPE_FCP + 1) /* size of tables */
49052+
49053 /*
49054 * libfc error codes
49055 */
49056@@ -195,6 +197,7 @@ struct fc_rport_libfc_priv {
49057 * @rp_mutex: The mutex that protects the remote port
49058 * @retry_work: Handle for retries
49059 * @event_callback: Callback when READY, FAILED or LOGO states complete
49060+ * @prli_count: Count of open PRLI sessions in providers
49061 */
49062 struct fc_rport_priv {
49063 struct fc_lport *local_port;
49064@@ -216,6 +219,7 @@ struct fc_rport_priv {
49065 struct list_head peers;
49066 struct work_struct event_work;
49067 u32 supported_classes;
49068+ u16 prli_count;
49069 };
49070
49071 /**
49072@@ -857,6 +861,28 @@ struct fc_lport {
49073 struct delayed_work retry_work;
49074 };
49075
49076+/**
49077+ * struct fc4_prov - FC-4 provider registration
49078+ * @prli: Handler for incoming PRLI
49079+ * @prlo: Handler for session reset
49080+ * @recv: Handler for incoming request
49081+ * @module: Pointer to module. May be NULL.
49082+ */
49083+struct fc4_prov {
49084+ int (*prli)(struct fc_rport_priv *, u32 spp_len,
49085+ const struct fc_els_spp *spp_in,
49086+ struct fc_els_spp *spp_out);
49087+ void (*prlo)(struct fc_rport_priv *);
49088+ void (*recv)(struct fc_lport *, struct fc_seq *, struct fc_frame *);
49089+ struct module *module;
49090+};
49091+
49092+/*
49093+ * Register FC-4 provider with libfc.
49094+ */
49095+int fc_fc4_register_provider(enum fc_fh_type type, struct fc4_prov *);
49096+void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *);
49097+
49098 /*
49099 * FC_LPORT HELPER FUNCTIONS
49100 *****************************/
49101libfc: add method for setting handler for incoming exchange
49102
49103Add a method for setting handler for incoming exchange.
49104For multi-sequence exchanges, this allows the target driver
49105to add a response handler for handling subsequent sequences,
49106and exchange manager resets.
49107
49108The new function is called fc_seq_set_resp().
49109
49110Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
49111
49112---
49113 drivers/scsi/libfc/fc_exch.c | 19 +++++++++++++++++++
49114 include/scsi/libfc.h | 11 ++++++++++-
49115 2 files changed, 29 insertions(+), 1 deletions(-)
49116
49117
49118---
49119diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
49120index 104e0fb..1828d1d 100644
49121--- a/drivers/scsi/libfc/fc_exch.c
49122+++ b/drivers/scsi/libfc/fc_exch.c
49123@@ -545,6 +545,22 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp)
49124 return sp;
49125 }
49126
49127+/*
49128+ * Set the response handler for the exchange associated with a sequence.
49129+ */
49130+static void fc_seq_set_resp(struct fc_seq *sp,
49131+ void (*resp)(struct fc_seq *, struct fc_frame *,
49132+ void *),
49133+ void *arg)
49134+{
49135+ struct fc_exch *ep = fc_seq_exch(sp);
49136+
49137+ spin_lock_bh(&ep->ex_lock);
49138+ ep->resp = resp;
49139+ ep->arg = arg;
49140+ spin_unlock_bh(&ep->ex_lock);
49141+}
49142+
49143 /**
49144 * fc_seq_exch_abort() - Abort an exchange and sequence
49145 * @req_sp: The sequence to be aborted
49146@@ -2263,6 +2279,9 @@ int fc_exch_init(struct fc_lport *lport)
49147 if (!lport->tt.seq_start_next)
49148 lport->tt.seq_start_next = fc_seq_start_next;
49149
49150+ if (!lport->tt.seq_set_resp)
49151+ lport->tt.seq_set_resp = fc_seq_set_resp;
49152+
49153 if (!lport->tt.exch_seq_send)
49154 lport->tt.exch_seq_send = fc_exch_seq_send;
49155
49156diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
49157index 4ac290f..64a4756 100644
49158--- a/include/scsi/libfc.h
49159+++ b/include/scsi/libfc.h
49160@@ -571,6 +571,16 @@ struct libfc_function_template {
49161 struct fc_seq *(*seq_start_next)(struct fc_seq *);
49162
49163 /*
49164+ * Set a response handler for the exchange of the sequence.
49165+ *
49166+ * STATUS: OPTIONAL
49167+ */
49168+ void (*seq_set_resp)(struct fc_seq *sp,
49169+ void (*resp)(struct fc_seq *, struct fc_frame *,
49170+ void *),
49171+ void *arg);
49172+
49173+ /*
49174 * Reset an exchange manager, completing all sequences and exchanges.
49175 * If s_id is non-zero, reset only exchanges originating from that FID.
49176 * If d_id is non-zero, reset only exchanges sending to that FID.
49177@@ -1056,7 +1066,6 @@ struct fc_seq *fc_elsct_send(struct fc_lport *, u32 did,
49178 void fc_lport_flogi_resp(struct fc_seq *, struct fc_frame *, void *);
49179 void fc_lport_logo_resp(struct fc_seq *, struct fc_frame *, void *);
49180
49181-
49182 /*
49183 * EXCHANGE MANAGER LAYER
49184 *****************************/
49185libfc: add local port hook for provider session lookup
49186
49187The target provider needs a per-instance lookup table
49188or other way to lookup sessions quickly without going through
49189a linear list or serializing too much.
49190
49191Add a simple void * array indexed by FC-4 type to the fc_lport.
49192
49193Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
49194
49195---
49196 include/scsi/libfc.h | 2 ++
49197 1 files changed, 2 insertions(+), 0 deletions(-)
49198
49199
49200---
49201diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
49202index 64a4756..9d7c8e3 100644
49203--- a/include/scsi/libfc.h
49204+++ b/include/scsi/libfc.h
49205@@ -816,6 +816,7 @@ struct fc_disc {
49206 * @lp_mutex: Mutex to protect the local port
49207 * @list: Handle for list of local ports
49208 * @retry_work: Handle to local port for delayed retry context
49209+ * @prov: Pointers available for use by passive FC-4 providers
49210 */
49211 struct fc_lport {
49212 /* Associations */
49213@@ -869,6 +870,7 @@ struct fc_lport {
49214 struct mutex lp_mutex;
49215 struct list_head list;
49216 struct delayed_work retry_work;
49217+ void *prov[FC_FC4_PROV_SIZE];
49218 };
49219
49220 /**
49221libfc: add hook to notify providers of local port changes
49222
49223When an SCST provider is registered, it needs to know what
49224local ports are available for configuration as targets.
49225
49226Add a notifier chain that is invoked when any local port
49227that is added or deleted.
49228
49229Maintain a global list of local ports and add an
49230interator function that calls a given function for
49231every existing local port. This is used when first
49232loading a provider.
49233
49234Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
49235
49236---
49237 drivers/scsi/libfc/fc_libfc.c | 41 +++++++++++++++++++++++++++++++++++++++++
49238 drivers/scsi/libfc/fc_libfc.h | 2 ++
49239 drivers/scsi/libfc/fc_lport.c | 2 ++
49240 include/scsi/libfc.h | 14 +++++++++++++-
49241 4 files changed, 58 insertions(+), 1 deletions(-)
49242
49243
49244---
49245diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c
49246index ce0de44..abd108a 100644
49247--- a/drivers/scsi/libfc/fc_libfc.c
49248+++ b/drivers/scsi/libfc/fc_libfc.c
49249@@ -35,6 +35,10 @@ module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR);
49250 MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
49251
49252 DEFINE_MUTEX(fc_prov_mutex);
49253+static LIST_HEAD(fc_local_ports);
49254+struct blocking_notifier_head fc_lport_notifier_head =
49255+ BLOCKING_NOTIFIER_INIT(fc_lport_notifier_head);
49256+EXPORT_SYMBOL(fc_lport_notifier_head);
49257
49258 /*
49259 * Providers which primarily send requests and PRLIs.
49260@@ -150,6 +154,17 @@ u32 fc_copy_buffer_to_sglist(void *buf, size_t len,
49261 return copy_len;
49262 }
49263
49264+void fc_lport_iterate(void (*notify)(struct fc_lport *, void *), void *arg)
49265+{
49266+ struct fc_lport *lport;
49267+
49268+ mutex_lock(&fc_prov_mutex);
49269+ list_for_each_entry(lport, &fc_local_ports, lport_list)
49270+ notify(lport, arg);
49271+ mutex_unlock(&fc_prov_mutex);
49272+}
49273+EXPORT_SYMBOL(fc_lport_iterate);
49274+
49275 /**
49276 * fc_fc4_register_provider() - register FC-4 upper-level provider.
49277 * @type: FC-4 type, such as FC_TYPE_FCP
49278@@ -192,3 +207,29 @@ void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *prov)
49279 synchronize_rcu();
49280 }
49281 EXPORT_SYMBOL(fc_fc4_deregister_provider);
49282+
49283+/**
49284+ * fc_fc4_add_lport() - add new local port to list and run notifiers.
49285+ * @lport: The new local port.
49286+ */
49287+void fc_fc4_add_lport(struct fc_lport *lport)
49288+{
49289+ mutex_lock(&fc_prov_mutex);
49290+ list_add_tail(&lport->lport_list, &fc_local_ports);
49291+ blocking_notifier_call_chain(&fc_lport_notifier_head,
49292+ FC_LPORT_EV_ADD, lport);
49293+ mutex_unlock(&fc_prov_mutex);
49294+}
49295+
49296+/**
49297+ * fc_fc4_del_lport() - remove local port from list and run notifiers.
49298+ * @lport: The new local port.
49299+ */
49300+void fc_fc4_del_lport(struct fc_lport *lport)
49301+{
49302+ mutex_lock(&fc_prov_mutex);
49303+ list_del(&lport->lport_list);
49304+ blocking_notifier_call_chain(&fc_lport_notifier_head,
49305+ FC_LPORT_EV_DEL, lport);
49306+ mutex_unlock(&fc_prov_mutex);
49307+}
49308diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h
49309index 2323c80..85ce01e 100644
49310--- a/drivers/scsi/libfc/fc_libfc.h
49311+++ b/drivers/scsi/libfc/fc_libfc.h
49312@@ -111,6 +111,8 @@ void fc_destroy_fcp(void);
49313 * Internal libfc functions
49314 */
49315 const char *fc_els_resp_type(struct fc_frame *);
49316+extern void fc_fc4_add_lport(struct fc_lport *);
49317+extern void fc_fc4_del_lport(struct fc_lport *);
49318
49319 /*
49320 * Copies a buffer into an sg list
49321diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
49322index b05329c..375a2a7 100644
49323--- a/drivers/scsi/libfc/fc_lport.c
49324+++ b/drivers/scsi/libfc/fc_lport.c
49325@@ -647,6 +647,7 @@ int fc_lport_destroy(struct fc_lport *lport)
49326 lport->tt.fcp_abort_io(lport);
49327 lport->tt.disc_stop_final(lport);
49328 lport->tt.exch_mgr_reset(lport, 0, 0);
49329+ fc_fc4_del_lport(lport);
49330 return 0;
49331 }
49332 EXPORT_SYMBOL(fc_lport_destroy);
49333@@ -1639,6 +1640,7 @@ int fc_lport_init(struct fc_lport *lport)
49334 fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_1GBIT;
49335 if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT)
49336 fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT;
49337+ fc_fc4_add_lport(lport);
49338
49339 return 0;
49340 }
49341diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
49342index 9d7c8e3..2fa3538 100644
49343--- a/include/scsi/libfc.h
49344+++ b/include/scsi/libfc.h
49345@@ -775,6 +775,15 @@ struct fc_disc {
49346 enum fc_disc_event);
49347 };
49348
49349+/*
49350+ * Local port notifier and events.
49351+ */
49352+extern struct blocking_notifier_head fc_lport_notifier_head;
49353+enum fc_lport_event {
49354+ FC_LPORT_EV_ADD,
49355+ FC_LPORT_EV_DEL,
49356+};
49357+
49358 /**
49359 * struct fc_lport - Local port
49360 * @host: The SCSI host associated with a local port
49361@@ -814,8 +823,9 @@ struct fc_disc {
49362 * @lso_max: The maximum large offload send size
49363 * @fcts: FC-4 type mask
49364 * @lp_mutex: Mutex to protect the local port
49365- * @list: Handle for list of local ports
49366+ * @list: Linkage on list of vport peers
49367 * @retry_work: Handle to local port for delayed retry context
49368+ * @lport_list: Linkage on module-wide list of local ports
49369 * @prov: Pointers available for use by passive FC-4 providers
49370 */
49371 struct fc_lport {
49372@@ -870,6 +880,7 @@ struct fc_lport {
49373 struct mutex lp_mutex;
49374 struct list_head list;
49375 struct delayed_work retry_work;
49376+ struct list_head lport_list;
49377 void *prov[FC_FC4_PROV_SIZE];
49378 };
49379
49380@@ -1024,6 +1035,7 @@ int fc_set_mfs(struct fc_lport *, u32 mfs);
49381 struct fc_lport *libfc_vport_create(struct fc_vport *, int privsize);
49382 struct fc_lport *fc_vport_id_lookup(struct fc_lport *, u32 port_id);
49383 int fc_lport_bsg_request(struct fc_bsg_job *);
49384+void fc_lport_iterate(void (*func)(struct fc_lport *, void *), void *);
49385
49386 /*
49387 * REMOTE PORT LAYER
49388--- a/include/scsi/fc_frame.h 2010-06-13 11:08:26.000000000 +0200
49389+++ b/include/scsi/fc_frame.h 2010-06-13 11:08:53.000000000 +0200
49390@@ -66,8 +66,8 @@ struct fcoe_rcv_info {
49391 struct fc_fcp_pkt *fr_fsp; /* for the corresponding fcp I/O */
49392 u32 fr_crc;
49393 u16 fr_max_payload; /* max FC payload */
49394- enum fc_sof fr_sof; /* start of frame delimiter */
49395- enum fc_eof fr_eof; /* end of frame delimiter */
49396+ u8 fr_sof; /* start of frame delimiter */
49397+ u8 fr_eof; /* end of frame delimiter */
49398 u8 fr_flags; /* flags - see below */
49399 u8 granted_mac[ETH_ALEN]; /* FCoE MAC address */
49400 };
49401diff -uprN orig/linux-2.6.35/drivers/scst/fcst/Makefile linux-2.6.35/drivers/scst/fcst/Makefile
49402--- orig/linux-2.6.35/drivers/scst/fcst/Makefile
49403+++ linux-2.6.35/drivers/scst/fcst/Makefile
49404@@ -0,0 +1,7 @@
49405+obj-$(CONFIG_FCST) += fcst.o
49406+
49407+fcst-objs := \
49408+ ft_cmd.o \
49409+ ft_io.o \
49410+ ft_scst.o \
49411+ ft_sess.o
49412diff -uprN orig/linux-2.6.35/drivers/scst/fcst/Kconfig linux-2.6.35/drivers/scst/fcst/Kconfig
49413--- orig/linux-2.6.35/drivers/scst/fcst/Kconfig
49414+++ linux-2.6.35/drivers/scst/fcst/Kconfig
49415@@ -0,0 +1,5 @@
49416+config FCST
49417+ tristate "SCST target module for Fibre Channel using libfc"
49418+ depends on LIBFC && SCST
49419+ ---help---
49420+ Supports using libfc HBAs as target adapters with SCST
49421diff -uprN orig/linux-2.6.35/drivers/scst/fcst/fcst.h linux-2.6.35/drivers/scst/fcst/fcst.h
49422--- orig/linux-2.6.35/drivers/scst/fcst/fcst.h
49423+++ linux-2.6.35/drivers/scst/fcst/fcst.h
49424@@ -0,0 +1,151 @@
49425+/*
49426+ * Copyright (c) 2010 Cisco Systems, Inc.
49427+ *
49428+ * This program is free software; you may redistribute it and/or modify
49429+ * it under the terms of the GNU General Public License as published by
49430+ * the Free Software Foundation; version 2 of the License.
49431+ *
49432+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
49433+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49434+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
49435+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
49436+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
49437+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
49438+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
49439+ * SOFTWARE.
49440+ *
49441+ * $Id$
49442+ */
49443+#ifndef __SCSI_FCST_H__
49444+#define __SCSI_FCST_H__
49445+
49446+#include <scst/scst.h>
49447+
49448+#define FT_VERSION "0.3"
49449+#define FT_MODULE "fcst"
49450+
49451+#define FT_MAX_HW_PENDING_TIME 20 /* max I/O time in seconds */
49452+
49453+/*
49454+ * Debug options.
49455+ */
49456+#define FT_DEBUG_CONF 0x01 /* configuration messages */
49457+#define FT_DEBUG_SESS 0x02 /* session messages */
49458+#define FT_DEBUG_IO 0x04 /* I/O operations */
49459+
49460+extern unsigned int ft_debug_logging; /* debug options */
49461+
49462+#define FT_ERR(fmt, args...) \
49463+ printk(KERN_ERR FT_MODULE ": %s: " fmt, __func__, ##args)
49464+
49465+#define FT_DEBUG(mask, fmt, args...) \
49466+ do { \
49467+ if (ft_debug_logging & (mask)) \
49468+ printk(KERN_INFO FT_MODULE ": %s: " fmt, \
49469+ __func__, ##args); \
49470+ } while (0)
49471+
49472+#define FT_CONF_DBG(fmt, args...) FT_DEBUG(FT_DEBUG_CONF, fmt, ##args)
49473+#define FT_SESS_DBG(fmt, args...) FT_DEBUG(FT_DEBUG_SESS, fmt, ##args)
49474+#define FT_IO_DBG(fmt, args...) FT_DEBUG(FT_DEBUG_IO, fmt, ##args)
49475+
49476+#define FT_NAMELEN 32 /* length of ASCI WWPNs including pad */
49477+
49478+/*
49479+ * Session (remote port).
49480+ */
49481+struct ft_sess {
49482+ u32 port_id; /* for hash lookup use only */
49483+ u32 params;
49484+ u16 max_payload; /* max transmitted payload size */
49485+ u32 max_lso_payload; /* max offloaded payload size */
49486+ u64 port_name; /* port name for transport ID */
49487+ struct ft_tport *tport;
49488+ struct hlist_node hash; /* linkage in ft_sess_hash table */
49489+ struct rcu_head rcu;
49490+ struct kref kref; /* ref for hash and outstanding I/Os */
49491+ struct scst_session *scst_sess;
49492+};
49493+
49494+/*
49495+ * Hash table of sessions per local port.
49496+ * Hash lookup by remote port FC_ID.
49497+ */
49498+#define FT_SESS_HASH_BITS 6
49499+#define FT_SESS_HASH_SIZE (1 << FT_SESS_HASH_BITS)
49500+
49501+/*
49502+ * Per local port data.
49503+ * This is created when the first session logs into the local port.
49504+ * Deleted when tpg is deleted or last session is logged off.
49505+ */
49506+struct ft_tport {
49507+ u32 sess_count; /* number of sessions in hash */
49508+ u8 enabled:1;
49509+ struct rcu_head rcu;
49510+ struct hlist_head hash[FT_SESS_HASH_SIZE]; /* list of sessions */
49511+ struct fc_lport *lport;
49512+ struct scst_tgt *tgt;
49513+};
49514+
49515+/*
49516+ * Commands
49517+ */
49518+struct ft_cmd {
49519+ int serial; /* order received, for debugging */
49520+ struct fc_seq *seq; /* sequence in exchange mgr */
49521+ struct fc_frame *req_frame; /* original request frame */
49522+ u32 write_data_len; /* data received from initiator */
49523+ u32 read_data_len; /* data sent to initiator */
49524+ u32 xfer_rdy_len; /* max xfer ready offset */
49525+ u32 max_lso_payload; /* max offloaded (LSO) data payload */
49526+ u16 max_payload; /* max transmitted data payload */
49527+ struct scst_cmd *scst_cmd;
49528+};
49529+
49530+extern struct list_head ft_lport_list;
49531+extern struct mutex ft_lport_lock;
49532+extern struct scst_tgt_template ft_scst_template;
49533+
49534+/*
49535+ * libfc interface.
49536+ */
49537+int ft_prli(struct fc_rport_priv *, u32 spp_len,
49538+ const struct fc_els_spp *, struct fc_els_spp *);
49539+void ft_prlo(struct fc_rport_priv *);
49540+void ft_recv(struct fc_lport *, struct fc_seq *, struct fc_frame *);
49541+
49542+/*
49543+ * SCST interface.
49544+ */
49545+int ft_send_response(struct scst_cmd *);
49546+int ft_send_xfer_rdy(struct scst_cmd *);
49547+void ft_cmd_timeout(struct scst_cmd *);
49548+void ft_cmd_free(struct scst_cmd *);
49549+void ft_cmd_tm_done(struct scst_mgmt_cmd *);
49550+int ft_tgt_detect(struct scst_tgt_template *);
49551+int ft_tgt_release(struct scst_tgt *);
49552+int ft_tgt_enable(struct scst_tgt *, bool);
49553+bool ft_tgt_enabled(struct scst_tgt *);
49554+int ft_report_aen(struct scst_aen *);
49555+int ft_get_transport_id(struct scst_session *, uint8_t **);
49556+
49557+/*
49558+ * Session interface.
49559+ */
49560+int ft_lport_notify(struct notifier_block *, unsigned long, void *);
49561+void ft_lport_add(struct fc_lport *, void *);
49562+void ft_lport_del(struct fc_lport *, void *);
49563+
49564+/*
49565+ * other internal functions.
49566+ */
49567+int ft_thread(void *);
49568+void ft_recv_req(struct ft_sess *, struct fc_seq *, struct fc_frame *);
49569+void ft_recv_write_data(struct scst_cmd *, struct fc_frame *);
49570+int ft_send_read_data(struct scst_cmd *);
49571+struct ft_tpg *ft_lport_find_tpg(struct fc_lport *);
49572+struct ft_node_acl *ft_acl_get(struct ft_tpg *, struct fc_rport_priv *);
49573+void ft_cmd_dump(struct scst_cmd *, const char *);
49574+
49575+#endif /* __SCSI_FCST_H__ */
49576diff -uprN orig/linux-2.6.35/drivers/scst/fcst/ft_cmd.c linux-2.6.35/drivers/scst/fcst/ft_cmd.c
49577--- orig/linux-2.6.35/drivers/scst/fcst/ft_cmd.c
49578+++ linux-2.6.35/drivers/scst/fcst/ft_cmd.c
49579@@ -0,0 +1,686 @@
49580+/*
49581+ * Copyright (c) 2010 Cisco Systems, Inc.
49582+ *
49583+ * This program is free software; you may redistribute it and/or modify
49584+ * it under the terms of the GNU General Public License as published by
49585+ * the Free Software Foundation; version 2 of the License.
49586+ *
49587+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
49588+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49589+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
49590+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
49591+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
49592+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
49593+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
49594+ * SOFTWARE.
49595+ */
49596+#include <linux/kernel.h>
49597+#include <linux/types.h>
49598+#include <scsi/libfc.h>
49599+#include <scsi/fc_encode.h>
49600+#include "fcst.h"
49601+
49602+/*
49603+ * Append string to buffer safely.
49604+ * Also prepends a space if there's already something the buf.
49605+ */
49606+static void ft_cmd_flag(char *buf, size_t len, const char *desc)
49607+{
49608+ if (buf[0])
49609+ strlcat(buf, " ", len);
49610+ strlcat(buf, desc, len);
49611+}
49612+
49613+/*
49614+ * Debug: dump command.
49615+ */
49616+void ft_cmd_dump(struct scst_cmd *cmd, const char *caller)
49617+{
49618+ static atomic_t serial;
49619+ struct ft_cmd *fcmd;
49620+ struct fc_exch *ep;
49621+ char prefix[30];
49622+ char buf[150];
49623+
49624+ if (!(ft_debug_logging & FT_DEBUG_IO))
49625+ return;
49626+
49627+ fcmd = scst_cmd_get_tgt_priv(cmd);
49628+ ep = fc_seq_exch(fcmd->seq);
49629+ snprintf(prefix, sizeof(prefix), FT_MODULE ": cmd %2x",
49630+ atomic_inc_return(&serial) & 0xff);
49631+
49632+ printk(KERN_INFO "%s %s oid %x oxid %x resp_len %u\n",
49633+ prefix, caller, ep->oid, ep->oxid,
49634+ scst_cmd_get_resp_data_len(cmd));
49635+ printk(KERN_INFO "%s scst_cmd %p wlen %u rlen %u\n",
49636+ prefix, cmd, fcmd->write_data_len, fcmd->read_data_len);
49637+ printk(KERN_INFO "%s exp_dir %x exp_xfer_len %d exp_in_len %d\n",
49638+ prefix, cmd->expected_data_direction,
49639+ cmd->expected_transfer_len, cmd->expected_out_transfer_len);
49640+ printk(KERN_INFO "%s dir %x data_len %d bufflen %d out_bufflen %d\n",
49641+ prefix, cmd->data_direction, cmd->data_len,
49642+ cmd->bufflen, cmd->out_bufflen);
49643+ printk(KERN_INFO "%s sg_cnt reg %d in %d tgt %d tgt_in %d\n",
49644+ prefix, cmd->sg_cnt, cmd->out_sg_cnt,
49645+ cmd->tgt_sg_cnt, cmd->tgt_out_sg_cnt);
49646+
49647+ buf[0] = '\0';
49648+ if (cmd->sent_for_exec)
49649+ ft_cmd_flag(buf, sizeof(buf), "sent");
49650+ if (cmd->completed)
49651+ ft_cmd_flag(buf, sizeof(buf), "comp");
49652+ if (cmd->ua_ignore)
49653+ ft_cmd_flag(buf, sizeof(buf), "ua_ign");
49654+ if (cmd->atomic)
49655+ ft_cmd_flag(buf, sizeof(buf), "atom");
49656+ if (cmd->double_ua_possible)
49657+ ft_cmd_flag(buf, sizeof(buf), "dbl_ua_poss");
49658+ if (cmd->is_send_status)
49659+ ft_cmd_flag(buf, sizeof(buf), "send_stat");
49660+ if (cmd->retry)
49661+ ft_cmd_flag(buf, sizeof(buf), "retry");
49662+ if (cmd->internal)
49663+ ft_cmd_flag(buf, sizeof(buf), "internal");
49664+ if (cmd->unblock_dev)
49665+ ft_cmd_flag(buf, sizeof(buf), "unblock_dev");
49666+ if (cmd->cmd_hw_pending)
49667+ ft_cmd_flag(buf, sizeof(buf), "hw_pend");
49668+ if (cmd->tgt_need_alloc_data_buf)
49669+ ft_cmd_flag(buf, sizeof(buf), "tgt_need_alloc");
49670+ if (cmd->tgt_data_buf_alloced)
49671+ ft_cmd_flag(buf, sizeof(buf), "tgt_alloced");
49672+ if (cmd->dh_data_buf_alloced)
49673+ ft_cmd_flag(buf, sizeof(buf), "dh_alloced");
49674+ if (cmd->expected_values_set)
49675+ ft_cmd_flag(buf, sizeof(buf), "exp_val");
49676+ if (cmd->sg_buff_modified)
49677+ ft_cmd_flag(buf, sizeof(buf), "sg_buf_mod");
49678+ if (cmd->preprocessing_only)
49679+ ft_cmd_flag(buf, sizeof(buf), "pre_only");
49680+ if (cmd->sn_set)
49681+ ft_cmd_flag(buf, sizeof(buf), "sn_set");
49682+ if (cmd->hq_cmd_inced)
49683+ ft_cmd_flag(buf, sizeof(buf), "hq_cmd_inc");
49684+ if (cmd->set_sn_on_restart_cmd)
49685+ ft_cmd_flag(buf, sizeof(buf), "set_sn_on_restart");
49686+ if (cmd->no_sgv)
49687+ ft_cmd_flag(buf, sizeof(buf), "no_sgv");
49688+ if (cmd->may_need_dma_sync)
49689+ ft_cmd_flag(buf, sizeof(buf), "dma_sync");
49690+ if (cmd->out_of_sn)
49691+ ft_cmd_flag(buf, sizeof(buf), "oo_sn");
49692+ if (cmd->inc_expected_sn_on_done)
49693+ ft_cmd_flag(buf, sizeof(buf), "inc_sn_exp");
49694+ if (cmd->done)
49695+ ft_cmd_flag(buf, sizeof(buf), "done");
49696+ if (cmd->finished)
49697+ ft_cmd_flag(buf, sizeof(buf), "fin");
49698+
49699+ printk(KERN_INFO "%s flags %s\n", prefix, buf);
49700+ printk(KERN_INFO "%s lun %lld sn %d tag %lld cmd_flags %lx\n",
49701+ prefix, cmd->lun, cmd->sn, cmd->tag, cmd->cmd_flags);
49702+ printk(KERN_INFO "%s tgt_sn %d op_flags %x op %s\n",
49703+ prefix, cmd->tgt_sn, cmd->op_flags, cmd->op_name);
49704+ printk(KERN_INFO "%s status %x msg_status %x "
49705+ "host_status %x driver_status %x\n",
49706+ prefix, cmd->status, cmd->msg_status,
49707+ cmd->host_status, cmd->driver_status);
49708+ printk(KERN_INFO "%s cdb_len %d ext_cdb_len %u\n",
49709+ prefix, cmd->cdb_len, cmd->ext_cdb_len);
49710+ snprintf(buf, sizeof(buf), "%s cdb ", prefix);
49711+ print_hex_dump(KERN_INFO, buf, DUMP_PREFIX_NONE,
49712+ 16, 4, cmd->cdb, SCST_MAX_CDB_SIZE, 0);
49713+}
49714+
49715+/*
49716+ * Debug: dump mgmt command.
49717+ */
49718+static void ft_cmd_tm_dump(struct scst_mgmt_cmd *mcmd, const char *caller)
49719+{
49720+ struct ft_cmd *fcmd;
49721+ struct fc_exch *ep;
49722+ char prefix[30];
49723+ char buf[150];
49724+
49725+ if (!(ft_debug_logging & FT_DEBUG_IO))
49726+ return;
49727+ fcmd = scst_mgmt_cmd_get_tgt_priv(mcmd);
49728+ ep = fc_seq_exch(fcmd->seq);
49729+
49730+ snprintf(prefix, sizeof(prefix), FT_MODULE ": mcmd");
49731+
49732+ printk(KERN_INFO "%s %s oid %x oxid %x lun %lld\n",
49733+ prefix, caller, ep->oid, ep->oxid,
49734+ (unsigned long long)mcmd->lun);
49735+ printk(KERN_INFO "%s state %d fn %d fin_wait %d done_wait %d comp %d\n",
49736+ prefix, mcmd->state, mcmd->fn,
49737+ mcmd->cmd_finish_wait_count, mcmd->cmd_done_wait_count,
49738+ mcmd->completed_cmd_count);
49739+ buf[0] = '\0';
49740+ if (mcmd->needs_unblocking)
49741+ ft_cmd_flag(buf, sizeof(buf), "needs_unblock");
49742+ if (mcmd->lun_set)
49743+ ft_cmd_flag(buf, sizeof(buf), "lun_set");
49744+ if (mcmd->cmd_sn_set)
49745+ ft_cmd_flag(buf, sizeof(buf), "cmd_sn_set");
49746+ printk(KERN_INFO "%s flags %s\n", prefix, buf);
49747+ if (mcmd->cmd_to_abort)
49748+ ft_cmd_dump(mcmd->cmd_to_abort, caller);
49749+}
49750+
49751+/*
49752+ * Free command.
49753+ */
49754+void ft_cmd_free(struct scst_cmd *cmd)
49755+{
49756+ struct ft_cmd *fcmd;
49757+
49758+ fcmd = scst_cmd_get_tgt_priv(cmd);
49759+ if (fcmd) {
49760+ scst_cmd_set_tgt_priv(cmd, NULL);
49761+ fc_frame_free(fcmd->req_frame);
49762+ kfree(fcmd);
49763+ }
49764+}
49765+
49766+/*
49767+ * Send response, after data if applicable.
49768+ */
49769+int ft_send_response(struct scst_cmd *cmd)
49770+{
49771+ struct ft_cmd *fcmd;
49772+ struct fc_frame *fp;
49773+ struct fcp_resp_with_ext *fcp;
49774+ struct fc_lport *lport;
49775+ struct fc_exch *ep;
49776+ unsigned int slen;
49777+ size_t len;
49778+ int resid = 0;
49779+ int bi_resid = 0;
49780+ int error;
49781+ int dir;
49782+ u32 status;
49783+
49784+ ft_cmd_dump(cmd, __func__);
49785+ fcmd = scst_cmd_get_tgt_priv(cmd);
49786+ ep = fc_seq_exch(fcmd->seq);
49787+ lport = ep->lp;
49788+
49789+ if (scst_cmd_aborted(cmd)) {
49790+ FT_IO_DBG("cmd aborted did %x oxid %x\n", ep->did, ep->oxid);
49791+ scst_set_delivery_status(cmd, SCST_CMD_DELIVERY_ABORTED);
49792+ goto done;
49793+ }
49794+
49795+ if (!scst_cmd_get_is_send_status(cmd)) {
49796+ FT_IO_DBG("send status not set. feature not implemented\n");
49797+ return SCST_TGT_RES_FATAL_ERROR;
49798+ }
49799+
49800+ status = scst_cmd_get_status(cmd);
49801+ dir = scst_cmd_get_data_direction(cmd);
49802+
49803+ slen = scst_cmd_get_sense_buffer_len(cmd);
49804+ len = sizeof(*fcp) + slen;
49805+
49806+ /*
49807+ * Send read data and set underflow/overflow residual count.
49808+ * For bi-directional comands, the bi_resid is for the read direction.
49809+ */
49810+ if (dir & SCST_DATA_WRITE)
49811+ resid = (signed)scst_cmd_get_bufflen(cmd) -
49812+ fcmd->write_data_len;
49813+ if (dir & SCST_DATA_READ) {
49814+ error = ft_send_read_data(cmd);
49815+ if (error) {
49816+ FT_ERR("ft_send_read_data returned %d\n", error);
49817+ return error;
49818+ }
49819+
49820+ if (dir == SCST_DATA_BIDI) {
49821+ bi_resid = (signed)scst_cmd_get_out_bufflen(cmd) -
49822+ scst_cmd_get_resp_data_len(cmd);
49823+ if (bi_resid)
49824+ len += sizeof(__be32);
49825+ } else
49826+ resid = (signed)scst_cmd_get_bufflen(cmd) -
49827+ scst_cmd_get_resp_data_len(cmd);
49828+ }
49829+
49830+ fp = fc_frame_alloc(lport, len);
49831+ if (!fp)
49832+ return SCST_TGT_RES_QUEUE_FULL;
49833+
49834+ fcp = fc_frame_payload_get(fp, len);
49835+ memset(fcp, 0, sizeof(*fcp));
49836+ fcp->resp.fr_status = status;
49837+
49838+ if (slen) {
49839+ fcp->resp.fr_flags |= FCP_SNS_LEN_VAL;
49840+ fcp->ext.fr_sns_len = htonl(slen);
49841+ memcpy(fcp + 1, scst_cmd_get_sense_buffer(cmd), slen);
49842+ }
49843+ if (bi_resid) {
49844+ if (bi_resid < 0) {
49845+ fcp->resp.fr_flags |= FCP_BIDI_READ_OVER;
49846+ bi_resid = -bi_resid;
49847+ } else
49848+ fcp->resp.fr_flags |= FCP_BIDI_READ_UNDER;
49849+ *(__be32 *)((u8 *)(fcp + 1) + slen) = htonl(bi_resid);
49850+ }
49851+ if (resid) {
49852+ if (resid < 0) {
49853+ resid = -resid;
49854+ fcp->resp.fr_flags |= FCP_RESID_OVER;
49855+ } else
49856+ fcp->resp.fr_flags |= FCP_RESID_UNDER;
49857+ fcp->ext.fr_resid = htonl(resid);
49858+ }
49859+ FT_IO_DBG("response did %x oxid %x\n", ep->did, ep->oxid);
49860+
49861+ /*
49862+ * Send response.
49863+ */
49864+ fcmd->seq = lport->tt.seq_start_next(fcmd->seq);
49865+ fc_fill_fc_hdr(fp, FC_RCTL_DD_CMD_STATUS, ep->did, ep->sid, FC_TYPE_FCP,
49866+ FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ, 0);
49867+
49868+ lport->tt.seq_send(lport, fcmd->seq, fp);
49869+done:
49870+ lport->tt.exch_done(fcmd->seq);
49871+ scst_tgt_cmd_done(cmd, SCST_CONTEXT_SAME);
49872+ return SCST_TGT_RES_SUCCESS;
49873+}
49874+
49875+/*
49876+ * FC sequence response handler for follow-on sequences (data) and aborts.
49877+ */
49878+static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
49879+{
49880+ struct scst_cmd *cmd = arg;
49881+ struct fc_frame_header *fh;
49882+
49883+ /*
49884+ * If an error is being reported, it must be FC_EX_CLOSED.
49885+ * Timeouts don't occur on incoming requests, and there are
49886+ * currently no other errors.
49887+ * The PRLO handler will be also called by libfc to delete
49888+ * the session and all pending commands, so we ignore this response.
49889+ */
49890+ if (IS_ERR(fp)) {
49891+ FT_IO_DBG("exchange error %ld - not handled\n", -PTR_ERR(fp));
49892+ return;
49893+ }
49894+
49895+ fh = fc_frame_header_get(fp);
49896+ switch (fh->fh_r_ctl) {
49897+ case FC_RCTL_DD_SOL_DATA: /* write data */
49898+ ft_recv_write_data(cmd, fp);
49899+ break;
49900+ case FC_RCTL_DD_UNSOL_CTL: /* command */
49901+ case FC_RCTL_DD_SOL_CTL: /* transfer ready */
49902+ case FC_RCTL_DD_DATA_DESC: /* transfer ready */
49903+ default:
49904+ printk(KERN_INFO "%s: unhandled frame r_ctl %x\n",
49905+ __func__, fh->fh_r_ctl);
49906+ fc_frame_free(fp);
49907+ break;
49908+ }
49909+}
49910+
49911+/*
49912+ * Command timeout.
49913+ * SCST calls this when the command has taken too long in the device handler.
49914+ */
49915+void ft_cmd_timeout(struct scst_cmd *cmd)
49916+{
49917+ FT_IO_DBG("timeout not implemented\n"); /* XXX TBD */
49918+}
49919+
49920+/*
49921+ * Send TX_RDY (transfer ready).
49922+ */
49923+static int ft_send_xfer_rdy_off(struct scst_cmd *cmd, u32 offset, u32 len)
49924+{
49925+ struct ft_cmd *fcmd;
49926+ struct fc_frame *fp;
49927+ struct fcp_txrdy *txrdy;
49928+ struct fc_lport *lport;
49929+ struct fc_exch *ep;
49930+
49931+ fcmd = scst_cmd_get_tgt_priv(cmd);
49932+ if (fcmd->xfer_rdy_len < len + offset)
49933+ fcmd->xfer_rdy_len = len + offset;
49934+
49935+ ep = fc_seq_exch(fcmd->seq);
49936+ lport = ep->lp;
49937+ fp = fc_frame_alloc(lport, sizeof(*txrdy));
49938+ if (!fp)
49939+ return SCST_TGT_RES_QUEUE_FULL;
49940+
49941+ txrdy = fc_frame_payload_get(fp, sizeof(*txrdy));
49942+ memset(txrdy, 0, sizeof(*txrdy));
49943+ txrdy->ft_data_ro = htonl(offset);
49944+ txrdy->ft_burst_len = htonl(len);
49945+
49946+ fcmd->seq = lport->tt.seq_start_next(fcmd->seq);
49947+ fc_fill_fc_hdr(fp, FC_RCTL_DD_DATA_DESC, ep->did, ep->sid, FC_TYPE_FCP,
49948+ FC_FC_EX_CTX | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
49949+ lport->tt.seq_send(lport, fcmd->seq, fp);
49950+ return SCST_TGT_RES_SUCCESS;
49951+}
49952+
49953+/*
49954+ * Send TX_RDY (transfer ready).
49955+ */
49956+int ft_send_xfer_rdy(struct scst_cmd *cmd)
49957+{
49958+ return ft_send_xfer_rdy_off(cmd, 0, scst_cmd_get_bufflen(cmd));
49959+}
49960+
49961+/*
49962+ * Send a FCP response including SCSI status and optional FCP rsp_code.
49963+ * status is SAM_STAT_GOOD (zero) if code is valid.
49964+ * This is used in error cases, such as allocation failures.
49965+ */
49966+static void ft_send_resp_status(struct fc_seq *sp, u32 status,
49967+ enum fcp_resp_rsp_codes code)
49968+{
49969+ struct fc_frame *fp;
49970+ size_t len;
49971+ struct fcp_resp_with_ext *fcp;
49972+ struct fcp_resp_rsp_info *info;
49973+ struct fc_lport *lport;
49974+ struct fc_exch *ep;
49975+
49976+ ep = fc_seq_exch(sp);
49977+
49978+ FT_IO_DBG("FCP error response: did %x oxid %x status %x code %x\n",
49979+ ep->did, ep->oxid, status, code);
49980+ lport = ep->lp;
49981+ len = sizeof(*fcp);
49982+ if (status == SAM_STAT_GOOD)
49983+ len += sizeof(*info);
49984+ fp = fc_frame_alloc(lport, len);
49985+ if (!fp)
49986+ goto out;
49987+ fcp = fc_frame_payload_get(fp, len);
49988+ memset(fcp, 0, len);
49989+ fcp->resp.fr_status = status;
49990+ if (status == SAM_STAT_GOOD) {
49991+ fcp->ext.fr_rsp_len = htonl(sizeof(*info));
49992+ fcp->resp.fr_flags |= FCP_RSP_LEN_VAL;
49993+ info = (struct fcp_resp_rsp_info *)(fcp + 1);
49994+ info->rsp_code = code;
49995+ }
49996+
49997+ sp = lport->tt.seq_start_next(sp);
49998+ fc_fill_fc_hdr(fp, FC_RCTL_DD_CMD_STATUS, ep->did, ep->sid, FC_TYPE_FCP,
49999+ FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ, 0);
50000+
50001+ lport->tt.seq_send(lport, sp, fp);
50002+out:
50003+ lport->tt.exch_done(sp);
50004+}
50005+
50006+/*
50007+ * Send error or task management response.
50008+ * Always frees the fcmd and associated state.
50009+ */
50010+static void ft_send_resp_code(struct ft_cmd *fcmd, enum fcp_resp_rsp_codes code)
50011+{
50012+ ft_send_resp_status(fcmd->seq, SAM_STAT_GOOD, code);
50013+ fc_frame_free(fcmd->req_frame);
50014+ kfree(fcmd);
50015+}
50016+
50017+void ft_cmd_tm_done(struct scst_mgmt_cmd *mcmd)
50018+{
50019+ struct ft_cmd *fcmd;
50020+ enum fcp_resp_rsp_codes code;
50021+
50022+ ft_cmd_tm_dump(mcmd, __func__);
50023+ fcmd = scst_mgmt_cmd_get_tgt_priv(mcmd);
50024+ switch (scst_mgmt_cmd_get_status(mcmd)) {
50025+ case SCST_MGMT_STATUS_SUCCESS:
50026+ code = FCP_TMF_CMPL;
50027+ break;
50028+ case SCST_MGMT_STATUS_REJECTED:
50029+ code = FCP_TMF_REJECTED;
50030+ break;
50031+ case SCST_MGMT_STATUS_LUN_NOT_EXIST:
50032+ code = FCP_TMF_INVALID_LUN;
50033+ break;
50034+ case SCST_MGMT_STATUS_TASK_NOT_EXIST:
50035+ case SCST_MGMT_STATUS_FN_NOT_SUPPORTED:
50036+ case SCST_MGMT_STATUS_FAILED:
50037+ default:
50038+ code = FCP_TMF_FAILED;
50039+ break;
50040+ }
50041+ FT_IO_DBG("tm cmd done fn %d code %d\n", mcmd->fn, code);
50042+ ft_send_resp_code(fcmd, code);
50043+}
50044+
50045+/*
50046+ * Handle an incoming FCP task management command frame.
50047+ * Note that this may be called directly from the softirq context.
50048+ */
50049+static void ft_recv_tm(struct scst_session *scst_sess,
50050+ struct ft_cmd *fcmd, struct fcp_cmnd *fcp)
50051+{
50052+ struct scst_rx_mgmt_params params;
50053+ int ret;
50054+
50055+ memset(&params, 0, sizeof(params));
50056+ params.lun = fcp->fc_lun;
50057+ params.lun_len = sizeof(fcp->fc_lun);
50058+ params.lun_set = 1;
50059+ params.atomic = SCST_ATOMIC;
50060+ params.tgt_priv = fcmd;
50061+
50062+ switch (fcp->fc_tm_flags) {
50063+ case FCP_TMF_LUN_RESET:
50064+ params.fn = SCST_LUN_RESET;
50065+ break;
50066+ case FCP_TMF_TGT_RESET:
50067+ params.fn = SCST_TARGET_RESET;
50068+ params.lun_set = 0;
50069+ break;
50070+ case FCP_TMF_CLR_TASK_SET:
50071+ params.fn = SCST_CLEAR_TASK_SET;
50072+ break;
50073+ case FCP_TMF_ABT_TASK_SET:
50074+ params.fn = SCST_ABORT_TASK_SET;
50075+ break;
50076+ case FCP_TMF_CLR_ACA:
50077+ params.fn = SCST_CLEAR_ACA;
50078+ break;
50079+ default:
50080+ /*
50081+ * FCP4r01 indicates having a combination of
50082+ * tm_flags set is invalid.
50083+ */
50084+ FT_IO_DBG("invalid FCP tm_flags %x\n", fcp->fc_tm_flags);
50085+ ft_send_resp_code(fcmd, FCP_CMND_FIELDS_INVALID);
50086+ return;
50087+ }
50088+ FT_IO_DBG("submit tm cmd fn %d\n", params.fn);
50089+ ret = scst_rx_mgmt_fn(scst_sess, &params);
50090+ FT_IO_DBG("scst_rx_mgmt_fn ret %d\n", ret);
50091+ if (ret)
50092+ ft_send_resp_code(fcmd, FCP_TMF_FAILED);
50093+}
50094+
50095+/*
50096+ * Handle an incoming FCP command frame.
50097+ * Note that this may be called directly from the softirq context.
50098+ */
50099+static void ft_recv_cmd(struct ft_sess *sess, struct fc_seq *sp,
50100+ struct fc_frame *fp)
50101+{
50102+ static atomic_t serial;
50103+ struct scst_cmd *cmd;
50104+ struct ft_cmd *fcmd;
50105+ struct fcp_cmnd *fcp;
50106+ struct fc_lport *lport;
50107+ int data_dir;
50108+ u32 data_len;
50109+ int cdb_len;
50110+
50111+ lport = fc_seq_exch(sp)->lp;
50112+ fcmd = kzalloc(sizeof(*fcmd), GFP_ATOMIC);
50113+ if (!fcmd)
50114+ goto busy;
50115+ fcmd->serial = atomic_inc_return(&serial); /* debug only */
50116+ fcmd->seq = sp;
50117+ fcmd->max_payload = sess->max_payload;
50118+ fcmd->max_lso_payload = sess->max_lso_payload;
50119+ fcmd->req_frame = fp;
50120+
50121+ fcp = fc_frame_payload_get(fp, sizeof(*fcp));
50122+ if (!fcp)
50123+ goto err;
50124+ if (fcp->fc_tm_flags) {
50125+ ft_recv_tm(sess->scst_sess, fcmd, fcp);
50126+ return;
50127+ }
50128+
50129+ /*
50130+ * re-check length including specified CDB length.
50131+ * data_len is just after the CDB.
50132+ */
50133+ cdb_len = fcp->fc_flags & FCP_CFL_LEN_MASK;
50134+ fcp = fc_frame_payload_get(fp, sizeof(*fcp) + cdb_len);
50135+ if (!fcp)
50136+ goto err;
50137+ cdb_len += sizeof(fcp->fc_cdb);
50138+ data_len = ntohl(*(__be32 *)(fcp->fc_cdb + cdb_len));
50139+
50140+ cmd = scst_rx_cmd(sess->scst_sess, fcp->fc_lun, sizeof(fcp->fc_lun),
50141+ fcp->fc_cdb, cdb_len, SCST_ATOMIC);
50142+ if (!cmd) {
50143+ kfree(fcmd);
50144+ goto busy;
50145+ }
50146+ fcmd->scst_cmd = cmd;
50147+ scst_cmd_set_tgt_priv(cmd, fcmd);
50148+
50149+ switch (fcp->fc_flags & (FCP_CFL_RDDATA | FCP_CFL_WRDATA)) {
50150+ case 0:
50151+ data_dir = SCST_DATA_NONE;
50152+ break;
50153+ case FCP_CFL_RDDATA:
50154+ data_dir = SCST_DATA_READ;
50155+ break;
50156+ case FCP_CFL_WRDATA:
50157+ data_dir = SCST_DATA_WRITE;
50158+ break;
50159+ case FCP_CFL_RDDATA | FCP_CFL_WRDATA:
50160+ data_dir = SCST_DATA_BIDI;
50161+ break;
50162+ }
50163+ scst_cmd_set_expected(cmd, data_dir, data_len);
50164+
50165+ switch (fcp->fc_pri_ta & FCP_PTA_MASK) {
50166+ case FCP_PTA_SIMPLE:
50167+ scst_cmd_set_queue_type(cmd, SCST_CMD_QUEUE_SIMPLE);
50168+ break;
50169+ case FCP_PTA_HEADQ:
50170+ scst_cmd_set_queue_type(cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
50171+ break;
50172+ case FCP_PTA_ACA:
50173+ scst_cmd_set_queue_type(cmd, SCST_CMD_QUEUE_ACA);
50174+ break;
50175+ case FCP_PTA_ORDERED:
50176+ default:
50177+ scst_cmd_set_queue_type(cmd, SCST_CMD_QUEUE_ORDERED);
50178+ break;
50179+ }
50180+
50181+ lport->tt.seq_set_resp(sp, ft_recv_seq, cmd);
50182+ scst_cmd_init_done(cmd, SCST_CONTEXT_THREAD);
50183+ return;
50184+
50185+err:
50186+ ft_send_resp_code(fcmd, FCP_CMND_FIELDS_INVALID);
50187+ return;
50188+
50189+busy:
50190+ FT_IO_DBG("cmd allocation failure - sending BUSY\n");
50191+ ft_send_resp_status(sp, SAM_STAT_BUSY, 0);
50192+ fc_frame_free(fp);
50193+}
50194+
50195+/*
50196+ * Send FCP ELS-4 Reject.
50197+ */
50198+static void ft_cmd_ls_rjt(struct fc_seq *sp, enum fc_els_rjt_reason reason,
50199+ enum fc_els_rjt_explan explan)
50200+{
50201+ struct fc_frame *fp;
50202+ struct fc_els_ls_rjt *rjt;
50203+ struct fc_lport *lport;
50204+ struct fc_exch *ep;
50205+
50206+ ep = fc_seq_exch(sp);
50207+ lport = ep->lp;
50208+ fp = fc_frame_alloc(lport, sizeof(*rjt));
50209+ if (!fp)
50210+ return;
50211+
50212+ rjt = fc_frame_payload_get(fp, sizeof(*rjt));
50213+ memset(rjt, 0, sizeof(*rjt));
50214+ rjt->er_cmd = ELS_LS_RJT;
50215+ rjt->er_reason = reason;
50216+ rjt->er_explan = explan;
50217+
50218+ sp = lport->tt.seq_start_next(sp);
50219+ fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, FC_TYPE_FCP,
50220+ FC_FC_EX_CTX | FC_FC_END_SEQ | FC_FC_LAST_SEQ, 0);
50221+ lport->tt.seq_send(lport, sp, fp);
50222+}
50223+
50224+/*
50225+ * Handle an incoming FCP ELS-4 command frame.
50226+ * Note that this may be called directly from the softirq context.
50227+ */
50228+static void ft_recv_els4(struct ft_sess *sess, struct fc_seq *sp,
50229+ struct fc_frame *fp)
50230+{
50231+ u8 op = fc_frame_payload_op(fp);
50232+
50233+ switch (op) {
50234+ case ELS_SRR: /* TBD */
50235+ default:
50236+ FT_IO_DBG("unsupported ELS-4 op %x\n", op);
50237+ ft_cmd_ls_rjt(sp, ELS_RJT_INVAL, ELS_EXPL_NONE);
50238+ fc_frame_free(fp);
50239+ break;
50240+ }
50241+}
50242+
50243+/*
50244+ * Handle an incoming FCP frame.
50245+ * Note that this may be called directly from the softirq context.
50246+ */
50247+void ft_recv_req(struct ft_sess *sess, struct fc_seq *sp, struct fc_frame *fp)
50248+{
50249+ struct fc_frame_header *fh = fc_frame_header_get(fp);
50250+
50251+ switch (fh->fh_r_ctl) {
50252+ case FC_RCTL_DD_UNSOL_CMD:
50253+ ft_recv_cmd(sess, sp, fp);
50254+ break;
50255+ case FC_RCTL_ELS4_REQ:
50256+ ft_recv_els4(sess, sp, fp);
50257+ break;
50258+ default:
50259+ printk(KERN_INFO "%s: unhandled frame r_ctl %x\n",
50260+ __func__, fh->fh_r_ctl);
50261+ fc_frame_free(fp);
50262+ sess->tport->lport->tt.exch_done(sp);
50263+ break;
50264+ }
50265+}
50266diff -uprN orig/linux-2.6.35/drivers/scst/fcst/ft_io.c linux-2.6.35/drivers/scst/fcst/ft_io.c
50267--- orig/linux-2.6.35/drivers/scst/fcst/ft_io.c
50268+++ linux-2.6.35/drivers/scst/fcst/ft_io.c
50269@@ -0,0 +1,272 @@
50270+/*
50271+ * Copyright (c) 2010 Cisco Systems, Inc.
50272+ *
50273+ * Portions based on drivers/scsi/libfc/fc_fcp.c and subject to the following:
50274+ *
50275+ * Copyright (c) 2007 Intel Corporation. All rights reserved.
50276+ * Copyright (c) 2008 Red Hat, Inc. All rights reserved.
50277+ * Copyright (c) 2008 Mike Christie
50278+ *
50279+ * This program is free software; you can redistribute it and/or modify it
50280+ * under the terms and conditions of the GNU General Public License,
50281+ * version 2, as published by the Free Software Foundation.
50282+ *
50283+ * This program is distributed in the hope it will be useful, but WITHOUT
50284+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
50285+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
50286+ * more details.
50287+ *
50288+ * You should have received a copy of the GNU General Public License along with
50289+ * this program; if not, write to the Free Software Foundation, Inc.,
50290+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
50291+ */
50292+#include <linux/kernel.h>
50293+#include <linux/types.h>
50294+#include <scsi/libfc.h>
50295+#include <scsi/fc_encode.h>
50296+#include "fcst.h"
50297+
50298+/*
50299+ * Receive write data frame.
50300+ */
50301+void ft_recv_write_data(struct scst_cmd *cmd, struct fc_frame *fp)
50302+{
50303+ struct ft_cmd *fcmd;
50304+ struct fc_frame_header *fh;
50305+ unsigned int bufflen;
50306+ u32 rel_off;
50307+ size_t frame_len;
50308+ size_t mem_len;
50309+ size_t tlen;
50310+ void *from;
50311+ void *to;
50312+ int dir;
50313+ u8 *buf;
50314+
50315+ dir = scst_cmd_get_data_direction(cmd);
50316+ if (dir == SCST_DATA_BIDI) {
50317+ mem_len = scst_get_out_buf_first(cmd, &buf);
50318+ bufflen = scst_cmd_get_out_bufflen(cmd);
50319+ } else {
50320+ mem_len = scst_get_buf_first(cmd, &buf);
50321+ bufflen = scst_cmd_get_bufflen(cmd);
50322+ }
50323+ to = buf;
50324+
50325+ fcmd = scst_cmd_get_tgt_priv(cmd);
50326+ fh = fc_frame_header_get(fp);
50327+ frame_len = fr_len(fp);
50328+ rel_off = ntohl(fh->fh_parm_offset);
50329+
50330+ FT_IO_DBG("sid %x oxid %x payload_len %zd rel_off %x\n",
50331+ ntoh24(fh->fh_s_id), ntohs(fh->fh_ox_id),
50332+ frame_len - sizeof(*fh), rel_off);
50333+
50334+ if (!(ntoh24(fh->fh_f_ctl) & FC_FC_REL_OFF))
50335+ goto drop;
50336+ if (frame_len <= sizeof(*fh))
50337+ goto drop;
50338+ frame_len -= sizeof(*fh);
50339+ from = fc_frame_payload_get(fp, 0);
50340+
50341+ if (rel_off >= bufflen)
50342+ goto drop;
50343+ if (frame_len + rel_off > bufflen)
50344+ frame_len = bufflen - rel_off;
50345+
50346+ while (frame_len) {
50347+ if (!mem_len) {
50348+ if (dir == SCST_DATA_BIDI) {
50349+ scst_put_out_buf(cmd, buf);
50350+ mem_len = scst_get_out_buf_next(cmd, &buf);
50351+ } else {
50352+ scst_put_buf(cmd, buf);
50353+ mem_len = scst_get_buf_next(cmd, &buf);
50354+ }
50355+ to = buf;
50356+ if (!mem_len)
50357+ break;
50358+ }
50359+ if (rel_off) {
50360+ if (rel_off >= mem_len) {
50361+ rel_off -= mem_len;
50362+ mem_len = 0;
50363+ continue;
50364+ }
50365+ mem_len -= rel_off;
50366+ to += rel_off;
50367+ rel_off = 0;
50368+ }
50369+
50370+ tlen = min(mem_len, frame_len);
50371+ memcpy(to, from, tlen);
50372+
50373+ from += tlen;
50374+ frame_len -= tlen;
50375+ mem_len -= tlen;
50376+ to += tlen;
50377+ fcmd->write_data_len += tlen;
50378+ }
50379+ if (mem_len) {
50380+ if (dir == SCST_DATA_BIDI)
50381+ scst_put_out_buf(cmd, buf);
50382+ else
50383+ scst_put_buf(cmd, buf);
50384+ }
50385+ if (fcmd->write_data_len == cmd->data_len)
50386+ scst_rx_data(cmd, SCST_RX_STATUS_SUCCESS, SCST_CONTEXT_THREAD);
50387+drop:
50388+ fc_frame_free(fp);
50389+}
50390+
50391+/*
50392+ * Send read data back to initiator.
50393+ */
50394+int ft_send_read_data(struct scst_cmd *cmd)
50395+{
50396+ struct ft_cmd *fcmd;
50397+ struct fc_frame *fp = NULL;
50398+ struct fc_exch *ep;
50399+ struct fc_lport *lport;
50400+ size_t remaining;
50401+ u32 fh_off = 0;
50402+ u32 frame_off;
50403+ size_t frame_len = 0;
50404+ size_t mem_len;
50405+ u32 mem_off;
50406+ size_t tlen;
50407+ struct page *page;
50408+ int use_sg;
50409+ int error;
50410+ void *to = NULL;
50411+ u8 *from = NULL;
50412+ int loop_limit = 10000;
50413+
50414+ fcmd = scst_cmd_get_tgt_priv(cmd);
50415+ ep = fc_seq_exch(fcmd->seq);
50416+ lport = ep->lp;
50417+
50418+ frame_off = fcmd->read_data_len;
50419+ tlen = scst_cmd_get_resp_data_len(cmd);
50420+ FT_IO_DBG("oid %x oxid %x resp_len %zd frame_off %u\n",
50421+ ep->oid, ep->oxid, tlen, frame_off);
50422+ if (tlen <= frame_off)
50423+ return SCST_TGT_RES_SUCCESS;
50424+ remaining = tlen - frame_off;
50425+ if (remaining > UINT_MAX)
50426+ FT_ERR("oid %x oxid %x resp_len %zd frame_off %u\n",
50427+ ep->oid, ep->oxid, tlen, frame_off);
50428+
50429+ mem_len = scst_get_buf_first(cmd, &from);
50430+ mem_off = 0;
50431+ if (!mem_len) {
50432+ FT_IO_DBG("mem_len 0\n");
50433+ return SCST_TGT_RES_SUCCESS;
50434+ }
50435+ FT_IO_DBG("sid %x oxid %x mem_len %zd frame_off %u remaining %zd\n",
50436+ ep->sid, ep->oxid, mem_len, frame_off, remaining);
50437+
50438+ /*
50439+ * If we've already transferred some of the data, skip through
50440+ * the buffer over the data already sent and continue with the
50441+ * same sequence. Otherwise, get a new sequence for the data.
50442+ */
50443+ if (frame_off) {
50444+ tlen = frame_off;
50445+ while (mem_len <= tlen) {
50446+ tlen -= mem_len;
50447+ scst_put_buf(cmd, from);
50448+ mem_len = scst_get_buf_next(cmd, &from);
50449+ if (!mem_len)
50450+ return SCST_TGT_RES_SUCCESS;
50451+ }
50452+ mem_len -= tlen;
50453+ mem_off = tlen;
50454+ } else
50455+ fcmd->seq = lport->tt.seq_start_next(fcmd->seq);
50456+
50457+ /* no scatter/gather in skb for odd word length due to fc_seq_send() */
50458+ use_sg = !(remaining % 4) && lport->sg_supp;
50459+
50460+ while (remaining) {
50461+ if (!loop_limit) {
50462+ FT_ERR("hit loop limit. remaining %zx mem_len %zx "
50463+ "frame_len %zx tlen %zx\n",
50464+ remaining, mem_len, frame_len, tlen);
50465+ break;
50466+ }
50467+ loop_limit--;
50468+ if (!mem_len) {
50469+ scst_put_buf(cmd, from);
50470+ mem_len = scst_get_buf_next(cmd, &from);
50471+ mem_off = 0;
50472+ if (!mem_len) {
50473+ FT_ERR("mem_len 0 from get_buf_next\n");
50474+ break;
50475+ }
50476+ }
50477+ if (!frame_len) {
50478+ frame_len = fcmd->max_lso_payload;
50479+ frame_len = min(frame_len, remaining);
50480+ fp = fc_frame_alloc(lport, use_sg ? 0 : frame_len);
50481+ if (!fp) {
50482+ FT_IO_DBG("frame_alloc failed. "
50483+ "use_sg %d frame_len %zd\n",
50484+ use_sg, frame_len);
50485+ break;
50486+ }
50487+ fr_max_payload(fp) = fcmd->max_payload;
50488+ to = fc_frame_payload_get(fp, 0);
50489+ fh_off = frame_off;
50490+ frame_off += frame_len;
50491+ }
50492+ tlen = min(mem_len, frame_len);
50493+ BUG_ON(!tlen);
50494+ BUG_ON(tlen > remaining);
50495+ BUG_ON(tlen > mem_len);
50496+ BUG_ON(tlen > frame_len);
50497+
50498+ if (use_sg) {
50499+ page = virt_to_page(from + mem_off);
50500+ get_page(page);
50501+ tlen = min_t(size_t, tlen,
50502+ PAGE_SIZE - (mem_off & ~PAGE_MASK));
50503+ skb_fill_page_desc(fp_skb(fp),
50504+ skb_shinfo(fp_skb(fp))->nr_frags,
50505+ page, mem_off, tlen);
50506+ fr_len(fp) += tlen;
50507+ fp_skb(fp)->data_len += tlen;
50508+ fp_skb(fp)->truesize +=
50509+ PAGE_SIZE << compound_order(page);
50510+ } else {
50511+ memcpy(to, from + mem_off, tlen);
50512+ to += tlen;
50513+ }
50514+
50515+ mem_len -= tlen;
50516+ mem_off += tlen;
50517+ frame_len -= tlen;
50518+ remaining -= tlen;
50519+
50520+ if (frame_len)
50521+ continue;
50522+ fc_fill_fc_hdr(fp, FC_RCTL_DD_SOL_DATA, ep->did, ep->sid,
50523+ FC_TYPE_FCP,
50524+ remaining ? (FC_FC_EX_CTX | FC_FC_REL_OFF) :
50525+ (FC_FC_EX_CTX | FC_FC_REL_OFF | FC_FC_END_SEQ),
50526+ fh_off);
50527+ error = lport->tt.seq_send(lport, fcmd->seq, fp);
50528+ if (error) {
50529+ WARN_ON(1);
50530+ /* XXX For now, initiator will retry */
50531+ } else
50532+ fcmd->read_data_len = frame_off;
50533+ }
50534+ if (mem_len)
50535+ scst_put_buf(cmd, from);
50536+ if (remaining) {
50537+ FT_IO_DBG("remaining read data %zd\n", remaining);
50538+ return SCST_TGT_RES_QUEUE_FULL;
50539+ }
50540+ return SCST_TGT_RES_SUCCESS;
50541+}
50542diff -uprN orig/linux-2.6.35/drivers/scst/fcst/ft_scst.c linux-2.6.35/drivers/scst/fcst/ft_scst.c
50543--- orig/linux-2.6.35/drivers/scst/fcst/ft_scst.c
50544+++ linux-2.6.35/drivers/scst/fcst/ft_scst.c
50545@@ -0,0 +1,96 @@
50546+/*
50547+ * Copyright (c) 2010 Cisco Systems, Inc.
50548+ *
50549+ * This program is free software; you may redistribute it and/or modify
50550+ * it under the terms of the GNU General Public License as published by
50551+ * the Free Software Foundation; version 2 of the License.
50552+ *
50553+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
50554+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
50555+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
50556+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
50557+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
50558+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
50559+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
50560+ * SOFTWARE.
50561+ */
50562+#include <linux/kernel.h>
50563+#include <linux/types.h>
50564+#include <scsi/libfc.h>
50565+#include "fcst.h"
50566+
50567+MODULE_AUTHOR("Joe Eykholt <jeykholt@cisco.com>");
50568+MODULE_DESCRIPTION("Fibre-Channel SCST target");
50569+MODULE_LICENSE("GPL v2");
50570+
50571+unsigned int ft_debug_logging;
50572+module_param_named(debug_logging, ft_debug_logging, int, S_IRUGO | S_IWUSR);
50573+MODULE_PARM_DESC(debug_logging, "log levels bigmask");
50574+
50575+DEFINE_MUTEX(ft_lport_lock);
50576+
50577+/*
50578+ * Provider ops for libfc.
50579+ */
50580+static struct fc4_prov ft_prov = {
50581+ .prli = ft_prli,
50582+ .prlo = ft_prlo,
50583+ .recv = ft_recv,
50584+ .module = THIS_MODULE,
50585+};
50586+
50587+static struct notifier_block ft_notifier = {
50588+ .notifier_call = ft_lport_notify
50589+};
50590+
50591+/*
50592+ * SCST target ops and configuration.
50593+ * XXX - re-check uninitialized fields
50594+ */
50595+struct scst_tgt_template ft_scst_template = {
50596+ .sg_tablesize = 128, /* XXX get true limit from libfc */
50597+ .xmit_response_atomic = 1,
50598+ .rdy_to_xfer_atomic = 1,
50599+ .xmit_response = ft_send_response,
50600+ .rdy_to_xfer = ft_send_xfer_rdy,
50601+ .on_hw_pending_cmd_timeout = ft_cmd_timeout,
50602+ .on_free_cmd = ft_cmd_free,
50603+ .task_mgmt_fn_done = ft_cmd_tm_done,
50604+ .detect = ft_tgt_detect,
50605+ .release = ft_tgt_release,
50606+ .report_aen = ft_report_aen,
50607+ .enable_target = ft_tgt_enable,
50608+ .is_target_enabled = ft_tgt_enabled,
50609+ .get_initiator_port_transport_id = ft_get_transport_id,
50610+ .max_hw_pending_time = FT_MAX_HW_PENDING_TIME,
50611+ .name = FT_MODULE,
50612+};
50613+
50614+static int __init ft_module_init(void)
50615+{
50616+ int err;
50617+
50618+ err = scst_register_target_template(&ft_scst_template);
50619+ if (err)
50620+ return err;
50621+ err = fc_fc4_register_provider(FC_TYPE_FCP, &ft_prov);
50622+ if (err) {
50623+ scst_unregister_target_template(&ft_scst_template);
50624+ return err;
50625+ }
50626+ blocking_notifier_chain_register(&fc_lport_notifier_head, &ft_notifier);
50627+ fc_lport_iterate(ft_lport_add, NULL);
50628+ return 0;
50629+}
50630+module_init(ft_module_init);
50631+
50632+static void __exit ft_module_exit(void)
50633+{
50634+ blocking_notifier_chain_unregister(&fc_lport_notifier_head,
50635+ &ft_notifier);
50636+ fc_fc4_deregister_provider(FC_TYPE_FCP, &ft_prov);
50637+ fc_lport_iterate(ft_lport_del, NULL);
50638+ scst_unregister_target_template(&ft_scst_template);
50639+ synchronize_rcu();
50640+}
50641+module_exit(ft_module_exit);
50642diff -uprN orig/linux-2.6.35/drivers/scst/fcst/ft_sess.c linux-2.6.35/drivers/scst/fcst/ft_sess.c
50643--- orig/linux-2.6.35/drivers/scst/fcst/ft_sess.c
50644+++ linux-2.6.35/drivers/scst/fcst/ft_sess.c
50645@@ -0,0 +1,570 @@
50646+/*
50647+ * Copyright (c) 2010 Cisco Systems, Inc.
50648+ *
50649+ * This program is free software; you may redistribute it and/or modify
50650+ * it under the terms of the GNU General Public License as published by
50651+ * the Free Software Foundation; version 2 of the License.
50652+ *
50653+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
50654+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
50655+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
50656+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
50657+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
50658+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
50659+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
50660+ * SOFTWARE.
50661+ */
50662+#include <linux/kernel.h>
50663+#include <linux/types.h>
50664+#include <linux/mutex.h>
50665+#include <linux/hash.h>
50666+#include <asm/unaligned.h>
50667+#include <scsi/libfc.h>
50668+#include <scsi/fc/fc_els.h>
50669+#include "fcst.h"
50670+
50671+static int ft_tport_count;
50672+
50673+static ssize_t ft_format_wwn(char *buf, size_t len, u64 wwn)
50674+{
50675+ u8 b[8];
50676+
50677+ put_unaligned_be64(wwn, b);
50678+ return snprintf(buf, len,
50679+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
50680+ b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
50681+}
50682+
50683+/*
50684+ * Lookup or allocate target local port.
50685+ * Caller holds ft_lport_lock.
50686+ */
50687+static struct ft_tport *ft_tport_create(struct fc_lport *lport)
50688+{
50689+ struct ft_tport *tport;
50690+ char name[FT_NAMELEN];
50691+ int i;
50692+
50693+ ft_format_wwn(name, sizeof(name), lport->wwpn);
50694+ FT_SESS_DBG("create %s\n", name);
50695+
50696+ tport = rcu_dereference(lport->prov[FC_TYPE_FCP]);
50697+ if (tport)
50698+ return tport;
50699+
50700+ tport = kzalloc(sizeof(*tport), GFP_KERNEL);
50701+ if (!tport)
50702+ return NULL;
50703+
50704+ tport->tgt = scst_register_target(&ft_scst_template, name);
50705+ if (!tport->tgt) {
50706+ kfree(tport);
50707+ return NULL;
50708+ }
50709+ scst_tgt_set_tgt_priv(tport->tgt, tport);
50710+ ft_tport_count++;
50711+
50712+ tport->lport = lport;
50713+ for (i = 0; i < FT_SESS_HASH_SIZE; i++)
50714+ INIT_HLIST_HEAD(&tport->hash[i]);
50715+
50716+ rcu_assign_pointer(lport->prov[FC_TYPE_FCP], tport);
50717+ return tport;
50718+}
50719+
50720+/*
50721+ * Free tport via RCU.
50722+ */
50723+static void ft_tport_rcu_free(struct rcu_head *rcu)
50724+{
50725+ struct ft_tport *tport = container_of(rcu, struct ft_tport, rcu);
50726+
50727+ kfree(tport);
50728+}
50729+
50730+/*
50731+ * Delete target local port, if any, associated with the local port.
50732+ * Caller holds ft_lport_lock.
50733+ */
50734+static void ft_tport_delete(struct ft_tport *tport)
50735+{
50736+ struct fc_lport *lport;
50737+ struct scst_tgt *tgt;
50738+
50739+ tgt = tport->tgt;
50740+ BUG_ON(!tgt);
50741+ FT_SESS_DBG("delete %s\n", scst_get_tgt_name(tgt));
50742+ scst_unregister_target(tgt);
50743+ lport = tport->lport;
50744+ BUG_ON(tport != lport->prov[FC_TYPE_FCP]);
50745+ rcu_assign_pointer(lport->prov[FC_TYPE_FCP], NULL);
50746+ tport->lport = NULL;
50747+ call_rcu(&tport->rcu, ft_tport_rcu_free);
50748+ ft_tport_count--;
50749+}
50750+
50751+/*
50752+ * Add local port.
50753+ * Called thru fc_lport_iterate().
50754+ */
50755+void ft_lport_add(struct fc_lport *lport, void *arg)
50756+{
50757+ mutex_lock(&ft_lport_lock);
50758+ ft_tport_create(lport);
50759+ mutex_unlock(&ft_lport_lock);
50760+}
50761+
50762+/*
50763+ * Delete local port.
50764+ * Called thru fc_lport_iterate().
50765+ */
50766+void ft_lport_del(struct fc_lport *lport, void *arg)
50767+{
50768+ struct ft_tport *tport;
50769+
50770+ mutex_lock(&ft_lport_lock);
50771+ tport = lport->prov[FC_TYPE_FCP];
50772+ if (tport)
50773+ ft_tport_delete(tport);
50774+ mutex_unlock(&ft_lport_lock);
50775+}
50776+
50777+/*
50778+ * Notification of local port change from libfc.
50779+ * Create or delete local port and associated tport.
50780+ */
50781+int ft_lport_notify(struct notifier_block *nb, unsigned long event, void *arg)
50782+{
50783+ struct fc_lport *lport = arg;
50784+
50785+ switch (event) {
50786+ case FC_LPORT_EV_ADD:
50787+ ft_lport_add(lport, NULL);
50788+ break;
50789+ case FC_LPORT_EV_DEL:
50790+ ft_lport_del(lport, NULL);
50791+ break;
50792+ }
50793+ return NOTIFY_DONE;
50794+}
50795+
50796+/*
50797+ * Find session in local port.
50798+ * Sessions and hash lists are RCU-protected.
50799+ * A reference is taken which must be eventually freed.
50800+ */
50801+static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id)
50802+{
50803+ struct ft_tport *tport;
50804+ struct hlist_head *head;
50805+ struct hlist_node *pos;
50806+ struct ft_sess *sess = NULL;
50807+
50808+ rcu_read_lock();
50809+ tport = rcu_dereference(lport->prov[FC_TYPE_FCP]);
50810+ if (!tport)
50811+ goto out;
50812+
50813+ head = &tport->hash[hash_32(port_id, FT_SESS_HASH_BITS)];
50814+ hlist_for_each_entry_rcu(sess, pos, head, hash) {
50815+ if (sess->port_id == port_id) {
50816+ kref_get(&sess->kref);
50817+ rcu_read_unlock();
50818+ FT_SESS_DBG("port_id %x found %p\n", port_id, sess);
50819+ return sess;
50820+ }
50821+ }
50822+out:
50823+ rcu_read_unlock();
50824+ FT_SESS_DBG("port_id %x not found\n", port_id);
50825+ return NULL;
50826+}
50827+
50828+/*
50829+ * Allocate session and enter it in the hash for the local port.
50830+ * Caller holds ft_lport_lock.
50831+ */
50832+static int ft_sess_create(struct ft_tport *tport, struct fc_rport_priv *rdata,
50833+ u32 fcp_parm)
50834+{
50835+ struct ft_sess *sess;
50836+ struct scst_session *scst_sess;
50837+ struct hlist_head *head;
50838+ struct hlist_node *pos;
50839+ u32 port_id;
50840+ char name[FT_NAMELEN];
50841+
50842+ port_id = rdata->ids.port_id;
50843+ if (!rdata->maxframe_size) {
50844+ FT_SESS_DBG("port_id %x maxframe_size 0\n", port_id);
50845+ return FC_SPP_RESP_CONF;
50846+ }
50847+
50848+ head = &tport->hash[hash_32(port_id, FT_SESS_HASH_BITS)];
50849+ hlist_for_each_entry_rcu(sess, pos, head, hash) {
50850+ if (sess->port_id == port_id) {
50851+ sess->params = fcp_parm;
50852+ return 0;
50853+ }
50854+ }
50855+
50856+ sess = kzalloc(sizeof(*sess), GFP_KERNEL);
50857+ if (!sess)
50858+ return FC_SPP_RESP_RES; /* out of resources */
50859+
50860+ sess->port_name = rdata->ids.port_name;
50861+ sess->max_payload = rdata->maxframe_size;
50862+ sess->max_lso_payload = rdata->maxframe_size;
50863+ if (tport->lport->seq_offload)
50864+ sess->max_lso_payload = tport->lport->lso_max;
50865+ sess->params = fcp_parm;
50866+ sess->tport = tport;
50867+ sess->port_id = port_id;
50868+ kref_init(&sess->kref); /* ref for table entry */
50869+
50870+ ft_format_wwn(name, sizeof(name), rdata->ids.port_name);
50871+ FT_SESS_DBG("register %s\n", name);
50872+ scst_sess = scst_register_session(tport->tgt, 0, name, sess, NULL,
50873+ NULL);
50874+ if (!scst_sess) {
50875+ kfree(sess);
50876+ return FC_SPP_RESP_RES; /* out of resources */
50877+ }
50878+ sess->scst_sess = scst_sess;
50879+ hlist_add_head_rcu(&sess->hash, head);
50880+ tport->sess_count++;
50881+
50882+ FT_SESS_DBG("port_id %x sess %p\n", port_id, sess);
50883+
50884+ rdata->prli_count++;
50885+ return 0;
50886+}
50887+
50888+/*
50889+ * Unhash the session.
50890+ * Caller holds ft_lport_lock.
50891+ */
50892+static void ft_sess_unhash(struct ft_sess *sess)
50893+{
50894+ struct ft_tport *tport = sess->tport;
50895+
50896+ hlist_del_rcu(&sess->hash);
50897+ BUG_ON(!tport->sess_count);
50898+ tport->sess_count--;
50899+ sess->port_id = -1;
50900+ sess->params = 0;
50901+}
50902+
50903+/*
50904+ * Delete session from hash.
50905+ * Caller holds ft_lport_lock.
50906+ */
50907+static struct ft_sess *ft_sess_delete(struct ft_tport *tport, u32 port_id)
50908+{
50909+ struct hlist_head *head;
50910+ struct hlist_node *pos;
50911+ struct ft_sess *sess;
50912+
50913+ head = &tport->hash[hash_32(port_id, FT_SESS_HASH_BITS)];
50914+ hlist_for_each_entry_rcu(sess, pos, head, hash) {
50915+ if (sess->port_id == port_id) {
50916+ ft_sess_unhash(sess);
50917+ return sess;
50918+ }
50919+ }
50920+ return NULL;
50921+}
50922+
50923+/*
50924+ * Remove session and send PRLO.
50925+ * This is called when the target is being deleted.
50926+ * Caller holds ft_lport_lock.
50927+ */
50928+static void ft_sess_close(struct ft_sess *sess)
50929+{
50930+ struct fc_lport *lport;
50931+ u32 port_id;
50932+
50933+ lport = sess->tport->lport;
50934+ port_id = sess->port_id;
50935+ if (port_id == -1)
50936+ return;
50937+ FT_SESS_DBG("port_id %x\n", port_id);
50938+ ft_sess_unhash(sess);
50939+ /* XXX should send LOGO or PRLO to rport */
50940+}
50941+
50942+/*
50943+ * Allocate and fill in the SPC Transport ID for persistent reservations.
50944+ */
50945+int ft_get_transport_id(struct scst_session *scst_sess, uint8_t **result)
50946+{
50947+ struct ft_sess *sess;
50948+ struct {
50949+ u8 format_proto; /* format and protocol ID (0 for FC) */
50950+ u8 __resv1[7];
50951+ __be64 port_name; /* N_Port Name */
50952+ u8 __resv2[8];
50953+ } __attribute__((__packed__)) *id;
50954+
50955+ if (!scst_sess)
50956+ return SCSI_TRANSPORTID_PROTOCOLID_FCP2;
50957+
50958+ id = kzalloc(sizeof(*id), GFP_KERNEL);
50959+ if (!id)
50960+ return -ENOMEM;
50961+
50962+ sess = scst_sess_get_tgt_priv(scst_sess);
50963+ id->port_name = cpu_to_be64(sess->port_name);
50964+ id->format_proto = SCSI_TRANSPORTID_PROTOCOLID_FCP2;
50965+ *result = (uint8_t *)id;
50966+ return 0;
50967+}
50968+
50969+/*
50970+ * libfc ops involving sessions.
50971+ */
50972+
50973+/*
50974+ * Handle PRLI (process login) request.
50975+ * This could be a PRLI we're sending or receiving.
50976+ * Caller holds ft_lport_lock.
50977+ */
50978+static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len,
50979+ const struct fc_els_spp *rspp, struct fc_els_spp *spp)
50980+{
50981+ struct ft_tport *tport;
50982+ u32 fcp_parm;
50983+ int ret;
50984+
50985+ if (rspp->spp_flags & (FC_SPP_OPA_VAL | FC_SPP_RPA_VAL))
50986+ return FC_SPP_RESP_NO_PA;
50987+
50988+ /*
50989+ * If both target and initiator bits are off, the SPP is invalid.
50990+ */
50991+ fcp_parm = ntohl(rspp->spp_params); /* requested parameters */
50992+ if (!(fcp_parm & (FCP_SPPF_INIT_FCN | FCP_SPPF_TARG_FCN)))
50993+ return FC_SPP_RESP_INVL;
50994+
50995+ /*
50996+ * Create session (image pair) only if requested by
50997+ * EST_IMG_PAIR flag and if the requestor is an initiator.
50998+ */
50999+ if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR) {
51000+ spp->spp_flags |= FC_SPP_EST_IMG_PAIR;
51001+
51002+ if (!(fcp_parm & FCP_SPPF_INIT_FCN))
51003+ return FC_SPP_RESP_CONF;
51004+ tport = rcu_dereference(rdata->local_port->prov[FC_TYPE_FCP]);
51005+ if (!tport || !tport->enabled)
51006+ return 0; /* not a target for this local port */
51007+
51008+ ret = ft_sess_create(tport, rdata, fcp_parm);
51009+ if (ret)
51010+ return ret;
51011+ }
51012+
51013+ /*
51014+ * OR in our service parameters with other provider (initiator), if any.
51015+ * If the initiator indicates RETRY, we must support that, too.
51016+ * Don't force RETRY on the initiator, though.
51017+ */
51018+ fcp_parm = ntohl(spp->spp_params); /* response parameters */
51019+ spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN);
51020+ return FC_SPP_RESP_ACK;
51021+}
51022+
51023+/**
51024+ * tcm_fcp_prli() - Handle incoming or outgoing PRLI for the FCP target
51025+ * @rdata: remote port private
51026+ * @spp_len: service parameter page length
51027+ * @rspp: received service parameter page (NULL for outgoing PRLI)
51028+ * @spp: response service parameter page
51029+ *
51030+ * Returns spp response code.
51031+ */
51032+int ft_prli(struct fc_rport_priv *rdata, u32 spp_len,
51033+ const struct fc_els_spp *rspp, struct fc_els_spp *spp)
51034+{
51035+ int ret;
51036+
51037+ FT_SESS_DBG("starting PRLI port_id %x\n", rdata->ids.port_id);
51038+ mutex_lock(&ft_lport_lock);
51039+ ret = ft_prli_locked(rdata, spp_len, rspp, spp);
51040+ mutex_unlock(&ft_lport_lock);
51041+ FT_SESS_DBG("port_id %x flags %x parms %x ret %x\n",
51042+ rdata->ids.port_id,
51043+ rspp->spp_flags,
51044+ ntohl(spp->spp_params), ret);
51045+ return ret;
51046+}
51047+
51048+static void ft_sess_rcu_free(struct rcu_head *rcu)
51049+{
51050+ struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu);
51051+
51052+ kfree(sess);
51053+}
51054+
51055+static void ft_sess_free(struct kref *kref)
51056+{
51057+ struct ft_sess *sess = container_of(kref, struct ft_sess, kref);
51058+ struct scst_session *scst_sess;
51059+
51060+ scst_sess = sess->scst_sess;
51061+ FT_SESS_DBG("unregister %s\n", scst_sess->initiator_name);
51062+ scst_unregister_session(scst_sess, 0, NULL);
51063+ call_rcu(&sess->rcu, ft_sess_rcu_free);
51064+}
51065+
51066+static void ft_sess_put(struct ft_sess *sess)
51067+{
51068+ int sess_held = atomic_read(&sess->kref.refcount);
51069+
51070+ BUG_ON(!sess_held);
51071+ kref_put(&sess->kref, ft_sess_free);
51072+}
51073+
51074+/*
51075+ * Delete ft_sess for PRLO.
51076+ * Called with ft_lport_lock held.
51077+ */
51078+static struct ft_sess *ft_sess_lookup_delete(struct fc_rport_priv *rdata)
51079+{
51080+ struct ft_sess *sess;
51081+ struct ft_tport *tport;
51082+
51083+ tport = rcu_dereference(rdata->local_port->prov[FC_TYPE_FCP]);
51084+ if (!tport)
51085+ return NULL;
51086+ sess = ft_sess_delete(tport, rdata->ids.port_id);
51087+ if (sess)
51088+ sess->params = 0;
51089+ return sess;
51090+}
51091+
51092+/*
51093+ * Handle PRLO.
51094+ */
51095+void ft_prlo(struct fc_rport_priv *rdata)
51096+{
51097+ struct ft_sess *sess;
51098+
51099+ mutex_lock(&ft_lport_lock);
51100+ sess = ft_sess_lookup_delete(rdata);
51101+ mutex_unlock(&ft_lport_lock);
51102+ if (!sess)
51103+ return;
51104+
51105+ /*
51106+ * Release the session hold from the table.
51107+ * When all command-starting threads have returned,
51108+ * kref will call ft_sess_free which will unregister
51109+ * the session.
51110+ * fcmds referencing the session are safe.
51111+ */
51112+ ft_sess_put(sess); /* release from table */
51113+ rdata->prli_count--;
51114+}
51115+
51116+/*
51117+ * Handle incoming FCP request.
51118+ *
51119+ * Caller has verified that the frame is type FCP.
51120+ * Note that this may be called directly from the softirq context.
51121+ */
51122+void ft_recv(struct fc_lport *lport, struct fc_seq *sp, struct fc_frame *fp)
51123+{
51124+ struct ft_sess *sess;
51125+ struct fc_frame_header *fh;
51126+ u32 sid;
51127+
51128+ fh = fc_frame_header_get(fp);
51129+ sid = ntoh24(fh->fh_s_id);
51130+
51131+ FT_SESS_DBG("sid %x preempt %x\n", sid, preempt_count());
51132+
51133+ sess = ft_sess_get(lport, sid);
51134+ if (!sess) {
51135+ FT_SESS_DBG("sid %x sess lookup failed\n", sid);
51136+ lport->tt.exch_done(sp);
51137+ /* TBD XXX - if FCP_CMND, send LOGO */
51138+ fc_frame_free(fp);
51139+ return;
51140+ }
51141+ FT_SESS_DBG("sid %x sess lookup returned %p preempt %x\n",
51142+ sid, sess, preempt_count());
51143+ ft_recv_req(sess, sp, fp);
51144+ ft_sess_put(sess);
51145+}
51146+
51147+/*
51148+ * Release all sessions for a target.
51149+ * Called through scst_unregister_target() as well as directly.
51150+ * Caller holds ft_lport_lock.
51151+ */
51152+int ft_tgt_release(struct scst_tgt *tgt)
51153+{
51154+ struct ft_tport *tport;
51155+ struct hlist_head *head;
51156+ struct hlist_node *pos;
51157+ struct ft_sess *sess;
51158+
51159+ tport = scst_tgt_get_tgt_priv(tgt);
51160+ tport->enabled = 0;
51161+ tport->lport->service_params &= ~FCP_SPPF_TARG_FCN;
51162+
51163+ for (head = tport->hash; head < &tport->hash[FT_SESS_HASH_SIZE]; head++)
51164+ hlist_for_each_entry_rcu(sess, pos, head, hash)
51165+ ft_sess_close(sess);
51166+
51167+ synchronize_rcu();
51168+ return 0;
51169+}
51170+
51171+int ft_tgt_enable(struct scst_tgt *tgt, bool enable)
51172+{
51173+ struct ft_tport *tport;
51174+ int ret = 0;
51175+
51176+ mutex_lock(&ft_lport_lock);
51177+ if (enable) {
51178+ FT_SESS_DBG("enable tgt %s\n", tgt->tgt_name);
51179+ tport = scst_tgt_get_tgt_priv(tgt);
51180+ tport->enabled = 1;
51181+ tport->lport->service_params |= FCP_SPPF_TARG_FCN;
51182+ } else {
51183+ FT_SESS_DBG("disable tgt %s\n", tgt->tgt_name);
51184+ ft_tgt_release(tgt);
51185+ }
51186+ mutex_unlock(&ft_lport_lock);
51187+ return ret;
51188+}
51189+
51190+bool ft_tgt_enabled(struct scst_tgt *tgt)
51191+{
51192+ struct ft_tport *tport;
51193+
51194+ tport = scst_tgt_get_tgt_priv(tgt);
51195+ return tport->enabled;
51196+}
51197+
51198+int ft_tgt_detect(struct scst_tgt_template *tt)
51199+{
51200+ return ft_tport_count;
51201+}
51202+
51203+/*
51204+ * Report AEN (Asynchronous Event Notification) from device to initiator.
51205+ * See notes in scst.h.
51206+ */
51207+int ft_report_aen(struct scst_aen *aen)
51208+{
51209+ struct ft_sess *sess;
51210+
51211+ sess = scst_sess_get_tgt_priv(scst_aen_get_sess(aen));
51212+ FT_SESS_DBG("AEN event %d sess to %x lun %lld\n",
51213+ aen->event_fn, sess->port_id, scst_aen_get_lun(aen));
51214+ return SCST_AEN_RES_FAILED; /* XXX TBD */
51215+}
51216diff -uprN orig/linux-2.6.35/Documentation/scst/README.fcst linux-2.6.35/Documentation/scst/README.fcst
51217--- orig/linux-2.6.35/Documentation/scst/README.fcst
51218+++ linux-2.6.35/Documentation/scst/README.fcst
51219@@ -0,0 +1,99 @@
51220+fcst README v1.0 06/10/2010
51221+
51222+$Id$
51223+
51224+FCST is a module that depends on libfc and SCST to provide FC target support.
51225+
51226+To build for linux-2.6.34, do:
51227+
51228+1. Get the kernel source:
51229+
51230+ KERNEL=linux-2.6.34
51231+
51232+ cd /usr/src/kernels
51233+ URL_DIR=http://www.kernel.org/pub/linux/kernel/v2.6
51234+ TARFILE=$KERNEL.tar.bz2
51235+ wget -o $TARFILE $URL_DIR/$TARFILE
51236+ tar xfj $TARFILE
51237+ cd $KERNEL
51238+
51239+2. Apply patches needed for libfc target hooks and point-to-point fixes:
51240+
51241+ KDIR=/usr/src/kernels/$KERNEL
51242+ PDIR=/usr/src/scst/trunk/fcst/linux-patches # use your dir here
51243+
51244+ cd $PDIR
51245+ for patch in `grep -v '^#' series-2.6.34`
51246+ do
51247+ (cd $KDIR; patch -p1) < $patch
51248+ done
51249+
51250+3. Apply SCST patches to the kernel
51251+ See trunk/scst/README
51252+ The readahead patches are not needed in 2.6.33 or later.
51253+
51254+4. Configure, make, and install your kernel
51255+
51256+5. Install SCST
51257+ See trunk/scst/README. Make sure you are building sysfs SCST build,
51258+ because FCST supports only it. You need to do
51259+
51260+ cd trunk/scst
51261+ make
51262+ make install
51263+
51264+6. Make FCST
51265+ In the directory containing this README, just do
51266+ make
51267+ make install
51268+
51269+7. Install the FCoE admin tools, including dcbd and fcoeadm.
51270+ Some distros may have these.
51271+ You should be able to use the source at
51272+ http://www.open-fcoe.org/openfc/downloads/2.6.34/open-fcoe-2.6.34.tar.gz
51273+
51274+8. Bring up SCST and configure the devices.
51275+
51276+9. Bring up an FCoE initiator (we'll enable target mode on it later):
51277+ modprobe fcoe
51278+ fcoeadm -c eth3
51279+
51280+ The other end can be an initiator as well, in point-to-point mode
51281+ over a full-duplex loss-less link (enable pause on both sides).
51282+ Alternatively, the other end can be an FCoE switch.
51283+
51284+10. Use fcc (part of the open-fcoe contrib tools in step 7) to see the
51285+ initiator setup. To get the FCoE port name for eth3
51286+
51287+ # fcc
51288+ FC HBAs:
51289+ HBA Port Name Port ID State Device
51290+ host4 20:00:00:1b:21:06:58:21 01:01:02 Online eth3
51291+
51292+ host4 Remote Ports:
51293+ Path Port Name Port ID State Roles
51294+ 4:0-0 10:00:50:41:4c:4f:3b:00 01:01:01 Online FCP Initiator
51295+
51296+ In the above example, there's one local host on eth3, and it's in
51297+ a point-to-point connection with the remote initiator with Port_id 010101.
51298+
51299+11. Load fcst
51300+
51301+ modprobe fcst
51302+
51303+12. Add any disks (configured in step 8) you want to export
51304+ Note that you must have a LUN 0.
51305+
51306+ LPORT=20:00:00:1b:21:06:58:21 # the local Port_Name
51307+
51308+ cd /sys/kernel/scst_tgt/targets/fcst/$LPORT
51309+ echo add disk-name 0 > luns/mgmt
51310+ echo add disk-name 1 > luns/mgmt
51311+
51312+13. Enable the initiator:
51313+
51314+ echo 1 > $LPORT/enabled
51315+
51316+14. As a temporary workaround, you may need to reset the interface
51317+ on the initiator side so it sees the SCST device as a target and
51318+ discovers LUNs. You can avoid this by bringing up the initiator last.
51319diff -uprN orig/linux-2.6.35/include/scst/iscsi_scst.h linux-2.6.35/include/scst/iscsi_scst.h
51320--- orig/linux-2.6.35/include/scst/iscsi_scst.h
51321+++ linux-2.6.35/include/scst/iscsi_scst.h
51322@@ -0,0 +1,220 @@
51323+/*
51324+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
51325+ * Copyright (C) 2007 - 2010 ID7 Ltd.
51326+ *
51327+ * This program is free software; you can redistribute it and/or
51328+ * modify it under the terms of the GNU General Public License
51329+ * as published by the Free Software Foundation, version 2
51330+ * of the License.
51331+ *
51332+ * This program is distributed in the hope that it will be useful,
51333+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
51334+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51335+ * GNU General Public License for more details.
51336+ */
51337+
51338+#ifndef _ISCSI_SCST_U_H
51339+#define _ISCSI_SCST_U_H
51340+
51341+#ifndef __KERNEL__
51342+#include <sys/uio.h>
51343+#endif
51344+
51345+#include "iscsi_scst_ver.h"
51346+#include "iscsi_scst_itf_ver.h"
51347+
51348+/* The maximum length of 223 bytes in the RFC. */
51349+#define ISCSI_NAME_LEN 256
51350+
51351+#define ISCSI_PORTAL_LEN 64
51352+
51353+/* Full name is iSCSI name + connected portal */
51354+#define ISCSI_FULL_NAME_LEN (ISCSI_NAME_LEN + ISCSI_PORTAL_LEN)
51355+
51356+#define ISCSI_LISTEN_PORT 3260
51357+
51358+#define SCSI_ID_LEN 24
51359+
51360+#ifndef aligned_u64
51361+#define aligned_u64 uint64_t __attribute__((aligned(8)))
51362+#endif
51363+
51364+#define ISCSI_MAX_ATTR_NAME_LEN 50
51365+#define ISCSI_MAX_ATTR_VALUE_LEN 512
51366+
51367+enum {
51368+ key_initial_r2t,
51369+ key_immediate_data,
51370+ key_max_connections,
51371+ key_max_recv_data_length,
51372+ key_max_xmit_data_length,
51373+ key_max_burst_length,
51374+ key_first_burst_length,
51375+ key_default_wait_time,
51376+ key_default_retain_time,
51377+ key_max_outstanding_r2t,
51378+ key_data_pdu_inorder,
51379+ key_data_sequence_inorder,
51380+ key_error_recovery_level,
51381+ key_header_digest,
51382+ key_data_digest,
51383+ key_ofmarker,
51384+ key_ifmarker,
51385+ key_ofmarkint,
51386+ key_ifmarkint,
51387+ session_key_last,
51388+};
51389+
51390+enum {
51391+ key_queued_cmnds,
51392+ key_rsp_timeout,
51393+ key_nop_in_interval,
51394+ key_max_sessions,
51395+ target_key_last,
51396+};
51397+
51398+enum {
51399+ key_session,
51400+ key_target,
51401+};
51402+
51403+struct iscsi_kern_target_info {
51404+ u32 tid;
51405+ u32 cookie;
51406+ char name[ISCSI_NAME_LEN];
51407+ u32 attrs_num;
51408+ aligned_u64 attrs_ptr;
51409+};
51410+
51411+struct iscsi_kern_session_info {
51412+ u32 tid;
51413+ aligned_u64 sid;
51414+ char initiator_name[ISCSI_NAME_LEN];
51415+ char full_initiator_name[ISCSI_FULL_NAME_LEN];
51416+ u32 exp_cmd_sn;
51417+ s32 session_params[session_key_last];
51418+ s32 target_params[target_key_last];
51419+};
51420+
51421+#define DIGEST_ALL (DIGEST_NONE | DIGEST_CRC32C)
51422+#define DIGEST_NONE (1 << 0)
51423+#define DIGEST_CRC32C (1 << 1)
51424+
51425+struct iscsi_kern_conn_info {
51426+ u32 tid;
51427+ aligned_u64 sid;
51428+
51429+ u32 cid;
51430+ u32 stat_sn;
51431+ u32 exp_stat_sn;
51432+ int fd;
51433+};
51434+
51435+struct iscsi_kern_attr {
51436+ u32 mode;
51437+ char name[ISCSI_MAX_ATTR_NAME_LEN];
51438+};
51439+
51440+struct iscsi_kern_mgmt_cmd_res_info {
51441+ u32 tid;
51442+ u32 cookie;
51443+ u32 req_cmd;
51444+ u32 result;
51445+ char value[ISCSI_MAX_ATTR_VALUE_LEN];
51446+};
51447+
51448+struct iscsi_kern_params_info {
51449+ u32 tid;
51450+ aligned_u64 sid;
51451+
51452+ u32 params_type;
51453+ u32 partial;
51454+
51455+ s32 session_params[session_key_last];
51456+ s32 target_params[target_key_last];
51457+};
51458+
51459+enum iscsi_kern_event_code {
51460+ E_ADD_TARGET,
51461+ E_DEL_TARGET,
51462+ E_MGMT_CMD,
51463+ E_ENABLE_TARGET,
51464+ E_DISABLE_TARGET,
51465+ E_GET_ATTR_VALUE,
51466+ E_SET_ATTR_VALUE,
51467+ E_CONN_CLOSE,
51468+};
51469+
51470+struct iscsi_kern_event {
51471+ u32 tid;
51472+ aligned_u64 sid;
51473+ u32 cid;
51474+ u32 code;
51475+ u32 cookie;
51476+ char target_name[ISCSI_NAME_LEN];
51477+ u32 param1_size;
51478+ u32 param2_size;
51479+};
51480+
51481+struct iscsi_kern_register_info {
51482+ union {
51483+ aligned_u64 version;
51484+ struct {
51485+ int max_data_seg_len;
51486+ int max_queued_cmds;
51487+ };
51488+ };
51489+};
51490+
51491+struct iscsi_kern_attr_info {
51492+ u32 tid;
51493+ u32 cookie;
51494+ struct iscsi_kern_attr attr;
51495+};
51496+
51497+struct iscsi_kern_initiator_info {
51498+ u32 tid;
51499+ char full_initiator_name[ISCSI_FULL_NAME_LEN];
51500+};
51501+
51502+#define DEFAULT_NR_QUEUED_CMNDS 32
51503+#define MIN_NR_QUEUED_CMNDS 1
51504+#define MAX_NR_QUEUED_CMNDS 256
51505+
51506+#define DEFAULT_RSP_TIMEOUT 30
51507+#define MIN_RSP_TIMEOUT 2
51508+#define MAX_RSP_TIMEOUT 65535
51509+
51510+#define DEFAULT_NOP_IN_INTERVAL 30
51511+#define MIN_NOP_IN_INTERVAL 0
51512+#define MAX_NOP_IN_INTERVAL 65535
51513+
51514+#define NETLINK_ISCSI_SCST 25
51515+
51516+#define REGISTER_USERD _IOWR('s', 0, struct iscsi_kern_register_info)
51517+#define ADD_TARGET _IOW('s', 1, struct iscsi_kern_target_info)
51518+#define DEL_TARGET _IOW('s', 2, struct iscsi_kern_target_info)
51519+#define ADD_SESSION _IOW('s', 3, struct iscsi_kern_session_info)
51520+#define DEL_SESSION _IOW('s', 4, struct iscsi_kern_session_info)
51521+#define ADD_CONN _IOW('s', 5, struct iscsi_kern_conn_info)
51522+#define DEL_CONN _IOW('s', 6, struct iscsi_kern_conn_info)
51523+#define ISCSI_PARAM_SET _IOW('s', 7, struct iscsi_kern_params_info)
51524+#define ISCSI_PARAM_GET _IOWR('s', 8, struct iscsi_kern_params_info)
51525+
51526+#define ISCSI_ATTR_ADD _IOW('s', 9, struct iscsi_kern_attr_info)
51527+#define ISCSI_ATTR_DEL _IOW('s', 10, struct iscsi_kern_attr_info)
51528+#define MGMT_CMD_CALLBACK _IOW('s', 11, struct iscsi_kern_mgmt_cmd_res_info)
51529+
51530+#define ISCSI_INITIATOR_ALLOWED _IOW('s', 12, struct iscsi_kern_initiator_info)
51531+
51532+static inline int iscsi_is_key_internal(int key)
51533+{
51534+ switch (key) {
51535+ case key_max_xmit_data_length:
51536+ return 1;
51537+ default:
51538+ return 0;
51539+ }
51540+}
51541+
51542+#endif
51543diff -uprN orig/linux-2.6.35/include/scst/iscsi_scst_ver.h linux-2.6.35/include/scst/iscsi_scst_ver.h
51544--- orig/linux-2.6.35/include/scst/iscsi_scst_ver.h
51545+++ linux-2.6.35/include/scst/iscsi_scst_ver.h
51546@@ -0,0 +1,20 @@
51547+/*
51548+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
51549+ * Copyright (C) 2007 - 2010 ID7 Ltd.
51550+ *
51551+ * This program is free software; you can redistribute it and/or
51552+ * modify it under the terms of the GNU General Public License
51553+ * as published by the Free Software Foundation, version 2
51554+ * of the License.
51555+ *
51556+ * This program is distributed in the hope that it will be useful,
51557+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
51558+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51559+ * GNU General Public License for more details.
51560+ */
51561+
51562+/* #define CONFIG_SCST_PROC */
51563+
51564+#define ISCSI_VERSION_STRING_SUFFIX
51565+
51566+#define ISCSI_VERSION_STRING "2.0.0-rc3" ISCSI_VERSION_STRING_SUFFIX
51567diff -uprN orig/linux-2.6.35/include/scst/iscsi_scst_itf_ver.h linux-2.6.35/include/scst/iscsi_scst_itf_ver.h
51568--- orig/linux-2.6.35/include/scst/iscsi_scst_itf_ver.h
51569+++ linux-2.6.35/include/scst/iscsi_scst_itf_ver.h
51570@@ -0,0 +1,3 @@
51571+/* Autogenerated, don't edit */
51572+
51573+#define ISCSI_SCST_INTERFACE_VERSION ISCSI_VERSION_STRING "_" "31815603fdea2196eb9774eac0e41bf15c9a9130"
51574diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/Makefile linux-2.6.35/drivers/scst/iscsi-scst/Makefile
51575--- orig/linux-2.6.35/drivers/scst/iscsi-scst/Makefile
51576+++ linux-2.6.35/drivers/scst/iscsi-scst/Makefile
51577@@ -0,0 +1,4 @@
51578+iscsi-scst-y := iscsi.o nthread.o config.o digest.o \
51579+ conn.o session.o target.o event.o param.o
51580+
51581+obj-$(CONFIG_SCST_ISCSI) += iscsi-scst.o
51582diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/Kconfig linux-2.6.35/drivers/scst/iscsi-scst/Kconfig
51583--- orig/linux-2.6.35/drivers/scst/iscsi-scst/Kconfig
51584+++ linux-2.6.35/drivers/scst/iscsi-scst/Kconfig
51585@@ -0,0 +1,25 @@
51586+config SCST_ISCSI
51587+ tristate "ISCSI Target"
51588+ depends on SCST && INET
51589+ default SCST
51590+ help
51591+ ISCSI target driver for SCST framework. The iSCSI protocol has been
51592+ defined in RFC 3720. To use it you should download from
51593+ http://scst.sourceforge.net the user space part of it.
51594+
51595+config SCST_ISCSI_DEBUG_DIGEST_FAILURES
51596+ bool "Simulate iSCSI digest failures"
51597+ depends on SCST_ISCSI
51598+ help
51599+ Simulates iSCSI digest failures in random places. Even when iSCSI
51600+ traffic is sent over a TCP connection, the 16-bit TCP checksum is too
51601+ weak for the requirements of a storage protocol. Furthermore, there
51602+ are also instances where the TCP checksum does not protect iSCSI
51603+ data, as when data is corrupted while being transferred on a PCI bus
51604+ or while in memory. The iSCSI protocol therefore defines a 32-bit CRC
51605+ digest on iSCSI packets in order to detect data corruption on an
51606+ end-to-end basis. CRCs can be used on iSCSI PDU headers and/or data.
51607+ Enabling this option allows to test digest failure recovery in the
51608+ iSCSI initiator that is talking to SCST.
51609+
51610+ If unsure, say "N".
51611diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/config.c linux-2.6.35/drivers/scst/iscsi-scst/config.c
51612--- orig/linux-2.6.35/drivers/scst/iscsi-scst/config.c
51613+++ linux-2.6.35/drivers/scst/iscsi-scst/config.c
51614@@ -0,0 +1,1033 @@
51615+/*
51616+ * Copyright (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
51617+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
51618+ * Copyright (C) 2007 - 2010 ID7 Ltd.
51619+ *
51620+ * This program is free software; you can redistribute it and/or
51621+ * modify it under the terms of the GNU General Public License
51622+ * as published by the Free Software Foundation.
51623+ *
51624+ * This program is distributed in the hope that it will be useful,
51625+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
51626+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51627+ * GNU General Public License for more details.
51628+ */
51629+
51630+#include "iscsi.h"
51631+
51632+/* Protected by target_mgmt_mutex */
51633+int ctr_open_state;
51634+
51635+/* Protected by target_mgmt_mutex */
51636+static LIST_HEAD(iscsi_attrs_list);
51637+
51638+static ssize_t iscsi_version_show(struct kobject *kobj,
51639+ struct kobj_attribute *attr, char *buf)
51640+{
51641+ TRACE_ENTRY();
51642+
51643+ sprintf(buf, "%s\n", ISCSI_VERSION_STRING);
51644+
51645+#ifdef CONFIG_SCST_EXTRACHECKS
51646+ strcat(buf, "EXTRACHECKS\n");
51647+#endif
51648+
51649+#ifdef CONFIG_SCST_TRACING
51650+ strcat(buf, "TRACING\n");
51651+#endif
51652+
51653+#ifdef CONFIG_SCST_DEBUG
51654+ strcat(buf, "DEBUG\n");
51655+#endif
51656+
51657+#ifdef CONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES
51658+ strcat(buf, "DEBUG_DIGEST_FAILURES\n");
51659+#endif
51660+
51661+ TRACE_EXIT();
51662+ return strlen(buf);
51663+}
51664+
51665+static struct kobj_attribute iscsi_version_attr =
51666+ __ATTR(version, S_IRUGO, iscsi_version_show, NULL);
51667+
51668+static ssize_t iscsi_open_state_show(struct kobject *kobj,
51669+ struct kobj_attribute *attr, char *buf)
51670+{
51671+ switch (ctr_open_state) {
51672+ case ISCSI_CTR_OPEN_STATE_CLOSED:
51673+ sprintf(buf, "%s\n", "closed");
51674+ break;
51675+ case ISCSI_CTR_OPEN_STATE_OPEN:
51676+ sprintf(buf, "%s\n", "open");
51677+ break;
51678+ case ISCSI_CTR_OPEN_STATE_CLOSING:
51679+ sprintf(buf, "%s\n", "closing");
51680+ break;
51681+ default:
51682+ sprintf(buf, "%s\n", "unknown");
51683+ break;
51684+ }
51685+
51686+ return strlen(buf);
51687+}
51688+
51689+static struct kobj_attribute iscsi_open_state_attr =
51690+ __ATTR(open_state, S_IRUGO, iscsi_open_state_show, NULL);
51691+
51692+const struct attribute *iscsi_attrs[] = {
51693+ &iscsi_version_attr.attr,
51694+ &iscsi_open_state_attr.attr,
51695+ NULL,
51696+};
51697+
51698+/* target_mgmt_mutex supposed to be locked */
51699+static int add_conn(void __user *ptr)
51700+{
51701+ int err, rc;
51702+ struct iscsi_session *session;
51703+ struct iscsi_kern_conn_info info;
51704+ struct iscsi_target *target;
51705+
51706+ TRACE_ENTRY();
51707+
51708+ rc = copy_from_user(&info, ptr, sizeof(info));
51709+ if (rc != 0) {
51710+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
51711+ err = -EFAULT;
51712+ goto out;
51713+ }
51714+
51715+ target = target_lookup_by_id(info.tid);
51716+ if (target == NULL) {
51717+ PRINT_ERROR("Target %d not found", info.tid);
51718+ err = -ENOENT;
51719+ goto out;
51720+ }
51721+
51722+ mutex_lock(&target->target_mutex);
51723+
51724+ session = session_lookup(target, info.sid);
51725+ if (!session) {
51726+ PRINT_ERROR("Session %lld not found",
51727+ (long long unsigned int)info.tid);
51728+ err = -ENOENT;
51729+ goto out_unlock;
51730+ }
51731+
51732+ err = __add_conn(session, &info);
51733+
51734+out_unlock:
51735+ mutex_unlock(&target->target_mutex);
51736+
51737+out:
51738+ TRACE_EXIT_RES(err);
51739+ return err;
51740+}
51741+
51742+/* target_mgmt_mutex supposed to be locked */
51743+static int del_conn(void __user *ptr)
51744+{
51745+ int err, rc;
51746+ struct iscsi_session *session;
51747+ struct iscsi_kern_conn_info info;
51748+ struct iscsi_target *target;
51749+
51750+ TRACE_ENTRY();
51751+
51752+ rc = copy_from_user(&info, ptr, sizeof(info));
51753+ if (rc != 0) {
51754+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
51755+ err = -EFAULT;
51756+ goto out;
51757+ }
51758+
51759+ target = target_lookup_by_id(info.tid);
51760+ if (target == NULL) {
51761+ PRINT_ERROR("Target %d not found", info.tid);
51762+ err = -ENOENT;
51763+ goto out;
51764+ }
51765+
51766+ mutex_lock(&target->target_mutex);
51767+
51768+ session = session_lookup(target, info.sid);
51769+ if (!session) {
51770+ PRINT_ERROR("Session %llx not found",
51771+ (long long unsigned int)info.sid);
51772+ err = -ENOENT;
51773+ goto out_unlock;
51774+ }
51775+
51776+ err = __del_conn(session, &info);
51777+
51778+out_unlock:
51779+ mutex_unlock(&target->target_mutex);
51780+
51781+out:
51782+ TRACE_EXIT_RES(err);
51783+ return err;
51784+}
51785+
51786+/* target_mgmt_mutex supposed to be locked */
51787+static int add_session(void __user *ptr)
51788+{
51789+ int err, rc;
51790+ struct iscsi_kern_session_info *info;
51791+ struct iscsi_target *target;
51792+
51793+ TRACE_ENTRY();
51794+
51795+ info = kzalloc(sizeof(*info), GFP_KERNEL);
51796+ if (info == NULL) {
51797+ PRINT_ERROR("Can't alloc info (size %zd)", sizeof(*info));
51798+ err = -ENOMEM;
51799+ goto out;
51800+ }
51801+
51802+ rc = copy_from_user(info, ptr, sizeof(*info));
51803+ if (rc != 0) {
51804+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
51805+ err = -EFAULT;
51806+ goto out_free;
51807+ }
51808+
51809+ info->initiator_name[sizeof(info->initiator_name)-1] = '\0';
51810+ info->full_initiator_name[sizeof(info->full_initiator_name)-1] = '\0';
51811+
51812+ target = target_lookup_by_id(info->tid);
51813+ if (target == NULL) {
51814+ PRINT_ERROR("Target %d not found", info->tid);
51815+ err = -ENOENT;
51816+ goto out_free;
51817+ }
51818+
51819+ err = __add_session(target, info);
51820+
51821+out_free:
51822+ kfree(info);
51823+
51824+out:
51825+ TRACE_EXIT_RES(err);
51826+ return err;
51827+}
51828+
51829+/* target_mgmt_mutex supposed to be locked */
51830+static int del_session(void __user *ptr)
51831+{
51832+ int err, rc;
51833+ struct iscsi_kern_session_info *info;
51834+ struct iscsi_target *target;
51835+
51836+ TRACE_ENTRY();
51837+
51838+ info = kzalloc(sizeof(*info), GFP_KERNEL);
51839+ if (info == NULL) {
51840+ PRINT_ERROR("Can't alloc info (size %zd)", sizeof(*info));
51841+ err = -ENOMEM;
51842+ goto out;
51843+ }
51844+
51845+ rc = copy_from_user(info, ptr, sizeof(*info));
51846+ if (rc != 0) {
51847+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
51848+ err = -EFAULT;
51849+ goto out_free;
51850+ }
51851+
51852+ info->initiator_name[sizeof(info->initiator_name)-1] = '\0';
51853+
51854+ target = target_lookup_by_id(info->tid);
51855+ if (target == NULL) {
51856+ PRINT_ERROR("Target %d not found", info->tid);
51857+ err = -ENOENT;
51858+ goto out_free;
51859+ }
51860+
51861+ mutex_lock(&target->target_mutex);
51862+ err = __del_session(target, info->sid);
51863+ mutex_unlock(&target->target_mutex);
51864+
51865+out_free:
51866+ kfree(info);
51867+
51868+out:
51869+ TRACE_EXIT_RES(err);
51870+ return err;
51871+}
51872+
51873+/* target_mgmt_mutex supposed to be locked */
51874+static int iscsi_params_config(void __user *ptr, int set)
51875+{
51876+ int err, rc;
51877+ struct iscsi_kern_params_info info;
51878+ struct iscsi_target *target;
51879+
51880+ TRACE_ENTRY();
51881+
51882+ rc = copy_from_user(&info, ptr, sizeof(info));
51883+ if (rc != 0) {
51884+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
51885+ err = -EFAULT;
51886+ goto out;
51887+ }
51888+
51889+ target = target_lookup_by_id(info.tid);
51890+ if (target == NULL) {
51891+ PRINT_ERROR("Target %d not found", info.tid);
51892+ err = -ENOENT;
51893+ goto out;
51894+ }
51895+
51896+ mutex_lock(&target->target_mutex);
51897+ err = iscsi_params_set(target, &info, set);
51898+ mutex_unlock(&target->target_mutex);
51899+
51900+ if (err < 0)
51901+ goto out;
51902+
51903+ if (!set) {
51904+ rc = copy_to_user(ptr, &info, sizeof(info));
51905+ if (rc != 0) {
51906+ PRINT_ERROR("Failed to copy to user %d bytes", rc);
51907+ err = -EFAULT;
51908+ goto out;
51909+ }
51910+ }
51911+
51912+out:
51913+ TRACE_EXIT_RES(err);
51914+ return err;
51915+}
51916+
51917+/* target_mgmt_mutex supposed to be locked */
51918+static int iscsi_initiator_allowed(void __user *ptr)
51919+{
51920+ int err = 0, rc;
51921+ struct iscsi_kern_initiator_info cinfo;
51922+ struct iscsi_target *target;
51923+
51924+ TRACE_ENTRY();
51925+
51926+ rc = copy_from_user(&cinfo, ptr, sizeof(cinfo));
51927+ if (rc != 0) {
51928+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
51929+ err = -EFAULT;
51930+ goto out;
51931+ }
51932+
51933+ cinfo.full_initiator_name[sizeof(cinfo.full_initiator_name)-1] = '\0';
51934+
51935+ target = target_lookup_by_id(cinfo.tid);
51936+ if (target == NULL) {
51937+ PRINT_ERROR("Target %d not found", cinfo.tid);
51938+ err = -ENOENT;
51939+ goto out;
51940+ }
51941+
51942+ err = scst_initiator_has_luns(target->scst_tgt,
51943+ cinfo.full_initiator_name);
51944+
51945+out:
51946+ TRACE_EXIT_RES(err);
51947+ return err;
51948+}
51949+
51950+/* target_mgmt_mutex supposed to be locked */
51951+static int mgmt_cmd_callback(void __user *ptr)
51952+{
51953+ int err = 0, rc;
51954+ struct iscsi_kern_mgmt_cmd_res_info cinfo;
51955+ struct scst_sysfs_user_info *info;
51956+
51957+ TRACE_ENTRY();
51958+
51959+ rc = copy_from_user(&cinfo, ptr, sizeof(cinfo));
51960+ if (rc != 0) {
51961+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
51962+ err = -EFAULT;
51963+ goto out;
51964+ }
51965+
51966+ cinfo.value[sizeof(cinfo.value)-1] = '\0';
51967+
51968+ info = scst_sysfs_user_get_info(cinfo.cookie);
51969+ TRACE_DBG("cookie %u, info %p, result %d", cinfo.cookie, info,
51970+ cinfo.result);
51971+ if (info == NULL) {
51972+ err = -EINVAL;
51973+ goto out;
51974+ }
51975+
51976+ info->info_status = 0;
51977+
51978+ if (cinfo.result != 0) {
51979+ info->info_status = cinfo.result;
51980+ goto out_complete;
51981+ }
51982+
51983+ switch (cinfo.req_cmd) {
51984+ case E_ENABLE_TARGET:
51985+ case E_DISABLE_TARGET:
51986+ {
51987+ struct iscsi_target *target;
51988+
51989+ target = target_lookup_by_id(cinfo.tid);
51990+ if (target == NULL) {
51991+ PRINT_ERROR("Target %d not found", cinfo.tid);
51992+ err = -ENOENT;
51993+ goto out_status;
51994+ }
51995+
51996+ target->tgt_enabled = (cinfo.req_cmd == E_ENABLE_TARGET) ? 1 : 0;
51997+ break;
51998+ }
51999+
52000+ case E_GET_ATTR_VALUE:
52001+ info->data = kstrdup(cinfo.value, GFP_KERNEL);
52002+ if (info->data == NULL) {
52003+ PRINT_ERROR("Can't dublicate value %s", cinfo.value);
52004+ info->info_status = -ENOMEM;
52005+ goto out_complete;
52006+ }
52007+ break;
52008+ }
52009+
52010+out_complete:
52011+ complete(&info->info_completion);
52012+
52013+out:
52014+ TRACE_EXIT_RES(err);
52015+ return err;
52016+
52017+out_status:
52018+ info->info_status = err;
52019+ goto out_complete;
52020+}
52021+
52022+static ssize_t iscsi_attr_show(struct kobject *kobj,
52023+ struct kobj_attribute *attr, char *buf)
52024+{
52025+ int pos;
52026+ struct iscsi_attr *tgt_attr;
52027+ void *value;
52028+
52029+ TRACE_ENTRY();
52030+
52031+ tgt_attr = container_of(attr, struct iscsi_attr, attr);
52032+
52033+ pos = iscsi_sysfs_send_event(
52034+ (tgt_attr->target != NULL) ? tgt_attr->target->tid : 0,
52035+ E_GET_ATTR_VALUE, tgt_attr->name, NULL, &value);
52036+
52037+ if (pos != 0)
52038+ goto out;
52039+
52040+ pos = scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n", (char *)value);
52041+
52042+ kfree(value);
52043+
52044+out:
52045+ TRACE_EXIT_RES(pos);
52046+ return pos;
52047+}
52048+
52049+static ssize_t iscsi_attr_store(struct kobject *kobj,
52050+ struct kobj_attribute *attr, const char *buf, size_t count)
52051+{
52052+ int res;
52053+ char *buffer;
52054+ struct iscsi_attr *tgt_attr;
52055+
52056+ TRACE_ENTRY();
52057+
52058+ buffer = kzalloc(count+1, GFP_KERNEL);
52059+ if (buffer == NULL) {
52060+ res = -ENOMEM;
52061+ goto out;
52062+ }
52063+ memcpy(buffer, buf, count);
52064+ buffer[count] = '\0';
52065+
52066+ tgt_attr = container_of(attr, struct iscsi_attr, attr);
52067+
52068+ TRACE_DBG("attr %s, buffer %s", tgt_attr->attr.attr.name, buffer);
52069+
52070+ res = iscsi_sysfs_send_event(
52071+ (tgt_attr->target != NULL) ? tgt_attr->target->tid : 0,
52072+ E_SET_ATTR_VALUE, tgt_attr->name, buffer, NULL);
52073+
52074+ kfree(buffer);
52075+
52076+ if (res == 0)
52077+ res = count;
52078+
52079+out:
52080+ TRACE_EXIT_RES(res);
52081+ return res;
52082+}
52083+
52084+/*
52085+ * target_mgmt_mutex supposed to be locked. If target != 0, target_mutex
52086+ * supposed to be locked as well.
52087+ */
52088+int iscsi_add_attr(struct iscsi_target *target,
52089+ const struct iscsi_kern_attr *attr_info)
52090+{
52091+ int res = 0;
52092+ struct iscsi_attr *tgt_attr;
52093+ struct list_head *attrs_list;
52094+ const char *name;
52095+#ifdef CONFIG_DEBUG_LOCK_ALLOC
52096+ static struct lock_class_key __key;
52097+#endif
52098+
52099+ TRACE_ENTRY();
52100+
52101+ if (target != NULL) {
52102+ attrs_list = &target->attrs_list;
52103+ name = target->name;
52104+ } else {
52105+ attrs_list = &iscsi_attrs_list;
52106+ name = "global";
52107+ }
52108+
52109+ list_for_each_entry(tgt_attr, attrs_list, attrs_list_entry) {
52110+ /* Both for sure NULL-terminated */
52111+ if (strcmp(tgt_attr->name, attr_info->name) == 0) {
52112+ PRINT_ERROR("Attribute %s for %s already exist",
52113+ attr_info->name, name);
52114+ res = -EEXIST;
52115+ goto out;
52116+ }
52117+ }
52118+
52119+ TRACE_DBG("Adding %s's attr %s with mode %x", name,
52120+ attr_info->name, attr_info->mode);
52121+
52122+ tgt_attr = kzalloc(sizeof(*tgt_attr), GFP_KERNEL);
52123+ if (tgt_attr == NULL) {
52124+ PRINT_ERROR("Unable to allocate user (size %zd)",
52125+ sizeof(*tgt_attr));
52126+ res = -ENOMEM;
52127+ goto out;
52128+ }
52129+
52130+ tgt_attr->target = target;
52131+
52132+ tgt_attr->name = kstrdup(attr_info->name, GFP_KERNEL);
52133+ if (tgt_attr->name == NULL) {
52134+ PRINT_ERROR("Unable to allocate attr %s name/value (target %s)",
52135+ attr_info->name, name);
52136+ res = -ENOMEM;
52137+ goto out_free;
52138+ }
52139+
52140+ list_add(&tgt_attr->attrs_list_entry, attrs_list);
52141+
52142+ tgt_attr->attr.attr.name = tgt_attr->name;
52143+ tgt_attr->attr.attr.owner = THIS_MODULE;
52144+#ifdef CONFIG_DEBUG_LOCK_ALLOC
52145+ tgt_attr->attr.attr.key = &__key;
52146+#endif
52147+ tgt_attr->attr.attr.mode = attr_info->mode & (S_IRUGO | S_IWUGO);
52148+ tgt_attr->attr.show = iscsi_attr_show;
52149+ tgt_attr->attr.store = iscsi_attr_store;
52150+
52151+ TRACE_DBG("tgt_attr %p, attr %p", tgt_attr, &tgt_attr->attr.attr);
52152+
52153+ res = sysfs_create_file(
52154+ (target != NULL) ? scst_sysfs_get_tgt_kobj(target->scst_tgt) :
52155+ scst_sysfs_get_tgtt_kobj(&iscsi_template),
52156+ &tgt_attr->attr.attr);
52157+ if (res != 0) {
52158+ PRINT_ERROR("Unable to create file '%s' for target '%s'",
52159+ tgt_attr->attr.attr.name, name);
52160+ goto out_del;
52161+ }
52162+
52163+out:
52164+ TRACE_EXIT_RES(res);
52165+ return res;
52166+
52167+out_del:
52168+ list_del(&tgt_attr->attrs_list_entry);
52169+
52170+out_free:
52171+ kfree(tgt_attr->name);
52172+ kfree(tgt_attr);
52173+ goto out;
52174+}
52175+
52176+void __iscsi_del_attr(struct iscsi_target *target,
52177+ struct iscsi_attr *tgt_attr)
52178+{
52179+ TRACE_ENTRY();
52180+
52181+ TRACE_DBG("Deleting attr %s (target %s, tgt_attr %p, attr %p)",
52182+ tgt_attr->name, (target != NULL) ? target->name : "global",
52183+ tgt_attr, &tgt_attr->attr.attr);
52184+
52185+ list_del(&tgt_attr->attrs_list_entry);
52186+
52187+ sysfs_remove_file((target != NULL) ?
52188+ scst_sysfs_get_tgt_kobj(target->scst_tgt) :
52189+ scst_sysfs_get_tgtt_kobj(&iscsi_template),
52190+ &tgt_attr->attr.attr);
52191+
52192+ kfree(tgt_attr->name);
52193+ kfree(tgt_attr);
52194+
52195+ TRACE_EXIT();
52196+ return;
52197+}
52198+
52199+/*
52200+ * target_mgmt_mutex supposed to be locked. If target != 0, target_mutex
52201+ * supposed to be locked as well.
52202+ */
52203+static int iscsi_del_attr(struct iscsi_target *target,
52204+ const char *attr_name)
52205+{
52206+ int res = 0;
52207+ struct iscsi_attr *tgt_attr, *a;
52208+ struct list_head *attrs_list;
52209+
52210+ TRACE_ENTRY();
52211+
52212+ if (target != NULL)
52213+ attrs_list = &target->attrs_list;
52214+ else
52215+ attrs_list = &iscsi_attrs_list;
52216+
52217+ tgt_attr = NULL;
52218+ list_for_each_entry(a, attrs_list, attrs_list_entry) {
52219+ /* Both for sure NULL-terminated */
52220+ if (strcmp(a->name, attr_name) == 0) {
52221+ tgt_attr = a;
52222+ break;
52223+ }
52224+ }
52225+
52226+ if (tgt_attr == NULL) {
52227+ PRINT_ERROR("attr %s not found (target %s)", attr_name,
52228+ (target != NULL) ? target->name : "global");
52229+ res = -ENOENT;
52230+ goto out;
52231+ }
52232+
52233+ __iscsi_del_attr(target, tgt_attr);
52234+
52235+out:
52236+ TRACE_EXIT_RES(res);
52237+ return res;
52238+}
52239+
52240+/* target_mgmt_mutex supposed to be locked */
52241+static int iscsi_attr_cmd(void __user *ptr, unsigned int cmd)
52242+{
52243+ int rc, err = 0;
52244+ struct iscsi_kern_attr_info info;
52245+ struct iscsi_target *target;
52246+ struct scst_sysfs_user_info *i = NULL;
52247+
52248+ TRACE_ENTRY();
52249+
52250+ rc = copy_from_user(&info, ptr, sizeof(info));
52251+ if (rc != 0) {
52252+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
52253+ err = -EFAULT;
52254+ goto out;
52255+ }
52256+
52257+ info.attr.name[sizeof(info.attr.name)-1] = '\0';
52258+
52259+ if (info.cookie != 0) {
52260+ i = scst_sysfs_user_get_info(info.cookie);
52261+ TRACE_DBG("cookie %u, uinfo %p", info.cookie, i);
52262+ if (i == NULL) {
52263+ err = -EINVAL;
52264+ goto out;
52265+ }
52266+ }
52267+
52268+ target = target_lookup_by_id(info.tid);
52269+
52270+ if (target != NULL)
52271+ mutex_lock(&target->target_mutex);
52272+
52273+ switch (cmd) {
52274+ case ISCSI_ATTR_ADD:
52275+ err = iscsi_add_attr(target, &info.attr);
52276+ break;
52277+ case ISCSI_ATTR_DEL:
52278+ err = iscsi_del_attr(target, info.attr.name);
52279+ break;
52280+ default:
52281+ BUG();
52282+ }
52283+
52284+ if (target != NULL)
52285+ mutex_unlock(&target->target_mutex);
52286+
52287+ if (i != NULL) {
52288+ i->info_status = err;
52289+ complete(&i->info_completion);
52290+ }
52291+
52292+out:
52293+ TRACE_EXIT_RES(err);
52294+ return err;
52295+}
52296+
52297+/* target_mgmt_mutex supposed to be locked */
52298+static int add_target(void __user *ptr)
52299+{
52300+ int err, rc;
52301+ struct iscsi_kern_target_info *info;
52302+ struct scst_sysfs_user_info *uinfo;
52303+
52304+ TRACE_ENTRY();
52305+
52306+ info = kzalloc(sizeof(*info), GFP_KERNEL);
52307+ if (info == NULL) {
52308+ PRINT_ERROR("Can't alloc info (size %zd)", sizeof(*info));
52309+ err = -ENOMEM;
52310+ goto out;
52311+ }
52312+
52313+ rc = copy_from_user(info, ptr, sizeof(*info));
52314+ if (rc != 0) {
52315+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
52316+ err = -EFAULT;
52317+ goto out_free;
52318+ }
52319+
52320+ if (target_lookup_by_id(info->tid) != NULL) {
52321+ PRINT_ERROR("Target %u already exist!", info->tid);
52322+ err = -EEXIST;
52323+ goto out_free;
52324+ }
52325+
52326+ info->name[sizeof(info->name)-1] = '\0';
52327+
52328+ if (info->cookie != 0) {
52329+ uinfo = scst_sysfs_user_get_info(info->cookie);
52330+ TRACE_DBG("cookie %u, uinfo %p", info->cookie, uinfo);
52331+ if (uinfo == NULL) {
52332+ err = -EINVAL;
52333+ goto out_free;
52334+ }
52335+ } else
52336+ uinfo = NULL;
52337+
52338+ err = __add_target(info);
52339+
52340+ if (uinfo != NULL) {
52341+ uinfo->info_status = err;
52342+ complete(&uinfo->info_completion);
52343+ }
52344+
52345+out_free:
52346+ kfree(info);
52347+
52348+out:
52349+ TRACE_EXIT_RES(err);
52350+ return err;
52351+}
52352+
52353+/* target_mgmt_mutex supposed to be locked */
52354+static int del_target(void __user *ptr)
52355+{
52356+ int err, rc;
52357+ struct iscsi_kern_target_info info;
52358+ struct scst_sysfs_user_info *uinfo;
52359+
52360+ TRACE_ENTRY();
52361+
52362+ rc = copy_from_user(&info, ptr, sizeof(info));
52363+ if (rc != 0) {
52364+ PRINT_ERROR("Failed to copy %d user's bytes", rc);
52365+ err = -EFAULT;
52366+ goto out;
52367+ }
52368+
52369+ info.name[sizeof(info.name)-1] = '\0';
52370+
52371+ if (info.cookie != 0) {
52372+ uinfo = scst_sysfs_user_get_info(info.cookie);
52373+ TRACE_DBG("cookie %u, uinfo %p", info.cookie, uinfo);
52374+ if (uinfo == NULL) {
52375+ err = -EINVAL;
52376+ goto out;
52377+ }
52378+ } else
52379+ uinfo = NULL;
52380+
52381+ err = __del_target(info.tid);
52382+
52383+ if (uinfo != NULL) {
52384+ uinfo->info_status = err;
52385+ complete(&uinfo->info_completion);
52386+ }
52387+
52388+out:
52389+ TRACE_EXIT_RES(err);
52390+ return err;
52391+}
52392+
52393+static int iscsi_register(void __user *arg)
52394+{
52395+ struct iscsi_kern_register_info reg;
52396+ char ver[sizeof(ISCSI_SCST_INTERFACE_VERSION)+1];
52397+ int res, rc;
52398+
52399+ TRACE_ENTRY();
52400+
52401+ rc = copy_from_user(&reg, arg, sizeof(reg));
52402+ if (rc != 0) {
52403+ PRINT_ERROR("%s", "Unable to get register info");
52404+ res = -EFAULT;
52405+ goto out;
52406+ }
52407+
52408+ rc = copy_from_user(ver, (void __user *)(unsigned long)reg.version,
52409+ sizeof(ver));
52410+ if (rc != 0) {
52411+ PRINT_ERROR("%s", "Unable to get version string");
52412+ res = -EFAULT;
52413+ goto out;
52414+ }
52415+ ver[sizeof(ver)-1] = '\0';
52416+
52417+ if (strcmp(ver, ISCSI_SCST_INTERFACE_VERSION) != 0) {
52418+ PRINT_ERROR("Incorrect version of user space %s (expected %s)",
52419+ ver, ISCSI_SCST_INTERFACE_VERSION);
52420+ res = -EINVAL;
52421+ goto out;
52422+ }
52423+
52424+ memset(&reg, 0, sizeof(reg));
52425+ reg.max_data_seg_len = ISCSI_CONN_IOV_MAX << PAGE_SHIFT;
52426+ reg.max_queued_cmds = scst_get_max_lun_commands(NULL, NO_SUCH_LUN);
52427+
52428+ res = 0;
52429+
52430+ rc = copy_to_user(arg, &reg, sizeof(reg));
52431+ if (rc != 0) {
52432+ PRINT_ERROR("Failed to copy to user %d bytes", rc);
52433+ res = -EFAULT;
52434+ goto out;
52435+ }
52436+
52437+out:
52438+ TRACE_EXIT_RES(res);
52439+ return res;
52440+}
52441+
52442+static long ioctl(struct file *file, unsigned int cmd, unsigned long arg)
52443+{
52444+ long err;
52445+
52446+ TRACE_ENTRY();
52447+
52448+ if (cmd == REGISTER_USERD) {
52449+ err = iscsi_register((void __user *)arg);
52450+ goto out;
52451+ }
52452+
52453+ err = mutex_lock_interruptible(&target_mgmt_mutex);
52454+ if (err < 0)
52455+ goto out;
52456+
52457+ switch (cmd) {
52458+ case ADD_TARGET:
52459+ err = add_target((void __user *)arg);
52460+ break;
52461+
52462+ case DEL_TARGET:
52463+ err = del_target((void __user *)arg);
52464+ break;
52465+
52466+ case ISCSI_ATTR_ADD:
52467+ case ISCSI_ATTR_DEL:
52468+ err = iscsi_attr_cmd((void __user *)arg, cmd);
52469+ break;
52470+
52471+ case MGMT_CMD_CALLBACK:
52472+ err = mgmt_cmd_callback((void __user *)arg);
52473+ break;
52474+
52475+ case ISCSI_INITIATOR_ALLOWED:
52476+ err = iscsi_initiator_allowed((void __user *)arg);
52477+ break;
52478+
52479+ case ADD_SESSION:
52480+ err = add_session((void __user *)arg);
52481+ break;
52482+
52483+ case DEL_SESSION:
52484+ err = del_session((void __user *)arg);
52485+ break;
52486+
52487+ case ISCSI_PARAM_SET:
52488+ err = iscsi_params_config((void __user *)arg, 1);
52489+ break;
52490+
52491+ case ISCSI_PARAM_GET:
52492+ err = iscsi_params_config((void __user *)arg, 0);
52493+ break;
52494+
52495+ case ADD_CONN:
52496+ err = add_conn((void __user *)arg);
52497+ break;
52498+
52499+ case DEL_CONN:
52500+ err = del_conn((void __user *)arg);
52501+ break;
52502+
52503+ default:
52504+ PRINT_ERROR("Invalid ioctl cmd %x", cmd);
52505+ err = -EINVAL;
52506+ goto out_unlock;
52507+ }
52508+
52509+out_unlock:
52510+ mutex_unlock(&target_mgmt_mutex);
52511+
52512+out:
52513+ TRACE_EXIT_RES(err);
52514+ return err;
52515+}
52516+
52517+static int open(struct inode *inode, struct file *file)
52518+{
52519+ bool already;
52520+
52521+ mutex_lock(&target_mgmt_mutex);
52522+ already = (ctr_open_state != ISCSI_CTR_OPEN_STATE_CLOSED);
52523+ if (!already)
52524+ ctr_open_state = ISCSI_CTR_OPEN_STATE_OPEN;
52525+ mutex_unlock(&target_mgmt_mutex);
52526+
52527+ if (already) {
52528+ PRINT_WARNING("%s", "Attempt to second open the control "
52529+ "device!");
52530+ return -EBUSY;
52531+ } else
52532+ return 0;
52533+}
52534+
52535+static int release(struct inode *inode, struct file *filp)
52536+{
52537+ struct iscsi_attr *attr, *t;
52538+
52539+ TRACE(TRACE_MGMT, "%s", "Releasing allocated resources");
52540+
52541+ mutex_lock(&target_mgmt_mutex);
52542+ ctr_open_state = ISCSI_CTR_OPEN_STATE_CLOSING;
52543+ mutex_unlock(&target_mgmt_mutex);
52544+
52545+ target_del_all();
52546+
52547+ mutex_lock(&target_mgmt_mutex);
52548+
52549+ list_for_each_entry_safe(attr, t, &iscsi_attrs_list,
52550+ attrs_list_entry) {
52551+ __iscsi_del_attr(NULL, attr);
52552+ }
52553+
52554+ ctr_open_state = ISCSI_CTR_OPEN_STATE_CLOSED;
52555+
52556+ mutex_unlock(&target_mgmt_mutex);
52557+
52558+ return 0;
52559+}
52560+
52561+const struct file_operations ctr_fops = {
52562+ .owner = THIS_MODULE,
52563+ .unlocked_ioctl = ioctl,
52564+ .compat_ioctl = ioctl,
52565+ .open = open,
52566+ .release = release,
52567+};
52568+
52569+#ifdef CONFIG_SCST_DEBUG
52570+static void iscsi_dump_char(int ch, unsigned char *text, int *pos)
52571+{
52572+ int i = *pos;
52573+
52574+ if (ch < 0) {
52575+ while ((i % 16) != 0) {
52576+ printk(KERN_CONT " ");
52577+ text[i] = ' ';
52578+ i++;
52579+ if ((i % 16) == 0)
52580+ printk(KERN_CONT " | %.16s |\n", text);
52581+ else if ((i % 4) == 0)
52582+ printk(KERN_CONT " |");
52583+ }
52584+ i = 0;
52585+ goto out;
52586+ }
52587+
52588+ text[i] = (ch < 0x20 || (ch >= 0x80 && ch <= 0xa0)) ? ' ' : ch;
52589+ printk(KERN_CONT " %02x", ch);
52590+ i++;
52591+ if ((i % 16) == 0) {
52592+ printk(KERN_CONT " | %.16s |\n", text);
52593+ i = 0;
52594+ } else if ((i % 4) == 0)
52595+ printk(KERN_CONT " |");
52596+
52597+out:
52598+ *pos = i;
52599+ return;
52600+}
52601+
52602+void iscsi_dump_pdu(struct iscsi_pdu *pdu)
52603+{
52604+ unsigned char text[16];
52605+ int pos = 0;
52606+
52607+ if (trace_flag & TRACE_D_DUMP_PDU) {
52608+ unsigned char *buf;
52609+ int i;
52610+
52611+ buf = (void *)&pdu->bhs;
52612+ printk(KERN_DEBUG "BHS: (%p,%zd)\n", buf, sizeof(pdu->bhs));
52613+ for (i = 0; i < (int)sizeof(pdu->bhs); i++)
52614+ iscsi_dump_char(*buf++, text, &pos);
52615+ iscsi_dump_char(-1, text, &pos);
52616+
52617+ buf = (void *)pdu->ahs;
52618+ printk(KERN_DEBUG "AHS: (%p,%d)\n", buf, pdu->ahssize);
52619+ for (i = 0; i < pdu->ahssize; i++)
52620+ iscsi_dump_char(*buf++, text, &pos);
52621+ iscsi_dump_char(-1, text, &pos);
52622+
52623+ printk(KERN_DEBUG "Data: (%d)\n", pdu->datasize);
52624+ }
52625+}
52626+
52627+unsigned long iscsi_get_flow_ctrl_or_mgmt_dbg_log_flag(struct iscsi_cmnd *cmnd)
52628+{
52629+ unsigned long flag;
52630+
52631+ if (cmnd->cmd_req != NULL)
52632+ cmnd = cmnd->cmd_req;
52633+
52634+ if (cmnd->scst_cmd == NULL)
52635+ flag = TRACE_MGMT_DEBUG;
52636+ else {
52637+ int status = scst_cmd_get_status(cmnd->scst_cmd);
52638+ if ((status == SAM_STAT_TASK_SET_FULL) ||
52639+ (status == SAM_STAT_BUSY))
52640+ flag = TRACE_FLOW_CONTROL;
52641+ else
52642+ flag = TRACE_MGMT_DEBUG;
52643+ }
52644+ return flag;
52645+}
52646+
52647+#endif /* CONFIG_SCST_DEBUG */
52648diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/conn.c linux-2.6.35/drivers/scst/iscsi-scst/conn.c
52649--- orig/linux-2.6.35/drivers/scst/iscsi-scst/conn.c
52650+++ linux-2.6.35/drivers/scst/iscsi-scst/conn.c
52651@@ -0,0 +1,910 @@
52652+/*
52653+ * Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
52654+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
52655+ * Copyright (C) 2007 - 2010 ID7 Ltd.
52656+ *
52657+ * This program is free software; you can redistribute it and/or
52658+ * modify it under the terms of the GNU General Public License
52659+ * as published by the Free Software Foundation, version 2
52660+ * of the License.
52661+ *
52662+ * This program is distributed in the hope that it will be useful,
52663+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
52664+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52665+ * GNU General Public License for more details.
52666+ */
52667+
52668+#include <linux/file.h>
52669+#include <linux/ip.h>
52670+#include <net/tcp.h>
52671+
52672+#include "iscsi.h"
52673+#include "digest.h"
52674+
52675+static int print_conn_state(char *p, size_t size, struct iscsi_conn *conn)
52676+{
52677+ int pos = 0;
52678+
52679+ if (conn->closing) {
52680+ pos += scnprintf(p, size, "%s", "closing");
52681+ goto out;
52682+ }
52683+
52684+ switch (conn->rd_state) {
52685+ case ISCSI_CONN_RD_STATE_PROCESSING:
52686+ pos += scnprintf(&p[pos], size - pos, "%s", "read_processing ");
52687+ break;
52688+ case ISCSI_CONN_RD_STATE_IN_LIST:
52689+ pos += scnprintf(&p[pos], size - pos, "%s", "in_read_list ");
52690+ break;
52691+ }
52692+
52693+ switch (conn->wr_state) {
52694+ case ISCSI_CONN_WR_STATE_PROCESSING:
52695+ pos += scnprintf(&p[pos], size - pos, "%s", "write_processing ");
52696+ break;
52697+ case ISCSI_CONN_WR_STATE_IN_LIST:
52698+ pos += scnprintf(&p[pos], size - pos, "%s", "in_write_list ");
52699+ break;
52700+ case ISCSI_CONN_WR_STATE_SPACE_WAIT:
52701+ pos += scnprintf(&p[pos], size - pos, "%s", "space_waiting ");
52702+ break;
52703+ }
52704+
52705+ if (test_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags))
52706+ pos += scnprintf(&p[pos], size - pos, "%s", "reinstating ");
52707+ else if (pos == 0)
52708+ pos += scnprintf(&p[pos], size - pos, "%s", "established idle ");
52709+
52710+out:
52711+ return pos;
52712+}
52713+
52714+static void iscsi_conn_release(struct kobject *kobj)
52715+{
52716+ struct iscsi_conn *conn;
52717+
52718+ TRACE_ENTRY();
52719+
52720+ conn = container_of(kobj, struct iscsi_conn, conn_kobj);
52721+ complete_all(&conn->conn_kobj_release_cmpl);
52722+
52723+ TRACE_EXIT();
52724+ return;
52725+}
52726+
52727+struct kobj_type iscsi_conn_ktype = {
52728+ .release = iscsi_conn_release,
52729+};
52730+
52731+static ssize_t iscsi_get_initiator_ip(struct iscsi_conn *conn,
52732+ char *buf, int size)
52733+{
52734+ int pos;
52735+ struct sock *sk;
52736+
52737+ TRACE_ENTRY();
52738+
52739+ sk = conn->sock->sk;
52740+ switch (sk->sk_family) {
52741+ case AF_INET:
52742+ pos = scnprintf(buf, size,
52743+ "%pI4", &inet_sk(sk)->inet_daddr);
52744+ break;
52745+ case AF_INET6:
52746+ pos = scnprintf(buf, size, "[%p6]",
52747+ &inet6_sk(sk)->daddr);
52748+ break;
52749+ default:
52750+ pos = scnprintf(buf, size, "Unknown family %d",
52751+ sk->sk_family);
52752+ break;
52753+ }
52754+
52755+ TRACE_EXIT_RES(pos);
52756+ return pos;
52757+}
52758+
52759+static ssize_t iscsi_conn_ip_show(struct kobject *kobj,
52760+ struct kobj_attribute *attr, char *buf)
52761+{
52762+ int pos;
52763+ struct iscsi_conn *conn;
52764+
52765+ TRACE_ENTRY();
52766+
52767+ conn = container_of(kobj, struct iscsi_conn, conn_kobj);
52768+
52769+ pos = iscsi_get_initiator_ip(conn, buf, SCST_SYSFS_BLOCK_SIZE);
52770+
52771+ TRACE_EXIT_RES(pos);
52772+ return pos;
52773+}
52774+
52775+static struct kobj_attribute iscsi_conn_ip_attr =
52776+ __ATTR(ip, S_IRUGO, iscsi_conn_ip_show, NULL);
52777+
52778+static ssize_t iscsi_conn_cid_show(struct kobject *kobj,
52779+ struct kobj_attribute *attr, char *buf)
52780+{
52781+ int pos;
52782+ struct iscsi_conn *conn;
52783+
52784+ TRACE_ENTRY();
52785+
52786+ conn = container_of(kobj, struct iscsi_conn, conn_kobj);
52787+
52788+ pos = sprintf(buf, "%u", conn->cid);
52789+
52790+ TRACE_EXIT_RES(pos);
52791+ return pos;
52792+}
52793+
52794+static struct kobj_attribute iscsi_conn_cid_attr =
52795+ __ATTR(cid, S_IRUGO, iscsi_conn_cid_show, NULL);
52796+
52797+static ssize_t iscsi_conn_state_show(struct kobject *kobj,
52798+ struct kobj_attribute *attr, char *buf)
52799+{
52800+ int pos;
52801+ struct iscsi_conn *conn;
52802+
52803+ TRACE_ENTRY();
52804+
52805+ conn = container_of(kobj, struct iscsi_conn, conn_kobj);
52806+
52807+ pos = print_conn_state(buf, SCST_SYSFS_BLOCK_SIZE, conn);
52808+
52809+ TRACE_EXIT_RES(pos);
52810+ return pos;
52811+}
52812+
52813+static struct kobj_attribute iscsi_conn_state_attr =
52814+ __ATTR(state, S_IRUGO, iscsi_conn_state_show, NULL);
52815+
52816+static void conn_sysfs_del(struct iscsi_conn *conn)
52817+{
52818+ int rc;
52819+
52820+ TRACE_ENTRY();
52821+
52822+ kobject_del(&conn->conn_kobj);
52823+ kobject_put(&conn->conn_kobj);
52824+
52825+ rc = wait_for_completion_timeout(&conn->conn_kobj_release_cmpl, HZ);
52826+ if (rc == 0) {
52827+ PRINT_INFO("Waiting for releasing sysfs entry "
52828+ "for conn %p (%d refs)...", conn,
52829+ atomic_read(&conn->conn_kobj.kref.refcount));
52830+ wait_for_completion(&conn->conn_kobj_release_cmpl);
52831+ PRINT_INFO("Done waiting for releasing sysfs "
52832+ "entry for conn %p", conn);
52833+ }
52834+
52835+ TRACE_EXIT();
52836+ return;
52837+}
52838+
52839+static int conn_sysfs_add(struct iscsi_conn *conn)
52840+{
52841+ int res;
52842+ struct iscsi_session *session = conn->session;
52843+ struct iscsi_conn *c;
52844+ int n = 1;
52845+ char addr[64];
52846+
52847+ TRACE_ENTRY();
52848+
52849+ iscsi_get_initiator_ip(conn, addr, sizeof(addr));
52850+
52851+restart:
52852+ list_for_each_entry(c, &session->conn_list, conn_list_entry) {
52853+ if (strcmp(addr, kobject_name(&conn->conn_kobj)) == 0) {
52854+ char c_addr[64];
52855+
52856+ iscsi_get_initiator_ip(conn, c_addr, sizeof(c_addr));
52857+
52858+ TRACE_DBG("Duplicated conn from the same initiator "
52859+ "%s found", c_addr);
52860+
52861+ snprintf(addr, sizeof(addr), "%s_%d", c_addr, n);
52862+ n++;
52863+ goto restart;
52864+ }
52865+ }
52866+
52867+ init_completion(&conn->conn_kobj_release_cmpl);
52868+
52869+ res = kobject_init_and_add(&conn->conn_kobj, &iscsi_conn_ktype,
52870+ scst_sysfs_get_sess_kobj(session->scst_sess), addr);
52871+ if (res != 0) {
52872+ PRINT_ERROR("Unable create sysfs entries for conn %s",
52873+ addr);
52874+ goto out;
52875+ }
52876+
52877+ TRACE_DBG("conn %p, conn_kobj %p", conn, &conn->conn_kobj);
52878+
52879+ res = sysfs_create_file(&conn->conn_kobj,
52880+ &iscsi_conn_state_attr.attr);
52881+ if (res != 0) {
52882+ PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
52883+ iscsi_conn_state_attr.attr.name, addr);
52884+ goto out_err;
52885+ }
52886+
52887+ res = sysfs_create_file(&conn->conn_kobj,
52888+ &iscsi_conn_cid_attr.attr);
52889+ if (res != 0) {
52890+ PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
52891+ iscsi_conn_cid_attr.attr.name, addr);
52892+ goto out_err;
52893+ }
52894+
52895+ res = sysfs_create_file(&conn->conn_kobj,
52896+ &iscsi_conn_ip_attr.attr);
52897+ if (res != 0) {
52898+ PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
52899+ iscsi_conn_ip_attr.attr.name, addr);
52900+ goto out_err;
52901+ }
52902+
52903+out:
52904+ TRACE_EXIT_RES(res);
52905+ return res;
52906+
52907+out_err:
52908+ conn_sysfs_del(conn);
52909+ goto out;
52910+}
52911+
52912+/* target_mutex supposed to be locked */
52913+struct iscsi_conn *conn_lookup(struct iscsi_session *session, u16 cid)
52914+{
52915+ struct iscsi_conn *conn;
52916+
52917+ /*
52918+ * We need to find the latest conn to correctly handle
52919+ * multi-reinstatements
52920+ */
52921+ list_for_each_entry_reverse(conn, &session->conn_list,
52922+ conn_list_entry) {
52923+ if (conn->cid == cid)
52924+ return conn;
52925+ }
52926+ return NULL;
52927+}
52928+
52929+void iscsi_make_conn_rd_active(struct iscsi_conn *conn)
52930+{
52931+ TRACE_ENTRY();
52932+
52933+ spin_lock_bh(&iscsi_rd_lock);
52934+
52935+ TRACE_DBG("conn %p, rd_state %x, rd_data_ready %d", conn,
52936+ conn->rd_state, conn->rd_data_ready);
52937+
52938+ /*
52939+ * Let's start processing ASAP not waiting for all the being waited
52940+ * data be received, even if we need several wakup iteration to receive
52941+ * them all, because starting ASAP, i.e. in parallel, is better for
52942+ * performance, especially on multi-CPU/core systems.
52943+ */
52944+
52945+ conn->rd_data_ready = 1;
52946+
52947+ if (conn->rd_state == ISCSI_CONN_RD_STATE_IDLE) {
52948+ list_add_tail(&conn->rd_list_entry, &iscsi_rd_list);
52949+ conn->rd_state = ISCSI_CONN_RD_STATE_IN_LIST;
52950+ wake_up(&iscsi_rd_waitQ);
52951+ }
52952+
52953+ spin_unlock_bh(&iscsi_rd_lock);
52954+
52955+ TRACE_EXIT();
52956+ return;
52957+}
52958+
52959+void iscsi_make_conn_wr_active(struct iscsi_conn *conn)
52960+{
52961+ TRACE_ENTRY();
52962+
52963+ spin_lock_bh(&iscsi_wr_lock);
52964+
52965+ TRACE_DBG("conn %p, wr_state %x, wr_space_ready %d", conn,
52966+ conn->wr_state, conn->wr_space_ready);
52967+
52968+ /*
52969+ * Let's start sending waiting to be sent data ASAP, even if there's
52970+ * still not all the needed buffers ready and we need several wakup
52971+ * iteration to send them all, because starting ASAP, i.e. in parallel,
52972+ * is better for performance, especially on multi-CPU/core systems.
52973+ */
52974+
52975+ if (conn->wr_state == ISCSI_CONN_WR_STATE_IDLE) {
52976+ list_add_tail(&conn->wr_list_entry, &iscsi_wr_list);
52977+ conn->wr_state = ISCSI_CONN_WR_STATE_IN_LIST;
52978+ wake_up(&iscsi_wr_waitQ);
52979+ }
52980+
52981+ spin_unlock_bh(&iscsi_wr_lock);
52982+
52983+ TRACE_EXIT();
52984+ return;
52985+}
52986+
52987+void __mark_conn_closed(struct iscsi_conn *conn, int flags)
52988+{
52989+ spin_lock_bh(&iscsi_rd_lock);
52990+ conn->closing = 1;
52991+ if (flags & ISCSI_CONN_ACTIVE_CLOSE)
52992+ conn->active_close = 1;
52993+ if (flags & ISCSI_CONN_DELETING)
52994+ conn->deleting = 1;
52995+ spin_unlock_bh(&iscsi_rd_lock);
52996+
52997+ iscsi_make_conn_rd_active(conn);
52998+}
52999+
53000+void mark_conn_closed(struct iscsi_conn *conn)
53001+{
53002+ __mark_conn_closed(conn, ISCSI_CONN_ACTIVE_CLOSE);
53003+}
53004+
53005+static void __iscsi_state_change(struct sock *sk)
53006+{
53007+ struct iscsi_conn *conn = sk->sk_user_data;
53008+
53009+ TRACE_ENTRY();
53010+
53011+ if (unlikely(sk->sk_state != TCP_ESTABLISHED)) {
53012+ if (!conn->closing) {
53013+ PRINT_ERROR("Connection with initiator %s "
53014+ "unexpectedly closed!",
53015+ conn->session->initiator_name);
53016+ TRACE_MGMT_DBG("conn %p, sk state %d", conn,
53017+ sk->sk_state);
53018+ __mark_conn_closed(conn, 0);
53019+ }
53020+ } else
53021+ iscsi_make_conn_rd_active(conn);
53022+
53023+ TRACE_EXIT();
53024+ return;
53025+}
53026+
53027+static void iscsi_state_change(struct sock *sk)
53028+{
53029+ struct iscsi_conn *conn = sk->sk_user_data;
53030+
53031+ __iscsi_state_change(sk);
53032+ conn->old_state_change(sk);
53033+
53034+ return;
53035+}
53036+
53037+static void iscsi_data_ready(struct sock *sk, int len)
53038+{
53039+ struct iscsi_conn *conn = sk->sk_user_data;
53040+
53041+ TRACE_ENTRY();
53042+
53043+ iscsi_make_conn_rd_active(conn);
53044+
53045+ conn->old_data_ready(sk, len);
53046+
53047+ TRACE_EXIT();
53048+ return;
53049+}
53050+
53051+void __iscsi_write_space_ready(struct iscsi_conn *conn)
53052+{
53053+ TRACE_ENTRY();
53054+
53055+ spin_lock_bh(&iscsi_wr_lock);
53056+ conn->wr_space_ready = 1;
53057+ if ((conn->wr_state == ISCSI_CONN_WR_STATE_SPACE_WAIT)) {
53058+ TRACE_DBG("wr space ready (conn %p)", conn);
53059+ list_add_tail(&conn->wr_list_entry, &iscsi_wr_list);
53060+ conn->wr_state = ISCSI_CONN_WR_STATE_IN_LIST;
53061+ wake_up(&iscsi_wr_waitQ);
53062+ }
53063+ spin_unlock_bh(&iscsi_wr_lock);
53064+
53065+ TRACE_EXIT();
53066+ return;
53067+}
53068+
53069+static void iscsi_write_space_ready(struct sock *sk)
53070+{
53071+ struct iscsi_conn *conn = sk->sk_user_data;
53072+
53073+ TRACE_ENTRY();
53074+
53075+ TRACE_DBG("Write space ready for conn %p", conn);
53076+
53077+ __iscsi_write_space_ready(conn);
53078+
53079+ conn->old_write_space(sk);
53080+
53081+ TRACE_EXIT();
53082+ return;
53083+}
53084+
53085+static void conn_rsp_timer_fn(unsigned long arg)
53086+{
53087+ struct iscsi_conn *conn = (struct iscsi_conn *)arg;
53088+ struct iscsi_cmnd *cmnd;
53089+ unsigned long j = jiffies;
53090+
53091+ TRACE_ENTRY();
53092+
53093+ TRACE_DBG("Timer (conn %p)", conn);
53094+
53095+ spin_lock_bh(&conn->write_list_lock);
53096+
53097+ if (!list_empty(&conn->write_timeout_list)) {
53098+ unsigned long timeout_time;
53099+ cmnd = list_entry(conn->write_timeout_list.next,
53100+ struct iscsi_cmnd, write_timeout_list_entry);
53101+
53102+ timeout_time = j + conn->rsp_timeout + ISCSI_ADD_SCHED_TIME;
53103+
53104+ if (unlikely(time_after_eq(j, cmnd->write_start +
53105+ conn->rsp_timeout))) {
53106+ if (!conn->closing) {
53107+ PRINT_ERROR("Timeout sending data/waiting "
53108+ "for reply to/from initiator "
53109+ "%s (SID %llx), closing connection",
53110+ conn->session->initiator_name,
53111+ (long long unsigned int)
53112+ conn->session->sid);
53113+ /*
53114+ * We must call mark_conn_closed() outside of
53115+ * write_list_lock or we will have a circular
53116+ * locking dependency with iscsi_rd_lock.
53117+ */
53118+ spin_unlock_bh(&conn->write_list_lock);
53119+ mark_conn_closed(conn);
53120+ goto out;
53121+ }
53122+ } else if (!timer_pending(&conn->rsp_timer) ||
53123+ time_after(conn->rsp_timer.expires, timeout_time)) {
53124+ TRACE_DBG("Restarting timer on %ld (conn %p)",
53125+ timeout_time, conn);
53126+ /*
53127+ * Timer might have been restarted while we were
53128+ * entering here.
53129+ *
53130+ * Since we have not empty write_timeout_list, we are
53131+ * safe to restart the timer, because we not race with
53132+ * del_timer_sync() in conn_free().
53133+ */
53134+ mod_timer(&conn->rsp_timer, timeout_time);
53135+ }
53136+ }
53137+
53138+ spin_unlock_bh(&conn->write_list_lock);
53139+
53140+ if (unlikely(conn->conn_tm_active)) {
53141+ TRACE_MGMT_DBG("TM active: making conn %p RD active", conn);
53142+ iscsi_make_conn_rd_active(conn);
53143+ }
53144+
53145+out:
53146+ TRACE_EXIT();
53147+ return;
53148+}
53149+
53150+static void conn_nop_in_delayed_work_fn(struct delayed_work *work)
53151+{
53152+ struct iscsi_conn *conn = container_of(work, struct iscsi_conn,
53153+ nop_in_delayed_work);
53154+
53155+ TRACE_ENTRY();
53156+
53157+ if (time_after_eq(jiffies, conn->last_rcv_time +
53158+ conn->nop_in_interval)) {
53159+ iscsi_send_nop_in(conn);
53160+ }
53161+
53162+ if ((conn->nop_in_interval > 0) &&
53163+ !test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags)) {
53164+ TRACE_DBG("Reschedule Nop-In work for conn %p", conn);
53165+ schedule_delayed_work(&conn->nop_in_delayed_work,
53166+ conn->nop_in_interval + ISCSI_ADD_SCHED_TIME);
53167+ }
53168+
53169+ TRACE_EXIT();
53170+ return;
53171+}
53172+
53173+/* Must be called from rd thread only */
53174+void iscsi_check_tm_data_wait_timeouts(struct iscsi_conn *conn, bool force)
53175+{
53176+ struct iscsi_cmnd *cmnd;
53177+ unsigned long j = jiffies;
53178+ bool aborted_cmds_pending;
53179+ unsigned long timeout_time = j + ISCSI_TM_DATA_WAIT_TIMEOUT +
53180+ ISCSI_ADD_SCHED_TIME;
53181+
53182+ TRACE_ENTRY();
53183+
53184+ TRACE_DBG_FLAG(force ? TRACE_CONN_OC_DBG : TRACE_MGMT_DEBUG,
53185+ "j %ld (TIMEOUT %d, force %d)", j,
53186+ ISCSI_TM_DATA_WAIT_TIMEOUT + ISCSI_ADD_SCHED_TIME, force);
53187+
53188+ iscsi_extracheck_is_rd_thread(conn);
53189+
53190+again:
53191+ spin_lock_bh(&iscsi_rd_lock);
53192+ spin_lock(&conn->write_list_lock);
53193+
53194+ aborted_cmds_pending = false;
53195+ list_for_each_entry(cmnd, &conn->write_timeout_list,
53196+ write_timeout_list_entry) {
53197+ if (test_bit(ISCSI_CMD_ABORTED, &cmnd->prelim_compl_flags)) {
53198+ TRACE_DBG_FLAG(force ? TRACE_CONN_OC_DBG : TRACE_MGMT_DEBUG,
53199+ "Checking aborted cmnd %p (scst_state %d, "
53200+ "on_write_timeout_list %d, write_start %ld, "
53201+ "r2t_len_to_receive %d)", cmnd,
53202+ cmnd->scst_state, cmnd->on_write_timeout_list,
53203+ cmnd->write_start, cmnd->r2t_len_to_receive);
53204+ if ((cmnd->r2t_len_to_receive != 0) &&
53205+ (time_after_eq(j, cmnd->write_start + ISCSI_TM_DATA_WAIT_TIMEOUT) ||
53206+ force)) {
53207+ spin_unlock(&conn->write_list_lock);
53208+ spin_unlock_bh(&iscsi_rd_lock);
53209+ iscsi_fail_data_waiting_cmnd(cmnd);
53210+ goto again;
53211+ }
53212+ aborted_cmds_pending = true;
53213+ }
53214+ }
53215+
53216+ if (aborted_cmds_pending) {
53217+ if (!force &&
53218+ (!timer_pending(&conn->rsp_timer) ||
53219+ time_after(conn->rsp_timer.expires, timeout_time))) {
53220+ TRACE_MGMT_DBG("Mod timer on %ld (conn %p)",
53221+ timeout_time, conn);
53222+ mod_timer(&conn->rsp_timer, timeout_time);
53223+ }
53224+ } else {
53225+ TRACE_MGMT_DBG("Clearing conn_tm_active for conn %p", conn);
53226+ conn->conn_tm_active = 0;
53227+ }
53228+
53229+ spin_unlock(&conn->write_list_lock);
53230+ spin_unlock_bh(&iscsi_rd_lock);
53231+
53232+ TRACE_EXIT();
53233+ return;
53234+}
53235+
53236+/* target_mutex supposed to be locked */
53237+void conn_reinst_finished(struct iscsi_conn *conn)
53238+{
53239+ struct iscsi_cmnd *cmnd, *t;
53240+
53241+ TRACE_ENTRY();
53242+
53243+ clear_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags);
53244+
53245+ list_for_each_entry_safe(cmnd, t, &conn->reinst_pending_cmd_list,
53246+ reinst_pending_cmd_list_entry) {
53247+ TRACE_MGMT_DBG("Restarting reinst pending cmnd %p",
53248+ cmnd);
53249+
53250+ list_del(&cmnd->reinst_pending_cmd_list_entry);
53251+
53252+ /* Restore the state for preliminary completion/cmnd_done() */
53253+ cmnd->scst_state = ISCSI_CMD_STATE_AFTER_PREPROC;
53254+
53255+ iscsi_restart_cmnd(cmnd);
53256+ }
53257+
53258+ TRACE_EXIT();
53259+ return;
53260+}
53261+
53262+static void conn_activate(struct iscsi_conn *conn)
53263+{
53264+ TRACE_MGMT_DBG("Enabling conn %p", conn);
53265+
53266+ /* Catch double bind */
53267+ BUG_ON(conn->sock->sk->sk_state_change == iscsi_state_change);
53268+
53269+ write_lock_bh(&conn->sock->sk->sk_callback_lock);
53270+
53271+ conn->old_state_change = conn->sock->sk->sk_state_change;
53272+ conn->sock->sk->sk_state_change = iscsi_state_change;
53273+
53274+ conn->old_data_ready = conn->sock->sk->sk_data_ready;
53275+ conn->sock->sk->sk_data_ready = iscsi_data_ready;
53276+
53277+ conn->old_write_space = conn->sock->sk->sk_write_space;
53278+ conn->sock->sk->sk_write_space = iscsi_write_space_ready;
53279+
53280+ write_unlock_bh(&conn->sock->sk->sk_callback_lock);
53281+
53282+ /*
53283+ * Check, if conn was closed while we were initializing it.
53284+ * This function will make conn rd_active, if necessary.
53285+ */
53286+ __iscsi_state_change(conn->sock->sk);
53287+
53288+ return;
53289+}
53290+
53291+/*
53292+ * Note: the code below passes a kernel space pointer (&opt) to setsockopt()
53293+ * while the declaration of setsockopt specifies that it expects a user space
53294+ * pointer. This seems to work fine, and this approach is also used in some
53295+ * other parts of the Linux kernel (see e.g. fs/ocfs2/cluster/tcp.c).
53296+ */
53297+static int conn_setup_sock(struct iscsi_conn *conn)
53298+{
53299+ int res = 0;
53300+ int opt = 1;
53301+ mm_segment_t oldfs;
53302+ struct iscsi_session *session = conn->session;
53303+
53304+ TRACE_DBG("%llx", (long long unsigned int)session->sid);
53305+
53306+ conn->sock = SOCKET_I(conn->file->f_dentry->d_inode);
53307+
53308+ if (conn->sock->ops->sendpage == NULL) {
53309+ PRINT_ERROR("Socket for sid %llx doesn't support sendpage()",
53310+ (long long unsigned int)session->sid);
53311+ res = -EINVAL;
53312+ goto out;
53313+ }
53314+
53315+#if 0
53316+ conn->sock->sk->sk_allocation = GFP_NOIO;
53317+#endif
53318+ conn->sock->sk->sk_user_data = conn;
53319+
53320+ oldfs = get_fs();
53321+ set_fs(get_ds());
53322+ conn->sock->ops->setsockopt(conn->sock, SOL_TCP, TCP_NODELAY,
53323+ (void __force __user *)&opt, sizeof(opt));
53324+ set_fs(oldfs);
53325+
53326+out:
53327+ return res;
53328+}
53329+
53330+/* target_mutex supposed to be locked */
53331+int conn_free(struct iscsi_conn *conn)
53332+{
53333+ struct iscsi_session *session = conn->session;
53334+
53335+ TRACE_ENTRY();
53336+
53337+ TRACE_MGMT_DBG("Freeing conn %p (sess=%p, %#Lx %u)", conn,
53338+ session, (long long unsigned int)session->sid, conn->cid);
53339+
53340+ del_timer_sync(&conn->rsp_timer);
53341+
53342+ conn_sysfs_del(conn);
53343+
53344+ BUG_ON(atomic_read(&conn->conn_ref_cnt) != 0);
53345+ BUG_ON(!list_empty(&conn->cmd_list));
53346+ BUG_ON(!list_empty(&conn->write_list));
53347+ BUG_ON(!list_empty(&conn->write_timeout_list));
53348+ BUG_ON(conn->conn_reinst_successor != NULL);
53349+ BUG_ON(!test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags));
53350+
53351+ /* Just in case if new conn gets freed before the old one */
53352+ if (test_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags)) {
53353+ struct iscsi_conn *c;
53354+ TRACE_MGMT_DBG("Freeing being reinstated conn %p", conn);
53355+ list_for_each_entry(c, &session->conn_list,
53356+ conn_list_entry) {
53357+ if (c->conn_reinst_successor == conn) {
53358+ c->conn_reinst_successor = NULL;
53359+ break;
53360+ }
53361+ }
53362+ }
53363+
53364+ list_del(&conn->conn_list_entry);
53365+
53366+ fput(conn->file);
53367+ conn->file = NULL;
53368+ conn->sock = NULL;
53369+
53370+ free_page((unsigned long)conn->read_iov);
53371+
53372+ kfree(conn);
53373+
53374+ if (list_empty(&session->conn_list)) {
53375+ BUG_ON(session->sess_reinst_successor != NULL);
53376+ session_free(session, true);
53377+ }
53378+
53379+ return 0;
53380+}
53381+
53382+/* target_mutex supposed to be locked */
53383+static int iscsi_conn_alloc(struct iscsi_session *session,
53384+ struct iscsi_kern_conn_info *info, struct iscsi_conn **new_conn)
53385+{
53386+ struct iscsi_conn *conn;
53387+ int res = 0;
53388+
53389+ conn = kzalloc(sizeof(*conn), GFP_KERNEL);
53390+ if (!conn) {
53391+ res = -ENOMEM;
53392+ goto out_err;
53393+ }
53394+
53395+ TRACE_MGMT_DBG("Creating connection %p for sid %#Lx, cid %u", conn,
53396+ (long long unsigned int)session->sid, info->cid);
53397+
53398+ /* Changing it, change ISCSI_CONN_IOV_MAX as well !! */
53399+ conn->read_iov = (struct iovec *)get_zeroed_page(GFP_KERNEL);
53400+ if (conn->read_iov == NULL) {
53401+ res = -ENOMEM;
53402+ goto out_err_free_conn;
53403+ }
53404+
53405+ atomic_set(&conn->conn_ref_cnt, 0);
53406+ conn->session = session;
53407+ if (session->sess_reinstating)
53408+ __set_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags);
53409+ conn->cid = info->cid;
53410+ conn->stat_sn = info->stat_sn;
53411+ conn->exp_stat_sn = info->exp_stat_sn;
53412+ conn->rd_state = ISCSI_CONN_RD_STATE_IDLE;
53413+ conn->wr_state = ISCSI_CONN_WR_STATE_IDLE;
53414+
53415+ conn->hdigest_type = session->sess_params.header_digest;
53416+ conn->ddigest_type = session->sess_params.data_digest;
53417+ res = digest_init(conn);
53418+ if (res != 0)
53419+ goto out_free_iov;
53420+
53421+ conn->target = session->target;
53422+ spin_lock_init(&conn->cmd_list_lock);
53423+ INIT_LIST_HEAD(&conn->cmd_list);
53424+ spin_lock_init(&conn->write_list_lock);
53425+ INIT_LIST_HEAD(&conn->write_list);
53426+ INIT_LIST_HEAD(&conn->write_timeout_list);
53427+ setup_timer(&conn->rsp_timer, conn_rsp_timer_fn, (unsigned long)conn);
53428+ init_waitqueue_head(&conn->read_state_waitQ);
53429+ init_completion(&conn->ready_to_free);
53430+ INIT_LIST_HEAD(&conn->reinst_pending_cmd_list);
53431+ INIT_LIST_HEAD(&conn->nop_req_list);
53432+ spin_lock_init(&conn->nop_req_list_lock);
53433+
53434+ conn->nop_in_ttt = 0;
53435+ INIT_DELAYED_WORK(&conn->nop_in_delayed_work,
53436+ (void (*)(struct work_struct *))conn_nop_in_delayed_work_fn);
53437+ conn->last_rcv_time = jiffies;
53438+ conn->rsp_timeout = session->tgt_params.rsp_timeout * HZ;
53439+ conn->nop_in_interval = session->tgt_params.nop_in_interval * HZ;
53440+ if (conn->nop_in_interval > 0) {
53441+ TRACE_DBG("Schedule Nop-In work for conn %p", conn);
53442+ schedule_delayed_work(&conn->nop_in_delayed_work,
53443+ conn->nop_in_interval + ISCSI_ADD_SCHED_TIME);
53444+ }
53445+
53446+ conn->file = fget(info->fd);
53447+
53448+ res = conn_setup_sock(conn);
53449+ if (res != 0)
53450+ goto out_fput;
53451+
53452+ res = conn_sysfs_add(conn);
53453+ if (res != 0)
53454+ goto out_fput;
53455+
53456+ list_add_tail(&conn->conn_list_entry, &session->conn_list);
53457+
53458+ *new_conn = conn;
53459+
53460+out:
53461+ return res;
53462+
53463+out_fput:
53464+ fput(conn->file);
53465+
53466+out_free_iov:
53467+ free_page((unsigned long)conn->read_iov);
53468+
53469+out_err_free_conn:
53470+ kfree(conn);
53471+
53472+out_err:
53473+ goto out;
53474+}
53475+
53476+/* target_mutex supposed to be locked */
53477+int __add_conn(struct iscsi_session *session, struct iscsi_kern_conn_info *info)
53478+{
53479+ struct iscsi_conn *conn, *new_conn = NULL;
53480+ int err;
53481+ bool reinstatement = false;
53482+
53483+ conn = conn_lookup(session, info->cid);
53484+ if ((conn != NULL) &&
53485+ !test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags)) {
53486+ /* conn reinstatement */
53487+ reinstatement = true;
53488+ } else if (!list_empty(&session->conn_list)) {
53489+ err = -EEXIST;
53490+ goto out;
53491+ }
53492+
53493+ err = iscsi_conn_alloc(session, info, &new_conn);
53494+ if (err != 0)
53495+ goto out;
53496+
53497+ if (reinstatement) {
53498+ TRACE_MGMT_DBG("Reinstating conn (old %p, new %p)", conn,
53499+ new_conn);
53500+ conn->conn_reinst_successor = new_conn;
53501+ __set_bit(ISCSI_CONN_REINSTATING, &new_conn->conn_aflags);
53502+ __mark_conn_closed(conn, 0);
53503+ }
53504+
53505+ conn_activate(new_conn);
53506+
53507+out:
53508+ return err;
53509+}
53510+
53511+/* target_mutex supposed to be locked */
53512+int __del_conn(struct iscsi_session *session, struct iscsi_kern_conn_info *info)
53513+{
53514+ struct iscsi_conn *conn;
53515+ int err = -EEXIST;
53516+
53517+ conn = conn_lookup(session, info->cid);
53518+ if (!conn) {
53519+ PRINT_WARNING("Connection %d not found", info->cid);
53520+ return err;
53521+ }
53522+
53523+ PRINT_INFO("Deleting connection with initiator %s (%p)",
53524+ conn->session->initiator_name, conn);
53525+
53526+ __mark_conn_closed(conn, ISCSI_CONN_ACTIVE_CLOSE|ISCSI_CONN_DELETING);
53527+
53528+ return 0;
53529+}
53530+
53531+#ifdef CONFIG_SCST_EXTRACHECKS
53532+
53533+void iscsi_extracheck_is_rd_thread(struct iscsi_conn *conn)
53534+{
53535+ if (unlikely(current != conn->rd_task)) {
53536+ printk(KERN_EMERG "conn %p rd_task != current %p (pid %d)\n",
53537+ conn, current, current->pid);
53538+ while (in_softirq())
53539+ local_bh_enable();
53540+ printk(KERN_EMERG "rd_state %x\n", conn->rd_state);
53541+ printk(KERN_EMERG "rd_task %p\n", conn->rd_task);
53542+ printk(KERN_EMERG "rd_task->pid %d\n", conn->rd_task->pid);
53543+ BUG();
53544+ }
53545+}
53546+
53547+void iscsi_extracheck_is_wr_thread(struct iscsi_conn *conn)
53548+{
53549+ if (unlikely(current != conn->wr_task)) {
53550+ printk(KERN_EMERG "conn %p wr_task != current %p (pid %d)\n",
53551+ conn, current, current->pid);
53552+ while (in_softirq())
53553+ local_bh_enable();
53554+ printk(KERN_EMERG "wr_state %x\n", conn->wr_state);
53555+ printk(KERN_EMERG "wr_task %p\n", conn->wr_task);
53556+ printk(KERN_EMERG "wr_task->pid %d\n", conn->wr_task->pid);
53557+ BUG();
53558+ }
53559+}
53560+
53561+#endif /* CONFIG_SCST_EXTRACHECKS */
53562diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/digest.c linux-2.6.35/drivers/scst/iscsi-scst/digest.c
53563--- orig/linux-2.6.35/drivers/scst/iscsi-scst/digest.c
53564+++ linux-2.6.35/drivers/scst/iscsi-scst/digest.c
53565@@ -0,0 +1,244 @@
53566+/*
53567+ * iSCSI digest handling.
53568+ *
53569+ * Copyright (C) 2004 - 2006 Xiranet Communications GmbH
53570+ * <arne.redlich@xiranet.com>
53571+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
53572+ * Copyright (C) 2007 - 2010 ID7 Ltd.
53573+ *
53574+ * This program is free software; you can redistribute it and/or
53575+ * modify it under the terms of the GNU General Public License
53576+ * as published by the Free Software Foundation.
53577+ *
53578+ * This program is distributed in the hope that it will be useful,
53579+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
53580+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53581+ * GNU General Public License for more details.
53582+ */
53583+
53584+#include <linux/types.h>
53585+#include <linux/scatterlist.h>
53586+
53587+#include "iscsi.h"
53588+#include "digest.h"
53589+#include <linux/crc32c.h>
53590+
53591+void digest_alg_available(int *val)
53592+{
53593+#if defined(CONFIG_LIBCRC32C_MODULE) || defined(CONFIG_LIBCRC32C)
53594+ int crc32c = 1;
53595+#else
53596+ int crc32c = 0;
53597+#endif
53598+
53599+ if ((*val & DIGEST_CRC32C) && !crc32c) {
53600+ PRINT_ERROR("%s", "CRC32C digest algorithm not available "
53601+ "in kernel");
53602+ *val |= ~DIGEST_CRC32C;
53603+ }
53604+}
53605+
53606+/**
53607+ * initialize support for digest calculation.
53608+ *
53609+ * digest_init -
53610+ * @conn: ptr to connection to make use of digests
53611+ *
53612+ * @return: 0 on success, < 0 on error
53613+ */
53614+int digest_init(struct iscsi_conn *conn)
53615+{
53616+ if (!(conn->hdigest_type & DIGEST_ALL))
53617+ conn->hdigest_type = DIGEST_NONE;
53618+
53619+ if (!(conn->ddigest_type & DIGEST_ALL))
53620+ conn->ddigest_type = DIGEST_NONE;
53621+
53622+ return 0;
53623+}
53624+
53625+static __be32 evaluate_crc32_from_sg(struct scatterlist *sg, int nbytes,
53626+ uint32_t padding)
53627+{
53628+ u32 crc = ~0;
53629+ int pad_bytes = ((nbytes + 3) & -4) - nbytes;
53630+
53631+#ifdef CONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES
53632+ if (((scst_random() % 100000) == 752)) {
53633+ PRINT_INFO("%s", "Simulating digest failure");
53634+ return 0;
53635+ }
53636+#endif
53637+
53638+#if defined(CONFIG_LIBCRC32C_MODULE) || defined(CONFIG_LIBCRC32C)
53639+ while (nbytes > 0) {
53640+ int d = min(nbytes, (int)(sg->length));
53641+ crc = crc32c(crc, sg_virt(sg), d);
53642+ nbytes -= d;
53643+ sg++;
53644+ }
53645+
53646+ if (pad_bytes)
53647+ crc = crc32c(crc, (u8 *)&padding, pad_bytes);
53648+#endif
53649+
53650+ return (__force __be32)~cpu_to_le32(crc);
53651+}
53652+
53653+static __be32 digest_header(struct iscsi_pdu *pdu)
53654+{
53655+ struct scatterlist sg[2];
53656+ unsigned int nbytes = sizeof(struct iscsi_hdr);
53657+ int asize = (pdu->ahssize + 3) & -4;
53658+
53659+ sg_init_table(sg, 2);
53660+
53661+ sg_set_buf(&sg[0], &pdu->bhs, nbytes);
53662+ if (pdu->ahssize) {
53663+ sg_set_buf(&sg[1], pdu->ahs, asize);
53664+ nbytes += asize;
53665+ }
53666+ EXTRACHECKS_BUG_ON((nbytes & 3) != 0);
53667+ return evaluate_crc32_from_sg(sg, nbytes, 0);
53668+}
53669+
53670+static __be32 digest_data(struct iscsi_cmnd *cmd, u32 size, u32 offset,
53671+ uint32_t padding)
53672+{
53673+ struct scatterlist *sg = cmd->sg;
53674+ int idx, count;
53675+ struct scatterlist saved_sg;
53676+ __be32 crc;
53677+
53678+ offset += sg[0].offset;
53679+ idx = offset >> PAGE_SHIFT;
53680+ offset &= ~PAGE_MASK;
53681+
53682+ count = get_pgcnt(size, offset);
53683+
53684+ TRACE_DBG("req %p, idx %d, count %d, sg_cnt %d, size %d, "
53685+ "offset %d", cmd, idx, count, cmd->sg_cnt, size, offset);
53686+ BUG_ON(idx + count > cmd->sg_cnt);
53687+
53688+ saved_sg = sg[idx];
53689+ sg[idx].offset = offset;
53690+ sg[idx].length -= offset - saved_sg.offset;
53691+
53692+ crc = evaluate_crc32_from_sg(sg + idx, size, padding);
53693+
53694+ sg[idx] = saved_sg;
53695+ return crc;
53696+}
53697+
53698+int digest_rx_header(struct iscsi_cmnd *cmnd)
53699+{
53700+ __be32 crc;
53701+
53702+ crc = digest_header(&cmnd->pdu);
53703+ if (unlikely(crc != cmnd->hdigest)) {
53704+ PRINT_ERROR("%s", "RX header digest failed");
53705+ return -EIO;
53706+ } else
53707+ TRACE_DBG("RX header digest OK for cmd %p", cmnd);
53708+
53709+ return 0;
53710+}
53711+
53712+void digest_tx_header(struct iscsi_cmnd *cmnd)
53713+{
53714+ cmnd->hdigest = digest_header(&cmnd->pdu);
53715+ TRACE_DBG("TX header digest for cmd %p: %x", cmnd, cmnd->hdigest);
53716+}
53717+
53718+int digest_rx_data(struct iscsi_cmnd *cmnd)
53719+{
53720+ struct iscsi_cmnd *req;
53721+ struct iscsi_data_out_hdr *req_hdr;
53722+ u32 offset;
53723+ __be32 crc;
53724+ int res = 0;
53725+
53726+ switch (cmnd_opcode(cmnd)) {
53727+ case ISCSI_OP_SCSI_DATA_OUT:
53728+ req = cmnd->cmd_req;
53729+ if (unlikely(req == NULL)) {
53730+ /* It can be for prelim completed commands */
53731+ req = cmnd;
53732+ goto out;
53733+ }
53734+ req_hdr = (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs;
53735+ offset = be32_to_cpu(req_hdr->buffer_offset);
53736+ break;
53737+
53738+ default:
53739+ req = cmnd;
53740+ offset = 0;
53741+ }
53742+
53743+ /*
53744+ * We need to skip the digest check for prelim completed commands,
53745+ * because we use shared data buffer for them, so, most likely, the
53746+ * check will fail. Plus, for such commands we sometimes don't have
53747+ * sg_cnt set correctly (cmnd_prepare_get_rejected_cmd_data() doesn't
53748+ * do it).
53749+ */
53750+ if (unlikely(req->prelim_compl_flags != 0))
53751+ goto out;
53752+
53753+ /*
53754+ * Temporary to not crash with write residual overflows. ToDo. Until
53755+ * that let's always have succeeded data digests for such overflows.
53756+ * In ideal, we should allocate additional one or more sg's for the
53757+ * overflowed data and free them here or on req release. It's quite
53758+ * not trivial for such virtually never used case, so let's do it,
53759+ * when it gets needed.
53760+ */
53761+ if (unlikely(offset + cmnd->pdu.datasize > req->bufflen)) {
53762+ PRINT_WARNING("Skipping RX data digest check for residual "
53763+ "overflow command op %x (data size %d, buffer size %d)",
53764+ cmnd_hdr(req)->scb[0], offset + cmnd->pdu.datasize,
53765+ req->bufflen);
53766+ goto out;
53767+ }
53768+
53769+ crc = digest_data(req, cmnd->pdu.datasize, offset,
53770+ cmnd->conn->rpadding);
53771+
53772+ if (unlikely(crc != cmnd->ddigest)) {
53773+ TRACE(TRACE_MINOR|TRACE_MGMT_DEBUG, "%s", "RX data digest "
53774+ "failed");
53775+ TRACE_MGMT_DBG("Calculated crc %x, ddigest %x, offset %d", crc,
53776+ cmnd->ddigest, offset);
53777+ iscsi_dump_pdu(&cmnd->pdu);
53778+ res = -EIO;
53779+ } else
53780+ TRACE_DBG("RX data digest OK for cmd %p", cmnd);
53781+
53782+out:
53783+ return res;
53784+}
53785+
53786+void digest_tx_data(struct iscsi_cmnd *cmnd)
53787+{
53788+ struct iscsi_data_in_hdr *hdr;
53789+ u32 offset;
53790+
53791+ TRACE_DBG("%s:%d req %p, own_sg %d, sg %p, sgcnt %d cmnd %p, "
53792+ "own_sg %d, sg %p, sgcnt %d", __func__, __LINE__,
53793+ cmnd->parent_req, cmnd->parent_req->own_sg,
53794+ cmnd->parent_req->sg, cmnd->parent_req->sg_cnt,
53795+ cmnd, cmnd->own_sg, cmnd->sg, cmnd->sg_cnt);
53796+
53797+ switch (cmnd_opcode(cmnd)) {
53798+ case ISCSI_OP_SCSI_DATA_IN:
53799+ hdr = (struct iscsi_data_in_hdr *)&cmnd->pdu.bhs;
53800+ offset = be32_to_cpu(hdr->buffer_offset);
53801+ break;
53802+ default:
53803+ offset = 0;
53804+ }
53805+
53806+ cmnd->ddigest = digest_data(cmnd, cmnd->pdu.datasize, offset, 0);
53807+ TRACE_DBG("TX data digest for cmd %p: %x (offset %d, opcode %x)", cmnd,
53808+ cmnd->ddigest, offset, cmnd_opcode(cmnd));
53809+}
53810diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/digest.h linux-2.6.35/drivers/scst/iscsi-scst/digest.h
53811--- orig/linux-2.6.35/drivers/scst/iscsi-scst/digest.h
53812+++ linux-2.6.35/drivers/scst/iscsi-scst/digest.h
53813@@ -0,0 +1,31 @@
53814+/*
53815+ * iSCSI digest handling.
53816+ *
53817+ * Copyright (C) 2004 Xiranet Communications GmbH <arne.redlich@xiranet.com>
53818+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
53819+ * Copyright (C) 2007 - 2010 ID7 Ltd.
53820+ *
53821+ * This program is free software; you can redistribute it and/or
53822+ * modify it under the terms of the GNU General Public License
53823+ * as published by the Free Software Foundation.
53824+ *
53825+ * This program is distributed in the hope that it will be useful,
53826+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
53827+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53828+ * GNU General Public License for more details.
53829+ */
53830+
53831+#ifndef __ISCSI_DIGEST_H__
53832+#define __ISCSI_DIGEST_H__
53833+
53834+extern void digest_alg_available(int *val);
53835+
53836+extern int digest_init(struct iscsi_conn *conn);
53837+
53838+extern int digest_rx_header(struct iscsi_cmnd *cmnd);
53839+extern int digest_rx_data(struct iscsi_cmnd *cmnd);
53840+
53841+extern void digest_tx_header(struct iscsi_cmnd *cmnd);
53842+extern void digest_tx_data(struct iscsi_cmnd *cmnd);
53843+
53844+#endif /* __ISCSI_DIGEST_H__ */
53845diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/event.c linux-2.6.35/drivers/scst/iscsi-scst/event.c
53846--- orig/linux-2.6.35/drivers/scst/iscsi-scst/event.c
53847+++ linux-2.6.35/drivers/scst/iscsi-scst/event.c
53848@@ -0,0 +1,165 @@
53849+/*
53850+ * Event notification code.
53851+ *
53852+ * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org>
53853+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
53854+ * Copyright (C) 2007 - 2010 ID7 Ltd.
53855+ *
53856+ * This program is free software; you can redistribute it and/or
53857+ * modify it under the terms of the GNU General Public License
53858+ * as published by the Free Software Foundation.
53859+ *
53860+ * This program is distributed in the hope that it will be useful,
53861+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
53862+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53863+ * GNU General Public License for more details.
53864+ *
53865+ */
53866+
53867+#include <net/tcp.h>
53868+#include <scst/iscsi_scst.h>
53869+#include "iscsi.h"
53870+
53871+static struct sock *nl;
53872+static u32 iscsid_pid;
53873+
53874+static int event_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
53875+{
53876+ u32 uid, pid, seq;
53877+ char *data;
53878+
53879+ pid = NETLINK_CREDS(skb)->pid;
53880+ uid = NETLINK_CREDS(skb)->uid;
53881+ seq = nlh->nlmsg_seq;
53882+ data = NLMSG_DATA(nlh);
53883+
53884+ iscsid_pid = pid;
53885+
53886+ return 0;
53887+}
53888+
53889+static void event_recv_skb(struct sk_buff *skb)
53890+{
53891+ int err;
53892+ struct nlmsghdr *nlh;
53893+ u32 rlen;
53894+
53895+ while (skb->len >= NLMSG_SPACE(0)) {
53896+ nlh = (struct nlmsghdr *)skb->data;
53897+ if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
53898+ goto out;
53899+ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
53900+ if (rlen > skb->len)
53901+ rlen = skb->len;
53902+ err = event_recv_msg(skb, nlh);
53903+ if (err)
53904+ netlink_ack(skb, nlh, -err);
53905+ else if (nlh->nlmsg_flags & NLM_F_ACK)
53906+ netlink_ack(skb, nlh, 0);
53907+ skb_pull(skb, rlen);
53908+ }
53909+
53910+out:
53911+ return;
53912+}
53913+
53914+/* event_mutex supposed to be held */
53915+static int __event_send(const void *buf, int buf_len)
53916+{
53917+ int res = 0, len;
53918+ struct sk_buff *skb;
53919+ struct nlmsghdr *nlh;
53920+ static u32 seq; /* protected by event_mutex */
53921+
53922+ TRACE_ENTRY();
53923+
53924+ if (ctr_open_state != ISCSI_CTR_OPEN_STATE_OPEN)
53925+ goto out;
53926+
53927+ len = NLMSG_SPACE(buf_len);
53928+
53929+ skb = alloc_skb(NLMSG_SPACE(len), GFP_KERNEL);
53930+ if (skb == NULL) {
53931+ PRINT_ERROR("alloc_skb() failed (len %d)", len);
53932+ res = -ENOMEM;
53933+ goto out;
53934+ }
53935+
53936+ nlh = __nlmsg_put(skb, iscsid_pid, seq++, NLMSG_DONE,
53937+ len - sizeof(*nlh), 0);
53938+
53939+ memcpy(NLMSG_DATA(nlh), buf, buf_len);
53940+ res = netlink_unicast(nl, skb, iscsid_pid, 0);
53941+ if (res <= 0) {
53942+ if (res != -ECONNREFUSED)
53943+ PRINT_ERROR("netlink_unicast() failed: %d", res);
53944+ else
53945+ TRACE(TRACE_MINOR, "netlink_unicast() failed: %s. "
53946+ "Not functioning user space?",
53947+ "Connection refused");
53948+ goto out;
53949+ }
53950+
53951+out:
53952+ TRACE_EXIT_RES(res);
53953+ return res;
53954+}
53955+
53956+int event_send(u32 tid, u64 sid, u32 cid, u32 cookie,
53957+ enum iscsi_kern_event_code code,
53958+ const char *param1, const char *param2)
53959+{
53960+ int err;
53961+ static DEFINE_MUTEX(event_mutex);
53962+ struct iscsi_kern_event event;
53963+ int param1_size, param2_size;
53964+
53965+ param1_size = (param1 != NULL) ? strlen(param1) : 0;
53966+ param2_size = (param2 != NULL) ? strlen(param2) : 0;
53967+
53968+ event.tid = tid;
53969+ event.sid = sid;
53970+ event.cid = cid;
53971+ event.code = code;
53972+ event.cookie = cookie;
53973+ event.param1_size = param1_size;
53974+ event.param2_size = param2_size;
53975+
53976+ mutex_lock(&event_mutex);
53977+
53978+ err = __event_send(&event, sizeof(event));
53979+ if (err <= 0)
53980+ goto out_unlock;
53981+
53982+ if (param1_size > 0) {
53983+ err = __event_send(param1, param1_size);
53984+ if (err <= 0)
53985+ goto out_unlock;
53986+ }
53987+
53988+ if (param2_size > 0) {
53989+ err = __event_send(param2, param2_size);
53990+ if (err <= 0)
53991+ goto out_unlock;
53992+ }
53993+
53994+out_unlock:
53995+ mutex_unlock(&event_mutex);
53996+ return err;
53997+}
53998+
53999+int __init event_init(void)
54000+{
54001+ nl = netlink_kernel_create(&init_net, NETLINK_ISCSI_SCST, 1,
54002+ event_recv_skb, NULL, THIS_MODULE);
54003+ if (!nl) {
54004+ PRINT_ERROR("%s", "netlink_kernel_create() failed");
54005+ return -ENOMEM;
54006+ } else
54007+ return 0;
54008+}
54009+
54010+void event_exit(void)
54011+{
54012+ netlink_kernel_release(nl);
54013+}
54014diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/iscsi.c linux-2.6.35/drivers/scst/iscsi-scst/iscsi.c
54015--- orig/linux-2.6.35/drivers/scst/iscsi-scst/iscsi.c
54016+++ linux-2.6.35/drivers/scst/iscsi-scst/iscsi.c
54017@@ -0,0 +1,3956 @@
54018+/*
54019+ * Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
54020+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
54021+ * Copyright (C) 2007 - 2010 ID7 Ltd.
54022+ *
54023+ * This program is free software; you can redistribute it and/or
54024+ * modify it under the terms of the GNU General Public License
54025+ * as published by the Free Software Foundation, version 2
54026+ * of the License.
54027+ *
54028+ * This program is distributed in the hope that it will be useful,
54029+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
54030+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54031+ * GNU General Public License for more details.
54032+ */
54033+
54034+#include <linux/module.h>
54035+#include <linux/hash.h>
54036+#include <linux/kthread.h>
54037+#include <linux/scatterlist.h>
54038+#include <linux/ctype.h>
54039+#include <net/tcp.h>
54040+#include <scsi/scsi.h>
54041+#include <asm/byteorder.h>
54042+#include <asm/unaligned.h>
54043+
54044+#include "iscsi.h"
54045+#include "digest.h"
54046+
54047+#ifndef GENERATING_UPSTREAM_PATCH
54048+#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
54049+#warning "Patch put_page_callback-<kernel-version>.patch not applied on your\
54050+ kernel or CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION\
54051+ config option not set. ISCSI-SCST will be working with not the best\
54052+ performance. Refer README file for details."
54053+#endif
54054+#endif
54055+
54056+#define ISCSI_INIT_WRITE_WAKE 0x1
54057+
54058+static int ctr_major;
54059+static char ctr_name[] = "iscsi-scst-ctl";
54060+
54061+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
54062+unsigned long iscsi_trace_flag = ISCSI_DEFAULT_LOG_FLAGS;
54063+#endif
54064+
54065+static struct kmem_cache *iscsi_cmnd_cache;
54066+
54067+DEFINE_SPINLOCK(iscsi_rd_lock);
54068+LIST_HEAD(iscsi_rd_list);
54069+DECLARE_WAIT_QUEUE_HEAD(iscsi_rd_waitQ);
54070+
54071+DEFINE_SPINLOCK(iscsi_wr_lock);
54072+LIST_HEAD(iscsi_wr_list);
54073+DECLARE_WAIT_QUEUE_HEAD(iscsi_wr_waitQ);
54074+
54075+static struct page *dummy_page;
54076+static struct scatterlist dummy_sg;
54077+
54078+struct iscsi_thread_t {
54079+ struct task_struct *thr;
54080+ struct list_head threads_list_entry;
54081+};
54082+
54083+static LIST_HEAD(iscsi_threads_list);
54084+
54085+static void cmnd_remove_data_wait_hash(struct iscsi_cmnd *cmnd);
54086+static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status);
54087+static void iscsi_check_send_delayed_tm_resp(struct iscsi_session *sess);
54088+static void req_cmnd_release(struct iscsi_cmnd *req);
54089+static int cmnd_insert_data_wait_hash(struct iscsi_cmnd *cmnd);
54090+static void __cmnd_abort(struct iscsi_cmnd *cmnd);
54091+static void iscsi_cmnd_init_write(struct iscsi_cmnd *rsp, int flags);
54092+static void iscsi_set_resid_no_scst_cmd(struct iscsi_cmnd *rsp);
54093+static void iscsi_set_resid(struct iscsi_cmnd *rsp);
54094+
54095+static void iscsi_set_not_received_data_len(struct iscsi_cmnd *req,
54096+ unsigned int not_received)
54097+{
54098+ req->not_received_data_len = not_received;
54099+ if (req->scst_cmd != NULL)
54100+ scst_cmd_set_write_not_received_data_len(req->scst_cmd,
54101+ not_received);
54102+ return;
54103+}
54104+
54105+static void req_del_from_write_timeout_list(struct iscsi_cmnd *req)
54106+{
54107+ struct iscsi_conn *conn;
54108+
54109+ TRACE_ENTRY();
54110+
54111+ if (!req->on_write_timeout_list)
54112+ goto out;
54113+
54114+ conn = req->conn;
54115+
54116+ TRACE_DBG("Deleting cmd %p from conn %p write_timeout_list",
54117+ req, conn);
54118+
54119+ spin_lock_bh(&conn->write_list_lock);
54120+
54121+ /* Recheck, since it can be changed behind us */
54122+ if (unlikely(!req->on_write_timeout_list))
54123+ goto out_unlock;
54124+
54125+ list_del(&req->write_timeout_list_entry);
54126+ req->on_write_timeout_list = 0;
54127+
54128+out_unlock:
54129+ spin_unlock_bh(&conn->write_list_lock);
54130+
54131+out:
54132+ TRACE_EXIT();
54133+ return;
54134+}
54135+
54136+static inline u32 cmnd_write_size(struct iscsi_cmnd *cmnd)
54137+{
54138+ struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd);
54139+
54140+ if (hdr->flags & ISCSI_CMD_WRITE)
54141+ return be32_to_cpu(hdr->data_length);
54142+ return 0;
54143+}
54144+
54145+static inline int cmnd_read_size(struct iscsi_cmnd *cmnd)
54146+{
54147+ struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd);
54148+
54149+ if (hdr->flags & ISCSI_CMD_READ) {
54150+ struct iscsi_ahs_hdr *ahdr;
54151+
54152+ if (!(hdr->flags & ISCSI_CMD_WRITE))
54153+ return be32_to_cpu(hdr->data_length);
54154+
54155+ ahdr = (struct iscsi_ahs_hdr *)cmnd->pdu.ahs;
54156+ if (ahdr != NULL) {
54157+ uint8_t *p = (uint8_t *)ahdr;
54158+ unsigned int size = 0;
54159+ do {
54160+ int s;
54161+
54162+ ahdr = (struct iscsi_ahs_hdr *)p;
54163+
54164+ if (ahdr->ahstype == ISCSI_AHSTYPE_RLENGTH) {
54165+ struct iscsi_rlength_ahdr *rh =
54166+ (struct iscsi_rlength_ahdr *)ahdr;
54167+ return be32_to_cpu(rh->read_length);
54168+ }
54169+
54170+ s = 3 + be16_to_cpu(ahdr->ahslength);
54171+ s = (s + 3) & -4;
54172+ size += s;
54173+ p += s;
54174+ } while (size < cmnd->pdu.ahssize);
54175+ }
54176+ return -1;
54177+ }
54178+ return 0;
54179+}
54180+
54181+void iscsi_restart_cmnd(struct iscsi_cmnd *cmnd)
54182+{
54183+ int status;
54184+
54185+ TRACE_ENTRY();
54186+
54187+ EXTRACHECKS_BUG_ON(cmnd->r2t_len_to_receive != 0);
54188+ EXTRACHECKS_BUG_ON(cmnd->r2t_len_to_send != 0);
54189+
54190+ req_del_from_write_timeout_list(cmnd);
54191+
54192+ /*
54193+ * Let's remove cmnd from the hash earlier to keep it smaller.
54194+ * Also we have to remove hashed req from the hash before sending
54195+ * response. Otherwise we can have a race, when for some reason cmd's
54196+ * release (and, hence, removal from the hash) is delayed after the
54197+ * transmission and initiator sends cmd with the same ITT, hence
54198+ * the new command will be erroneously rejected as a duplicate.
54199+ */
54200+ if (cmnd->hashed)
54201+ cmnd_remove_data_wait_hash(cmnd);
54202+
54203+ if (unlikely(test_bit(ISCSI_CONN_REINSTATING,
54204+ &cmnd->conn->conn_aflags))) {
54205+ struct iscsi_target *target = cmnd->conn->session->target;
54206+ bool get_out;
54207+
54208+ mutex_lock(&target->target_mutex);
54209+
54210+ get_out = test_bit(ISCSI_CONN_REINSTATING,
54211+ &cmnd->conn->conn_aflags);
54212+ /* Let's don't look dead */
54213+ if (scst_cmd_get_cdb(cmnd->scst_cmd)[0] == TEST_UNIT_READY)
54214+ get_out = false;
54215+
54216+ if (!get_out)
54217+ goto unlock_cont;
54218+
54219+ TRACE_MGMT_DBG("Pending cmnd %p, because conn %p is "
54220+ "reinstated", cmnd, cmnd->conn);
54221+
54222+ cmnd->scst_state = ISCSI_CMD_STATE_REINST_PENDING;
54223+ list_add_tail(&cmnd->reinst_pending_cmd_list_entry,
54224+ &cmnd->conn->reinst_pending_cmd_list);
54225+
54226+unlock_cont:
54227+ mutex_unlock(&target->target_mutex);
54228+
54229+ if (get_out)
54230+ goto out;
54231+ }
54232+
54233+ if (unlikely(cmnd->prelim_compl_flags != 0)) {
54234+ if (test_bit(ISCSI_CMD_ABORTED, &cmnd->prelim_compl_flags)) {
54235+ TRACE_MGMT_DBG("cmnd %p (scst_cmd %p) aborted", cmnd,
54236+ cmnd->scst_cmd);
54237+ req_cmnd_release_force(cmnd);
54238+ goto out;
54239+ }
54240+
54241+ if (cmnd->scst_cmd == NULL) {
54242+ TRACE_MGMT_DBG("Finishing preliminary completed cmd %p "
54243+ "with NULL scst_cmd", cmnd);
54244+ req_cmnd_release(cmnd);
54245+ goto out;
54246+ }
54247+
54248+ status = SCST_PREPROCESS_STATUS_ERROR_SENSE_SET;
54249+ } else
54250+ status = SCST_PREPROCESS_STATUS_SUCCESS;
54251+
54252+ cmnd->scst_state = ISCSI_CMD_STATE_RESTARTED;
54253+
54254+ scst_restart_cmd(cmnd->scst_cmd, status, SCST_CONTEXT_THREAD);
54255+
54256+out:
54257+ TRACE_EXIT();
54258+ return;
54259+}
54260+
54261+static struct iscsi_cmnd *iscsi_create_tm_clone(struct iscsi_cmnd *cmnd)
54262+{
54263+ struct iscsi_cmnd *tm_clone;
54264+
54265+ TRACE_ENTRY();
54266+
54267+ tm_clone = cmnd_alloc(cmnd->conn, NULL);
54268+ if (tm_clone != NULL) {
54269+ set_bit(ISCSI_CMD_ABORTED, &tm_clone->prelim_compl_flags);
54270+ tm_clone->pdu = cmnd->pdu;
54271+
54272+ TRACE_MGMT_DBG("TM clone %p for cmnd %p created",
54273+ tm_clone, cmnd);
54274+ } else
54275+ PRINT_ERROR("Failed to create TM clone for cmnd %p", cmnd);
54276+
54277+ TRACE_EXIT_HRES((unsigned long)tm_clone);
54278+ return tm_clone;
54279+}
54280+
54281+void iscsi_fail_data_waiting_cmnd(struct iscsi_cmnd *cmnd)
54282+{
54283+ TRACE_ENTRY();
54284+
54285+ TRACE_MGMT_DBG("Failing data waiting cmnd %p", cmnd);
54286+
54287+ /*
54288+ * There is no race with conn_abort(), since all functions
54289+ * called from single read thread
54290+ */
54291+ iscsi_extracheck_is_rd_thread(cmnd->conn);
54292+
54293+ /* This cmnd is going to die without response */
54294+ cmnd->r2t_len_to_receive = 0;
54295+ cmnd->r2t_len_to_send = 0;
54296+
54297+ if (cmnd->pending) {
54298+ struct iscsi_session *session = cmnd->conn->session;
54299+ struct iscsi_cmnd *tm_clone;
54300+
54301+ TRACE_MGMT_DBG("Unpending cmnd %p (sn %u, exp_cmd_sn %u)", cmnd,
54302+ cmnd->pdu.bhs.sn, session->exp_cmd_sn);
54303+
54304+ /*
54305+ * If cmnd is pending, then the next command, if any, must be
54306+ * pending too. So, just insert a clone instead of cmnd to
54307+ * fill the hole in SNs. Then we can release cmnd.
54308+ */
54309+
54310+ tm_clone = iscsi_create_tm_clone(cmnd);
54311+
54312+ spin_lock(&session->sn_lock);
54313+
54314+ if (tm_clone != NULL) {
54315+ TRACE_MGMT_DBG("Adding tm_clone %p after its cmnd",
54316+ tm_clone);
54317+ list_add(&tm_clone->pending_list_entry,
54318+ &cmnd->pending_list_entry);
54319+ }
54320+
54321+ list_del(&cmnd->pending_list_entry);
54322+ cmnd->pending = 0;
54323+
54324+ spin_unlock(&session->sn_lock);
54325+ }
54326+
54327+ req_cmnd_release_force(cmnd);
54328+
54329+ TRACE_EXIT();
54330+ return;
54331+}
54332+
54333+struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *conn,
54334+ struct iscsi_cmnd *parent)
54335+{
54336+ struct iscsi_cmnd *cmnd;
54337+
54338+ /* ToDo: __GFP_NOFAIL?? */
54339+ cmnd = kmem_cache_zalloc(iscsi_cmnd_cache, GFP_KERNEL|__GFP_NOFAIL);
54340+
54341+ atomic_set(&cmnd->ref_cnt, 1);
54342+ cmnd->scst_state = ISCSI_CMD_STATE_NEW;
54343+ cmnd->conn = conn;
54344+ cmnd->parent_req = parent;
54345+
54346+ if (parent == NULL) {
54347+ conn_get(conn);
54348+
54349+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
54350+ atomic_set(&cmnd->net_ref_cnt, 0);
54351+#endif
54352+ INIT_LIST_HEAD(&cmnd->rsp_cmd_list);
54353+ INIT_LIST_HEAD(&cmnd->rx_ddigest_cmd_list);
54354+ cmnd->target_task_tag = ISCSI_RESERVED_TAG_CPU32;
54355+
54356+ spin_lock_bh(&conn->cmd_list_lock);
54357+ list_add_tail(&cmnd->cmd_list_entry, &conn->cmd_list);
54358+ spin_unlock_bh(&conn->cmd_list_lock);
54359+ }
54360+
54361+ TRACE_DBG("conn %p, parent %p, cmnd %p", conn, parent, cmnd);
54362+ return cmnd;
54363+}
54364+
54365+/* Frees a command. Also frees the additional header. */
54366+static void cmnd_free(struct iscsi_cmnd *cmnd)
54367+{
54368+ TRACE_ENTRY();
54369+
54370+ TRACE_DBG("cmnd %p", cmnd);
54371+
54372+ if (unlikely(test_bit(ISCSI_CMD_ABORTED, &cmnd->prelim_compl_flags))) {
54373+ TRACE_MGMT_DBG("Free aborted cmd %p (scst cmd %p, state %d, "
54374+ "parent_req %p)", cmnd, cmnd->scst_cmd,
54375+ cmnd->scst_state, cmnd->parent_req);
54376+ }
54377+
54378+ /* Catch users from cmd_list or rsp_cmd_list */
54379+ EXTRACHECKS_BUG_ON(atomic_read(&cmnd->ref_cnt) != 0);
54380+
54381+ kfree(cmnd->pdu.ahs);
54382+
54383+#ifdef CONFIG_SCST_EXTRACHECKS
54384+ if (unlikely(cmnd->on_write_list || cmnd->on_write_timeout_list)) {
54385+ struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);
54386+
54387+ PRINT_CRIT_ERROR("cmnd %p still on some list?, %x, %x, %x, "
54388+ "%x, %x, %x, %x", cmnd, req->opcode, req->scb[0],
54389+ req->flags, req->itt, be32_to_cpu(req->data_length),
54390+ req->cmd_sn, be32_to_cpu((__force __be32)(cmnd->pdu.datasize)));
54391+
54392+ if (unlikely(cmnd->parent_req)) {
54393+ struct iscsi_scsi_cmd_hdr *preq =
54394+ cmnd_hdr(cmnd->parent_req);
54395+ PRINT_CRIT_ERROR("%p %x %u", preq, preq->opcode,
54396+ preq->scb[0]);
54397+ }
54398+ BUG();
54399+ }
54400+#endif
54401+
54402+ kmem_cache_free(iscsi_cmnd_cache, cmnd);
54403+
54404+ TRACE_EXIT();
54405+ return;
54406+}
54407+
54408+static void iscsi_dec_active_cmds(struct iscsi_cmnd *req)
54409+{
54410+ struct iscsi_session *sess = req->conn->session;
54411+
54412+ TRACE_DBG("Decrementing active_cmds (req %p, sess %p, "
54413+ "new value %d)", req, sess,
54414+ atomic_read(&sess->active_cmds)-1);
54415+
54416+ EXTRACHECKS_BUG_ON(!req->dec_active_cmds);
54417+
54418+ atomic_dec(&sess->active_cmds);
54419+ smp_mb__after_atomic_dec();
54420+ req->dec_active_cmds = 0;
54421+#ifdef CONFIG_SCST_EXTRACHECKS
54422+ if (unlikely(atomic_read(&sess->active_cmds) < 0)) {
54423+ PRINT_CRIT_ERROR("active_cmds < 0 (%d)!!",
54424+ atomic_read(&sess->active_cmds));
54425+ BUG();
54426+ }
54427+#endif
54428+ return;
54429+}
54430+
54431+/* Might be called under some lock and on SIRQ */
54432+void cmnd_done(struct iscsi_cmnd *cmnd)
54433+{
54434+ TRACE_ENTRY();
54435+
54436+ TRACE_DBG("cmnd %p", cmnd);
54437+
54438+ if (unlikely(test_bit(ISCSI_CMD_ABORTED, &cmnd->prelim_compl_flags))) {
54439+ TRACE_MGMT_DBG("Done aborted cmd %p (scst cmd %p, state %d, "
54440+ "parent_req %p)", cmnd, cmnd->scst_cmd,
54441+ cmnd->scst_state, cmnd->parent_req);
54442+ }
54443+
54444+ EXTRACHECKS_BUG_ON(cmnd->on_rx_digest_list);
54445+ EXTRACHECKS_BUG_ON(cmnd->hashed);
54446+
54447+ req_del_from_write_timeout_list(cmnd);
54448+
54449+ if (cmnd->parent_req == NULL) {
54450+ struct iscsi_conn *conn = cmnd->conn;
54451+ struct iscsi_cmnd *rsp, *t;
54452+
54453+ TRACE_DBG("Deleting req %p from conn %p", cmnd, conn);
54454+
54455+ spin_lock_bh(&conn->cmd_list_lock);
54456+ list_del(&cmnd->cmd_list_entry);
54457+ spin_unlock_bh(&conn->cmd_list_lock);
54458+
54459+ conn_put(conn);
54460+
54461+ EXTRACHECKS_BUG_ON(!list_empty(&cmnd->rx_ddigest_cmd_list));
54462+
54463+ /* Order between above and below code is important! */
54464+
54465+ if ((cmnd->scst_cmd != NULL) || (cmnd->scst_aen != NULL)) {
54466+ switch (cmnd->scst_state) {
54467+ case ISCSI_CMD_STATE_PROCESSED:
54468+ TRACE_DBG("cmd %p PROCESSED", cmnd);
54469+ scst_tgt_cmd_done(cmnd->scst_cmd,
54470+ SCST_CONTEXT_DIRECT_ATOMIC);
54471+ break;
54472+
54473+ case ISCSI_CMD_STATE_AFTER_PREPROC:
54474+ {
54475+ /* It can be for some aborted commands */
54476+ struct scst_cmd *scst_cmd = cmnd->scst_cmd;
54477+ TRACE_DBG("cmd %p AFTER_PREPROC", cmnd);
54478+ cmnd->scst_state = ISCSI_CMD_STATE_RESTARTED;
54479+ cmnd->scst_cmd = NULL;
54480+ scst_restart_cmd(scst_cmd,
54481+ SCST_PREPROCESS_STATUS_ERROR_FATAL,
54482+ SCST_CONTEXT_THREAD);
54483+ break;
54484+ }
54485+
54486+ case ISCSI_CMD_STATE_AEN:
54487+ TRACE_DBG("cmd %p AEN PROCESSED", cmnd);
54488+ scst_aen_done(cmnd->scst_aen);
54489+ break;
54490+
54491+ case ISCSI_CMD_STATE_OUT_OF_SCST_PRELIM_COMPL:
54492+ break;
54493+
54494+ default:
54495+ PRINT_CRIT_ERROR("Unexpected cmnd scst state "
54496+ "%d", cmnd->scst_state);
54497+ BUG();
54498+ break;
54499+ }
54500+ }
54501+
54502+ if (cmnd->own_sg) {
54503+ TRACE_DBG("own_sg for req %p", cmnd);
54504+ if (cmnd->sg != &dummy_sg)
54505+ scst_free(cmnd->sg, cmnd->sg_cnt);
54506+#ifdef CONFIG_SCST_DEBUG
54507+ cmnd->own_sg = 0;
54508+ cmnd->sg = NULL;
54509+ cmnd->sg_cnt = -1;
54510+#endif
54511+ }
54512+
54513+ if (unlikely(cmnd->dec_active_cmds))
54514+ iscsi_dec_active_cmds(cmnd);
54515+
54516+ list_for_each_entry_safe(rsp, t, &cmnd->rsp_cmd_list,
54517+ rsp_cmd_list_entry) {
54518+ cmnd_free(rsp);
54519+ }
54520+
54521+ cmnd_free(cmnd);
54522+ } else {
54523+ struct iscsi_cmnd *parent = cmnd->parent_req;
54524+
54525+ if (cmnd->own_sg) {
54526+ TRACE_DBG("own_sg for rsp %p", cmnd);
54527+ if ((cmnd->sg != &dummy_sg) && (cmnd->sg != cmnd->rsp_sg))
54528+ scst_free(cmnd->sg, cmnd->sg_cnt);
54529+#ifdef CONFIG_SCST_DEBUG
54530+ cmnd->own_sg = 0;
54531+ cmnd->sg = NULL;
54532+ cmnd->sg_cnt = -1;
54533+#endif
54534+ }
54535+
54536+ EXTRACHECKS_BUG_ON(cmnd->dec_active_cmds);
54537+
54538+ if (cmnd == parent->main_rsp) {
54539+ TRACE_DBG("Finishing main rsp %p (req %p)", cmnd,
54540+ parent);
54541+ parent->main_rsp = NULL;
54542+ }
54543+
54544+ cmnd_put(parent);
54545+ /*
54546+ * cmnd will be freed on the last parent's put and can already
54547+ * be freed!!
54548+ */
54549+ }
54550+
54551+ TRACE_EXIT();
54552+ return;
54553+}
54554+
54555+/*
54556+ * Corresponding conn may also get destroyed after this function, except only
54557+ * if it's called from the read thread!
54558+ *
54559+ * It can't be called in parallel with iscsi_cmnds_init_write()!
54560+ */
54561+void req_cmnd_release_force(struct iscsi_cmnd *req)
54562+{
54563+ struct iscsi_cmnd *rsp, *t;
54564+ struct iscsi_conn *conn = req->conn;
54565+ LIST_HEAD(cmds_list);
54566+
54567+ TRACE_ENTRY();
54568+
54569+ TRACE_MGMT_DBG("req %p", req);
54570+
54571+ BUG_ON(req == conn->read_cmnd);
54572+
54573+ spin_lock_bh(&conn->write_list_lock);
54574+ list_for_each_entry_safe(rsp, t, &conn->write_list, write_list_entry) {
54575+ if (rsp->parent_req != req)
54576+ continue;
54577+
54578+ cmd_del_from_write_list(rsp);
54579+
54580+ list_add_tail(&rsp->write_list_entry, &cmds_list);
54581+ }
54582+ spin_unlock_bh(&conn->write_list_lock);
54583+
54584+ list_for_each_entry_safe(rsp, t, &cmds_list, write_list_entry) {
54585+ TRACE_MGMT_DBG("Putting write rsp %p", rsp);
54586+ list_del(&rsp->write_list_entry);
54587+ cmnd_put(rsp);
54588+ }
54589+
54590+ /* Supposed nobody can add responses in the list anymore */
54591+ list_for_each_entry_reverse(rsp, &req->rsp_cmd_list,
54592+ rsp_cmd_list_entry) {
54593+ bool r;
54594+
54595+ if (rsp->force_cleanup_done)
54596+ continue;
54597+
54598+ rsp->force_cleanup_done = 1;
54599+
54600+ if (cmnd_get_check(rsp))
54601+ continue;
54602+
54603+ spin_lock_bh(&conn->write_list_lock);
54604+ r = rsp->on_write_list || rsp->write_processing_started;
54605+ spin_unlock_bh(&conn->write_list_lock);
54606+
54607+ cmnd_put(rsp);
54608+
54609+ if (r)
54610+ continue;
54611+
54612+ /*
54613+ * If both on_write_list and write_processing_started not set,
54614+ * we can safely put() rsp.
54615+ */
54616+ TRACE_MGMT_DBG("Putting rsp %p", rsp);
54617+ cmnd_put(rsp);
54618+ }
54619+
54620+ if (req->main_rsp != NULL) {
54621+ TRACE_MGMT_DBG("Putting main rsp %p", req->main_rsp);
54622+ cmnd_put(req->main_rsp);
54623+ req->main_rsp = NULL;
54624+ }
54625+
54626+ req_cmnd_release(req);
54627+
54628+ TRACE_EXIT();
54629+ return;
54630+}
54631+
54632+static void req_cmnd_pre_release(struct iscsi_cmnd *req)
54633+{
54634+ struct iscsi_cmnd *c, *t;
54635+
54636+ TRACE_ENTRY();
54637+
54638+ TRACE_DBG("req %p", req);
54639+
54640+#ifdef CONFIG_SCST_EXTRACHECKS
54641+ BUG_ON(req->release_called);
54642+ req->release_called = 1;
54643+#endif
54644+
54645+ if (unlikely(test_bit(ISCSI_CMD_ABORTED, &req->prelim_compl_flags))) {
54646+ TRACE_MGMT_DBG("Release aborted req cmd %p (scst cmd %p, "
54647+ "state %d)", req, req->scst_cmd, req->scst_state);
54648+ }
54649+
54650+ BUG_ON(req->parent_req != NULL);
54651+
54652+ if (unlikely(req->hashed)) {
54653+ /* It sometimes can happen during errors recovery */
54654+ cmnd_remove_data_wait_hash(req);
54655+ }
54656+
54657+ if (unlikely(req->main_rsp != NULL)) {
54658+ TRACE_DBG("Sending main rsp %p", req->main_rsp);
54659+ if (cmnd_opcode(req) == ISCSI_OP_SCSI_CMD) {
54660+ if (req->scst_cmd != NULL)
54661+ iscsi_set_resid(req->main_rsp);
54662+ else
54663+ iscsi_set_resid_no_scst_cmd(req->main_rsp);
54664+ }
54665+ iscsi_cmnd_init_write(req->main_rsp, ISCSI_INIT_WRITE_WAKE);
54666+ req->main_rsp = NULL;
54667+ }
54668+
54669+ list_for_each_entry_safe(c, t, &req->rx_ddigest_cmd_list,
54670+ rx_ddigest_cmd_list_entry) {
54671+ cmd_del_from_rx_ddigest_list(c);
54672+ cmnd_put(c);
54673+ }
54674+
54675+ EXTRACHECKS_BUG_ON(req->pending);
54676+
54677+ if (unlikely(req->dec_active_cmds))
54678+ iscsi_dec_active_cmds(req);
54679+
54680+ TRACE_EXIT();
54681+ return;
54682+}
54683+
54684+/*
54685+ * Corresponding conn may also get destroyed after this function, except only
54686+ * if it's called from the read thread!
54687+ */
54688+static void req_cmnd_release(struct iscsi_cmnd *req)
54689+{
54690+ TRACE_ENTRY();
54691+
54692+ req_cmnd_pre_release(req);
54693+ cmnd_put(req);
54694+
54695+ TRACE_EXIT();
54696+ return;
54697+}
54698+
54699+/*
54700+ * Corresponding conn may also get destroyed after this function, except only
54701+ * if it's called from the read thread!
54702+ */
54703+void rsp_cmnd_release(struct iscsi_cmnd *cmnd)
54704+{
54705+ TRACE_DBG("%p", cmnd);
54706+
54707+#ifdef CONFIG_SCST_EXTRACHECKS
54708+ BUG_ON(cmnd->release_called);
54709+ cmnd->release_called = 1;
54710+#endif
54711+
54712+ EXTRACHECKS_BUG_ON(cmnd->parent_req == NULL);
54713+
54714+ cmnd_put(cmnd);
54715+ return;
54716+}
54717+
54718+static struct iscsi_cmnd *iscsi_alloc_rsp(struct iscsi_cmnd *parent)
54719+{
54720+ struct iscsi_cmnd *rsp;
54721+
54722+ TRACE_ENTRY();
54723+
54724+ rsp = cmnd_alloc(parent->conn, parent);
54725+
54726+ TRACE_DBG("Adding rsp %p to parent %p", rsp, parent);
54727+ list_add_tail(&rsp->rsp_cmd_list_entry, &parent->rsp_cmd_list);
54728+
54729+ cmnd_get(parent);
54730+
54731+ TRACE_EXIT_HRES((unsigned long)rsp);
54732+ return rsp;
54733+}
54734+
54735+static inline struct iscsi_cmnd *iscsi_alloc_main_rsp(struct iscsi_cmnd *parent)
54736+{
54737+ struct iscsi_cmnd *rsp;
54738+
54739+ TRACE_ENTRY();
54740+
54741+ EXTRACHECKS_BUG_ON(parent->main_rsp != NULL);
54742+
54743+ rsp = iscsi_alloc_rsp(parent);
54744+ parent->main_rsp = rsp;
54745+
54746+ TRACE_EXIT_HRES((unsigned long)rsp);
54747+ return rsp;
54748+}
54749+
54750+static void iscsi_cmnds_init_write(struct list_head *send, int flags)
54751+{
54752+ struct iscsi_cmnd *rsp = list_entry(send->next, struct iscsi_cmnd,
54753+ write_list_entry);
54754+ struct iscsi_conn *conn = rsp->conn;
54755+ struct list_head *pos, *next;
54756+
54757+ BUG_ON(list_empty(send));
54758+
54759+ if (!(conn->ddigest_type & DIGEST_NONE)) {
54760+ list_for_each(pos, send) {
54761+ rsp = list_entry(pos, struct iscsi_cmnd,
54762+ write_list_entry);
54763+
54764+ if (rsp->pdu.datasize != 0) {
54765+ TRACE_DBG("Doing data digest (%p:%x)", rsp,
54766+ cmnd_opcode(rsp));
54767+ digest_tx_data(rsp);
54768+ }
54769+ }
54770+ }
54771+
54772+ spin_lock_bh(&conn->write_list_lock);
54773+ list_for_each_safe(pos, next, send) {
54774+ rsp = list_entry(pos, struct iscsi_cmnd, write_list_entry);
54775+
54776+ TRACE_DBG("%p:%x", rsp, cmnd_opcode(rsp));
54777+
54778+ BUG_ON(conn != rsp->conn);
54779+
54780+ list_del(&rsp->write_list_entry);
54781+ cmd_add_on_write_list(conn, rsp);
54782+ }
54783+ spin_unlock_bh(&conn->write_list_lock);
54784+
54785+ if (flags & ISCSI_INIT_WRITE_WAKE)
54786+ iscsi_make_conn_wr_active(conn);
54787+
54788+ return;
54789+}
54790+
54791+static void iscsi_cmnd_init_write(struct iscsi_cmnd *rsp, int flags)
54792+{
54793+ LIST_HEAD(head);
54794+
54795+#ifdef CONFIG_SCST_EXTRACHECKS
54796+ if (unlikely(rsp->on_write_list)) {
54797+ PRINT_CRIT_ERROR("cmd already on write list (%x %x %x "
54798+ "%u %u %d %d", rsp->pdu.bhs.itt,
54799+ cmnd_opcode(rsp), cmnd_scsicode(rsp),
54800+ rsp->hdigest, rsp->ddigest,
54801+ list_empty(&rsp->rsp_cmd_list), rsp->hashed);
54802+ BUG();
54803+ }
54804+#endif
54805+ list_add_tail(&rsp->write_list_entry, &head);
54806+ iscsi_cmnds_init_write(&head, flags);
54807+ return;
54808+}
54809+
54810+static void iscsi_set_resid_no_scst_cmd(struct iscsi_cmnd *rsp)
54811+{
54812+ struct iscsi_cmnd *req = rsp->parent_req;
54813+ struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req);
54814+ struct iscsi_scsi_rsp_hdr *rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs;
54815+ int resid, out_resid;
54816+
54817+ TRACE_ENTRY();
54818+
54819+ BUG_ON(req->scst_cmd != NULL);
54820+
54821+ TRACE_DBG("req %p, rsp %p, outstanding_r2t %d, r2t_len_to_receive %d, "
54822+ "r2t_len_to_send %d, not_received_data_len %d", req, rsp,
54823+ req->outstanding_r2t, req->r2t_len_to_receive,
54824+ req->r2t_len_to_send, req->not_received_data_len);
54825+
54826+ if ((req_hdr->flags & ISCSI_CMD_READ) &&
54827+ (req_hdr->flags & ISCSI_CMD_WRITE)) {
54828+ out_resid = req->not_received_data_len;
54829+ if (out_resid > 0) {
54830+ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
54831+ rsp_hdr->residual_count = cpu_to_be32(out_resid);
54832+ } else if (out_resid < 0) {
54833+ out_resid = -out_resid;
54834+ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_OVERFLOW;
54835+ rsp_hdr->residual_count = cpu_to_be32(out_resid);
54836+ }
54837+
54838+ resid = cmnd_read_size(req);
54839+ if (resid > 0) {
54840+ rsp_hdr->flags |= ISCSI_FLG_BIRESIDUAL_UNDERFLOW;
54841+ rsp_hdr->bi_residual_count = cpu_to_be32(resid);
54842+ } else if (resid < 0) {
54843+ resid = -resid;
54844+ rsp_hdr->flags |= ISCSI_FLG_BIRESIDUAL_OVERFLOW;
54845+ rsp_hdr->bi_residual_count = cpu_to_be32(resid);
54846+ }
54847+ } else if (req_hdr->flags & ISCSI_CMD_READ) {
54848+ resid = be32_to_cpu(req_hdr->data_length);
54849+ if (resid > 0) {
54850+ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
54851+ rsp_hdr->residual_count = cpu_to_be32(resid);
54852+ }
54853+ } else if (req_hdr->flags & ISCSI_CMD_WRITE) {
54854+ resid = req->not_received_data_len;
54855+ if (resid > 0) {
54856+ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
54857+ rsp_hdr->residual_count = cpu_to_be32(resid);
54858+ }
54859+ }
54860+
54861+ TRACE_EXIT();
54862+ return;
54863+}
54864+
54865+static void iscsi_set_resid(struct iscsi_cmnd *rsp)
54866+{
54867+ struct iscsi_cmnd *req = rsp->parent_req;
54868+ struct scst_cmd *scst_cmd = req->scst_cmd;
54869+ struct iscsi_scsi_cmd_hdr *req_hdr;
54870+ struct iscsi_scsi_rsp_hdr *rsp_hdr;
54871+ int resid, out_resid;
54872+
54873+ TRACE_ENTRY();
54874+
54875+ if (likely(!scst_get_resid(scst_cmd, &resid, &out_resid))) {
54876+ TRACE_DBG("No residuals for req %p", req);
54877+ goto out;
54878+ }
54879+
54880+ TRACE_DBG("req %p, resid %d, out_resid %d", req, resid, out_resid);
54881+
54882+ req_hdr = cmnd_hdr(req);
54883+ rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs;
54884+
54885+ if ((req_hdr->flags & ISCSI_CMD_READ) &&
54886+ (req_hdr->flags & ISCSI_CMD_WRITE)) {
54887+ if (out_resid > 0) {
54888+ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
54889+ rsp_hdr->residual_count = cpu_to_be32(out_resid);
54890+ } else if (out_resid < 0) {
54891+ out_resid = -out_resid;
54892+ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_OVERFLOW;
54893+ rsp_hdr->residual_count = cpu_to_be32(out_resid);
54894+ }
54895+
54896+ if (resid > 0) {
54897+ rsp_hdr->flags |= ISCSI_FLG_BIRESIDUAL_UNDERFLOW;
54898+ rsp_hdr->bi_residual_count = cpu_to_be32(resid);
54899+ } else if (resid < 0) {
54900+ resid = -resid;
54901+ rsp_hdr->flags |= ISCSI_FLG_BIRESIDUAL_OVERFLOW;
54902+ rsp_hdr->bi_residual_count = cpu_to_be32(resid);
54903+ }
54904+ } else {
54905+ if (resid > 0) {
54906+ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
54907+ rsp_hdr->residual_count = cpu_to_be32(resid);
54908+ } else if (resid < 0) {
54909+ resid = -resid;
54910+ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_OVERFLOW;
54911+ rsp_hdr->residual_count = cpu_to_be32(resid);
54912+ }
54913+ }
54914+
54915+out:
54916+ TRACE_EXIT();
54917+ return;
54918+}
54919+
54920+static void send_data_rsp(struct iscsi_cmnd *req, u8 status, int send_status)
54921+{
54922+ struct iscsi_cmnd *rsp;
54923+ struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req);
54924+ struct iscsi_data_in_hdr *rsp_hdr;
54925+ u32 pdusize, size, offset, sn;
54926+ LIST_HEAD(send);
54927+
54928+ TRACE_DBG("req %p", req);
54929+
54930+ pdusize = req->conn->session->sess_params.max_xmit_data_length;
54931+ size = req->bufflen;
54932+ offset = 0;
54933+ sn = 0;
54934+
54935+ while (1) {
54936+ rsp = iscsi_alloc_rsp(req);
54937+ TRACE_DBG("rsp %p", rsp);
54938+ rsp->sg = req->sg;
54939+ rsp->sg_cnt = req->sg_cnt;
54940+ rsp->bufflen = req->bufflen;
54941+ rsp_hdr = (struct iscsi_data_in_hdr *)&rsp->pdu.bhs;
54942+
54943+ rsp_hdr->opcode = ISCSI_OP_SCSI_DATA_IN;
54944+ rsp_hdr->itt = req_hdr->itt;
54945+ rsp_hdr->ttt = ISCSI_RESERVED_TAG;
54946+ rsp_hdr->buffer_offset = cpu_to_be32(offset);
54947+ rsp_hdr->data_sn = cpu_to_be32(sn);
54948+
54949+ if (size <= pdusize) {
54950+ TRACE_DBG("offset %d, size %d", offset, size);
54951+ rsp->pdu.datasize = size;
54952+ if (send_status) {
54953+ TRACE_DBG("status %x", status);
54954+
54955+ EXTRACHECKS_BUG_ON((cmnd_hdr(req)->flags & ISCSI_CMD_WRITE) != 0);
54956+
54957+ rsp_hdr->flags = ISCSI_FLG_FINAL | ISCSI_FLG_STATUS;
54958+ rsp_hdr->cmd_status = status;
54959+
54960+ iscsi_set_resid(rsp);
54961+ }
54962+ list_add_tail(&rsp->write_list_entry, &send);
54963+ break;
54964+ }
54965+
54966+ TRACE_DBG("pdusize %d, offset %d, size %d", pdusize, offset,
54967+ size);
54968+
54969+ rsp->pdu.datasize = pdusize;
54970+
54971+ size -= pdusize;
54972+ offset += pdusize;
54973+ sn++;
54974+
54975+ list_add_tail(&rsp->write_list_entry, &send);
54976+ }
54977+ iscsi_cmnds_init_write(&send, 0);
54978+ return;
54979+}
54980+
54981+static void iscsi_init_status_rsp(struct iscsi_cmnd *rsp,
54982+ int status, const u8 *sense_buf, int sense_len)
54983+{
54984+ struct iscsi_cmnd *req = rsp->parent_req;
54985+ struct iscsi_scsi_rsp_hdr *rsp_hdr;
54986+ struct scatterlist *sg;
54987+
54988+ TRACE_ENTRY();
54989+
54990+ rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs;
54991+ rsp_hdr->opcode = ISCSI_OP_SCSI_RSP;
54992+ rsp_hdr->flags = ISCSI_FLG_FINAL;
54993+ rsp_hdr->response = ISCSI_RESPONSE_COMMAND_COMPLETED;
54994+ rsp_hdr->cmd_status = status;
54995+ rsp_hdr->itt = cmnd_hdr(req)->itt;
54996+
54997+ if (SCST_SENSE_VALID(sense_buf)) {
54998+ TRACE_DBG("%s", "SENSE VALID");
54999+
55000+ sg = rsp->sg = rsp->rsp_sg;
55001+ rsp->sg_cnt = 2;
55002+ rsp->own_sg = 1;
55003+
55004+ sg_init_table(sg, 2);
55005+ sg_set_buf(&sg[0], &rsp->sense_hdr, sizeof(rsp->sense_hdr));
55006+ sg_set_buf(&sg[1], sense_buf, sense_len);
55007+
55008+ rsp->sense_hdr.length = cpu_to_be16(sense_len);
55009+
55010+ rsp->pdu.datasize = sizeof(rsp->sense_hdr) + sense_len;
55011+ rsp->bufflen = rsp->pdu.datasize;
55012+ } else {
55013+ rsp->pdu.datasize = 0;
55014+ rsp->bufflen = 0;
55015+ }
55016+
55017+ TRACE_EXIT();
55018+ return;
55019+}
55020+
55021+static inline struct iscsi_cmnd *create_status_rsp(struct iscsi_cmnd *req,
55022+ int status, const u8 *sense_buf, int sense_len)
55023+{
55024+ struct iscsi_cmnd *rsp;
55025+
55026+ TRACE_ENTRY();
55027+
55028+ rsp = iscsi_alloc_rsp(req);
55029+ TRACE_DBG("rsp %p", rsp);
55030+
55031+ iscsi_init_status_rsp(rsp, status, sense_buf, sense_len);
55032+ iscsi_set_resid(rsp);
55033+
55034+ TRACE_EXIT_HRES((unsigned long)rsp);
55035+ return rsp;
55036+}
55037+
55038+/*
55039+ * Initializes data receive fields. Can be called only when they have not been
55040+ * initialized yet.
55041+ */
55042+static int iscsi_set_prelim_r2t_len_to_receive(struct iscsi_cmnd *req)
55043+{
55044+ struct iscsi_scsi_cmd_hdr *req_hdr = (struct iscsi_scsi_cmd_hdr *)&req->pdu.bhs;
55045+ int res = 0;
55046+ unsigned int not_received;
55047+
55048+ TRACE_ENTRY();
55049+
55050+ if (req_hdr->flags & ISCSI_CMD_FINAL) {
55051+ if (req_hdr->flags & ISCSI_CMD_WRITE)
55052+ iscsi_set_not_received_data_len(req,
55053+ be32_to_cpu(req_hdr->data_length) -
55054+ req->pdu.datasize);
55055+ goto out;
55056+ }
55057+
55058+ BUG_ON(req->outstanding_r2t != 0);
55059+
55060+ res = cmnd_insert_data_wait_hash(req);
55061+ if (res != 0) {
55062+ /*
55063+ * We have to close connection, because otherwise a data
55064+ * corruption is possible if we allow to receive data
55065+ * for this request in another request with dublicated ITT.
55066+ */
55067+ mark_conn_closed(req->conn);
55068+ goto out;
55069+ }
55070+
55071+ /*
55072+ * We need to wait for one or more PDUs. Let's simplify
55073+ * other code and pretend we need to receive 1 byte.
55074+ * In data_out_start() we will correct it.
55075+ */
55076+ req->outstanding_r2t = 1;
55077+ req_add_to_write_timeout_list(req);
55078+ req->r2t_len_to_receive = 1;
55079+ req->r2t_len_to_send = 0;
55080+
55081+ not_received = be32_to_cpu(req_hdr->data_length) - req->pdu.datasize;
55082+ not_received -= min_t(unsigned int, not_received,
55083+ req->conn->session->sess_params.first_burst_length);
55084+ iscsi_set_not_received_data_len(req, not_received);
55085+
55086+ TRACE_DBG("req %p, op %x, outstanding_r2t %d, r2t_len_to_receive %d, "
55087+ "r2t_len_to_send %d, not_received_data_len %d", req,
55088+ cmnd_opcode(req), req->outstanding_r2t, req->r2t_len_to_receive,
55089+ req->r2t_len_to_send, req->not_received_data_len);
55090+
55091+out:
55092+ TRACE_EXIT_RES(res);
55093+ return res;
55094+}
55095+
55096+static int create_preliminary_no_scst_rsp(struct iscsi_cmnd *req,
55097+ int status, const u8 *sense_buf, int sense_len)
55098+{
55099+ struct iscsi_cmnd *rsp;
55100+ int res = 0;
55101+
55102+ TRACE_ENTRY();
55103+
55104+ if (req->prelim_compl_flags != 0) {
55105+ TRACE_MGMT_DBG("req %p already prelim completed", req);
55106+ goto out;
55107+ }
55108+
55109+ req->scst_state = ISCSI_CMD_STATE_OUT_OF_SCST_PRELIM_COMPL;
55110+
55111+ BUG_ON(req->scst_cmd != NULL);
55112+
55113+ res = iscsi_preliminary_complete(req, req, true);
55114+
55115+ rsp = iscsi_alloc_main_rsp(req);
55116+ TRACE_DBG("main rsp %p", rsp);
55117+
55118+ iscsi_init_status_rsp(rsp, status, sense_buf, sense_len);
55119+
55120+ /* Resid will be set in req_cmnd_release() */
55121+
55122+out:
55123+ TRACE_EXIT_RES(res);
55124+ return res;
55125+}
55126+
55127+int set_scst_preliminary_status_rsp(struct iscsi_cmnd *req,
55128+ bool get_data, int key, int asc, int ascq)
55129+{
55130+ int res = 0;
55131+
55132+ TRACE_ENTRY();
55133+
55134+ if (req->scst_cmd == NULL) {
55135+ /* There must be already error set */
55136+ goto complete;
55137+ }
55138+
55139+ scst_set_cmd_error(req->scst_cmd, key, asc, ascq);
55140+
55141+complete:
55142+ res = iscsi_preliminary_complete(req, req, get_data);
55143+
55144+ TRACE_EXIT_RES(res);
55145+ return res;
55146+}
55147+
55148+static int create_reject_rsp(struct iscsi_cmnd *req, int reason, bool get_data)
55149+{
55150+ int res = 0;
55151+ struct iscsi_cmnd *rsp;
55152+ struct iscsi_reject_hdr *rsp_hdr;
55153+ struct scatterlist *sg;
55154+
55155+ TRACE_ENTRY();
55156+
55157+ TRACE_MGMT_DBG("Reject: req %p, reason %x", req, reason);
55158+
55159+ if (cmnd_opcode(req) == ISCSI_OP_SCSI_CMD) {
55160+ if (req->scst_cmd == NULL) {
55161+ /* BUSY status must be already set */
55162+ struct iscsi_scsi_rsp_hdr *rsp_hdr1;
55163+ rsp_hdr1 = (struct iscsi_scsi_rsp_hdr *)&req->main_rsp->pdu.bhs;
55164+ BUG_ON(rsp_hdr1->cmd_status == 0);
55165+ /*
55166+ * Let's not send REJECT here. The initiator will retry
55167+ * and, hopefully, next time we will not fail allocating
55168+ * scst_cmd, so we will then send the REJECT.
55169+ */
55170+ goto out;
55171+ } else {
55172+ /*
55173+ * "In all the cases in which a pre-instantiated SCSI
55174+ * task is terminated because of the reject, the target
55175+ * MUST issue a proper SCSI command response with CHECK
55176+ * CONDITION as described in Section 10.4.3 Response" -
55177+ * RFC 3720.
55178+ */
55179+ set_scst_preliminary_status_rsp(req, get_data,
55180+ SCST_LOAD_SENSE(scst_sense_invalid_message));
55181+ }
55182+ }
55183+
55184+ rsp = iscsi_alloc_main_rsp(req);
55185+ rsp_hdr = (struct iscsi_reject_hdr *)&rsp->pdu.bhs;
55186+
55187+ rsp_hdr->opcode = ISCSI_OP_REJECT;
55188+ rsp_hdr->ffffffff = ISCSI_RESERVED_TAG;
55189+ rsp_hdr->reason = reason;
55190+
55191+ sg = rsp->sg = rsp->rsp_sg;
55192+ rsp->sg_cnt = 1;
55193+ rsp->own_sg = 1;
55194+ sg_init_one(sg, &req->pdu.bhs, sizeof(struct iscsi_hdr));
55195+ rsp->bufflen = rsp->pdu.datasize = sizeof(struct iscsi_hdr);
55196+
55197+ res = iscsi_preliminary_complete(req, req, true);
55198+
55199+out:
55200+ TRACE_EXIT_RES(res);
55201+ return res;
55202+}
55203+
55204+static inline int iscsi_get_allowed_cmds(struct iscsi_session *sess)
55205+{
55206+ int res = max(-1, (int)sess->tgt_params.queued_cmnds -
55207+ atomic_read(&sess->active_cmds)-1);
55208+ TRACE_DBG("allowed cmds %d (sess %p, active_cmds %d)", res,
55209+ sess, atomic_read(&sess->active_cmds));
55210+ return res;
55211+}
55212+
55213+static __be32 cmnd_set_sn(struct iscsi_cmnd *cmnd, int set_stat_sn)
55214+{
55215+ struct iscsi_conn *conn = cmnd->conn;
55216+ struct iscsi_session *sess = conn->session;
55217+ __be32 res;
55218+
55219+ spin_lock(&sess->sn_lock);
55220+
55221+ if (set_stat_sn)
55222+ cmnd->pdu.bhs.sn = (__force u32)cpu_to_be32(conn->stat_sn++);
55223+ cmnd->pdu.bhs.exp_sn = (__force u32)cpu_to_be32(sess->exp_cmd_sn);
55224+ cmnd->pdu.bhs.max_sn = (__force u32)cpu_to_be32(sess->exp_cmd_sn +
55225+ iscsi_get_allowed_cmds(sess));
55226+
55227+ res = cpu_to_be32(conn->stat_sn);
55228+
55229+ spin_unlock(&sess->sn_lock);
55230+ return res;
55231+}
55232+
55233+/* Called under sn_lock */
55234+static void update_stat_sn(struct iscsi_cmnd *cmnd)
55235+{
55236+ struct iscsi_conn *conn = cmnd->conn;
55237+ u32 exp_stat_sn;
55238+
55239+ cmnd->pdu.bhs.exp_sn = exp_stat_sn = be32_to_cpu((__force __be32)cmnd->pdu.bhs.exp_sn);
55240+ TRACE_DBG("%x,%x", cmnd_opcode(cmnd), exp_stat_sn);
55241+ if ((int)(exp_stat_sn - conn->exp_stat_sn) > 0 &&
55242+ (int)(exp_stat_sn - conn->stat_sn) <= 0) {
55243+ /* free pdu resources */
55244+ cmnd->conn->exp_stat_sn = exp_stat_sn;
55245+ }
55246+ return;
55247+}
55248+
55249+static struct iscsi_cmnd *cmnd_find_itt_get(struct iscsi_conn *conn, __be32 itt)
55250+{
55251+ struct iscsi_cmnd *cmnd, *found_cmnd = NULL;
55252+
55253+ spin_lock_bh(&conn->cmd_list_lock);
55254+ list_for_each_entry(cmnd, &conn->cmd_list, cmd_list_entry) {
55255+ if ((cmnd->pdu.bhs.itt == itt) && !cmnd_get_check(cmnd)) {
55256+ found_cmnd = cmnd;
55257+ break;
55258+ }
55259+ }
55260+ spin_unlock_bh(&conn->cmd_list_lock);
55261+
55262+ return found_cmnd;
55263+}
55264+
55265+/**
55266+ ** We use the ITT hash only to find original request PDU for subsequent
55267+ ** Data-Out PDUs.
55268+ **/
55269+
55270+/* Must be called under cmnd_data_wait_hash_lock */
55271+static struct iscsi_cmnd *__cmnd_find_data_wait_hash(struct iscsi_conn *conn,
55272+ __be32 itt)
55273+{
55274+ struct list_head *head;
55275+ struct iscsi_cmnd *cmnd;
55276+
55277+ head = &conn->session->cmnd_data_wait_hash[cmnd_hashfn(itt)];
55278+
55279+ list_for_each_entry(cmnd, head, hash_list_entry) {
55280+ if (cmnd->pdu.bhs.itt == itt)
55281+ return cmnd;
55282+ }
55283+ return NULL;
55284+}
55285+
55286+static struct iscsi_cmnd *cmnd_find_data_wait_hash(struct iscsi_conn *conn,
55287+ __be32 itt)
55288+{
55289+ struct iscsi_cmnd *res;
55290+ struct iscsi_session *session = conn->session;
55291+
55292+ spin_lock(&session->cmnd_data_wait_hash_lock);
55293+ res = __cmnd_find_data_wait_hash(conn, itt);
55294+ spin_unlock(&session->cmnd_data_wait_hash_lock);
55295+
55296+ return res;
55297+}
55298+
55299+static inline u32 get_next_ttt(struct iscsi_conn *conn)
55300+{
55301+ u32 ttt;
55302+ struct iscsi_session *session = conn->session;
55303+
55304+ /* Not compatible with MC/S! */
55305+
55306+ iscsi_extracheck_is_rd_thread(conn);
55307+
55308+ if (unlikely(session->next_ttt == ISCSI_RESERVED_TAG_CPU32))
55309+ session->next_ttt++;
55310+ ttt = session->next_ttt++;
55311+
55312+ return ttt;
55313+}
55314+
55315+static int cmnd_insert_data_wait_hash(struct iscsi_cmnd *cmnd)
55316+{
55317+ struct iscsi_session *session = cmnd->conn->session;
55318+ struct iscsi_cmnd *tmp;
55319+ struct list_head *head;
55320+ int err = 0;
55321+ __be32 itt = cmnd->pdu.bhs.itt;
55322+
55323+ if (unlikely(cmnd->hashed)) {
55324+ /*
55325+ * It can be for preliminary completed commands, when this
55326+ * function already failed.
55327+ */
55328+ goto out;
55329+ }
55330+
55331+ /*
55332+ * We don't need TTT, because ITT/buffer_offset pair is sufficient
55333+ * to find out the original request and buffer for Data-Out PDUs, but
55334+ * crazy iSCSI spec requires us to send this superfluous field in
55335+ * R2T PDUs and some initiators may rely on it.
55336+ */
55337+ cmnd->target_task_tag = get_next_ttt(cmnd->conn);
55338+
55339+ TRACE_DBG("%p:%x", cmnd, itt);
55340+ if (unlikely(itt == ISCSI_RESERVED_TAG)) {
55341+ PRINT_ERROR("%s", "ITT is RESERVED_TAG");
55342+ PRINT_BUFFER("Incorrect BHS", &cmnd->pdu.bhs,
55343+ sizeof(cmnd->pdu.bhs));
55344+ err = -ISCSI_REASON_PROTOCOL_ERROR;
55345+ goto out;
55346+ }
55347+
55348+ spin_lock(&session->cmnd_data_wait_hash_lock);
55349+
55350+ head = &session->cmnd_data_wait_hash[cmnd_hashfn(itt)];
55351+
55352+ tmp = __cmnd_find_data_wait_hash(cmnd->conn, itt);
55353+ if (likely(!tmp)) {
55354+ TRACE_DBG("Adding cmnd %p to the hash (ITT %x)", cmnd,
55355+ cmnd->pdu.bhs.itt);
55356+ list_add_tail(&cmnd->hash_list_entry, head);
55357+ cmnd->hashed = 1;
55358+ } else {
55359+ PRINT_ERROR("Task %x in progress, cmnd %p", itt, cmnd);
55360+ err = -ISCSI_REASON_TASK_IN_PROGRESS;
55361+ }
55362+
55363+ spin_unlock(&session->cmnd_data_wait_hash_lock);
55364+
55365+out:
55366+ return err;
55367+}
55368+
55369+static void cmnd_remove_data_wait_hash(struct iscsi_cmnd *cmnd)
55370+{
55371+ struct iscsi_session *session = cmnd->conn->session;
55372+ struct iscsi_cmnd *tmp;
55373+
55374+ spin_lock(&session->cmnd_data_wait_hash_lock);
55375+
55376+ tmp = __cmnd_find_data_wait_hash(cmnd->conn, cmnd->pdu.bhs.itt);
55377+
55378+ if (likely(tmp && tmp == cmnd)) {
55379+ TRACE_DBG("Deleting cmnd %p from the hash (ITT %x)", cmnd,
55380+ cmnd->pdu.bhs.itt);
55381+ list_del(&cmnd->hash_list_entry);
55382+ cmnd->hashed = 0;
55383+ } else
55384+ PRINT_ERROR("%p:%x not found", cmnd, cmnd->pdu.bhs.itt);
55385+
55386+ spin_unlock(&session->cmnd_data_wait_hash_lock);
55387+
55388+ return;
55389+}
55390+
55391+static void cmnd_prepare_get_rejected_immed_data(struct iscsi_cmnd *cmnd)
55392+{
55393+ struct iscsi_conn *conn = cmnd->conn;
55394+ struct scatterlist *sg = cmnd->sg;
55395+ char __user *addr;
55396+ u32 size;
55397+ unsigned int i;
55398+
55399+ TRACE_ENTRY();
55400+
55401+ TRACE_DBG_FLAG(iscsi_get_flow_ctrl_or_mgmt_dbg_log_flag(cmnd),
55402+ "Skipping (cmnd %p, ITT %x, op %x, cmd op %x, "
55403+ "datasize %u, scst_cmd %p, scst state %d)", cmnd,
55404+ cmnd->pdu.bhs.itt, cmnd_opcode(cmnd), cmnd_hdr(cmnd)->scb[0],
55405+ cmnd->pdu.datasize, cmnd->scst_cmd, cmnd->scst_state);
55406+
55407+ iscsi_extracheck_is_rd_thread(conn);
55408+
55409+ size = cmnd->pdu.datasize;
55410+ if (!size)
55411+ goto out;
55412+
55413+ /* We already checked pdu.datasize in check_segment_length() */
55414+
55415+ /*
55416+ * There are no problems with the safety from concurrent
55417+ * accesses to dummy_page in dummy_sg, since data only
55418+ * will be read and then discarded.
55419+ */
55420+ sg = &dummy_sg;
55421+ if (cmnd->sg == NULL) {
55422+ /* just in case */
55423+ cmnd->sg = sg;
55424+ cmnd->bufflen = PAGE_SIZE;
55425+ cmnd->own_sg = 1;
55426+ }
55427+
55428+ addr = (char __force __user *)(page_address(sg_page(&sg[0])));
55429+ conn->read_size = size;
55430+ for (i = 0; size > PAGE_SIZE; i++, size -= PAGE_SIZE) {
55431+ /* We already checked pdu.datasize in check_segment_length() */
55432+ BUG_ON(i >= ISCSI_CONN_IOV_MAX);
55433+ conn->read_iov[i].iov_base = addr;
55434+ conn->read_iov[i].iov_len = PAGE_SIZE;
55435+ }
55436+ conn->read_iov[i].iov_base = addr;
55437+ conn->read_iov[i].iov_len = size;
55438+ conn->read_msg.msg_iov = conn->read_iov;
55439+ conn->read_msg.msg_iovlen = ++i;
55440+
55441+out:
55442+ TRACE_EXIT();
55443+ return;
55444+}
55445+
55446+int iscsi_preliminary_complete(struct iscsi_cmnd *req,
55447+ struct iscsi_cmnd *orig_req, bool get_data)
55448+{
55449+ int res = 0;
55450+ bool set_r2t_len;
55451+ struct iscsi_hdr *orig_req_hdr = &orig_req->pdu.bhs;
55452+
55453+ TRACE_ENTRY();
55454+
55455+#ifdef CONFIG_SCST_DEBUG
55456+ {
55457+ struct iscsi_hdr *req_hdr = &req->pdu.bhs;
55458+ TRACE_DBG_FLAG(iscsi_get_flow_ctrl_or_mgmt_dbg_log_flag(orig_req),
55459+ "Prelim completed req %p, orig_req %p (FINAL %x, "
55460+ "outstanding_r2t %d)", req, orig_req,
55461+ (req_hdr->flags & ISCSI_CMD_FINAL),
55462+ orig_req->outstanding_r2t);
55463+ }
55464+#endif
55465+
55466+ iscsi_extracheck_is_rd_thread(req->conn);
55467+ BUG_ON(req->parent_req != NULL);
55468+
55469+ if (test_bit(ISCSI_CMD_PRELIM_COMPLETED, &req->prelim_compl_flags)) {
55470+ TRACE_MGMT_DBG("req %p already prelim completed", req);
55471+ /* To not try to get data twice */
55472+ get_data = false;
55473+ }
55474+
55475+ /*
55476+ * We need to receive all outstanding PDUs, even if direction isn't
55477+ * WRITE. Test of PRELIM_COMPLETED is needed, because
55478+ * iscsi_set_prelim_r2t_len_to_receive() could also have failed before.
55479+ */
55480+ set_r2t_len = !orig_req->hashed &&
55481+ (cmnd_opcode(orig_req) == ISCSI_OP_SCSI_CMD) &&
55482+ !test_bit(ISCSI_CMD_PRELIM_COMPLETED,
55483+ &orig_req->prelim_compl_flags);
55484+
55485+ TRACE_DBG("get_data %d, set_r2t_len %d", get_data, set_r2t_len);
55486+
55487+ if (get_data)
55488+ cmnd_prepare_get_rejected_immed_data(req);
55489+
55490+ if (test_bit(ISCSI_CMD_PRELIM_COMPLETED, &orig_req->prelim_compl_flags))
55491+ goto out_set;
55492+
55493+ if (set_r2t_len)
55494+ res = iscsi_set_prelim_r2t_len_to_receive(orig_req);
55495+ else if (orig_req_hdr->flags & ISCSI_CMD_WRITE) {
55496+ /*
55497+ * We will get here if orig_req prelim completed in the middle
55498+ * of data receiving. We won't send more R2T's, so
55499+ * r2t_len_to_send is final and won't be updated anymore in
55500+ * future.
55501+ */
55502+ iscsi_set_not_received_data_len(orig_req,
55503+ orig_req->r2t_len_to_send);
55504+ }
55505+
55506+out_set:
55507+ set_bit(ISCSI_CMD_PRELIM_COMPLETED, &orig_req->prelim_compl_flags);
55508+ set_bit(ISCSI_CMD_PRELIM_COMPLETED, &req->prelim_compl_flags);
55509+
55510+ TRACE_EXIT_RES(res);
55511+ return res;
55512+}
55513+
55514+static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn,
55515+ struct iscsi_cmnd *cmd, u32 offset, u32 size)
55516+{
55517+ struct scatterlist *sg = cmd->sg;
55518+ unsigned int bufflen = cmd->bufflen;
55519+ unsigned int idx, i, buff_offs;
55520+ int res = 0;
55521+
55522+ TRACE_ENTRY();
55523+
55524+ TRACE_DBG("cmd %p, sg %p, offset %u, size %u", cmd, cmd->sg,
55525+ offset, size);
55526+
55527+ iscsi_extracheck_is_rd_thread(conn);
55528+
55529+ buff_offs = offset;
55530+ idx = (offset + sg[0].offset) >> PAGE_SHIFT;
55531+ offset &= ~PAGE_MASK;
55532+
55533+ conn->read_msg.msg_iov = conn->read_iov;
55534+ conn->read_size = size;
55535+
55536+ i = 0;
55537+ while (1) {
55538+ unsigned int sg_len;
55539+ char __user *addr;
55540+
55541+ if (unlikely(buff_offs >= bufflen)) {
55542+ TRACE_DBG("Residual overflow (cmd %p, buff_offs %d, "
55543+ "bufflen %d)", cmd, buff_offs, bufflen);
55544+ idx = 0;
55545+ sg = &dummy_sg;
55546+ offset = 0;
55547+ }
55548+
55549+ addr = (char __force __user *)(sg_virt(&sg[idx]));
55550+ EXTRACHECKS_BUG_ON(addr == NULL);
55551+ sg_len = sg[idx].length - offset;
55552+
55553+ conn->read_iov[i].iov_base = addr + offset;
55554+
55555+ if (size <= sg_len) {
55556+ TRACE_DBG("idx=%d, i=%d, offset=%u, size=%d, addr=%p",
55557+ idx, i, offset, size, addr);
55558+ conn->read_iov[i].iov_len = size;
55559+ conn->read_msg.msg_iovlen = i+1;
55560+ break;
55561+ }
55562+ conn->read_iov[i].iov_len = sg_len;
55563+
55564+ TRACE_DBG("idx=%d, i=%d, offset=%u, size=%d, sg_len=%u, "
55565+ "addr=%p", idx, i, offset, size, sg_len, addr);
55566+
55567+ size -= sg_len;
55568+ buff_offs += sg_len;
55569+
55570+ i++;
55571+ if (unlikely(i >= ISCSI_CONN_IOV_MAX)) {
55572+ PRINT_ERROR("Initiator %s violated negotiated "
55573+ "parameters by sending too much data (size "
55574+ "left %d)", conn->session->initiator_name,
55575+ size);
55576+ mark_conn_closed(conn);
55577+ res = -EINVAL;
55578+ break;
55579+ }
55580+
55581+ idx++;
55582+ offset = 0;
55583+ }
55584+
55585+ TRACE_DBG("msg_iov=%p, msg_iovlen=%zd",
55586+ conn->read_msg.msg_iov, conn->read_msg.msg_iovlen);
55587+
55588+ TRACE_EXIT_RES(res);
55589+ return res;
55590+}
55591+
55592+static void send_r2t(struct iscsi_cmnd *req)
55593+{
55594+ struct iscsi_session *sess = req->conn->session;
55595+ struct iscsi_cmnd *rsp;
55596+ struct iscsi_r2t_hdr *rsp_hdr;
55597+ u32 offset, burst;
55598+ LIST_HEAD(send);
55599+
55600+ TRACE_ENTRY();
55601+
55602+ EXTRACHECKS_BUG_ON(req->r2t_len_to_send == 0);
55603+
55604+ /*
55605+ * There is no race with data_out_start() and conn_abort(), since
55606+ * all functions called from single read thread
55607+ */
55608+ iscsi_extracheck_is_rd_thread(req->conn);
55609+
55610+ /*
55611+ * We don't need to check for PRELIM_COMPLETED here, because for such
55612+ * commands we set r2t_len_to_send = 0, hence made sure we won't be
55613+ * called here.
55614+ */
55615+
55616+ EXTRACHECKS_BUG_ON(req->outstanding_r2t >
55617+ sess->sess_params.max_outstanding_r2t);
55618+
55619+ if (req->outstanding_r2t == sess->sess_params.max_outstanding_r2t)
55620+ goto out;
55621+
55622+ burst = sess->sess_params.max_burst_length;
55623+ offset = be32_to_cpu(cmnd_hdr(req)->data_length) -
55624+ req->r2t_len_to_send;
55625+
55626+ do {
55627+ rsp = iscsi_alloc_rsp(req);
55628+ rsp->pdu.bhs.ttt = (__force __be32)req->target_task_tag;
55629+ rsp_hdr = (struct iscsi_r2t_hdr *)&rsp->pdu.bhs;
55630+ rsp_hdr->opcode = ISCSI_OP_R2T;
55631+ rsp_hdr->flags = ISCSI_FLG_FINAL;
55632+ rsp_hdr->lun = cmnd_hdr(req)->lun;
55633+ rsp_hdr->itt = cmnd_hdr(req)->itt;
55634+ rsp_hdr->r2t_sn = (__force u32)cpu_to_be32(req->r2t_sn++);
55635+ rsp_hdr->buffer_offset = cpu_to_be32(offset);
55636+ if (req->r2t_len_to_send > burst) {
55637+ rsp_hdr->data_length = cpu_to_be32(burst);
55638+ req->r2t_len_to_send -= burst;
55639+ offset += burst;
55640+ } else {
55641+ rsp_hdr->data_length = cpu_to_be32(req->r2t_len_to_send);
55642+ req->r2t_len_to_send = 0;
55643+ }
55644+
55645+ TRACE_WRITE("req %p, data_length %u, buffer_offset %u, "
55646+ "r2t_sn %u, outstanding_r2t %u", req,
55647+ be32_to_cpu(rsp_hdr->data_length),
55648+ be32_to_cpu(rsp_hdr->buffer_offset),
55649+ be32_to_cpu((__force __be32)rsp_hdr->r2t_sn), req->outstanding_r2t);
55650+
55651+ list_add_tail(&rsp->write_list_entry, &send);
55652+ req->outstanding_r2t++;
55653+
55654+ } while ((req->outstanding_r2t < sess->sess_params.max_outstanding_r2t) &&
55655+ (req->r2t_len_to_send != 0));
55656+
55657+ iscsi_cmnds_init_write(&send, ISCSI_INIT_WRITE_WAKE);
55658+
55659+out:
55660+ TRACE_EXIT();
55661+ return;
55662+}
55663+
55664+static int iscsi_pre_exec(struct scst_cmd *scst_cmd)
55665+{
55666+ int res = SCST_PREPROCESS_STATUS_SUCCESS;
55667+ struct iscsi_cmnd *req = (struct iscsi_cmnd *)
55668+ scst_cmd_get_tgt_priv(scst_cmd);
55669+ struct iscsi_cmnd *c, *t;
55670+
55671+ TRACE_ENTRY();
55672+
55673+ EXTRACHECKS_BUG_ON(scst_cmd_atomic(scst_cmd));
55674+
55675+ /* If data digest isn't used this list will be empty */
55676+ list_for_each_entry_safe(c, t, &req->rx_ddigest_cmd_list,
55677+ rx_ddigest_cmd_list_entry) {
55678+ TRACE_DBG("Checking digest of RX ddigest cmd %p", c);
55679+ if (digest_rx_data(c) != 0) {
55680+ scst_set_cmd_error(scst_cmd,
55681+ SCST_LOAD_SENSE(iscsi_sense_crc_error));
55682+ res = SCST_PREPROCESS_STATUS_ERROR_SENSE_SET;
55683+ /*
55684+ * The rest of rx_ddigest_cmd_list will be freed
55685+ * in req_cmnd_release()
55686+ */
55687+ goto out;
55688+ }
55689+ cmd_del_from_rx_ddigest_list(c);
55690+ cmnd_put(c);
55691+ }
55692+
55693+out:
55694+ TRACE_EXIT_RES(res);
55695+ return res;
55696+}
55697+
55698+static int nop_out_start(struct iscsi_cmnd *cmnd)
55699+{
55700+ struct iscsi_conn *conn = cmnd->conn;
55701+ struct iscsi_hdr *req_hdr = &cmnd->pdu.bhs;
55702+ u32 size, tmp;
55703+ int i, err = 0;
55704+
55705+ TRACE_DBG("%p", cmnd);
55706+
55707+ iscsi_extracheck_is_rd_thread(conn);
55708+
55709+ if (!(req_hdr->flags & ISCSI_FLG_FINAL)) {
55710+ PRINT_ERROR("%s", "Initiator sent Nop-Out with not a single "
55711+ "PDU");
55712+ err = -ISCSI_REASON_PROTOCOL_ERROR;
55713+ goto out;
55714+ }
55715+
55716+ if (cmnd->pdu.bhs.itt == ISCSI_RESERVED_TAG) {
55717+ if (unlikely(!(cmnd->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE)))
55718+ PRINT_ERROR("%s", "Initiator sent RESERVED tag for "
55719+ "non-immediate Nop-Out command");
55720+ }
55721+
55722+ update_stat_sn(cmnd);
55723+
55724+ size = cmnd->pdu.datasize;
55725+
55726+ if (size) {
55727+ conn->read_msg.msg_iov = conn->read_iov;
55728+ if (cmnd->pdu.bhs.itt != ISCSI_RESERVED_TAG) {
55729+ struct scatterlist *sg;
55730+
55731+ cmnd->sg = sg = scst_alloc(size, GFP_KERNEL,
55732+ &cmnd->sg_cnt);
55733+ if (sg == NULL) {
55734+ TRACE(TRACE_OUT_OF_MEM, "Allocating buffer for"
55735+ " %d Nop-Out payload failed", size);
55736+ err = -ISCSI_REASON_OUT_OF_RESOURCES;
55737+ goto out;
55738+ }
55739+
55740+ /* We already checked it in check_segment_length() */
55741+ BUG_ON(cmnd->sg_cnt > (signed)ISCSI_CONN_IOV_MAX);
55742+
55743+ cmnd->own_sg = 1;
55744+ cmnd->bufflen = size;
55745+
55746+ for (i = 0; i < cmnd->sg_cnt; i++) {
55747+ conn->read_iov[i].iov_base =
55748+ (void __force __user *)(page_address(sg_page(&sg[i])));
55749+ tmp = min_t(u32, size, PAGE_SIZE);
55750+ conn->read_iov[i].iov_len = tmp;
55751+ conn->read_size += tmp;
55752+ size -= tmp;
55753+ }
55754+ BUG_ON(size != 0);
55755+ } else {
55756+ /*
55757+ * There are no problems with the safety from concurrent
55758+ * accesses to dummy_page, since for ISCSI_RESERVED_TAG
55759+ * the data only read and then discarded.
55760+ */
55761+ for (i = 0; i < (signed)ISCSI_CONN_IOV_MAX; i++) {
55762+ conn->read_iov[i].iov_base =
55763+ (void __force __user *)(page_address(dummy_page));
55764+ tmp = min_t(u32, size, PAGE_SIZE);
55765+ conn->read_iov[i].iov_len = tmp;
55766+ conn->read_size += tmp;
55767+ size -= tmp;
55768+ }
55769+
55770+ /* We already checked size in check_segment_length() */
55771+ BUG_ON(size != 0);
55772+ }
55773+
55774+ conn->read_msg.msg_iovlen = i;
55775+ TRACE_DBG("msg_iov=%p, msg_iovlen=%zd", conn->read_msg.msg_iov,
55776+ conn->read_msg.msg_iovlen);
55777+ }
55778+
55779+out:
55780+ return err;
55781+}
55782+
55783+int cmnd_rx_continue(struct iscsi_cmnd *req)
55784+{
55785+ struct iscsi_conn *conn = req->conn;
55786+ struct iscsi_session *session = conn->session;
55787+ struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req);
55788+ struct scst_cmd *scst_cmd = req->scst_cmd;
55789+ scst_data_direction dir;
55790+ bool unsolicited_data_expected = false;
55791+ int res = 0;
55792+
55793+ TRACE_ENTRY();
55794+
55795+ TRACE_DBG("scsi command: %x", req_hdr->scb[0]);
55796+
55797+ EXTRACHECKS_BUG_ON(req->scst_state != ISCSI_CMD_STATE_AFTER_PREPROC);
55798+
55799+ dir = scst_cmd_get_data_direction(scst_cmd);
55800+
55801+ /*
55802+ * Check for preliminary completion here to save R2Ts. For TASK QUEUE
55803+ * FULL statuses that might be a big performance win.
55804+ */
55805+ if (unlikely(scst_cmd_prelim_completed(scst_cmd) ||
55806+ unlikely(req->prelim_compl_flags != 0))) {
55807+ /*
55808+ * If necessary, ISCSI_CMD_ABORTED will be set by
55809+ * iscsi_xmit_response().
55810+ */
55811+ res = iscsi_preliminary_complete(req, req, true);
55812+ goto trace;
55813+ }
55814+
55815+ /* For prelim completed commands sg & K can be already set! */
55816+
55817+ if (dir & SCST_DATA_WRITE) {
55818+ req->bufflen = scst_cmd_get_write_fields(scst_cmd, &req->sg,
55819+ &req->sg_cnt);
55820+ unsolicited_data_expected = !(req_hdr->flags & ISCSI_CMD_FINAL);
55821+
55822+ if (unlikely(session->sess_params.initial_r2t &&
55823+ unsolicited_data_expected)) {
55824+ PRINT_ERROR("Initiator %s violated negotiated "
55825+ "parameters: initial R2T is required (ITT %x, "
55826+ "op %x)", session->initiator_name,
55827+ req->pdu.bhs.itt, req_hdr->scb[0]);
55828+ goto out_close;
55829+ }
55830+
55831+ if (unlikely(!session->sess_params.immediate_data &&
55832+ req->pdu.datasize)) {
55833+ PRINT_ERROR("Initiator %s violated negotiated "
55834+ "parameters: forbidden immediate data sent "
55835+ "(ITT %x, op %x)", session->initiator_name,
55836+ req->pdu.bhs.itt, req_hdr->scb[0]);
55837+ goto out_close;
55838+ }
55839+
55840+ if (unlikely(session->sess_params.first_burst_length < req->pdu.datasize)) {
55841+ PRINT_ERROR("Initiator %s violated negotiated "
55842+ "parameters: immediate data len (%d) > "
55843+ "first_burst_length (%d) (ITT %x, op %x)",
55844+ session->initiator_name,
55845+ req->pdu.datasize,
55846+ session->sess_params.first_burst_length,
55847+ req->pdu.bhs.itt, req_hdr->scb[0]);
55848+ goto out_close;
55849+ }
55850+
55851+ req->r2t_len_to_receive = be32_to_cpu(req_hdr->data_length) -
55852+ req->pdu.datasize;
55853+
55854+ /*
55855+ * In case of residual overflow req->r2t_len_to_receive and
55856+ * req->pdu.datasize might be > req->bufflen
55857+ */
55858+
55859+ res = cmnd_insert_data_wait_hash(req);
55860+ if (unlikely(res != 0)) {
55861+ /*
55862+ * We have to close connection, because otherwise a data
55863+ * corruption is possible if we allow to receive data
55864+ * for this request in another request with dublicated
55865+ * ITT.
55866+ */
55867+ goto out_close;
55868+ }
55869+
55870+ if (unsolicited_data_expected) {
55871+ req->outstanding_r2t = 1;
55872+ req->r2t_len_to_send = req->r2t_len_to_receive -
55873+ min_t(unsigned int,
55874+ session->sess_params.first_burst_length -
55875+ req->pdu.datasize,
55876+ req->r2t_len_to_receive);
55877+ } else
55878+ req->r2t_len_to_send = req->r2t_len_to_receive;
55879+
55880+ req_add_to_write_timeout_list(req);
55881+
55882+ if (req->pdu.datasize) {
55883+ res = cmnd_prepare_recv_pdu(conn, req, 0, req->pdu.datasize);
55884+ /* For performance better to send R2Ts ASAP */
55885+ if (likely(res == 0) && (req->r2t_len_to_send != 0))
55886+ send_r2t(req);
55887+ }
55888+ } else {
55889+ req->sg = scst_cmd_get_sg(scst_cmd);
55890+ req->sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
55891+ req->bufflen = scst_cmd_get_bufflen(scst_cmd);
55892+
55893+ if (unlikely(!(req_hdr->flags & ISCSI_CMD_FINAL) ||
55894+ req->pdu.datasize)) {
55895+ PRINT_ERROR("Unexpected unsolicited data (ITT %x "
55896+ "CDB %x)", req->pdu.bhs.itt, req_hdr->scb[0]);
55897+ set_scst_preliminary_status_rsp(req, true,
55898+ SCST_LOAD_SENSE(iscsi_sense_unexpected_unsolicited_data));
55899+ }
55900+ }
55901+
55902+trace:
55903+ TRACE_DBG("req=%p, dir=%d, unsolicited_data_expected=%d, "
55904+ "r2t_len_to_receive=%d, r2t_len_to_send=%d, bufflen=%d, "
55905+ "own_sg %d", req, dir, unsolicited_data_expected,
55906+ req->r2t_len_to_receive, req->r2t_len_to_send, req->bufflen,
55907+ req->own_sg);
55908+
55909+out:
55910+ TRACE_EXIT_RES(res);
55911+ return res;
55912+
55913+out_close:
55914+ mark_conn_closed(conn);
55915+ res = -EINVAL;
55916+ goto out;
55917+}
55918+
55919+static int scsi_cmnd_start(struct iscsi_cmnd *req)
55920+{
55921+ struct iscsi_conn *conn = req->conn;
55922+ struct iscsi_session *session = conn->session;
55923+ struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req);
55924+ struct scst_cmd *scst_cmd;
55925+ scst_data_direction dir;
55926+ struct iscsi_ahs_hdr *ahdr;
55927+ int res = 0;
55928+
55929+ TRACE_ENTRY();
55930+
55931+ TRACE_DBG("scsi command: %x", req_hdr->scb[0]);
55932+
55933+ TRACE_DBG("Incrementing active_cmds (cmd %p, sess %p, "
55934+ "new value %d)", req, session,
55935+ atomic_read(&session->active_cmds)+1);
55936+ atomic_inc(&session->active_cmds);
55937+ req->dec_active_cmds = 1;
55938+
55939+ scst_cmd = scst_rx_cmd(session->scst_sess,
55940+ (uint8_t *)&req_hdr->lun, sizeof(req_hdr->lun),
55941+ req_hdr->scb, sizeof(req_hdr->scb), SCST_NON_ATOMIC);
55942+ if (scst_cmd == NULL) {
55943+ res = create_preliminary_no_scst_rsp(req, SAM_STAT_BUSY,
55944+ NULL, 0);
55945+ goto out;
55946+ }
55947+
55948+ req->scst_cmd = scst_cmd;
55949+ scst_cmd_set_tag(scst_cmd, (__force u32)req_hdr->itt);
55950+ scst_cmd_set_tgt_priv(scst_cmd, req);
55951+
55952+ if ((req_hdr->flags & ISCSI_CMD_READ) &&
55953+ (req_hdr->flags & ISCSI_CMD_WRITE)) {
55954+ int sz = cmnd_read_size(req);
55955+ if (unlikely(sz < 0)) {
55956+ PRINT_ERROR("%s", "BIDI data transfer, but initiator "
55957+ "not supplied Bidirectional Read Expected Data "
55958+ "Transfer Length AHS");
55959+ set_scst_preliminary_status_rsp(req, true,
55960+ SCST_LOAD_SENSE(scst_sense_parameter_value_invalid));
55961+ } else {
55962+ dir = SCST_DATA_BIDI;
55963+ scst_cmd_set_expected(scst_cmd, dir, sz);
55964+ scst_cmd_set_expected_out_transfer_len(scst_cmd,
55965+ be32_to_cpu(req_hdr->data_length));
55966+#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
55967+ scst_cmd_set_tgt_need_alloc_data_buf(scst_cmd);
55968+#endif
55969+ }
55970+ } else if (req_hdr->flags & ISCSI_CMD_READ) {
55971+ dir = SCST_DATA_READ;
55972+ scst_cmd_set_expected(scst_cmd, dir,
55973+ be32_to_cpu(req_hdr->data_length));
55974+#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
55975+ scst_cmd_set_tgt_need_alloc_data_buf(scst_cmd);
55976+#endif
55977+ } else if (req_hdr->flags & ISCSI_CMD_WRITE) {
55978+ dir = SCST_DATA_WRITE;
55979+ scst_cmd_set_expected(scst_cmd, dir,
55980+ be32_to_cpu(req_hdr->data_length));
55981+ } else {
55982+ dir = SCST_DATA_NONE;
55983+ scst_cmd_set_expected(scst_cmd, dir, 0);
55984+ }
55985+
55986+ switch (req_hdr->flags & ISCSI_CMD_ATTR_MASK) {
55987+ case ISCSI_CMD_SIMPLE:
55988+ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_SIMPLE);
55989+ break;
55990+ case ISCSI_CMD_HEAD_OF_QUEUE:
55991+ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
55992+ break;
55993+ case ISCSI_CMD_ORDERED:
55994+ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_ORDERED);
55995+ break;
55996+ case ISCSI_CMD_ACA:
55997+ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_ACA);
55998+ break;
55999+ case ISCSI_CMD_UNTAGGED:
56000+ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_UNTAGGED);
56001+ break;
56002+ default:
56003+ PRINT_ERROR("Unknown task code %x, use ORDERED instead",
56004+ req_hdr->flags & ISCSI_CMD_ATTR_MASK);
56005+ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_ORDERED);
56006+ break;
56007+ }
56008+
56009+ scst_cmd_set_tgt_sn(scst_cmd, req_hdr->cmd_sn);
56010+
56011+ ahdr = (struct iscsi_ahs_hdr *)req->pdu.ahs;
56012+ if (ahdr != NULL) {
56013+ uint8_t *p = (uint8_t *)ahdr;
56014+ unsigned int size = 0;
56015+ do {
56016+ int s;
56017+
56018+ ahdr = (struct iscsi_ahs_hdr *)p;
56019+
56020+ if (ahdr->ahstype == ISCSI_AHSTYPE_CDB) {
56021+ struct iscsi_cdb_ahdr *eca =
56022+ (struct iscsi_cdb_ahdr *)ahdr;
56023+ scst_cmd_set_ext_cdb(scst_cmd, eca->cdb,
56024+ be16_to_cpu(ahdr->ahslength) - 1);
56025+ break;
56026+ }
56027+ s = 3 + be16_to_cpu(ahdr->ahslength);
56028+ s = (s + 3) & -4;
56029+ size += s;
56030+ p += s;
56031+ } while (size < req->pdu.ahssize);
56032+ }
56033+
56034+ TRACE_DBG("START Command (itt %x, queue_type %d)",
56035+ req_hdr->itt, scst_cmd_get_queue_type(scst_cmd));
56036+ req->scst_state = ISCSI_CMD_STATE_RX_CMD;
56037+ conn->rx_task = current;
56038+ scst_cmd_init_stage1_done(scst_cmd, SCST_CONTEXT_DIRECT, 0);
56039+
56040+ if (req->scst_state != ISCSI_CMD_STATE_RX_CMD)
56041+ res = cmnd_rx_continue(req);
56042+ else {
56043+ TRACE_DBG("Delaying req %p post processing (scst_state %d)",
56044+ req, req->scst_state);
56045+ res = 1;
56046+ }
56047+
56048+out:
56049+ TRACE_EXIT_RES(res);
56050+ return res;
56051+}
56052+
56053+static int data_out_start(struct iscsi_cmnd *cmnd)
56054+{
56055+ struct iscsi_conn *conn = cmnd->conn;
56056+ struct iscsi_data_out_hdr *req_hdr =
56057+ (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs;
56058+ struct iscsi_cmnd *orig_req;
56059+#if 0
56060+ struct iscsi_hdr *orig_req_hdr;
56061+#endif
56062+ u32 offset = be32_to_cpu(req_hdr->buffer_offset);
56063+ int res = 0;
56064+
56065+ TRACE_ENTRY();
56066+
56067+ /*
56068+ * There is no race with send_r2t() and conn_abort(), since
56069+ * all functions called from single read thread
56070+ */
56071+ iscsi_extracheck_is_rd_thread(cmnd->conn);
56072+
56073+ update_stat_sn(cmnd);
56074+
56075+ orig_req = cmnd_find_data_wait_hash(conn, req_hdr->itt);
56076+ cmnd->cmd_req = orig_req;
56077+ if (unlikely(orig_req == NULL)) {
56078+ /*
56079+ * It shouldn't happen, since we don't abort any request until
56080+ * we received all related PDUs from the initiator or timeout
56081+ * them. Let's quietly drop such PDUs.
56082+ */
56083+ TRACE_MGMT_DBG("Unable to find scsi task ITT %x",
56084+ cmnd->pdu.bhs.itt);
56085+ res = iscsi_preliminary_complete(cmnd, cmnd, true);
56086+ goto out;
56087+ }
56088+
56089+ if (unlikely(orig_req->r2t_len_to_receive < cmnd->pdu.datasize)) {
56090+ if (orig_req->prelim_compl_flags != 0) {
56091+ /* We can have fake r2t_len_to_receive */
56092+ goto go;
56093+ }
56094+ PRINT_ERROR("Data size (%d) > R2T length to receive (%d)",
56095+ cmnd->pdu.datasize, orig_req->r2t_len_to_receive);
56096+ set_scst_preliminary_status_rsp(orig_req, false,
56097+ SCST_LOAD_SENSE(iscsi_sense_incorrect_amount_of_data));
56098+ goto go;
56099+ }
56100+
56101+ /* Crazy iSCSI spec requires us to make this unneeded check */
56102+#if 0 /* ...but some initiators (Windows) don't care to correctly set it */
56103+ orig_req_hdr = &orig_req->pdu.bhs;
56104+ if (unlikely(orig_req_hdr->lun != req_hdr->lun)) {
56105+ PRINT_ERROR("Wrong LUN (%lld) in Data-Out PDU (expected %lld), "
56106+ "orig_req %p, cmnd %p", (unsigned long long)req_hdr->lun,
56107+ (unsigned long long)orig_req_hdr->lun, orig_req, cmnd);
56108+ create_reject_rsp(orig_req, ISCSI_REASON_PROTOCOL_ERROR, false);
56109+ goto go;
56110+ }
56111+#endif
56112+
56113+go:
56114+ if (req_hdr->flags & ISCSI_FLG_FINAL)
56115+ orig_req->outstanding_r2t--;
56116+
56117+ if (unlikely(orig_req->prelim_compl_flags != 0)) {
56118+ res = iscsi_preliminary_complete(cmnd, orig_req, true);
56119+ goto out;
56120+ }
56121+
56122+ TRACE_WRITE("cmnd %p, orig_req %p, offset %u, datasize %u", cmnd,
56123+ orig_req, offset, cmnd->pdu.datasize);
56124+
56125+ res = cmnd_prepare_recv_pdu(conn, orig_req, offset, cmnd->pdu.datasize);
56126+
56127+out:
56128+ TRACE_EXIT_RES(res);
56129+ return res;
56130+}
56131+
56132+static void data_out_end(struct iscsi_cmnd *cmnd)
56133+{
56134+ struct iscsi_data_out_hdr *req_hdr =
56135+ (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs;
56136+ struct iscsi_cmnd *req;
56137+
56138+ TRACE_ENTRY();
56139+
56140+ EXTRACHECKS_BUG_ON(cmnd == NULL);
56141+ req = cmnd->cmd_req;
56142+ if (unlikely(req == NULL))
56143+ goto out;
56144+
56145+ TRACE_DBG("cmnd %p, req %p", cmnd, req);
56146+
56147+ iscsi_extracheck_is_rd_thread(cmnd->conn);
56148+
56149+ if (!(cmnd->conn->ddigest_type & DIGEST_NONE) &&
56150+ !cmnd->ddigest_checked) {
56151+ cmd_add_on_rx_ddigest_list(req, cmnd);
56152+ cmnd_get(cmnd);
56153+ }
56154+
56155+ /*
56156+ * Now we received the data and can adjust r2t_len_to_receive of the
56157+ * orig req. We couldn't do it earlier, because it will break data
56158+ * receiving errors recovery (calls of iscsi_fail_data_waiting_cmnd()).
56159+ */
56160+ req->r2t_len_to_receive -= cmnd->pdu.datasize;
56161+
56162+ if (unlikely(req->prelim_compl_flags != 0)) {
56163+ /*
56164+ * We need to call iscsi_preliminary_complete() again
56165+ * to handle the case if we just been aborted. This call must
56166+ * be done before zeroing r2t_len_to_send to correctly calc.
56167+ * residual.
56168+ */
56169+ iscsi_preliminary_complete(cmnd, req, false);
56170+
56171+ /*
56172+ * We might need to wait for one or more PDUs. Let's simplify
56173+ * other code and not perform exact r2t_len_to_receive
56174+ * calculation.
56175+ */
56176+ req->r2t_len_to_receive = req->outstanding_r2t;
56177+ req->r2t_len_to_send = 0;
56178+ }
56179+
56180+ TRACE_DBG("req %p, FINAL %x, outstanding_r2t %d, r2t_len_to_receive %d,"
56181+ " r2t_len_to_send %d", req, req_hdr->flags & ISCSI_FLG_FINAL,
56182+ req->outstanding_r2t, req->r2t_len_to_receive,
56183+ req->r2t_len_to_send);
56184+
56185+ if (!(req_hdr->flags & ISCSI_FLG_FINAL))
56186+ goto out;
56187+
56188+ if (req->r2t_len_to_receive == 0) {
56189+ if (!req->pending)
56190+ iscsi_restart_cmnd(req);
56191+ } else if (req->r2t_len_to_send != 0)
56192+ send_r2t(req);
56193+
56194+out:
56195+ TRACE_EXIT();
56196+ return;
56197+}
56198+
56199+/* Might be called under target_mutex and cmd_list_lock */
56200+static void __cmnd_abort(struct iscsi_cmnd *cmnd)
56201+{
56202+ unsigned long timeout_time = jiffies + ISCSI_TM_DATA_WAIT_TIMEOUT +
56203+ ISCSI_ADD_SCHED_TIME;
56204+ struct iscsi_conn *conn = cmnd->conn;
56205+
56206+ TRACE_MGMT_DBG("Aborting cmd %p, scst_cmd %p (scst state %x, "
56207+ "ref_cnt %d, on_write_timeout_list %d, write_start %ld, ITT %x, "
56208+ "sn %u, op %x, r2t_len_to_receive %d, r2t_len_to_send %d, "
56209+ "CDB op %x, size to write %u, outstanding_r2t %d, "
56210+ "sess->exp_cmd_sn %u, conn %p, rd_task %p)",
56211+ cmnd, cmnd->scst_cmd, cmnd->scst_state,
56212+ atomic_read(&cmnd->ref_cnt), cmnd->on_write_timeout_list,
56213+ cmnd->write_start, cmnd->pdu.bhs.itt, cmnd->pdu.bhs.sn,
56214+ cmnd_opcode(cmnd), cmnd->r2t_len_to_receive,
56215+ cmnd->r2t_len_to_send, cmnd_scsicode(cmnd),
56216+ cmnd_write_size(cmnd), cmnd->outstanding_r2t,
56217+ cmnd->conn->session->exp_cmd_sn, cmnd->conn,
56218+ cmnd->conn->rd_task);
56219+
56220+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
56221+ TRACE_MGMT_DBG("net_ref_cnt %d", atomic_read(&cmnd->net_ref_cnt));
56222+#endif
56223+
56224+ /*
56225+ * Lock to sync with iscsi_check_tm_data_wait_timeouts(), including
56226+ * CMD_ABORTED bit set.
56227+ */
56228+ spin_lock_bh(&iscsi_rd_lock);
56229+
56230+ /*
56231+ * We suppose that preliminary commands completion is tested by
56232+ * comparing prelim_compl_flags with 0. Otherwise a race is possible,
56233+ * like sending command in SCST core as PRELIM_COMPLETED, while it
56234+ * wasn't aborted in it yet and have as the result a wrong success
56235+ * status sent to the initiator.
56236+ */
56237+ set_bit(ISCSI_CMD_ABORTED, &cmnd->prelim_compl_flags);
56238+
56239+ TRACE_MGMT_DBG("Setting conn_tm_active for conn %p", conn);
56240+ conn->conn_tm_active = 1;
56241+
56242+ spin_unlock_bh(&iscsi_rd_lock);
56243+
56244+ /*
56245+ * We need the lock to sync with req_add_to_write_timeout_list() and
56246+ * close races for rsp_timer.expires.
56247+ */
56248+ spin_lock_bh(&conn->write_list_lock);
56249+ if (!timer_pending(&conn->rsp_timer) ||
56250+ time_after(conn->rsp_timer.expires, timeout_time)) {
56251+ TRACE_MGMT_DBG("Mod timer on %ld (conn %p)", timeout_time,
56252+ conn);
56253+ mod_timer(&conn->rsp_timer, timeout_time);
56254+ } else
56255+ TRACE_MGMT_DBG("Timer for conn %p is going to fire on %ld "
56256+ "(timeout time %ld)", conn, conn->rsp_timer.expires,
56257+ timeout_time);
56258+ spin_unlock_bh(&conn->write_list_lock);
56259+
56260+ return;
56261+}
56262+
56263+/* Must be called from the read or conn close thread */
56264+static int cmnd_abort(struct iscsi_cmnd *req, int *status)
56265+{
56266+ struct iscsi_task_mgt_hdr *req_hdr =
56267+ (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
56268+ struct iscsi_cmnd *cmnd;
56269+ int res = -1;
56270+
56271+ req_hdr->ref_cmd_sn = be32_to_cpu((__force __be32)req_hdr->ref_cmd_sn);
56272+
56273+ if (!before(req_hdr->ref_cmd_sn, req_hdr->cmd_sn)) {
56274+ TRACE(TRACE_MGMT, "ABORT TASK: RefCmdSN(%u) > CmdSN(%u)",
56275+ req_hdr->ref_cmd_sn, req_hdr->cmd_sn);
56276+ *status = ISCSI_RESPONSE_UNKNOWN_TASK;
56277+ goto out;
56278+ }
56279+
56280+ cmnd = cmnd_find_itt_get(req->conn, req_hdr->rtt);
56281+ if (cmnd) {
56282+ struct iscsi_conn *conn = cmnd->conn;
56283+ struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd);
56284+
56285+ if (req_hdr->lun != hdr->lun) {
56286+ PRINT_ERROR("ABORT TASK: LUN mismatch: req LUN "
56287+ "%llx, cmd LUN %llx, rtt %u",
56288+ (long long unsigned)be64_to_cpu(req_hdr->lun),
56289+ (long long unsigned)be64_to_cpu(hdr->lun),
56290+ req_hdr->rtt);
56291+ *status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56292+ goto out_put;
56293+ }
56294+
56295+ if (cmnd->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE) {
56296+ if (req_hdr->ref_cmd_sn != req_hdr->cmd_sn) {
56297+ PRINT_ERROR("ABORT TASK: RefCmdSN(%u) != TM "
56298+ "cmd CmdSN(%u) for immediate command "
56299+ "%p", req_hdr->ref_cmd_sn,
56300+ req_hdr->cmd_sn, cmnd);
56301+ *status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56302+ goto out_put;
56303+ }
56304+ } else {
56305+ if (req_hdr->ref_cmd_sn != hdr->cmd_sn) {
56306+ PRINT_ERROR("ABORT TASK: RefCmdSN(%u) != "
56307+ "CmdSN(%u) for command %p",
56308+ req_hdr->ref_cmd_sn, req_hdr->cmd_sn,
56309+ cmnd);
56310+ *status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56311+ goto out_put;
56312+ }
56313+ }
56314+
56315+ if (before(req_hdr->cmd_sn, hdr->cmd_sn) ||
56316+ (req_hdr->cmd_sn == hdr->cmd_sn)) {
56317+ PRINT_ERROR("ABORT TASK: SN mismatch: req SN %x, "
56318+ "cmd SN %x, rtt %u", req_hdr->cmd_sn,
56319+ hdr->cmd_sn, req_hdr->rtt);
56320+ *status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56321+ goto out_put;
56322+ }
56323+
56324+ spin_lock_bh(&conn->cmd_list_lock);
56325+ __cmnd_abort(cmnd);
56326+ spin_unlock_bh(&conn->cmd_list_lock);
56327+
56328+ cmnd_put(cmnd);
56329+ res = 0;
56330+ } else {
56331+ TRACE_MGMT_DBG("cmd RTT %x not found", req_hdr->rtt);
56332+ /*
56333+ * iSCSI RFC:
56334+ *
56335+ * b) If the Referenced Task Tag does not identify an existing task,
56336+ * but if the CmdSN indicated by the RefCmdSN field in the Task
56337+ * Management function request is within the valid CmdSN window
56338+ * and less than the CmdSN of the Task Management function
56339+ * request itself, then targets must consider the CmdSN received
56340+ * and return the "Function complete" response.
56341+ *
56342+ * c) If the Referenced Task Tag does not identify an existing task
56343+ * and if the CmdSN indicated by the RefCmdSN field in the Task
56344+ * Management function request is outside the valid CmdSN window,
56345+ * then targets must return the "Task does not exist" response.
56346+ *
56347+ * 128 seems to be a good "window".
56348+ */
56349+ if (between(req_hdr->ref_cmd_sn, req_hdr->cmd_sn - 128,
56350+ req_hdr->cmd_sn)) {
56351+ *status = ISCSI_RESPONSE_FUNCTION_COMPLETE;
56352+ res = 0;
56353+ } else
56354+ *status = ISCSI_RESPONSE_UNKNOWN_TASK;
56355+ }
56356+
56357+out:
56358+ return res;
56359+
56360+out_put:
56361+ cmnd_put(cmnd);
56362+ goto out;
56363+}
56364+
56365+/* Must be called from the read or conn close thread */
56366+static int target_abort(struct iscsi_cmnd *req, int all)
56367+{
56368+ struct iscsi_target *target = req->conn->session->target;
56369+ struct iscsi_task_mgt_hdr *req_hdr =
56370+ (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
56371+ struct iscsi_session *session;
56372+ struct iscsi_conn *conn;
56373+ struct iscsi_cmnd *cmnd;
56374+
56375+ mutex_lock(&target->target_mutex);
56376+
56377+ list_for_each_entry(session, &target->session_list,
56378+ session_list_entry) {
56379+ list_for_each_entry(conn, &session->conn_list,
56380+ conn_list_entry) {
56381+ spin_lock_bh(&conn->cmd_list_lock);
56382+ list_for_each_entry(cmnd, &conn->cmd_list,
56383+ cmd_list_entry) {
56384+ if (cmnd == req)
56385+ continue;
56386+ if (all)
56387+ __cmnd_abort(cmnd);
56388+ else if (req_hdr->lun == cmnd_hdr(cmnd)->lun)
56389+ __cmnd_abort(cmnd);
56390+ }
56391+ spin_unlock_bh(&conn->cmd_list_lock);
56392+ }
56393+ }
56394+
56395+ mutex_unlock(&target->target_mutex);
56396+ return 0;
56397+}
56398+
56399+/* Must be called from the read or conn close thread */
56400+static void task_set_abort(struct iscsi_cmnd *req)
56401+{
56402+ struct iscsi_session *session = req->conn->session;
56403+ struct iscsi_task_mgt_hdr *req_hdr =
56404+ (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
56405+ struct iscsi_target *target = session->target;
56406+ struct iscsi_conn *conn;
56407+ struct iscsi_cmnd *cmnd;
56408+
56409+ mutex_lock(&target->target_mutex);
56410+
56411+ list_for_each_entry(conn, &session->conn_list, conn_list_entry) {
56412+ spin_lock_bh(&conn->cmd_list_lock);
56413+ list_for_each_entry(cmnd, &conn->cmd_list, cmd_list_entry) {
56414+ struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd);
56415+ if (cmnd == req)
56416+ continue;
56417+ if (req_hdr->lun != hdr->lun)
56418+ continue;
56419+ if (before(req_hdr->cmd_sn, hdr->cmd_sn) ||
56420+ req_hdr->cmd_sn == hdr->cmd_sn)
56421+ continue;
56422+ __cmnd_abort(cmnd);
56423+ }
56424+ spin_unlock_bh(&conn->cmd_list_lock);
56425+ }
56426+
56427+ mutex_unlock(&target->target_mutex);
56428+ return;
56429+}
56430+
56431+/* Must be called from the read or conn close thread */
56432+void conn_abort(struct iscsi_conn *conn)
56433+{
56434+ struct iscsi_cmnd *cmnd, *r, *t;
56435+
56436+ TRACE_MGMT_DBG("Aborting conn %p", conn);
56437+
56438+ iscsi_extracheck_is_rd_thread(conn);
56439+
56440+ cancel_delayed_work_sync(&conn->nop_in_delayed_work);
56441+
56442+ /* No locks, we are the only user */
56443+ list_for_each_entry_safe(r, t, &conn->nop_req_list,
56444+ nop_req_list_entry) {
56445+ list_del(&r->nop_req_list_entry);
56446+ cmnd_put(r);
56447+ }
56448+
56449+ spin_lock_bh(&conn->cmd_list_lock);
56450+again:
56451+ list_for_each_entry(cmnd, &conn->cmd_list, cmd_list_entry) {
56452+ __cmnd_abort(cmnd);
56453+ if (cmnd->r2t_len_to_receive != 0) {
56454+ if (!cmnd_get_check(cmnd)) {
56455+ spin_unlock_bh(&conn->cmd_list_lock);
56456+
56457+ /* ToDo: this is racy for MC/S */
56458+ iscsi_fail_data_waiting_cmnd(cmnd);
56459+
56460+ cmnd_put(cmnd);
56461+
56462+ /*
56463+ * We are in the read thread, so we may not
56464+ * worry that after cmnd release conn gets
56465+ * released as well.
56466+ */
56467+ spin_lock_bh(&conn->cmd_list_lock);
56468+ goto again;
56469+ }
56470+ }
56471+ }
56472+ spin_unlock_bh(&conn->cmd_list_lock);
56473+
56474+ return;
56475+}
56476+
56477+static void execute_task_management(struct iscsi_cmnd *req)
56478+{
56479+ struct iscsi_conn *conn = req->conn;
56480+ struct iscsi_session *sess = conn->session;
56481+ struct iscsi_task_mgt_hdr *req_hdr =
56482+ (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
56483+ int rc, status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56484+ int function = req_hdr->function & ISCSI_FUNCTION_MASK;
56485+ struct scst_rx_mgmt_params params;
56486+
56487+ TRACE(TRACE_MGMT, "iSCSI TM fn %d", function);
56488+
56489+ TRACE_MGMT_DBG("TM req %p, ITT %x, RTT %x, sn %u, con %p", req,
56490+ req->pdu.bhs.itt, req_hdr->rtt, req_hdr->cmd_sn, conn);
56491+
56492+ iscsi_extracheck_is_rd_thread(conn);
56493+
56494+ spin_lock(&sess->sn_lock);
56495+ sess->tm_active++;
56496+ sess->tm_sn = req_hdr->cmd_sn;
56497+ if (sess->tm_rsp != NULL) {
56498+ struct iscsi_cmnd *tm_rsp = sess->tm_rsp;
56499+
56500+ TRACE_MGMT_DBG("Dropping delayed TM rsp %p", tm_rsp);
56501+
56502+ sess->tm_rsp = NULL;
56503+ sess->tm_active--;
56504+
56505+ spin_unlock(&sess->sn_lock);
56506+
56507+ BUG_ON(sess->tm_active < 0);
56508+
56509+ rsp_cmnd_release(tm_rsp);
56510+ } else
56511+ spin_unlock(&sess->sn_lock);
56512+
56513+ memset(&params, 0, sizeof(params));
56514+ params.atomic = SCST_NON_ATOMIC;
56515+ params.tgt_priv = req;
56516+
56517+ if ((function != ISCSI_FUNCTION_ABORT_TASK) &&
56518+ (req_hdr->rtt != ISCSI_RESERVED_TAG)) {
56519+ PRINT_ERROR("Invalid RTT %x (TM fn %d)", req_hdr->rtt,
56520+ function);
56521+ rc = -1;
56522+ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56523+ goto reject;
56524+ }
56525+
56526+ /* cmd_sn is already in CPU format converted in cmnd_rx_start() */
56527+
56528+ switch (function) {
56529+ case ISCSI_FUNCTION_ABORT_TASK:
56530+ rc = cmnd_abort(req, &status);
56531+ if (rc == 0) {
56532+ params.fn = SCST_ABORT_TASK;
56533+ params.tag = (__force u32)req_hdr->rtt;
56534+ params.tag_set = 1;
56535+ params.lun = (uint8_t *)&req_hdr->lun;
56536+ params.lun_len = sizeof(req_hdr->lun);
56537+ params.lun_set = 1;
56538+ params.cmd_sn = req_hdr->cmd_sn;
56539+ params.cmd_sn_set = 1;
56540+ rc = scst_rx_mgmt_fn(conn->session->scst_sess,
56541+ &params);
56542+ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56543+ }
56544+ break;
56545+ case ISCSI_FUNCTION_ABORT_TASK_SET:
56546+ task_set_abort(req);
56547+ params.fn = SCST_ABORT_TASK_SET;
56548+ params.lun = (uint8_t *)&req_hdr->lun;
56549+ params.lun_len = sizeof(req_hdr->lun);
56550+ params.lun_set = 1;
56551+ params.cmd_sn = req_hdr->cmd_sn;
56552+ params.cmd_sn_set = 1;
56553+ rc = scst_rx_mgmt_fn(conn->session->scst_sess,
56554+ &params);
56555+ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56556+ break;
56557+ case ISCSI_FUNCTION_CLEAR_TASK_SET:
56558+ task_set_abort(req);
56559+ params.fn = SCST_CLEAR_TASK_SET;
56560+ params.lun = (uint8_t *)&req_hdr->lun;
56561+ params.lun_len = sizeof(req_hdr->lun);
56562+ params.lun_set = 1;
56563+ params.cmd_sn = req_hdr->cmd_sn;
56564+ params.cmd_sn_set = 1;
56565+ rc = scst_rx_mgmt_fn(conn->session->scst_sess,
56566+ &params);
56567+ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56568+ break;
56569+ case ISCSI_FUNCTION_CLEAR_ACA:
56570+ params.fn = SCST_CLEAR_ACA;
56571+ params.lun = (uint8_t *)&req_hdr->lun;
56572+ params.lun_len = sizeof(req_hdr->lun);
56573+ params.lun_set = 1;
56574+ params.cmd_sn = req_hdr->cmd_sn;
56575+ params.cmd_sn_set = 1;
56576+ rc = scst_rx_mgmt_fn(conn->session->scst_sess,
56577+ &params);
56578+ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56579+ break;
56580+ case ISCSI_FUNCTION_TARGET_COLD_RESET:
56581+ case ISCSI_FUNCTION_TARGET_WARM_RESET:
56582+ target_abort(req, 1);
56583+ params.fn = SCST_TARGET_RESET;
56584+ params.cmd_sn = req_hdr->cmd_sn;
56585+ params.cmd_sn_set = 1;
56586+ rc = scst_rx_mgmt_fn(conn->session->scst_sess,
56587+ &params);
56588+ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56589+ break;
56590+ case ISCSI_FUNCTION_LOGICAL_UNIT_RESET:
56591+ target_abort(req, 0);
56592+ params.fn = SCST_LUN_RESET;
56593+ params.lun = (uint8_t *)&req_hdr->lun;
56594+ params.lun_len = sizeof(req_hdr->lun);
56595+ params.lun_set = 1;
56596+ params.cmd_sn = req_hdr->cmd_sn;
56597+ params.cmd_sn_set = 1;
56598+ rc = scst_rx_mgmt_fn(conn->session->scst_sess,
56599+ &params);
56600+ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56601+ break;
56602+ case ISCSI_FUNCTION_TASK_REASSIGN:
56603+ rc = -1;
56604+ status = ISCSI_RESPONSE_ALLEGIANCE_REASSIGNMENT_UNSUPPORTED;
56605+ break;
56606+ default:
56607+ PRINT_ERROR("Unknown TM function %d", function);
56608+ rc = -1;
56609+ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
56610+ break;
56611+ }
56612+
56613+reject:
56614+ if (rc != 0)
56615+ iscsi_send_task_mgmt_resp(req, status);
56616+
56617+ return;
56618+}
56619+
56620+static void nop_out_exec(struct iscsi_cmnd *req)
56621+{
56622+ struct iscsi_cmnd *rsp;
56623+ struct iscsi_nop_in_hdr *rsp_hdr;
56624+
56625+ TRACE_ENTRY();
56626+
56627+ TRACE_DBG("%p", req);
56628+
56629+ if (req->pdu.bhs.itt != ISCSI_RESERVED_TAG) {
56630+ rsp = iscsi_alloc_main_rsp(req);
56631+
56632+ rsp_hdr = (struct iscsi_nop_in_hdr *)&rsp->pdu.bhs;
56633+ rsp_hdr->opcode = ISCSI_OP_NOP_IN;
56634+ rsp_hdr->flags = ISCSI_FLG_FINAL;
56635+ rsp_hdr->itt = req->pdu.bhs.itt;
56636+ rsp_hdr->ttt = ISCSI_RESERVED_TAG;
56637+
56638+ if (req->pdu.datasize)
56639+ BUG_ON(req->sg == NULL);
56640+ else
56641+ BUG_ON(req->sg != NULL);
56642+
56643+ if (req->sg) {
56644+ rsp->sg = req->sg;
56645+ rsp->sg_cnt = req->sg_cnt;
56646+ rsp->bufflen = req->bufflen;
56647+ }
56648+
56649+ /* We already checked it in check_segment_length() */
56650+ BUG_ON(get_pgcnt(req->pdu.datasize, 0) > ISCSI_CONN_IOV_MAX);
56651+
56652+ rsp->pdu.datasize = req->pdu.datasize;
56653+ } else {
56654+ bool found = false;
56655+ struct iscsi_cmnd *r;
56656+ struct iscsi_conn *conn = req->conn;
56657+
56658+ TRACE_DBG("Receive Nop-In response (ttt 0x%08x)",
56659+ be32_to_cpu(req->pdu.bhs.ttt));
56660+
56661+ spin_lock_bh(&conn->nop_req_list_lock);
56662+ list_for_each_entry(r, &conn->nop_req_list,
56663+ nop_req_list_entry) {
56664+ if (req->pdu.bhs.ttt == r->pdu.bhs.ttt) {
56665+ list_del(&r->nop_req_list_entry);
56666+ found = true;
56667+ break;
56668+ }
56669+ }
56670+ spin_unlock_bh(&conn->nop_req_list_lock);
56671+
56672+ if (found)
56673+ cmnd_put(r);
56674+ else
56675+ TRACE_MGMT_DBG("%s", "Got Nop-out response without "
56676+ "corresponding Nop-In request");
56677+ }
56678+
56679+ req_cmnd_release(req);
56680+
56681+ TRACE_EXIT();
56682+ return;
56683+}
56684+
56685+static void logout_exec(struct iscsi_cmnd *req)
56686+{
56687+ struct iscsi_logout_req_hdr *req_hdr;
56688+ struct iscsi_cmnd *rsp;
56689+ struct iscsi_logout_rsp_hdr *rsp_hdr;
56690+
56691+ PRINT_INFO("Logout received from initiator %s",
56692+ req->conn->session->initiator_name);
56693+ TRACE_DBG("%p", req);
56694+
56695+ req_hdr = (struct iscsi_logout_req_hdr *)&req->pdu.bhs;
56696+ rsp = iscsi_alloc_main_rsp(req);
56697+ rsp_hdr = (struct iscsi_logout_rsp_hdr *)&rsp->pdu.bhs;
56698+ rsp_hdr->opcode = ISCSI_OP_LOGOUT_RSP;
56699+ rsp_hdr->flags = ISCSI_FLG_FINAL;
56700+ rsp_hdr->itt = req_hdr->itt;
56701+ rsp->should_close_conn = 1;
56702+
56703+ req_cmnd_release(req);
56704+
56705+ return;
56706+}
56707+
56708+static void iscsi_cmnd_exec(struct iscsi_cmnd *cmnd)
56709+{
56710+ TRACE_ENTRY();
56711+
56712+ TRACE_DBG("cmnd %p, op %x, SN %u", cmnd, cmnd_opcode(cmnd),
56713+ cmnd->pdu.bhs.sn);
56714+
56715+ iscsi_extracheck_is_rd_thread(cmnd->conn);
56716+
56717+ if (cmnd_opcode(cmnd) == ISCSI_OP_SCSI_CMD) {
56718+ if (cmnd->r2t_len_to_receive == 0)
56719+ iscsi_restart_cmnd(cmnd);
56720+ else if (cmnd->r2t_len_to_send != 0)
56721+ send_r2t(cmnd);
56722+ goto out;
56723+ }
56724+
56725+ if (cmnd->prelim_compl_flags != 0) {
56726+ TRACE_MGMT_DBG("Terminating prelim completed non-SCSI cmnd %p "
56727+ "(op %x)", cmnd, cmnd_opcode(cmnd));
56728+ req_cmnd_release(cmnd);
56729+ goto out;
56730+ }
56731+
56732+ switch (cmnd_opcode(cmnd)) {
56733+ case ISCSI_OP_NOP_OUT:
56734+ nop_out_exec(cmnd);
56735+ break;
56736+ case ISCSI_OP_SCSI_TASK_MGT_MSG:
56737+ execute_task_management(cmnd);
56738+ break;
56739+ case ISCSI_OP_LOGOUT_CMD:
56740+ logout_exec(cmnd);
56741+ break;
56742+ default:
56743+ PRINT_CRIT_ERROR("Unexpected cmnd op %x", cmnd_opcode(cmnd));
56744+ BUG();
56745+ break;
56746+ }
56747+
56748+out:
56749+ TRACE_EXIT();
56750+ return;
56751+}
56752+
56753+static void set_cork(struct socket *sock, int on)
56754+{
56755+ int opt = on;
56756+ mm_segment_t oldfs;
56757+
56758+ oldfs = get_fs();
56759+ set_fs(get_ds());
56760+ sock->ops->setsockopt(sock, SOL_TCP, TCP_CORK,
56761+ (void __force __user *)&opt, sizeof(opt));
56762+ set_fs(oldfs);
56763+ return;
56764+}
56765+
56766+void cmnd_tx_start(struct iscsi_cmnd *cmnd)
56767+{
56768+ struct iscsi_conn *conn = cmnd->conn;
56769+
56770+ TRACE_DBG("conn %p, cmnd %p, opcode %x", conn, cmnd, cmnd_opcode(cmnd));
56771+ iscsi_cmnd_set_length(&cmnd->pdu);
56772+
56773+ iscsi_extracheck_is_wr_thread(conn);
56774+
56775+ set_cork(conn->sock, 1);
56776+
56777+ conn->write_iop = conn->write_iov;
56778+ conn->write_iop->iov_base = (void __force __user *)(&cmnd->pdu.bhs);
56779+ conn->write_iop->iov_len = sizeof(cmnd->pdu.bhs);
56780+ conn->write_iop_used = 1;
56781+ conn->write_size = sizeof(cmnd->pdu.bhs) + cmnd->pdu.datasize;
56782+ conn->write_offset = 0;
56783+
56784+ switch (cmnd_opcode(cmnd)) {
56785+ case ISCSI_OP_NOP_IN:
56786+ if (cmnd->pdu.bhs.itt == ISCSI_RESERVED_TAG)
56787+ cmnd->pdu.bhs.sn = (__force u32)cmnd_set_sn(cmnd, 0);
56788+ else
56789+ cmnd_set_sn(cmnd, 1);
56790+ break;
56791+ case ISCSI_OP_SCSI_RSP:
56792+ cmnd_set_sn(cmnd, 1);
56793+ break;
56794+ case ISCSI_OP_SCSI_TASK_MGT_RSP:
56795+ cmnd_set_sn(cmnd, 1);
56796+ break;
56797+ case ISCSI_OP_TEXT_RSP:
56798+ cmnd_set_sn(cmnd, 1);
56799+ break;
56800+ case ISCSI_OP_SCSI_DATA_IN:
56801+ {
56802+ struct iscsi_data_in_hdr *rsp =
56803+ (struct iscsi_data_in_hdr *)&cmnd->pdu.bhs;
56804+ u32 offset = be32_to_cpu(rsp->buffer_offset);
56805+
56806+ TRACE_DBG("cmnd %p, offset %u, datasize %u, bufflen %u", cmnd,
56807+ offset, cmnd->pdu.datasize, cmnd->bufflen);
56808+
56809+ BUG_ON(offset > cmnd->bufflen);
56810+ BUG_ON(offset + cmnd->pdu.datasize > cmnd->bufflen);
56811+
56812+ conn->write_offset = offset;
56813+
56814+ cmnd_set_sn(cmnd, (rsp->flags & ISCSI_FLG_FINAL) ? 1 : 0);
56815+ break;
56816+ }
56817+ case ISCSI_OP_LOGOUT_RSP:
56818+ cmnd_set_sn(cmnd, 1);
56819+ break;
56820+ case ISCSI_OP_R2T:
56821+ cmnd->pdu.bhs.sn = (__force u32)cmnd_set_sn(cmnd, 0);
56822+ break;
56823+ case ISCSI_OP_ASYNC_MSG:
56824+ cmnd_set_sn(cmnd, 1);
56825+ break;
56826+ case ISCSI_OP_REJECT:
56827+ cmnd_set_sn(cmnd, 1);
56828+ break;
56829+ default:
56830+ PRINT_ERROR("Unexpected cmnd op %x", cmnd_opcode(cmnd));
56831+ break;
56832+ }
56833+
56834+ iscsi_dump_pdu(&cmnd->pdu);
56835+ return;
56836+}
56837+
56838+void cmnd_tx_end(struct iscsi_cmnd *cmnd)
56839+{
56840+ struct iscsi_conn *conn = cmnd->conn;
56841+
56842+ TRACE_DBG("%p:%x (should_close_conn %d, should_close_all_conn %d)",
56843+ cmnd, cmnd_opcode(cmnd), cmnd->should_close_conn,
56844+ cmnd->should_close_all_conn);
56845+
56846+#ifdef CONFIG_SCST_EXTRACHECKS
56847+ switch (cmnd_opcode(cmnd)) {
56848+ case ISCSI_OP_NOP_IN:
56849+ case ISCSI_OP_SCSI_RSP:
56850+ case ISCSI_OP_SCSI_TASK_MGT_RSP:
56851+ case ISCSI_OP_TEXT_RSP:
56852+ case ISCSI_OP_R2T:
56853+ case ISCSI_OP_ASYNC_MSG:
56854+ case ISCSI_OP_REJECT:
56855+ case ISCSI_OP_SCSI_DATA_IN:
56856+ case ISCSI_OP_LOGOUT_RSP:
56857+ break;
56858+ default:
56859+ PRINT_CRIT_ERROR("unexpected cmnd op %x", cmnd_opcode(cmnd));
56860+ BUG();
56861+ break;
56862+ }
56863+#endif
56864+
56865+ if (unlikely(cmnd->should_close_conn)) {
56866+ if (cmnd->should_close_all_conn) {
56867+ PRINT_INFO("Closing all connections for target %x at "
56868+ "initiator's %s request",
56869+ cmnd->conn->session->target->tid,
56870+ conn->session->initiator_name);
56871+ target_del_all_sess(cmnd->conn->session->target, 0);
56872+ } else {
56873+ PRINT_INFO("Closing connection at initiator's %s "
56874+ "request", conn->session->initiator_name);
56875+ mark_conn_closed(conn);
56876+ }
56877+ }
56878+
56879+ set_cork(cmnd->conn->sock, 0);
56880+ return;
56881+}
56882+
56883+/*
56884+ * Push the command for execution. This functions reorders the commands.
56885+ * Called from the read thread.
56886+ *
56887+ * Basically, since we don't support MC/S and TCP guarantees data delivery
56888+ * order, all that SN's stuff isn't needed at all (commands delivery order is
56889+ * a natural commands execution order), but insane iSCSI spec requires
56890+ * us to check it and we have to, because some crazy initiators can rely
56891+ * on the SN's based order and reorder requests during sending. For all other
56892+ * normal initiators all that code is a NOP.
56893+ */
56894+static void iscsi_push_cmnd(struct iscsi_cmnd *cmnd)
56895+{
56896+ struct iscsi_session *session = cmnd->conn->session;
56897+ struct list_head *entry;
56898+ u32 cmd_sn;
56899+
56900+ TRACE_DBG("cmnd %p, iSCSI opcode %x, sn %u, exp sn %u", cmnd,
56901+ cmnd_opcode(cmnd), cmnd->pdu.bhs.sn, session->exp_cmd_sn);
56902+
56903+ iscsi_extracheck_is_rd_thread(cmnd->conn);
56904+
56905+ BUG_ON(cmnd->parent_req != NULL);
56906+
56907+ if (cmnd->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE) {
56908+ TRACE_DBG("Immediate cmd %p (cmd_sn %u)", cmnd,
56909+ cmnd->pdu.bhs.sn);
56910+ iscsi_cmnd_exec(cmnd);
56911+ goto out;
56912+ }
56913+
56914+ spin_lock(&session->sn_lock);
56915+
56916+ cmd_sn = cmnd->pdu.bhs.sn;
56917+ if (cmd_sn == session->exp_cmd_sn) {
56918+ while (1) {
56919+ session->exp_cmd_sn = ++cmd_sn;
56920+
56921+ if (unlikely(session->tm_active > 0)) {
56922+ if (before(cmd_sn, session->tm_sn)) {
56923+ struct iscsi_conn *conn = cmnd->conn;
56924+
56925+ spin_unlock(&session->sn_lock);
56926+
56927+ spin_lock_bh(&conn->cmd_list_lock);
56928+ __cmnd_abort(cmnd);
56929+ spin_unlock_bh(&conn->cmd_list_lock);
56930+
56931+ spin_lock(&session->sn_lock);
56932+ }
56933+ iscsi_check_send_delayed_tm_resp(session);
56934+ }
56935+
56936+ spin_unlock(&session->sn_lock);
56937+
56938+ iscsi_cmnd_exec(cmnd);
56939+
56940+ spin_lock(&session->sn_lock);
56941+
56942+ if (list_empty(&session->pending_list))
56943+ break;
56944+ cmnd = list_entry(session->pending_list.next,
56945+ struct iscsi_cmnd,
56946+ pending_list_entry);
56947+ if (cmnd->pdu.bhs.sn != cmd_sn)
56948+ break;
56949+
56950+ list_del(&cmnd->pending_list_entry);
56951+ cmnd->pending = 0;
56952+
56953+ TRACE_MGMT_DBG("Processing pending cmd %p (cmd_sn %u)",
56954+ cmnd, cmd_sn);
56955+ }
56956+ } else {
56957+ int drop = 0;
56958+
56959+ TRACE_DBG("Pending cmd %p (cmd_sn %u, exp_cmd_sn %u)",
56960+ cmnd, cmd_sn, session->exp_cmd_sn);
56961+
56962+ /*
56963+ * iSCSI RFC 3720: "The target MUST silently ignore any
56964+ * non-immediate command outside of [from ExpCmdSN to MaxCmdSN
56965+ * inclusive] range". But we won't honor the MaxCmdSN
56966+ * requirement, because, since we adjust MaxCmdSN from the
56967+ * separate write thread, rarely it is possible that initiator
56968+ * can legally send command with CmdSN>MaxSN. But it won't
56969+ * hurt anything, in the worst case it will lead to
56970+ * additional QUEUE FULL status.
56971+ */
56972+
56973+ if (unlikely(before(cmd_sn, session->exp_cmd_sn))) {
56974+ TRACE_MGMT_DBG("Ignoring out of expected range cmd_sn "
56975+ "(sn %u, exp_sn %u, op %x, CDB op %x)", cmd_sn,
56976+ session->exp_cmd_sn, cmnd_opcode(cmnd),
56977+ cmnd_scsicode(cmnd));
56978+ drop = 1;
56979+ }
56980+
56981+#if 0
56982+ if (unlikely(after(cmd_sn, session->exp_cmd_sn +
56983+ iscsi_get_allowed_cmds(session)))) {
56984+ TRACE_MGMT_DBG("Too large cmd_sn %u (exp_cmd_sn %u, "
56985+ "max_sn %u)", cmd_sn, session->exp_cmd_sn,
56986+ iscsi_get_allowed_cmds(session));
56987+ drop = 1;
56988+ }
56989+#endif
56990+
56991+ spin_unlock(&session->sn_lock);
56992+
56993+ if (unlikely(drop)) {
56994+ req_cmnd_release_force(cmnd);
56995+ goto out;
56996+ }
56997+
56998+ if (unlikely(test_bit(ISCSI_CMD_ABORTED,
56999+ &cmnd->prelim_compl_flags))) {
57000+ struct iscsi_cmnd *tm_clone;
57001+
57002+ TRACE_MGMT_DBG("Aborted pending cmnd %p, creating TM "
57003+ "clone (scst cmd %p, state %d)", cmnd,
57004+ cmnd->scst_cmd, cmnd->scst_state);
57005+
57006+ tm_clone = iscsi_create_tm_clone(cmnd);
57007+ if (tm_clone != NULL) {
57008+ iscsi_cmnd_exec(cmnd);
57009+ cmnd = tm_clone;
57010+ }
57011+ }
57012+
57013+ TRACE_MGMT_DBG("Pending cmnd %p (op %x, sn %u, exp sn %u)",
57014+ cmnd, cmnd_opcode(cmnd), cmd_sn, session->exp_cmd_sn);
57015+
57016+ spin_lock(&session->sn_lock);
57017+ list_for_each(entry, &session->pending_list) {
57018+ struct iscsi_cmnd *tmp =
57019+ list_entry(entry, struct iscsi_cmnd,
57020+ pending_list_entry);
57021+ if (before(cmd_sn, tmp->pdu.bhs.sn))
57022+ break;
57023+ }
57024+ list_add_tail(&cmnd->pending_list_entry, entry);
57025+ cmnd->pending = 1;
57026+ }
57027+
57028+ spin_unlock(&session->sn_lock);
57029+out:
57030+ return;
57031+}
57032+
57033+static int check_segment_length(struct iscsi_cmnd *cmnd)
57034+{
57035+ struct iscsi_conn *conn = cmnd->conn;
57036+ struct iscsi_session *session = conn->session;
57037+
57038+ if (unlikely(cmnd->pdu.datasize > session->sess_params.max_recv_data_length)) {
57039+ PRINT_ERROR("Initiator %s violated negotiated parameters: "
57040+ "data too long (ITT %x, datasize %u, "
57041+ "max_recv_data_length %u", session->initiator_name,
57042+ cmnd->pdu.bhs.itt, cmnd->pdu.datasize,
57043+ session->sess_params.max_recv_data_length);
57044+ mark_conn_closed(conn);
57045+ return -EINVAL;
57046+ }
57047+ return 0;
57048+}
57049+
57050+int cmnd_rx_start(struct iscsi_cmnd *cmnd)
57051+{
57052+ int res, rc = 0;
57053+
57054+ iscsi_dump_pdu(&cmnd->pdu);
57055+
57056+ res = check_segment_length(cmnd);
57057+ if (res != 0)
57058+ goto out;
57059+
57060+ cmnd->pdu.bhs.sn = be32_to_cpu((__force __be32)cmnd->pdu.bhs.sn);
57061+
57062+ switch (cmnd_opcode(cmnd)) {
57063+ case ISCSI_OP_SCSI_CMD:
57064+ res = scsi_cmnd_start(cmnd);
57065+ if (unlikely(res < 0))
57066+ goto out;
57067+ update_stat_sn(cmnd);
57068+ break;
57069+ case ISCSI_OP_SCSI_DATA_OUT:
57070+ res = data_out_start(cmnd);
57071+ goto out;
57072+ case ISCSI_OP_NOP_OUT:
57073+ rc = nop_out_start(cmnd);
57074+ break;
57075+ case ISCSI_OP_SCSI_TASK_MGT_MSG:
57076+ case ISCSI_OP_LOGOUT_CMD:
57077+ update_stat_sn(cmnd);
57078+ break;
57079+ case ISCSI_OP_TEXT_CMD:
57080+ case ISCSI_OP_SNACK_CMD:
57081+ default:
57082+ rc = -ISCSI_REASON_UNSUPPORTED_COMMAND;
57083+ break;
57084+ }
57085+
57086+ if (unlikely(rc < 0)) {
57087+ PRINT_ERROR("Error %d (iSCSI opcode %x, ITT %x)", rc,
57088+ cmnd_opcode(cmnd), cmnd->pdu.bhs.itt);
57089+ res = create_reject_rsp(cmnd, -rc, true);
57090+ }
57091+
57092+out:
57093+ TRACE_EXIT_RES(res);
57094+ return res;
57095+}
57096+
57097+void cmnd_rx_end(struct iscsi_cmnd *cmnd)
57098+{
57099+ TRACE_ENTRY();
57100+
57101+ TRACE_DBG("cmnd %p, opcode %x", cmnd, cmnd_opcode(cmnd));
57102+
57103+ cmnd->conn->last_rcv_time = jiffies;
57104+ TRACE_DBG("Updated last_rcv_time %ld", cmnd->conn->last_rcv_time);
57105+
57106+ switch (cmnd_opcode(cmnd)) {
57107+ case ISCSI_OP_SCSI_CMD:
57108+ case ISCSI_OP_NOP_OUT:
57109+ case ISCSI_OP_SCSI_TASK_MGT_MSG:
57110+ case ISCSI_OP_LOGOUT_CMD:
57111+ iscsi_push_cmnd(cmnd);
57112+ goto out;
57113+ case ISCSI_OP_SCSI_DATA_OUT:
57114+ data_out_end(cmnd);
57115+ break;
57116+ default:
57117+ PRINT_ERROR("Unexpected cmnd op %x", cmnd_opcode(cmnd));
57118+ break;
57119+ }
57120+
57121+ req_cmnd_release(cmnd);
57122+
57123+out:
57124+ TRACE_EXIT();
57125+ return;
57126+}
57127+
57128+#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
57129+static int iscsi_alloc_data_buf(struct scst_cmd *cmd)
57130+{
57131+ /*
57132+ * sock->ops->sendpage() is async zero copy operation,
57133+ * so we must be sure not to free and reuse
57134+ * the command's buffer before the sending was completed
57135+ * by the network layers. It is possible only if we
57136+ * don't use SGV cache.
57137+ */
57138+ EXTRACHECKS_BUG_ON(!(scst_cmd_get_data_direction(cmd) & SCST_DATA_READ));
57139+ scst_cmd_set_no_sgv(cmd);
57140+ return 1;
57141+}
57142+#endif
57143+
57144+static void iscsi_preprocessing_done(struct scst_cmd *scst_cmd)
57145+{
57146+ struct iscsi_cmnd *req = (struct iscsi_cmnd *)
57147+ scst_cmd_get_tgt_priv(scst_cmd);
57148+
57149+ TRACE_DBG("req %p", req);
57150+
57151+ if (req->conn->rx_task == current)
57152+ req->scst_state = ISCSI_CMD_STATE_AFTER_PREPROC;
57153+ else {
57154+ /*
57155+ * We wait for the state change without any protection, so
57156+ * without cmnd_get() it is possible that req will die
57157+ * "immediately" after the state assignment and
57158+ * iscsi_make_conn_rd_active() will operate on dead data.
57159+ * We use the ordered version of cmnd_get(), because "get"
57160+ * must be done before the state assignment.
57161+ *
57162+ * We protected from the race on calling cmnd_rx_continue(),
57163+ * because there can be only one read thread processing
57164+ * connection.
57165+ */
57166+ cmnd_get(req);
57167+ req->scst_state = ISCSI_CMD_STATE_AFTER_PREPROC;
57168+ iscsi_make_conn_rd_active(req->conn);
57169+ if (unlikely(req->conn->closing)) {
57170+ TRACE_DBG("Waking up closing conn %p", req->conn);
57171+ wake_up(&req->conn->read_state_waitQ);
57172+ }
57173+ cmnd_put(req);
57174+ }
57175+
57176+ return;
57177+}
57178+
57179+/* No locks */
57180+static void iscsi_try_local_processing(struct iscsi_cmnd *req)
57181+{
57182+ struct iscsi_conn *conn = req->conn;
57183+ bool local;
57184+
57185+ TRACE_ENTRY();
57186+
57187+ spin_lock_bh(&iscsi_wr_lock);
57188+ switch (conn->wr_state) {
57189+ case ISCSI_CONN_WR_STATE_IN_LIST:
57190+ list_del(&conn->wr_list_entry);
57191+ /* go through */
57192+ case ISCSI_CONN_WR_STATE_IDLE:
57193+#ifdef CONFIG_SCST_EXTRACHECKS
57194+ conn->wr_task = current;
57195+#endif
57196+ conn->wr_state = ISCSI_CONN_WR_STATE_PROCESSING;
57197+ conn->wr_space_ready = 0;
57198+ local = true;
57199+ break;
57200+ default:
57201+ local = false;
57202+ break;
57203+ }
57204+ spin_unlock_bh(&iscsi_wr_lock);
57205+
57206+ if (local) {
57207+ int rc = 1;
57208+
57209+ do {
57210+ rc = iscsi_send(conn);
57211+ if (rc <= 0)
57212+ break;
57213+ } while (req->not_processed_rsp_cnt != 0);
57214+
57215+ spin_lock_bh(&iscsi_wr_lock);
57216+#ifdef CONFIG_SCST_EXTRACHECKS
57217+ conn->wr_task = NULL;
57218+#endif
57219+ if ((rc == -EAGAIN) && !conn->wr_space_ready) {
57220+ TRACE_DBG("EAGAIN, setting WR_STATE_SPACE_WAIT "
57221+ "(conn %p)", conn);
57222+ conn->wr_state = ISCSI_CONN_WR_STATE_SPACE_WAIT;
57223+ } else if (test_write_ready(conn)) {
57224+ list_add_tail(&conn->wr_list_entry, &iscsi_wr_list);
57225+ conn->wr_state = ISCSI_CONN_WR_STATE_IN_LIST;
57226+ wake_up(&iscsi_wr_waitQ);
57227+ } else
57228+ conn->wr_state = ISCSI_CONN_WR_STATE_IDLE;
57229+ spin_unlock_bh(&iscsi_wr_lock);
57230+ }
57231+
57232+ TRACE_EXIT();
57233+ return;
57234+}
57235+
57236+static int iscsi_xmit_response(struct scst_cmd *scst_cmd)
57237+{
57238+ int is_send_status = scst_cmd_get_is_send_status(scst_cmd);
57239+ struct iscsi_cmnd *req = (struct iscsi_cmnd *)
57240+ scst_cmd_get_tgt_priv(scst_cmd);
57241+ struct iscsi_conn *conn = req->conn;
57242+ int status = scst_cmd_get_status(scst_cmd);
57243+ u8 *sense = scst_cmd_get_sense_buffer(scst_cmd);
57244+ int sense_len = scst_cmd_get_sense_buffer_len(scst_cmd);
57245+ struct iscsi_cmnd *wr_rsp, *our_rsp;
57246+
57247+ EXTRACHECKS_BUG_ON(scst_cmd_atomic(scst_cmd));
57248+
57249+ scst_cmd_set_tgt_priv(scst_cmd, NULL);
57250+
57251+ EXTRACHECKS_BUG_ON(req->scst_state != ISCSI_CMD_STATE_RESTARTED);
57252+
57253+ if (unlikely(scst_cmd_aborted(scst_cmd)))
57254+ set_bit(ISCSI_CMD_ABORTED, &req->prelim_compl_flags);
57255+
57256+ if (unlikely(req->prelim_compl_flags != 0)) {
57257+ if (test_bit(ISCSI_CMD_ABORTED, &req->prelim_compl_flags)) {
57258+ TRACE_MGMT_DBG("req %p (scst_cmd %p) aborted", req,
57259+ req->scst_cmd);
57260+ scst_set_delivery_status(req->scst_cmd,
57261+ SCST_CMD_DELIVERY_ABORTED);
57262+ req->scst_state = ISCSI_CMD_STATE_PROCESSED;
57263+ req_cmnd_release_force(req);
57264+ goto out;
57265+ }
57266+
57267+ TRACE_DBG("Prelim completed req %p", req);
57268+
57269+ /*
57270+ * We could preliminary have finished req before we
57271+ * knew its device, so check if we return correct sense
57272+ * format.
57273+ */
57274+ scst_check_convert_sense(scst_cmd);
57275+
57276+ if (!req->own_sg) {
57277+ req->sg = scst_cmd_get_sg(scst_cmd);
57278+ req->sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
57279+ }
57280+ } else {
57281+ EXTRACHECKS_BUG_ON(req->own_sg);
57282+ req->sg = scst_cmd_get_sg(scst_cmd);
57283+ req->sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
57284+ }
57285+
57286+ req->bufflen = scst_cmd_get_adjusted_resp_data_len(scst_cmd);
57287+
57288+ req->scst_state = ISCSI_CMD_STATE_PROCESSED;
57289+
57290+ TRACE_DBG("req %p, is_send_status=%x, req->bufflen=%d, req->sg=%p, "
57291+ "req->sg_cnt %d", req, is_send_status, req->bufflen, req->sg,
57292+ req->sg_cnt);
57293+
57294+ EXTRACHECKS_BUG_ON(req->hashed);
57295+ if (req->main_rsp != NULL)
57296+ EXTRACHECKS_BUG_ON(cmnd_opcode(req->main_rsp) != ISCSI_OP_REJECT);
57297+
57298+ if (unlikely((req->bufflen != 0) && !is_send_status)) {
57299+ PRINT_CRIT_ERROR("%s", "Sending DATA without STATUS is "
57300+ "unsupported");
57301+ scst_set_cmd_error(scst_cmd,
57302+ SCST_LOAD_SENSE(scst_sense_hardw_error));
57303+ BUG(); /* ToDo */
57304+ }
57305+
57306+ /*
57307+ * We need to decrement active_cmds before adding any responses into
57308+ * the write queue to eliminate a race, when all responses sent
57309+ * with wrong MaxCmdSN.
57310+ */
57311+ if (likely(req->dec_active_cmds))
57312+ iscsi_dec_active_cmds(req);
57313+
57314+ if (req->bufflen != 0) {
57315+ /*
57316+ * Check above makes sure that is_send_status is set,
57317+ * so status is valid here, but in future that could change.
57318+ * ToDo
57319+ */
57320+ if ((status != SAM_STAT_CHECK_CONDITION) &&
57321+ ((cmnd_hdr(req)->flags & (ISCSI_CMD_WRITE|ISCSI_CMD_READ)) !=
57322+ (ISCSI_CMD_WRITE|ISCSI_CMD_READ))) {
57323+ send_data_rsp(req, status, is_send_status);
57324+ } else {
57325+ struct iscsi_cmnd *rsp;
57326+ send_data_rsp(req, 0, 0);
57327+ if (is_send_status) {
57328+ rsp = create_status_rsp(req, status, sense,
57329+ sense_len);
57330+ iscsi_cmnd_init_write(rsp, 0);
57331+ }
57332+ }
57333+ } else if (is_send_status) {
57334+ struct iscsi_cmnd *rsp;
57335+ rsp = create_status_rsp(req, status, sense, sense_len);
57336+ iscsi_cmnd_init_write(rsp, 0);
57337+ }
57338+#ifdef CONFIG_SCST_EXTRACHECKS
57339+ else
57340+ BUG();
57341+#endif
57342+
57343+ /*
57344+ * There's no need for protection, since we are not going to
57345+ * dereference them.
57346+ */
57347+ wr_rsp = list_entry(conn->write_list.next, struct iscsi_cmnd,
57348+ write_list_entry);
57349+ our_rsp = list_entry(req->rsp_cmd_list.next, struct iscsi_cmnd,
57350+ rsp_cmd_list_entry);
57351+ if (wr_rsp == our_rsp) {
57352+ /*
57353+ * This is our rsp, so let's try to process it locally to
57354+ * decrease latency. We need to call pre_release before
57355+ * processing to handle some error recovery cases.
57356+ */
57357+ if (scst_get_active_cmd_count(scst_cmd) <= 2) {
57358+ req_cmnd_pre_release(req);
57359+ iscsi_try_local_processing(req);
57360+ cmnd_put(req);
57361+ } else {
57362+ /*
57363+ * There's too much backend activity, so it could be
57364+ * better to push it to the write thread.
57365+ */
57366+ goto out_push_to_wr_thread;
57367+ }
57368+ } else
57369+ goto out_push_to_wr_thread;
57370+
57371+out:
57372+ return SCST_TGT_RES_SUCCESS;
57373+
57374+out_push_to_wr_thread:
57375+ TRACE_DBG("Waking up write thread (conn %p)", conn);
57376+ req_cmnd_release(req);
57377+ iscsi_make_conn_wr_active(conn);
57378+ goto out;
57379+}
57380+
57381+/* Called under sn_lock */
57382+static bool iscsi_is_delay_tm_resp(struct iscsi_cmnd *rsp)
57383+{
57384+ bool res = 0;
57385+ struct iscsi_task_mgt_hdr *req_hdr =
57386+ (struct iscsi_task_mgt_hdr *)&rsp->parent_req->pdu.bhs;
57387+ int function = req_hdr->function & ISCSI_FUNCTION_MASK;
57388+ struct iscsi_session *sess = rsp->conn->session;
57389+
57390+ TRACE_ENTRY();
57391+
57392+ /* This should be checked for immediate TM commands as well */
57393+
57394+ switch (function) {
57395+ default:
57396+ if (before(sess->exp_cmd_sn, req_hdr->cmd_sn))
57397+ res = 1;
57398+ break;
57399+ }
57400+
57401+ TRACE_EXIT_RES(res);
57402+ return res;
57403+}
57404+
57405+/* Called under sn_lock, but might drop it inside, then reaquire */
57406+static void iscsi_check_send_delayed_tm_resp(struct iscsi_session *sess)
57407+ __acquires(&sn_lock)
57408+ __releases(&sn_lock)
57409+{
57410+ struct iscsi_cmnd *tm_rsp = sess->tm_rsp;
57411+
57412+ TRACE_ENTRY();
57413+
57414+ if (tm_rsp == NULL)
57415+ goto out;
57416+
57417+ if (iscsi_is_delay_tm_resp(tm_rsp))
57418+ goto out;
57419+
57420+ TRACE_MGMT_DBG("Sending delayed rsp %p", tm_rsp);
57421+
57422+ sess->tm_rsp = NULL;
57423+ sess->tm_active--;
57424+
57425+ spin_unlock(&sess->sn_lock);
57426+
57427+ BUG_ON(sess->tm_active < 0);
57428+
57429+ iscsi_cmnd_init_write(tm_rsp, ISCSI_INIT_WRITE_WAKE);
57430+
57431+ spin_lock(&sess->sn_lock);
57432+
57433+out:
57434+ TRACE_EXIT();
57435+ return;
57436+}
57437+
57438+static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status)
57439+{
57440+ struct iscsi_cmnd *rsp;
57441+ struct iscsi_task_mgt_hdr *req_hdr =
57442+ (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
57443+ struct iscsi_task_rsp_hdr *rsp_hdr;
57444+ struct iscsi_session *sess = req->conn->session;
57445+ int fn = req_hdr->function & ISCSI_FUNCTION_MASK;
57446+
57447+ TRACE_ENTRY();
57448+
57449+ TRACE_MGMT_DBG("TM req %p finished", req);
57450+ TRACE(TRACE_MGMT, "iSCSI TM fn %d finished, status %d", fn, status);
57451+
57452+ rsp = iscsi_alloc_rsp(req);
57453+ rsp_hdr = (struct iscsi_task_rsp_hdr *)&rsp->pdu.bhs;
57454+
57455+ rsp_hdr->opcode = ISCSI_OP_SCSI_TASK_MGT_RSP;
57456+ rsp_hdr->flags = ISCSI_FLG_FINAL;
57457+ rsp_hdr->itt = req_hdr->itt;
57458+ rsp_hdr->response = status;
57459+
57460+ if (fn == ISCSI_FUNCTION_TARGET_COLD_RESET) {
57461+ rsp->should_close_conn = 1;
57462+ rsp->should_close_all_conn = 1;
57463+ }
57464+
57465+ BUG_ON(sess->tm_rsp != NULL);
57466+
57467+ spin_lock(&sess->sn_lock);
57468+ if (iscsi_is_delay_tm_resp(rsp)) {
57469+ TRACE_MGMT_DBG("Delaying TM fn %d response %p "
57470+ "(req %p), because not all affected commands "
57471+ "received (TM cmd sn %u, exp sn %u)",
57472+ req_hdr->function & ISCSI_FUNCTION_MASK, rsp, req,
57473+ req_hdr->cmd_sn, sess->exp_cmd_sn);
57474+ sess->tm_rsp = rsp;
57475+ spin_unlock(&sess->sn_lock);
57476+ goto out_release;
57477+ }
57478+ sess->tm_active--;
57479+ spin_unlock(&sess->sn_lock);
57480+
57481+ BUG_ON(sess->tm_active < 0);
57482+
57483+ iscsi_cmnd_init_write(rsp, ISCSI_INIT_WRITE_WAKE);
57484+
57485+out_release:
57486+ req_cmnd_release(req);
57487+
57488+ TRACE_EXIT();
57489+ return;
57490+}
57491+
57492+static inline int iscsi_get_mgmt_response(int status)
57493+{
57494+ switch (status) {
57495+ case SCST_MGMT_STATUS_SUCCESS:
57496+ return ISCSI_RESPONSE_FUNCTION_COMPLETE;
57497+
57498+ case SCST_MGMT_STATUS_TASK_NOT_EXIST:
57499+ return ISCSI_RESPONSE_UNKNOWN_TASK;
57500+
57501+ case SCST_MGMT_STATUS_LUN_NOT_EXIST:
57502+ return ISCSI_RESPONSE_UNKNOWN_LUN;
57503+
57504+ case SCST_MGMT_STATUS_FN_NOT_SUPPORTED:
57505+ return ISCSI_RESPONSE_FUNCTION_UNSUPPORTED;
57506+
57507+ case SCST_MGMT_STATUS_REJECTED:
57508+ case SCST_MGMT_STATUS_FAILED:
57509+ default:
57510+ return ISCSI_RESPONSE_FUNCTION_REJECTED;
57511+ }
57512+}
57513+
57514+static void iscsi_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd)
57515+{
57516+ int fn = scst_mgmt_cmd_get_fn(scst_mcmd);
57517+ struct iscsi_cmnd *req = (struct iscsi_cmnd *)
57518+ scst_mgmt_cmd_get_tgt_priv(scst_mcmd);
57519+ int status =
57520+ iscsi_get_mgmt_response(scst_mgmt_cmd_get_status(scst_mcmd));
57521+
57522+ if ((status == ISCSI_RESPONSE_UNKNOWN_TASK) &&
57523+ (fn == SCST_ABORT_TASK)) {
57524+ /* If we are here, we found the task, so must succeed */
57525+ status = ISCSI_RESPONSE_FUNCTION_COMPLETE;
57526+ }
57527+
57528+ TRACE_MGMT_DBG("req %p, scst_mcmd %p, fn %d, scst status %d, status %d",
57529+ req, scst_mcmd, fn, scst_mgmt_cmd_get_status(scst_mcmd),
57530+ status);
57531+
57532+ switch (fn) {
57533+ case SCST_NEXUS_LOSS_SESS:
57534+ case SCST_ABORT_ALL_TASKS_SESS:
57535+ /* They are internal */
57536+ break;
57537+ default:
57538+ iscsi_send_task_mgmt_resp(req, status);
57539+ scst_mgmt_cmd_set_tgt_priv(scst_mcmd, NULL);
57540+ break;
57541+ }
57542+ return;
57543+}
57544+
57545+static int iscsi_scsi_aen(struct scst_aen *aen)
57546+{
57547+ int res = SCST_AEN_RES_SUCCESS;
57548+ __be64 lun = scst_aen_get_lun(aen);
57549+ const uint8_t *sense = scst_aen_get_sense(aen);
57550+ int sense_len = scst_aen_get_sense_len(aen);
57551+ struct iscsi_session *sess = scst_sess_get_tgt_priv(
57552+ scst_aen_get_sess(aen));
57553+ struct iscsi_conn *conn;
57554+ bool found;
57555+ struct iscsi_cmnd *fake_req, *rsp;
57556+ struct iscsi_async_msg_hdr *rsp_hdr;
57557+ struct scatterlist *sg;
57558+
57559+ TRACE_ENTRY();
57560+
57561+ TRACE_MGMT_DBG("SCSI AEN to sess %p (initiator %s)", sess,
57562+ sess->initiator_name);
57563+
57564+ mutex_lock(&sess->target->target_mutex);
57565+
57566+ found = false;
57567+ list_for_each_entry_reverse(conn, &sess->conn_list, conn_list_entry) {
57568+ if (!test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags) &&
57569+ (conn->conn_reinst_successor == NULL)) {
57570+ found = true;
57571+ break;
57572+ }
57573+ }
57574+ if (!found) {
57575+ TRACE_MGMT_DBG("Unable to find alive conn for sess %p", sess);
57576+ goto out_err;
57577+ }
57578+
57579+ /* Create a fake request */
57580+ fake_req = cmnd_alloc(conn, NULL);
57581+ if (fake_req == NULL) {
57582+ PRINT_ERROR("%s", "Unable to alloc fake AEN request");
57583+ goto out_err;
57584+ }
57585+
57586+ mutex_unlock(&sess->target->target_mutex);
57587+
57588+ rsp = iscsi_alloc_main_rsp(fake_req);
57589+ if (rsp == NULL) {
57590+ PRINT_ERROR("%s", "Unable to alloc AEN rsp");
57591+ goto out_err_free_req;
57592+ }
57593+
57594+ fake_req->scst_state = ISCSI_CMD_STATE_AEN;
57595+ fake_req->scst_aen = aen;
57596+
57597+ rsp_hdr = (struct iscsi_async_msg_hdr *)&rsp->pdu.bhs;
57598+
57599+ rsp_hdr->opcode = ISCSI_OP_ASYNC_MSG;
57600+ rsp_hdr->flags = ISCSI_FLG_FINAL;
57601+ rsp_hdr->lun = lun; /* it's already in SCSI form */
57602+ rsp_hdr->ffffffff = __constant_cpu_to_be32(0xffffffff);
57603+ rsp_hdr->async_event = ISCSI_ASYNC_SCSI;
57604+
57605+ sg = rsp->sg = rsp->rsp_sg;
57606+ rsp->sg_cnt = 2;
57607+ rsp->own_sg = 1;
57608+
57609+ sg_init_table(sg, 2);
57610+ sg_set_buf(&sg[0], &rsp->sense_hdr, sizeof(rsp->sense_hdr));
57611+ sg_set_buf(&sg[1], sense, sense_len);
57612+
57613+ rsp->sense_hdr.length = cpu_to_be16(sense_len);
57614+ rsp->pdu.datasize = sizeof(rsp->sense_hdr) + sense_len;
57615+ rsp->bufflen = rsp->pdu.datasize;
57616+
57617+ req_cmnd_release(fake_req);
57618+
57619+out:
57620+ TRACE_EXIT_RES(res);
57621+ return res;
57622+
57623+out_err_free_req:
57624+ req_cmnd_release(fake_req);
57625+
57626+out_err:
57627+ mutex_unlock(&sess->target->target_mutex);
57628+ res = SCST_AEN_RES_FAILED;
57629+ goto out;
57630+}
57631+
57632+static int iscsi_report_aen(struct scst_aen *aen)
57633+{
57634+ int res;
57635+ int event_fn = scst_aen_get_event_fn(aen);
57636+
57637+ TRACE_ENTRY();
57638+
57639+ switch (event_fn) {
57640+ case SCST_AEN_SCSI:
57641+ res = iscsi_scsi_aen(aen);
57642+ break;
57643+ default:
57644+ TRACE_MGMT_DBG("Unsupported AEN %d", event_fn);
57645+ res = SCST_AEN_RES_NOT_SUPPORTED;
57646+ break;
57647+ }
57648+
57649+ TRACE_EXIT_RES(res);
57650+ return res;
57651+}
57652+
57653+static int iscsi_get_initiator_port_transport_id(struct scst_session *scst_sess,
57654+ uint8_t **transport_id)
57655+{
57656+ struct iscsi_session *sess;
57657+ int res = 0;
57658+ union iscsi_sid sid;
57659+ int tr_id_size;
57660+ uint8_t *tr_id;
57661+ uint8_t q;
57662+
57663+ TRACE_ENTRY();
57664+
57665+ if (scst_sess == NULL) {
57666+ res = SCSI_TRANSPORTID_PROTOCOLID_ISCSI;
57667+ goto out;
57668+ }
57669+
57670+ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
57671+
57672+ sid = *(union iscsi_sid *)&sess->sid;
57673+ sid.id.tsih = 0;
57674+
57675+ tr_id_size = 4 + strlen(sess->initiator_name) + 5 +
57676+ snprintf(&q, sizeof(q), "%llx", sid.id64) + 1;
57677+ tr_id_size = (tr_id_size + 3) & -4;
57678+
57679+ tr_id = kzalloc(tr_id_size, GFP_KERNEL);
57680+ if (tr_id == NULL) {
57681+ PRINT_ERROR("Allocation of TransportID (size %d) failed",
57682+ tr_id_size);
57683+ res = -ENOMEM;
57684+ goto out;
57685+ }
57686+
57687+ tr_id[0] = 0x40 | SCSI_TRANSPORTID_PROTOCOLID_ISCSI;
57688+ sprintf(&tr_id[4], "%s,i,0x%llx", sess->initiator_name, sid.id64);
57689+
57690+ put_unaligned(cpu_to_be16(tr_id_size - 4),
57691+ (__be16 *)&tr_id[2]);
57692+
57693+ *transport_id = tr_id;
57694+
57695+ TRACE_DBG("Created tid '%s'", &tr_id[4]);
57696+
57697+out:
57698+ TRACE_EXIT_RES(res);
57699+ return res;
57700+}
57701+
57702+void iscsi_send_nop_in(struct iscsi_conn *conn)
57703+{
57704+ struct iscsi_cmnd *req, *rsp;
57705+ struct iscsi_nop_in_hdr *rsp_hdr;
57706+
57707+ TRACE_ENTRY();
57708+
57709+ req = cmnd_alloc(conn, NULL);
57710+ if (req == NULL) {
57711+ PRINT_ERROR("%s", "Unable to alloc fake Nop-In request");
57712+ goto out_err;
57713+ }
57714+
57715+ rsp = iscsi_alloc_main_rsp(req);
57716+ if (rsp == NULL) {
57717+ PRINT_ERROR("%s", "Unable to alloc Nop-In rsp");
57718+ goto out_err_free_req;
57719+ }
57720+
57721+ cmnd_get(rsp);
57722+
57723+ rsp_hdr = (struct iscsi_nop_in_hdr *)&rsp->pdu.bhs;
57724+ rsp_hdr->opcode = ISCSI_OP_NOP_IN;
57725+ rsp_hdr->flags = ISCSI_FLG_FINAL;
57726+ rsp_hdr->itt = ISCSI_RESERVED_TAG;
57727+ rsp_hdr->ttt = (__force __be32)conn->nop_in_ttt++;
57728+
57729+ if (conn->nop_in_ttt == ISCSI_RESERVED_TAG_CPU32)
57730+ conn->nop_in_ttt = 0;
57731+
57732+ /* Supposed that all other fields are zeroed */
57733+
57734+ TRACE_DBG("Sending Nop-In request (ttt 0x%08x)", rsp_hdr->ttt);
57735+ spin_lock_bh(&conn->nop_req_list_lock);
57736+ list_add_tail(&rsp->nop_req_list_entry, &conn->nop_req_list);
57737+ spin_unlock_bh(&conn->nop_req_list_lock);
57738+
57739+out_err_free_req:
57740+ req_cmnd_release(req);
57741+
57742+out_err:
57743+ TRACE_EXIT();
57744+ return;
57745+}
57746+
57747+static int iscsi_target_detect(struct scst_tgt_template *templ)
57748+{
57749+ /* Nothing to do */
57750+ return 0;
57751+}
57752+
57753+static int iscsi_target_release(struct scst_tgt *scst_tgt)
57754+{
57755+ /* Nothing to do */
57756+ return 0;
57757+}
57758+
57759+static struct scst_trace_log iscsi_local_trace_tbl[] = {
57760+ { TRACE_D_WRITE, "d_write" },
57761+ { TRACE_CONN_OC, "conn" },
57762+ { TRACE_CONN_OC_DBG, "conn_dbg" },
57763+ { TRACE_D_IOV, "iov" },
57764+ { TRACE_D_DUMP_PDU, "pdu" },
57765+ { TRACE_NET_PG, "net_page" },
57766+ { 0, NULL }
57767+};
57768+
57769+#define ISCSI_TRACE_TBL_HELP ", d_write, conn, conn_dbg, iov, pdu, net_page"
57770+
57771+static uint16_t iscsi_get_scsi_transport_version(struct scst_tgt *scst_tgt)
57772+{
57773+ return 0x0960; /* iSCSI */
57774+}
57775+
57776+struct scst_tgt_template iscsi_template = {
57777+ .name = "iscsi",
57778+ .sg_tablesize = 0xFFFF /* no limit */,
57779+ .threads_num = 0,
57780+ .no_clustering = 1,
57781+ .xmit_response_atomic = 0,
57782+ .tgtt_attrs = iscsi_attrs,
57783+ .tgt_attrs = iscsi_tgt_attrs,
57784+ .sess_attrs = iscsi_sess_attrs,
57785+ .enable_target = iscsi_enable_target,
57786+ .is_target_enabled = iscsi_is_target_enabled,
57787+ .add_target = iscsi_sysfs_add_target,
57788+ .del_target = iscsi_sysfs_del_target,
57789+ .mgmt_cmd = iscsi_sysfs_mgmt_cmd,
57790+ .tgtt_optional_attributes = "IncomingUser, OutgoingUser",
57791+ .tgt_optional_attributes = "IncomingUser, OutgoingUser, allowed_portal",
57792+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
57793+ .default_trace_flags = ISCSI_DEFAULT_LOG_FLAGS,
57794+ .trace_flags = &trace_flag,
57795+ .trace_tbl = iscsi_local_trace_tbl,
57796+ .trace_tbl_help = ISCSI_TRACE_TBL_HELP,
57797+#endif
57798+ .detect = iscsi_target_detect,
57799+ .release = iscsi_target_release,
57800+ .xmit_response = iscsi_xmit_response,
57801+#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
57802+ .alloc_data_buf = iscsi_alloc_data_buf,
57803+#endif
57804+ .preprocessing_done = iscsi_preprocessing_done,
57805+ .pre_exec = iscsi_pre_exec,
57806+ .task_mgmt_affected_cmds_done = iscsi_task_mgmt_affected_cmds_done,
57807+ .task_mgmt_fn_done = iscsi_task_mgmt_fn_done,
57808+ .report_aen = iscsi_report_aen,
57809+ .get_initiator_port_transport_id = iscsi_get_initiator_port_transport_id,
57810+ .get_scsi_transport_version = iscsi_get_scsi_transport_version,
57811+};
57812+
57813+static __init int iscsi_run_threads(int count, char *name, int (*fn)(void *))
57814+{
57815+ int res = 0;
57816+ int i;
57817+ struct iscsi_thread_t *thr;
57818+
57819+ for (i = 0; i < count; i++) {
57820+ thr = kmalloc(sizeof(*thr), GFP_KERNEL);
57821+ if (!thr) {
57822+ res = -ENOMEM;
57823+ PRINT_ERROR("Failed to allocate thr %d", res);
57824+ goto out;
57825+ }
57826+ thr->thr = kthread_run(fn, NULL, "%s%d", name, i);
57827+ if (IS_ERR(thr->thr)) {
57828+ res = PTR_ERR(thr->thr);
57829+ PRINT_ERROR("kthread_create() failed: %d", res);
57830+ kfree(thr);
57831+ goto out;
57832+ }
57833+ list_add_tail(&thr->threads_list_entry, &iscsi_threads_list);
57834+ }
57835+
57836+out:
57837+ return res;
57838+}
57839+
57840+static void iscsi_stop_threads(void)
57841+{
57842+ struct iscsi_thread_t *t, *tmp;
57843+
57844+ list_for_each_entry_safe(t, tmp, &iscsi_threads_list,
57845+ threads_list_entry) {
57846+ int rc = kthread_stop(t->thr);
57847+ if (rc < 0)
57848+ TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
57849+ list_del(&t->threads_list_entry);
57850+ kfree(t);
57851+ }
57852+ return;
57853+}
57854+
57855+static int __init iscsi_init(void)
57856+{
57857+ int err = 0;
57858+ int num;
57859+
57860+ PRINT_INFO("iSCSI SCST Target - version %s", ISCSI_VERSION_STRING);
57861+
57862+ dummy_page = alloc_pages(GFP_KERNEL, 0);
57863+ if (dummy_page == NULL) {
57864+ PRINT_ERROR("%s", "Dummy page allocation failed");
57865+ goto out;
57866+ }
57867+
57868+ sg_init_table(&dummy_sg, 1);
57869+ sg_set_page(&dummy_sg, dummy_page, PAGE_SIZE, 0);
57870+
57871+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
57872+ err = net_set_get_put_page_callbacks(iscsi_get_page_callback,
57873+ iscsi_put_page_callback);
57874+ if (err != 0) {
57875+ PRINT_INFO("Unable to set page callbackes: %d", err);
57876+ goto out_free_dummy;
57877+ }
57878+#else
57879+#ifndef GENERATING_UPSTREAM_PATCH
57880+ PRINT_WARNING("%s",
57881+ "CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION "
57882+ "not enabled in your kernel. ISCSI-SCST will be working with "
57883+ "not the best performance. Refer README file for details.");
57884+#endif
57885+#endif
57886+
57887+ ctr_major = register_chrdev(0, ctr_name, &ctr_fops);
57888+ if (ctr_major < 0) {
57889+ PRINT_ERROR("failed to register the control device %d",
57890+ ctr_major);
57891+ err = ctr_major;
57892+ goto out_callb;
57893+ }
57894+
57895+ err = event_init();
57896+ if (err < 0)
57897+ goto out_reg;
57898+
57899+ iscsi_cmnd_cache = KMEM_CACHE(iscsi_cmnd, SCST_SLAB_FLAGS);
57900+ if (!iscsi_cmnd_cache) {
57901+ err = -ENOMEM;
57902+ goto out_event;
57903+ }
57904+
57905+ err = scst_register_target_template(&iscsi_template);
57906+ if (err < 0)
57907+ goto out_kmem;
57908+
57909+ iscsi_conn_ktype.sysfs_ops = scst_sysfs_get_sysfs_ops();
57910+
57911+ num = max((int)num_online_cpus(), 2);
57912+
57913+ err = iscsi_run_threads(num, "iscsird", istrd);
57914+ if (err != 0)
57915+ goto out_thr;
57916+
57917+ err = iscsi_run_threads(num, "iscsiwr", istwr);
57918+ if (err != 0)
57919+ goto out_thr;
57920+
57921+out:
57922+ return err;
57923+
57924+out_thr:
57925+ iscsi_stop_threads();
57926+
57927+ scst_unregister_target_template(&iscsi_template);
57928+
57929+out_kmem:
57930+ kmem_cache_destroy(iscsi_cmnd_cache);
57931+
57932+out_event:
57933+ event_exit();
57934+
57935+out_reg:
57936+ unregister_chrdev(ctr_major, ctr_name);
57937+
57938+out_callb:
57939+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
57940+ net_set_get_put_page_callbacks(NULL, NULL);
57941+
57942+out_free_dummy:
57943+#endif
57944+ __free_pages(dummy_page, 0);
57945+ goto out;
57946+}
57947+
57948+static void __exit iscsi_exit(void)
57949+{
57950+ iscsi_stop_threads();
57951+
57952+ unregister_chrdev(ctr_major, ctr_name);
57953+
57954+ event_exit();
57955+
57956+ kmem_cache_destroy(iscsi_cmnd_cache);
57957+
57958+ scst_unregister_target_template(&iscsi_template);
57959+
57960+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
57961+ net_set_get_put_page_callbacks(NULL, NULL);
57962+#endif
57963+
57964+ __free_pages(dummy_page, 0);
57965+ return;
57966+}
57967+
57968+module_init(iscsi_init);
57969+module_exit(iscsi_exit);
57970+
57971+MODULE_VERSION(ISCSI_VERSION_STRING);
57972+MODULE_LICENSE("GPL");
57973+MODULE_DESCRIPTION("SCST iSCSI Target");
57974diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/iscsi.h linux-2.6.35/drivers/scst/iscsi-scst/iscsi.h
57975--- orig/linux-2.6.35/drivers/scst/iscsi-scst/iscsi.h
57976+++ linux-2.6.35/drivers/scst/iscsi-scst/iscsi.h
57977@@ -0,0 +1,743 @@
57978+/*
57979+ * Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
57980+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
57981+ * Copyright (C) 2007 - 2010 ID7 Ltd.
57982+ *
57983+ * This program is free software; you can redistribute it and/or
57984+ * modify it under the terms of the GNU General Public License
57985+ * as published by the Free Software Foundation, version 2
57986+ * of the License.
57987+ *
57988+ * This program is distributed in the hope that it will be useful,
57989+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
57990+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57991+ * GNU General Public License for more details.
57992+ */
57993+
57994+#ifndef __ISCSI_H__
57995+#define __ISCSI_H__
57996+
57997+#include <linux/pagemap.h>
57998+#include <linux/mm.h>
57999+#include <linux/net.h>
58000+#include <net/sock.h>
58001+
58002+#include <scst/scst.h>
58003+#include <scst/iscsi_scst.h>
58004+#include "iscsi_hdr.h"
58005+#include "iscsi_dbg.h"
58006+
58007+#define iscsi_sense_crc_error ABORTED_COMMAND, 0x47, 0x05
58008+#define iscsi_sense_unexpected_unsolicited_data ABORTED_COMMAND, 0x0C, 0x0C
58009+#define iscsi_sense_incorrect_amount_of_data ABORTED_COMMAND, 0x0C, 0x0D
58010+
58011+struct iscsi_sess_params {
58012+ int initial_r2t;
58013+ int immediate_data;
58014+ int max_connections;
58015+ unsigned int max_recv_data_length;
58016+ unsigned int max_xmit_data_length;
58017+ unsigned int max_burst_length;
58018+ unsigned int first_burst_length;
58019+ int default_wait_time;
58020+ int default_retain_time;
58021+ unsigned int max_outstanding_r2t;
58022+ int data_pdu_inorder;
58023+ int data_sequence_inorder;
58024+ int error_recovery_level;
58025+ int header_digest;
58026+ int data_digest;
58027+ int ofmarker;
58028+ int ifmarker;
58029+ int ofmarkint;
58030+ int ifmarkint;
58031+};
58032+
58033+struct iscsi_tgt_params {
58034+ int queued_cmnds;
58035+ unsigned int rsp_timeout;
58036+ unsigned int nop_in_interval;
58037+};
58038+
58039+struct network_thread_info {
58040+ struct task_struct *task;
58041+ unsigned int ready;
58042+};
58043+
58044+struct iscsi_target;
58045+struct iscsi_cmnd;
58046+
58047+struct iscsi_attr {
58048+ struct list_head attrs_list_entry;
58049+ struct kobj_attribute attr;
58050+ struct iscsi_target *target;
58051+ const char *name;
58052+};
58053+
58054+struct iscsi_target {
58055+ struct scst_tgt *scst_tgt;
58056+
58057+ struct mutex target_mutex;
58058+
58059+ struct list_head session_list; /* protected by target_mutex */
58060+
58061+ struct list_head target_list_entry;
58062+ u32 tid;
58063+
58064+ unsigned int tgt_enabled:1;
58065+
58066+ /* Protected by target_mutex */
58067+ struct list_head attrs_list;
58068+
58069+ char name[ISCSI_NAME_LEN];
58070+};
58071+
58072+#define ISCSI_HASH_ORDER 8
58073+#define cmnd_hashfn(itt) (BUILD_BUG_ON(!__same_type(itt, __be32)), \
58074+ hash_long((__force u32)(itt), ISCSI_HASH_ORDER))
58075+
58076+struct iscsi_session {
58077+ struct iscsi_target *target;
58078+ struct scst_session *scst_sess;
58079+
58080+ struct list_head pending_list; /* protected by sn_lock */
58081+
58082+ /* Unprotected, since accessed only from a single read thread */
58083+ u32 next_ttt;
58084+
58085+ /* Read only, if there are connection(s) */
58086+ struct iscsi_tgt_params tgt_params;
58087+ atomic_t active_cmds;
58088+
58089+ spinlock_t sn_lock;
58090+ u32 exp_cmd_sn; /* protected by sn_lock */
58091+
58092+ /* All 3 protected by sn_lock */
58093+ int tm_active;
58094+ u32 tm_sn;
58095+ struct iscsi_cmnd *tm_rsp;
58096+
58097+ /* Read only, if there are connection(s) */
58098+ struct iscsi_sess_params sess_params;
58099+
58100+ /*
58101+ * In some corner cases commands can be deleted from the hash
58102+ * not from the corresponding read thread. So, let's simplify
58103+ * errors recovery and have this lock.
58104+ */
58105+ spinlock_t cmnd_data_wait_hash_lock;
58106+ struct list_head cmnd_data_wait_hash[1 << ISCSI_HASH_ORDER];
58107+
58108+ struct list_head conn_list; /* protected by target_mutex */
58109+
58110+ struct list_head session_list_entry;
58111+
58112+ /* All protected by target_mutex, where necessary */
58113+ struct iscsi_session *sess_reinst_successor;
58114+ unsigned int sess_reinstating:1;
58115+ unsigned int sess_shutting_down:1;
58116+
58117+ /* All don't need any protection */
58118+ char *initiator_name;
58119+ u64 sid;
58120+};
58121+
58122+#define ISCSI_CONN_IOV_MAX (PAGE_SIZE/sizeof(struct iovec))
58123+
58124+#define ISCSI_CONN_RD_STATE_IDLE 0
58125+#define ISCSI_CONN_RD_STATE_IN_LIST 1
58126+#define ISCSI_CONN_RD_STATE_PROCESSING 2
58127+
58128+#define ISCSI_CONN_WR_STATE_IDLE 0
58129+#define ISCSI_CONN_WR_STATE_IN_LIST 1
58130+#define ISCSI_CONN_WR_STATE_SPACE_WAIT 2
58131+#define ISCSI_CONN_WR_STATE_PROCESSING 3
58132+
58133+struct iscsi_conn {
58134+ struct iscsi_session *session; /* owning session */
58135+
58136+ /* Both protected by session->sn_lock */
58137+ u32 stat_sn;
58138+ u32 exp_stat_sn;
58139+
58140+#define ISCSI_CONN_REINSTATING 1
58141+#define ISCSI_CONN_SHUTTINGDOWN 2
58142+ unsigned long conn_aflags;
58143+
58144+ spinlock_t cmd_list_lock; /* BH lock */
58145+
58146+ /* Protected by cmd_list_lock */
58147+ struct list_head cmd_list; /* in/outcoming pdus */
58148+
58149+ atomic_t conn_ref_cnt;
58150+
58151+ spinlock_t write_list_lock;
58152+ /* List of data pdus to be sent. Protected by write_list_lock */
58153+ struct list_head write_list;
58154+ /* List of data pdus being sent. Protected by write_list_lock */
58155+ struct list_head write_timeout_list;
58156+
58157+ /* Protected by write_list_lock */
58158+ struct timer_list rsp_timer;
58159+ unsigned int rsp_timeout; /* in jiffies */
58160+
58161+ /*
58162+ * All 2 protected by iscsi_wr_lock. Modified independently to the
58163+ * above field, hence the alignment.
58164+ */
58165+ unsigned short wr_state __attribute__((aligned(sizeof(long))));
58166+ unsigned short wr_space_ready:1;
58167+
58168+ struct list_head wr_list_entry;
58169+
58170+#ifdef CONFIG_SCST_EXTRACHECKS
58171+ struct task_struct *wr_task;
58172+#endif
58173+
58174+ /*
58175+ * All are unprotected, since accessed only from a single write
58176+ * thread.
58177+ */
58178+ struct iscsi_cmnd *write_cmnd;
58179+ struct iovec *write_iop;
58180+ int write_iop_used;
58181+ struct iovec write_iov[2];
58182+ u32 write_size;
58183+ u32 write_offset;
58184+ int write_state;
58185+
58186+ /* Both don't need any protection */
58187+ struct file *file;
58188+ struct socket *sock;
58189+
58190+ void (*old_state_change)(struct sock *);
58191+ void (*old_data_ready)(struct sock *, int);
58192+ void (*old_write_space)(struct sock *);
58193+
58194+ /* Both read only. Stay here for better CPU cache locality. */
58195+ int hdigest_type;
58196+ int ddigest_type;
58197+
58198+ /* All 6 protected by iscsi_rd_lock */
58199+ unsigned short rd_state;
58200+ unsigned short rd_data_ready:1;
58201+ /* Let's save some cache footprint by putting them here */
58202+ unsigned short closing:1;
58203+ unsigned short active_close:1;
58204+ unsigned short deleting:1;
58205+ unsigned short conn_tm_active:1;
58206+
58207+ struct list_head rd_list_entry;
58208+
58209+#ifdef CONFIG_SCST_EXTRACHECKS
58210+ struct task_struct *rd_task;
58211+#endif
58212+
58213+ unsigned long last_rcv_time;
58214+
58215+ /*
58216+ * All are unprotected, since accessed only from a single read
58217+ * thread.
58218+ */
58219+ struct iscsi_cmnd *read_cmnd;
58220+ struct msghdr read_msg;
58221+ u32 read_size;
58222+ int read_state;
58223+ struct iovec *read_iov;
58224+ struct task_struct *rx_task;
58225+ uint32_t rpadding;
58226+
58227+ struct iscsi_target *target;
58228+
58229+ struct list_head conn_list_entry; /* list entry in session conn_list */
58230+
58231+ /* All protected by target_mutex, where necessary */
58232+ struct iscsi_conn *conn_reinst_successor;
58233+ struct list_head reinst_pending_cmd_list;
58234+
58235+ wait_queue_head_t read_state_waitQ;
58236+ struct completion ready_to_free;
58237+
58238+ /* Doesn't need any protection */
58239+ u16 cid;
58240+
58241+ struct delayed_work nop_in_delayed_work;
58242+ unsigned int nop_in_interval; /* in jiffies */
58243+ struct list_head nop_req_list;
58244+ spinlock_t nop_req_list_lock;
58245+ u32 nop_in_ttt;
58246+
58247+ /* Don't need any protection */
58248+ struct kobject conn_kobj;
58249+ struct completion conn_kobj_release_cmpl;
58250+};
58251+
58252+struct iscsi_pdu {
58253+ struct iscsi_hdr bhs;
58254+ void *ahs;
58255+ unsigned int ahssize;
58256+ unsigned int datasize;
58257+};
58258+
58259+typedef void (iscsi_show_info_t)(struct seq_file *seq,
58260+ struct iscsi_target *target);
58261+
58262+/** Commands' states **/
58263+
58264+/* New command and SCST processes it */
58265+#define ISCSI_CMD_STATE_NEW 0
58266+
58267+/* SCST processes cmd after scst_rx_cmd() */
58268+#define ISCSI_CMD_STATE_RX_CMD 1
58269+
58270+/* The command returned from preprocessing_done() */
58271+#define ISCSI_CMD_STATE_AFTER_PREPROC 2
58272+
58273+/* The command is waiting for session or connection reinstatement finished */
58274+#define ISCSI_CMD_STATE_REINST_PENDING 3
58275+
58276+/* scst_restart_cmd() called and SCST processing it */
58277+#define ISCSI_CMD_STATE_RESTARTED 4
58278+
58279+/* SCST done processing */
58280+#define ISCSI_CMD_STATE_PROCESSED 5
58281+
58282+/* AEN processing */
58283+#define ISCSI_CMD_STATE_AEN 6
58284+
58285+/* Out of SCST core preliminary completed */
58286+#define ISCSI_CMD_STATE_OUT_OF_SCST_PRELIM_COMPL 7
58287+
58288+/*
58289+ * Most of the fields don't need any protection, since accessed from only a
58290+ * single thread, except where noted.
58291+ *
58292+ * ToDo: Eventually divide request and response structures in 2 separate
58293+ * structures and stop this IET-derived garbage.
58294+ */
58295+struct iscsi_cmnd {
58296+ struct iscsi_conn *conn;
58297+
58298+ /*
58299+ * Some flags used under conn->write_list_lock, but all modified only
58300+ * from single read thread or when there are no references to cmd.
58301+ */
58302+ unsigned int hashed:1;
58303+ unsigned int should_close_conn:1;
58304+ unsigned int should_close_all_conn:1;
58305+ unsigned int pending:1;
58306+ unsigned int own_sg:1;
58307+ unsigned int on_write_list:1;
58308+ unsigned int write_processing_started:1;
58309+ unsigned int force_cleanup_done:1;
58310+ unsigned int dec_active_cmds:1;
58311+ unsigned int ddigest_checked:1;
58312+#ifdef CONFIG_SCST_EXTRACHECKS
58313+ unsigned int on_rx_digest_list:1;
58314+ unsigned int release_called:1;
58315+#endif
58316+
58317+ /*
58318+ * We suppose that preliminary commands completion is tested by
58319+ * comparing prelim_compl_flags with 0. Otherwise, because of the
58320+ * gap between setting different flags a race is possible,
58321+ * like sending command in SCST core as PRELIM_COMPLETED, while it
58322+ * wasn't aborted in it yet and have as the result a wrong success
58323+ * status sent to the initiator.
58324+ */
58325+#define ISCSI_CMD_ABORTED 0
58326+#define ISCSI_CMD_PRELIM_COMPLETED 1
58327+ unsigned long prelim_compl_flags;
58328+
58329+ struct list_head hash_list_entry;
58330+
58331+ /*
58332+ * Unions are for readability and grepability and to save some
58333+ * cache footprint.
58334+ */
58335+
58336+ union {
58337+ /*
58338+ * Used only to abort not yet sent responses. Usage in
58339+ * cmnd_done() is only a side effect to have a lockless
58340+ * accesss to this list from always only a single thread
58341+ * at any time. So, all responses live in the parent
58342+ * until it has the last reference put.
58343+ */
58344+ struct list_head rsp_cmd_list;
58345+ struct list_head rsp_cmd_list_entry;
58346+ };
58347+
58348+ union {
58349+ struct list_head pending_list_entry;
58350+ struct list_head reinst_pending_cmd_list_entry;
58351+ };
58352+
58353+ union {
58354+ struct list_head write_list_entry;
58355+ struct list_head write_timeout_list_entry;
58356+ };
58357+
58358+ /* Both protected by conn->write_list_lock */
58359+ unsigned int on_write_timeout_list:1;
58360+ unsigned long write_start;
58361+
58362+ /*
58363+ * All unprotected, since could be accessed from only a single
58364+ * thread at time
58365+ */
58366+ struct iscsi_cmnd *parent_req;
58367+ struct iscsi_cmnd *cmd_req;
58368+
58369+ /*
58370+ * All unprotected, since could be accessed from only a single
58371+ * thread at time
58372+ */
58373+ union {
58374+ /* Request only fields */
58375+ struct {
58376+ struct list_head rx_ddigest_cmd_list;
58377+ struct list_head rx_ddigest_cmd_list_entry;
58378+
58379+ int scst_state;
58380+ union {
58381+ struct scst_cmd *scst_cmd;
58382+ struct scst_aen *scst_aen;
58383+ };
58384+
58385+ struct iscsi_cmnd *main_rsp;
58386+
58387+ /*
58388+ * Protected on modify by conn->write_list_lock, hence
58389+ * modified independently to the above field, hence the
58390+ * alignment.
58391+ */
58392+ int not_processed_rsp_cnt
58393+ __attribute__((aligned(sizeof(long))));
58394+ };
58395+
58396+ /* Response only fields */
58397+ struct {
58398+ struct scatterlist rsp_sg[2];
58399+ struct iscsi_sense_data sense_hdr;
58400+ };
58401+ };
58402+
58403+ atomic_t ref_cnt;
58404+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
58405+ atomic_t net_ref_cnt;
58406+#endif
58407+
58408+ struct iscsi_pdu pdu;
58409+
58410+ struct scatterlist *sg;
58411+ int sg_cnt;
58412+ unsigned int bufflen;
58413+ u32 r2t_sn;
58414+ unsigned int r2t_len_to_receive;
58415+ unsigned int r2t_len_to_send;
58416+ unsigned int outstanding_r2t;
58417+ u32 target_task_tag;
58418+ __be32 hdigest;
58419+ __be32 ddigest;
58420+
58421+ struct list_head cmd_list_entry;
58422+ struct list_head nop_req_list_entry;
58423+
58424+ unsigned int not_received_data_len;
58425+};
58426+
58427+/* Max time to wait for our response satisfied for aborted commands */
58428+#define ISCSI_TM_DATA_WAIT_TIMEOUT (10 * HZ)
58429+
58430+/*
58431+ * Needed addition to all timeouts to complete a burst of commands at once.
58432+ * Otherwise, a part of the burst can be timeouted only in double timeout time.
58433+ */
58434+#define ISCSI_ADD_SCHED_TIME HZ
58435+
58436+#define ISCSI_CTR_OPEN_STATE_CLOSED 0
58437+#define ISCSI_CTR_OPEN_STATE_OPEN 1
58438+#define ISCSI_CTR_OPEN_STATE_CLOSING 2
58439+
58440+extern struct mutex target_mgmt_mutex;
58441+
58442+extern int ctr_open_state;
58443+extern const struct file_operations ctr_fops;
58444+
58445+extern spinlock_t iscsi_rd_lock;
58446+extern struct list_head iscsi_rd_list;
58447+extern wait_queue_head_t iscsi_rd_waitQ;
58448+
58449+extern spinlock_t iscsi_wr_lock;
58450+extern struct list_head iscsi_wr_list;
58451+extern wait_queue_head_t iscsi_wr_waitQ;
58452+
58453+/* iscsi.c */
58454+extern struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *,
58455+ struct iscsi_cmnd *parent);
58456+extern int cmnd_rx_start(struct iscsi_cmnd *);
58457+extern int cmnd_rx_continue(struct iscsi_cmnd *req);
58458+extern void cmnd_rx_end(struct iscsi_cmnd *);
58459+extern void cmnd_tx_start(struct iscsi_cmnd *);
58460+extern void cmnd_tx_end(struct iscsi_cmnd *);
58461+extern void req_cmnd_release_force(struct iscsi_cmnd *req);
58462+extern void rsp_cmnd_release(struct iscsi_cmnd *);
58463+extern void cmnd_done(struct iscsi_cmnd *cmnd);
58464+extern void conn_abort(struct iscsi_conn *conn);
58465+extern void iscsi_restart_cmnd(struct iscsi_cmnd *cmnd);
58466+extern void iscsi_fail_data_waiting_cmnd(struct iscsi_cmnd *cmnd);
58467+extern void iscsi_send_nop_in(struct iscsi_conn *conn);
58468+extern int iscsi_preliminary_complete(struct iscsi_cmnd *req,
58469+ struct iscsi_cmnd *orig_req, bool get_data);
58470+extern int set_scst_preliminary_status_rsp(struct iscsi_cmnd *req,
58471+ bool get_data, int key, int asc, int ascq);
58472+
58473+/* conn.c */
58474+extern struct kobj_type iscsi_conn_ktype;
58475+extern struct iscsi_conn *conn_lookup(struct iscsi_session *, u16);
58476+extern void conn_reinst_finished(struct iscsi_conn *);
58477+extern int __add_conn(struct iscsi_session *, struct iscsi_kern_conn_info *);
58478+extern int __del_conn(struct iscsi_session *, struct iscsi_kern_conn_info *);
58479+extern int conn_free(struct iscsi_conn *);
58480+extern void iscsi_make_conn_rd_active(struct iscsi_conn *conn);
58481+#define ISCSI_CONN_ACTIVE_CLOSE 1
58482+#define ISCSI_CONN_DELETING 2
58483+extern void __mark_conn_closed(struct iscsi_conn *, int);
58484+extern void mark_conn_closed(struct iscsi_conn *);
58485+extern void iscsi_make_conn_wr_active(struct iscsi_conn *);
58486+extern void iscsi_check_tm_data_wait_timeouts(struct iscsi_conn *conn,
58487+ bool force);
58488+extern void __iscsi_write_space_ready(struct iscsi_conn *conn);
58489+
58490+/* nthread.c */
58491+extern int iscsi_send(struct iscsi_conn *conn);
58492+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
58493+extern void iscsi_get_page_callback(struct page *page);
58494+extern void iscsi_put_page_callback(struct page *page);
58495+#endif
58496+extern int istrd(void *arg);
58497+extern int istwr(void *arg);
58498+extern void iscsi_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *scst_mcmd);
58499+extern void req_add_to_write_timeout_list(struct iscsi_cmnd *req);
58500+
58501+/* target.c */
58502+extern const struct attribute *iscsi_tgt_attrs[];
58503+extern int iscsi_enable_target(struct scst_tgt *scst_tgt, bool enable);
58504+extern bool iscsi_is_target_enabled(struct scst_tgt *scst_tgt);
58505+extern ssize_t iscsi_sysfs_send_event(uint32_t tid,
58506+ enum iscsi_kern_event_code code,
58507+ const char *param1, const char *param2, void **data);
58508+extern struct iscsi_target *target_lookup_by_id(u32);
58509+extern int __add_target(struct iscsi_kern_target_info *);
58510+extern int __del_target(u32 id);
58511+extern ssize_t iscsi_sysfs_add_target(const char *target_name, char *params);
58512+extern ssize_t iscsi_sysfs_del_target(const char *target_name);
58513+extern ssize_t iscsi_sysfs_mgmt_cmd(char *cmd);
58514+extern void target_del_session(struct iscsi_target *target,
58515+ struct iscsi_session *session, int flags);
58516+extern void target_del_all_sess(struct iscsi_target *target, int flags);
58517+extern void target_del_all(void);
58518+
58519+/* config.c */
58520+extern const struct attribute *iscsi_attrs[];
58521+extern int iscsi_add_attr(struct iscsi_target *target,
58522+ const struct iscsi_kern_attr *user_info);
58523+extern void __iscsi_del_attr(struct iscsi_target *target,
58524+ struct iscsi_attr *tgt_attr);
58525+
58526+/* session.c */
58527+extern const struct attribute *iscsi_sess_attrs[];
58528+extern const struct file_operations session_seq_fops;
58529+extern struct iscsi_session *session_lookup(struct iscsi_target *, u64);
58530+extern void sess_reinst_finished(struct iscsi_session *);
58531+extern int __add_session(struct iscsi_target *,
58532+ struct iscsi_kern_session_info *);
58533+extern int __del_session(struct iscsi_target *, u64);
58534+extern int session_free(struct iscsi_session *session, bool del);
58535+
58536+/* params.c */
58537+extern const char *iscsi_get_digest_name(int val, char *res);
58538+extern const char *iscsi_get_bool_value(int val);
58539+extern int iscsi_params_set(struct iscsi_target *,
58540+ struct iscsi_kern_params_info *, int);
58541+
58542+/* event.c */
58543+extern int event_send(u32, u64, u32, u32, enum iscsi_kern_event_code,
58544+ const char *param1, const char *param2);
58545+extern int event_init(void);
58546+extern void event_exit(void);
58547+
58548+#define get_pgcnt(size, offset) \
58549+ ((((size) + ((offset) & ~PAGE_MASK)) + PAGE_SIZE - 1) >> PAGE_SHIFT)
58550+
58551+static inline void iscsi_cmnd_get_length(struct iscsi_pdu *pdu)
58552+{
58553+#if defined(__BIG_ENDIAN)
58554+ pdu->ahssize = pdu->bhs.length.ahslength * 4;
58555+ pdu->datasize = pdu->bhs.length.datalength;
58556+#elif defined(__LITTLE_ENDIAN)
58557+ pdu->ahssize = ((__force __u32)pdu->bhs.length & 0xff) * 4;
58558+ pdu->datasize = be32_to_cpu((__force __be32)((__force __u32)pdu->bhs.length & ~0xff));
58559+#else
58560+#error
58561+#endif
58562+}
58563+
58564+static inline void iscsi_cmnd_set_length(struct iscsi_pdu *pdu)
58565+{
58566+#if defined(__BIG_ENDIAN)
58567+ pdu->bhs.length.ahslength = pdu->ahssize / 4;
58568+ pdu->bhs.length.datalength = pdu->datasize;
58569+#elif defined(__LITTLE_ENDIAN)
58570+ pdu->bhs.length = cpu_to_be32(pdu->datasize) | (__force __be32)(pdu->ahssize / 4);
58571+#else
58572+#error
58573+#endif
58574+}
58575+
58576+extern struct scst_tgt_template iscsi_template;
58577+
58578+/*
58579+ * Skip this command if result is not 0. Must be called under
58580+ * corresponding lock.
58581+ */
58582+static inline bool cmnd_get_check(struct iscsi_cmnd *cmnd)
58583+{
58584+ int r = atomic_inc_return(&cmnd->ref_cnt);
58585+ int res;
58586+ if (unlikely(r == 1)) {
58587+ TRACE_DBG("cmnd %p is being destroyed", cmnd);
58588+ atomic_dec(&cmnd->ref_cnt);
58589+ res = 1;
58590+ /* Necessary code is serialized by locks in cmnd_done() */
58591+ } else {
58592+ TRACE_DBG("cmnd %p, new ref_cnt %d", cmnd,
58593+ atomic_read(&cmnd->ref_cnt));
58594+ res = 0;
58595+ }
58596+ return res;
58597+}
58598+
58599+static inline void cmnd_get(struct iscsi_cmnd *cmnd)
58600+{
58601+ atomic_inc(&cmnd->ref_cnt);
58602+ TRACE_DBG("cmnd %p, new cmnd->ref_cnt %d", cmnd,
58603+ atomic_read(&cmnd->ref_cnt));
58604+ /*
58605+ * For the same reason as in kref_get(). Let's be safe and
58606+ * always do it.
58607+ */
58608+ smp_mb__after_atomic_inc();
58609+}
58610+
58611+static inline void cmnd_put(struct iscsi_cmnd *cmnd)
58612+{
58613+ TRACE_DBG("cmnd %p, new ref_cnt %d", cmnd,
58614+ atomic_read(&cmnd->ref_cnt)-1);
58615+
58616+ EXTRACHECKS_BUG_ON(atomic_read(&cmnd->ref_cnt) == 0);
58617+
58618+ if (atomic_dec_and_test(&cmnd->ref_cnt))
58619+ cmnd_done(cmnd);
58620+}
58621+
58622+/* conn->write_list_lock supposed to be locked and BHs off */
58623+static inline void cmd_add_on_write_list(struct iscsi_conn *conn,
58624+ struct iscsi_cmnd *cmnd)
58625+{
58626+ struct iscsi_cmnd *parent = cmnd->parent_req;
58627+
58628+ TRACE_DBG("cmnd %p", cmnd);
58629+ /* See comment in iscsi_restart_cmnd() */
58630+ EXTRACHECKS_BUG_ON(cmnd->parent_req->hashed &&
58631+ (cmnd_opcode(cmnd) != ISCSI_OP_R2T));
58632+ list_add_tail(&cmnd->write_list_entry, &conn->write_list);
58633+ cmnd->on_write_list = 1;
58634+
58635+ parent->not_processed_rsp_cnt++;
58636+ TRACE_DBG("not processed rsp cnt %d (parent %p)",
58637+ parent->not_processed_rsp_cnt, parent);
58638+}
58639+
58640+/* conn->write_list_lock supposed to be locked and BHs off */
58641+static inline void cmd_del_from_write_list(struct iscsi_cmnd *cmnd)
58642+{
58643+ struct iscsi_cmnd *parent = cmnd->parent_req;
58644+
58645+ TRACE_DBG("%p", cmnd);
58646+ list_del(&cmnd->write_list_entry);
58647+ cmnd->on_write_list = 0;
58648+
58649+ parent->not_processed_rsp_cnt--;
58650+ TRACE_DBG("not processed rsp cnt %d (parent %p)",
58651+ parent->not_processed_rsp_cnt, parent);
58652+ EXTRACHECKS_BUG_ON(parent->not_processed_rsp_cnt < 0);
58653+}
58654+
58655+static inline void cmd_add_on_rx_ddigest_list(struct iscsi_cmnd *req,
58656+ struct iscsi_cmnd *cmnd)
58657+{
58658+ TRACE_DBG("Adding RX ddigest cmd %p to digest list "
58659+ "of req %p", cmnd, req);
58660+ list_add_tail(&cmnd->rx_ddigest_cmd_list_entry,
58661+ &req->rx_ddigest_cmd_list);
58662+#ifdef CONFIG_SCST_EXTRACHECKS
58663+ cmnd->on_rx_digest_list = 1;
58664+#endif
58665+}
58666+
58667+static inline void cmd_del_from_rx_ddigest_list(struct iscsi_cmnd *cmnd)
58668+{
58669+ TRACE_DBG("Deleting RX digest cmd %p from digest list", cmnd);
58670+ list_del(&cmnd->rx_ddigest_cmd_list_entry);
58671+#ifdef CONFIG_SCST_EXTRACHECKS
58672+ cmnd->on_rx_digest_list = 0;
58673+#endif
58674+}
58675+
58676+static inline int test_write_ready(struct iscsi_conn *conn)
58677+{
58678+ /*
58679+ * No need for write_list protection, in the worst case we will be
58680+ * restarted again.
58681+ */
58682+ return !list_empty(&conn->write_list) || conn->write_cmnd;
58683+}
58684+
58685+static inline void conn_get(struct iscsi_conn *conn)
58686+{
58687+ atomic_inc(&conn->conn_ref_cnt);
58688+ TRACE_DBG("conn %p, new conn_ref_cnt %d", conn,
58689+ atomic_read(&conn->conn_ref_cnt));
58690+ /*
58691+ * For the same reason as in kref_get(). Let's be safe and
58692+ * always do it.
58693+ */
58694+ smp_mb__after_atomic_inc();
58695+}
58696+
58697+static inline void conn_put(struct iscsi_conn *conn)
58698+{
58699+ TRACE_DBG("conn %p, new conn_ref_cnt %d", conn,
58700+ atomic_read(&conn->conn_ref_cnt)-1);
58701+ BUG_ON(atomic_read(&conn->conn_ref_cnt) == 0);
58702+
58703+ /*
58704+ * Make it always ordered to protect from undesired side effects like
58705+ * accessing just destroyed by close_conn() conn caused by reordering
58706+ * of this atomic_dec().
58707+ */
58708+ smp_mb__before_atomic_dec();
58709+ atomic_dec(&conn->conn_ref_cnt);
58710+}
58711+
58712+#ifdef CONFIG_SCST_EXTRACHECKS
58713+extern void iscsi_extracheck_is_rd_thread(struct iscsi_conn *conn);
58714+extern void iscsi_extracheck_is_wr_thread(struct iscsi_conn *conn);
58715+#else
58716+static inline void iscsi_extracheck_is_rd_thread(struct iscsi_conn *conn) {}
58717+static inline void iscsi_extracheck_is_wr_thread(struct iscsi_conn *conn) {}
58718+#endif
58719+
58720+#endif /* __ISCSI_H__ */
58721diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/iscsi_dbg.h linux-2.6.35/drivers/scst/iscsi-scst/iscsi_dbg.h
58722--- orig/linux-2.6.35/drivers/scst/iscsi-scst/iscsi_dbg.h
58723+++ linux-2.6.35/drivers/scst/iscsi-scst/iscsi_dbg.h
58724@@ -0,0 +1,60 @@
58725+/*
58726+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
58727+ * Copyright (C) 2007 - 2010 ID7 Ltd.
58728+ *
58729+ * This program is free software; you can redistribute it and/or
58730+ * modify it under the terms of the GNU General Public License
58731+ * as published by the Free Software Foundation, version 2
58732+ * of the License.
58733+ *
58734+ * This program is distributed in the hope that it will be useful,
58735+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58736+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
58737+ * GNU General Public License for more details.
58738+ */
58739+
58740+#ifndef ISCSI_DBG_H
58741+#define ISCSI_DBG_H
58742+
58743+#define LOG_PREFIX "iscsi-scst"
58744+
58745+#include <scst/scst_debug.h>
58746+
58747+#define TRACE_D_WRITE 0x80000000
58748+#define TRACE_CONN_OC 0x40000000
58749+#define TRACE_D_IOV 0x20000000
58750+#define TRACE_D_DUMP_PDU 0x10000000
58751+#define TRACE_NET_PG 0x08000000
58752+#define TRACE_CONN_OC_DBG 0x04000000
58753+
58754+#ifdef CONFIG_SCST_DEBUG
58755+#define ISCSI_DEFAULT_LOG_FLAGS (TRACE_FUNCTION | TRACE_LINE | TRACE_PID | \
58756+ TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MGMT_DEBUG | \
58757+ TRACE_MINOR | TRACE_SPECIAL | TRACE_CONN_OC)
58758+#else
58759+#define ISCSI_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
58760+ TRACE_SPECIAL)
58761+#endif
58762+
58763+#ifdef CONFIG_SCST_DEBUG
58764+struct iscsi_pdu;
58765+struct iscsi_cmnd;
58766+extern void iscsi_dump_pdu(struct iscsi_pdu *pdu);
58767+extern unsigned long iscsi_get_flow_ctrl_or_mgmt_dbg_log_flag(
58768+ struct iscsi_cmnd *cmnd);
58769+#else
58770+#define iscsi_dump_pdu(x) do {} while (0)
58771+#define iscsi_get_flow_ctrl_or_mgmt_dbg_log_flag(x) do {} while (0)
58772+#endif
58773+
58774+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
58775+extern unsigned long iscsi_trace_flag;
58776+#define trace_flag iscsi_trace_flag
58777+#endif
58778+
58779+#define TRACE_CONN_CLOSE(args...) TRACE_DBG_FLAG(TRACE_DEBUG|TRACE_CONN_OC, args)
58780+#define TRACE_CONN_CLOSE_DBG(args...) TRACE(TRACE_CONN_OC_DBG, args)
58781+#define TRACE_NET_PAGE(args...) TRACE_DBG_FLAG(TRACE_NET_PG, args)
58782+#define TRACE_WRITE(args...) TRACE_DBG_FLAG(TRACE_DEBUG|TRACE_D_WRITE, args)
58783+
58784+#endif
58785diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/iscsi_hdr.h linux-2.6.35/drivers/scst/iscsi-scst/iscsi_hdr.h
58786--- orig/linux-2.6.35/drivers/scst/iscsi-scst/iscsi_hdr.h
58787+++ linux-2.6.35/drivers/scst/iscsi-scst/iscsi_hdr.h
58788@@ -0,0 +1,525 @@
58789+/*
58790+ * Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
58791+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
58792+ * Copyright (C) 2007 - 2010 ID7 Ltd.
58793+ *
58794+ * This program is free software; you can redistribute it and/or
58795+ * modify it under the terms of the GNU General Public License
58796+ * as published by the Free Software Foundation, version 2
58797+ * of the License.
58798+ *
58799+ * This program is distributed in the hope that it will be useful,
58800+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58801+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
58802+ * GNU General Public License for more details.
58803+ */
58804+
58805+#ifndef __ISCSI_HDR_H__
58806+#define __ISCSI_HDR_H__
58807+
58808+#include <linux/types.h>
58809+#include <asm/byteorder.h>
58810+
58811+#define ISCSI_VERSION 0
58812+
58813+#ifndef __packed
58814+#define __packed __attribute__ ((packed))
58815+#endif
58816+
58817+/* iSCSI command PDU header. See also section 10.3 in RFC 3720. */
58818+struct iscsi_hdr {
58819+ u8 opcode; /* 0 */
58820+ u8 flags;
58821+ u8 spec1[2];
58822+#if defined(__BIG_ENDIAN_BITFIELD)
58823+ struct { /* 4 */
58824+ unsigned ahslength:8;
58825+ unsigned datalength:24;
58826+ } length;
58827+#elif defined(__LITTLE_ENDIAN_BITFIELD)
58828+ __be32 length; /* 4 */
58829+#endif
58830+ __be64 lun; /* 8 */
58831+ __be32 itt; /* 16 */
58832+ __be32 ttt; /* 20 */
58833+
58834+ /*
58835+ * SN fields most time stay converted to the CPU form and only received
58836+ * and send in the BE form.
58837+ */
58838+ u32 sn; /* 24 */
58839+ u32 exp_sn; /* 28 */
58840+ u32 max_sn; /* 32 */
58841+
58842+ __be32 spec3[3]; /* 36 */
58843+} __packed; /* 48 */
58844+
58845+/* Opcode encoding bits */
58846+#define ISCSI_OP_RETRY 0x80
58847+#define ISCSI_OP_IMMEDIATE 0x40
58848+#define ISCSI_OPCODE_MASK 0x3F
58849+
58850+/* Client to Server Message Opcode values */
58851+#define ISCSI_OP_NOP_OUT 0x00
58852+#define ISCSI_OP_SCSI_CMD 0x01
58853+#define ISCSI_OP_SCSI_TASK_MGT_MSG 0x02
58854+#define ISCSI_OP_LOGIN_CMD 0x03
58855+#define ISCSI_OP_TEXT_CMD 0x04
58856+#define ISCSI_OP_SCSI_DATA_OUT 0x05
58857+#define ISCSI_OP_LOGOUT_CMD 0x06
58858+#define ISCSI_OP_SNACK_CMD 0x10
58859+
58860+/* Server to Client Message Opcode values */
58861+#define ISCSI_OP_NOP_IN 0x20
58862+#define ISCSI_OP_SCSI_RSP 0x21
58863+#define ISCSI_OP_SCSI_TASK_MGT_RSP 0x22
58864+#define ISCSI_OP_LOGIN_RSP 0x23
58865+#define ISCSI_OP_TEXT_RSP 0x24
58866+#define ISCSI_OP_SCSI_DATA_IN 0x25
58867+#define ISCSI_OP_LOGOUT_RSP 0x26
58868+#define ISCSI_OP_R2T 0x31
58869+#define ISCSI_OP_ASYNC_MSG 0x32
58870+#define ISCSI_OP_REJECT 0x3f
58871+
58872+struct iscsi_ahs_hdr {
58873+ __be16 ahslength;
58874+ u8 ahstype;
58875+} __packed;
58876+
58877+#define ISCSI_AHSTYPE_CDB 1
58878+#define ISCSI_AHSTYPE_RLENGTH 2
58879+
58880+union iscsi_sid {
58881+ struct {
58882+ u8 isid[6]; /* Initiator Session ID */
58883+ __be16 tsih; /* Target Session ID */
58884+ } id;
58885+ __be64 id64;
58886+} __packed;
58887+
58888+struct iscsi_scsi_cmd_hdr {
58889+ u8 opcode;
58890+ u8 flags;
58891+ __be16 rsvd1;
58892+ u8 ahslength;
58893+ u8 datalength[3];
58894+ __be64 lun;
58895+ __be32 itt;
58896+ __be32 data_length;
58897+ u32 cmd_sn;
58898+ u32 exp_stat_sn;
58899+ u8 scb[16];
58900+} __packed;
58901+
58902+#define ISCSI_CMD_FINAL 0x80
58903+#define ISCSI_CMD_READ 0x40
58904+#define ISCSI_CMD_WRITE 0x20
58905+#define ISCSI_CMD_ATTR_MASK 0x07
58906+#define ISCSI_CMD_UNTAGGED 0x00
58907+#define ISCSI_CMD_SIMPLE 0x01
58908+#define ISCSI_CMD_ORDERED 0x02
58909+#define ISCSI_CMD_HEAD_OF_QUEUE 0x03
58910+#define ISCSI_CMD_ACA 0x04
58911+
58912+struct iscsi_cdb_ahdr {
58913+ __be16 ahslength;
58914+ u8 ahstype;
58915+ u8 reserved;
58916+ u8 cdb[0];
58917+} __packed;
58918+
58919+struct iscsi_rlength_ahdr {
58920+ __be16 ahslength;
58921+ u8 ahstype;
58922+ u8 reserved;
58923+ __be32 read_length;
58924+} __packed;
58925+
58926+struct iscsi_scsi_rsp_hdr {
58927+ u8 opcode;
58928+ u8 flags;
58929+ u8 response;
58930+ u8 cmd_status;
58931+ u8 ahslength;
58932+ u8 datalength[3];
58933+ u32 rsvd1[2];
58934+ __be32 itt;
58935+ __be32 snack;
58936+ u32 stat_sn;
58937+ u32 exp_cmd_sn;
58938+ u32 max_cmd_sn;
58939+ u32 exp_data_sn;
58940+ __be32 bi_residual_count;
58941+ __be32 residual_count;
58942+} __packed;
58943+
58944+#define ISCSI_FLG_RESIDUAL_UNDERFLOW 0x02
58945+#define ISCSI_FLG_RESIDUAL_OVERFLOW 0x04
58946+#define ISCSI_FLG_BIRESIDUAL_UNDERFLOW 0x08
58947+#define ISCSI_FLG_BIRESIDUAL_OVERFLOW 0x10
58948+
58949+#define ISCSI_RESPONSE_COMMAND_COMPLETED 0x00
58950+#define ISCSI_RESPONSE_TARGET_FAILURE 0x01
58951+
58952+struct iscsi_sense_data {
58953+ __be16 length;
58954+ u8 data[0];
58955+} __packed;
58956+
58957+struct iscsi_task_mgt_hdr {
58958+ u8 opcode;
58959+ u8 function;
58960+ __be16 rsvd1;
58961+ u8 ahslength;
58962+ u8 datalength[3];
58963+ __be64 lun;
58964+ __be32 itt;
58965+ __be32 rtt;
58966+ u32 cmd_sn;
58967+ u32 exp_stat_sn;
58968+ u32 ref_cmd_sn;
58969+ u32 exp_data_sn;
58970+ u32 rsvd2[2];
58971+} __packed;
58972+
58973+#define ISCSI_FUNCTION_MASK 0x7f
58974+
58975+#define ISCSI_FUNCTION_ABORT_TASK 1
58976+#define ISCSI_FUNCTION_ABORT_TASK_SET 2
58977+#define ISCSI_FUNCTION_CLEAR_ACA 3
58978+#define ISCSI_FUNCTION_CLEAR_TASK_SET 4
58979+#define ISCSI_FUNCTION_LOGICAL_UNIT_RESET 5
58980+#define ISCSI_FUNCTION_TARGET_WARM_RESET 6
58981+#define ISCSI_FUNCTION_TARGET_COLD_RESET 7
58982+#define ISCSI_FUNCTION_TASK_REASSIGN 8
58983+
58984+struct iscsi_task_rsp_hdr {
58985+ u8 opcode;
58986+ u8 flags;
58987+ u8 response;
58988+ u8 rsvd1;
58989+ u8 ahslength;
58990+ u8 datalength[3];
58991+ u32 rsvd2[2];
58992+ __be32 itt;
58993+ u32 rsvd3;
58994+ u32 stat_sn;
58995+ u32 exp_cmd_sn;
58996+ u32 max_cmd_sn;
58997+ u32 rsvd4[3];
58998+} __packed;
58999+
59000+#define ISCSI_RESPONSE_FUNCTION_COMPLETE 0
59001+#define ISCSI_RESPONSE_UNKNOWN_TASK 1
59002+#define ISCSI_RESPONSE_UNKNOWN_LUN 2
59003+#define ISCSI_RESPONSE_TASK_ALLEGIANT 3
59004+#define ISCSI_RESPONSE_ALLEGIANCE_REASSIGNMENT_UNSUPPORTED 4
59005+#define ISCSI_RESPONSE_FUNCTION_UNSUPPORTED 5
59006+#define ISCSI_RESPONSE_NO_AUTHORIZATION 6
59007+#define ISCSI_RESPONSE_FUNCTION_REJECTED 255
59008+
59009+struct iscsi_data_out_hdr {
59010+ u8 opcode;
59011+ u8 flags;
59012+ u16 rsvd1;
59013+ u8 ahslength;
59014+ u8 datalength[3];
59015+ __be64 lun;
59016+ __be32 itt;
59017+ __be32 ttt;
59018+ u32 rsvd2;
59019+ u32 exp_stat_sn;
59020+ u32 rsvd3;
59021+ __be32 data_sn;
59022+ __be32 buffer_offset;
59023+ u32 rsvd4;
59024+} __packed;
59025+
59026+struct iscsi_data_in_hdr {
59027+ u8 opcode;
59028+ u8 flags;
59029+ u8 rsvd1;
59030+ u8 cmd_status;
59031+ u8 ahslength;
59032+ u8 datalength[3];
59033+ u32 rsvd2[2];
59034+ __be32 itt;
59035+ __be32 ttt;
59036+ u32 stat_sn;
59037+ u32 exp_cmd_sn;
59038+ u32 max_cmd_sn;
59039+ __be32 data_sn;
59040+ __be32 buffer_offset;
59041+ __be32 residual_count;
59042+} __packed;
59043+
59044+#define ISCSI_FLG_STATUS 0x01
59045+
59046+struct iscsi_r2t_hdr {
59047+ u8 opcode;
59048+ u8 flags;
59049+ u16 rsvd1;
59050+ u8 ahslength;
59051+ u8 datalength[3];
59052+ __be64 lun;
59053+ __be32 itt;
59054+ __be32 ttt;
59055+ u32 stat_sn;
59056+ u32 exp_cmd_sn;
59057+ u32 max_cmd_sn;
59058+ u32 r2t_sn;
59059+ __be32 buffer_offset;
59060+ __be32 data_length;
59061+} __packed;
59062+
59063+struct iscsi_async_msg_hdr {
59064+ u8 opcode;
59065+ u8 flags;
59066+ u16 rsvd1;
59067+ u8 ahslength;
59068+ u8 datalength[3];
59069+ __be64 lun;
59070+ __be32 ffffffff;
59071+ u32 rsvd2;
59072+ u32 stat_sn;
59073+ u32 exp_cmd_sn;
59074+ u32 max_cmd_sn;
59075+ u8 async_event;
59076+ u8 async_vcode;
59077+ __be16 param1;
59078+ __be16 param2;
59079+ __be16 param3;
59080+ u32 rsvd3;
59081+} __packed;
59082+
59083+#define ISCSI_ASYNC_SCSI 0
59084+#define ISCSI_ASYNC_LOGOUT 1
59085+#define ISCSI_ASYNC_DROP_CONNECTION 2
59086+#define ISCSI_ASYNC_DROP_SESSION 3
59087+#define ISCSI_ASYNC_PARAM_REQUEST 4
59088+#define ISCSI_ASYNC_VENDOR 255
59089+
59090+struct iscsi_text_req_hdr {
59091+ u8 opcode;
59092+ u8 flags;
59093+ u16 rsvd1;
59094+ u8 ahslength;
59095+ u8 datalength[3];
59096+ u32 rsvd2[2];
59097+ __be32 itt;
59098+ __be32 ttt;
59099+ u32 cmd_sn;
59100+ u32 exp_stat_sn;
59101+ u32 rsvd3[4];
59102+} __packed;
59103+
59104+struct iscsi_text_rsp_hdr {
59105+ u8 opcode;
59106+ u8 flags;
59107+ u16 rsvd1;
59108+ u8 ahslength;
59109+ u8 datalength[3];
59110+ u32 rsvd2[2];
59111+ __be32 itt;
59112+ __be32 ttt;
59113+ u32 stat_sn;
59114+ u32 exp_cmd_sn;
59115+ u32 max_cmd_sn;
59116+ u32 rsvd3[3];
59117+} __packed;
59118+
59119+struct iscsi_login_req_hdr {
59120+ u8 opcode;
59121+ u8 flags;
59122+ u8 max_version; /* Max. version supported */
59123+ u8 min_version; /* Min. version supported */
59124+ u8 ahslength;
59125+ u8 datalength[3];
59126+ union iscsi_sid sid;
59127+ __be32 itt; /* Initiator Task Tag */
59128+ __be16 cid; /* Connection ID */
59129+ u16 rsvd1;
59130+ u32 cmd_sn;
59131+ u32 exp_stat_sn;
59132+ u32 rsvd2[4];
59133+} __packed;
59134+
59135+struct iscsi_login_rsp_hdr {
59136+ u8 opcode;
59137+ u8 flags;
59138+ u8 max_version; /* Max. version supported */
59139+ u8 active_version; /* Active version */
59140+ u8 ahslength;
59141+ u8 datalength[3];
59142+ union iscsi_sid sid;
59143+ __be32 itt; /* Initiator Task Tag */
59144+ u32 rsvd1;
59145+ u32 stat_sn;
59146+ u32 exp_cmd_sn;
59147+ u32 max_cmd_sn;
59148+ u8 status_class; /* see Login RSP Status classes below */
59149+ u8 status_detail; /* see Login RSP Status details below */
59150+ u8 rsvd2[10];
59151+} __packed;
59152+
59153+#define ISCSI_FLG_FINAL 0x80
59154+#define ISCSI_FLG_TRANSIT 0x80
59155+#define ISCSI_FLG_CSG_SECURITY 0x00
59156+#define ISCSI_FLG_CSG_LOGIN 0x04
59157+#define ISCSI_FLG_CSG_FULL_FEATURE 0x0c
59158+#define ISCSI_FLG_CSG_MASK 0x0c
59159+#define ISCSI_FLG_NSG_SECURITY 0x00
59160+#define ISCSI_FLG_NSG_LOGIN 0x01
59161+#define ISCSI_FLG_NSG_FULL_FEATURE 0x03
59162+#define ISCSI_FLG_NSG_MASK 0x03
59163+
59164+/* Login Status response classes */
59165+#define ISCSI_STATUS_SUCCESS 0x00
59166+#define ISCSI_STATUS_REDIRECT 0x01
59167+#define ISCSI_STATUS_INITIATOR_ERR 0x02
59168+#define ISCSI_STATUS_TARGET_ERR 0x03
59169+
59170+/* Login Status response detail codes */
59171+/* Class-0 (Success) */
59172+#define ISCSI_STATUS_ACCEPT 0x00
59173+
59174+/* Class-1 (Redirection) */
59175+#define ISCSI_STATUS_TGT_MOVED_TEMP 0x01
59176+#define ISCSI_STATUS_TGT_MOVED_PERM 0x02
59177+
59178+/* Class-2 (Initiator Error) */
59179+#define ISCSI_STATUS_INIT_ERR 0x00
59180+#define ISCSI_STATUS_AUTH_FAILED 0x01
59181+#define ISCSI_STATUS_TGT_FORBIDDEN 0x02
59182+#define ISCSI_STATUS_TGT_NOT_FOUND 0x03
59183+#define ISCSI_STATUS_TGT_REMOVED 0x04
59184+#define ISCSI_STATUS_NO_VERSION 0x05
59185+#define ISCSI_STATUS_TOO_MANY_CONN 0x06
59186+#define ISCSI_STATUS_MISSING_FIELDS 0x07
59187+#define ISCSI_STATUS_CONN_ADD_FAILED 0x08
59188+#define ISCSI_STATUS_INV_SESSION_TYPE 0x09
59189+#define ISCSI_STATUS_SESSION_NOT_FOUND 0x0a
59190+#define ISCSI_STATUS_INV_REQ_TYPE 0x0b
59191+
59192+/* Class-3 (Target Error) */
59193+#define ISCSI_STATUS_TARGET_ERROR 0x00
59194+#define ISCSI_STATUS_SVC_UNAVAILABLE 0x01
59195+#define ISCSI_STATUS_NO_RESOURCES 0x02
59196+
59197+struct iscsi_logout_req_hdr {
59198+ u8 opcode;
59199+ u8 flags;
59200+ u16 rsvd1;
59201+ u8 ahslength;
59202+ u8 datalength[3];
59203+ u32 rsvd2[2];
59204+ __be32 itt;
59205+ __be16 cid;
59206+ u16 rsvd3;
59207+ u32 cmd_sn;
59208+ u32 exp_stat_sn;
59209+ u32 rsvd4[4];
59210+} __packed;
59211+
59212+struct iscsi_logout_rsp_hdr {
59213+ u8 opcode;
59214+ u8 flags;
59215+ u8 response;
59216+ u8 rsvd1;
59217+ u8 ahslength;
59218+ u8 datalength[3];
59219+ u32 rsvd2[2];
59220+ __be32 itt;
59221+ u32 rsvd3;
59222+ u32 stat_sn;
59223+ u32 exp_cmd_sn;
59224+ u32 max_cmd_sn;
59225+ u32 rsvd4;
59226+ __be16 time2wait;
59227+ __be16 time2retain;
59228+ u32 rsvd5;
59229+} __packed;
59230+
59231+struct iscsi_snack_req_hdr {
59232+ u8 opcode;
59233+ u8 flags;
59234+ u16 rsvd1;
59235+ u8 ahslength;
59236+ u8 datalength[3];
59237+ u32 rsvd2[2];
59238+ __be32 itt;
59239+ __be32 ttt;
59240+ u32 rsvd3;
59241+ u32 exp_stat_sn;
59242+ u32 rsvd4[2];
59243+ __be32 beg_run;
59244+ __be32 run_length;
59245+} __packed;
59246+
59247+struct iscsi_reject_hdr {
59248+ u8 opcode;
59249+ u8 flags;
59250+ u8 reason;
59251+ u8 rsvd1;
59252+ u8 ahslength;
59253+ u8 datalength[3];
59254+ u32 rsvd2[2];
59255+ __be32 ffffffff;
59256+ __be32 rsvd3;
59257+ u32 stat_sn;
59258+ u32 exp_cmd_sn;
59259+ u32 max_cmd_sn;
59260+ __be32 data_sn;
59261+ u32 rsvd4[2];
59262+} __packed;
59263+
59264+#define ISCSI_REASON_RESERVED 0x01
59265+#define ISCSI_REASON_DATA_DIGEST_ERROR 0x02
59266+#define ISCSI_REASON_DATA_SNACK_REJECT 0x03
59267+#define ISCSI_REASON_PROTOCOL_ERROR 0x04
59268+#define ISCSI_REASON_UNSUPPORTED_COMMAND 0x05
59269+#define ISCSI_REASON_IMMEDIATE_COMMAND_REJECT 0x06
59270+#define ISCSI_REASON_TASK_IN_PROGRESS 0x07
59271+#define ISCSI_REASON_INVALID_DATA_ACK 0x08
59272+#define ISCSI_REASON_INVALID_PDU_FIELD 0x09
59273+#define ISCSI_REASON_OUT_OF_RESOURCES 0x0a
59274+#define ISCSI_REASON_NEGOTIATION_RESET 0x0b
59275+#define ISCSI_REASON_WAITING_LOGOUT 0x0c
59276+
59277+struct iscsi_nop_out_hdr {
59278+ u8 opcode;
59279+ u8 flags;
59280+ u16 rsvd1;
59281+ u8 ahslength;
59282+ u8 datalength[3];
59283+ __be64 lun;
59284+ __be32 itt;
59285+ __be32 ttt;
59286+ u32 cmd_sn;
59287+ u32 exp_stat_sn;
59288+ u32 rsvd2[4];
59289+} __packed;
59290+
59291+struct iscsi_nop_in_hdr {
59292+ u8 opcode;
59293+ u8 flags;
59294+ u16 rsvd1;
59295+ u8 ahslength;
59296+ u8 datalength[3];
59297+ __be64 lun;
59298+ __be32 itt;
59299+ __be32 ttt;
59300+ u32 stat_sn;
59301+ u32 exp_cmd_sn;
59302+ u32 max_cmd_sn;
59303+ u32 rsvd2[3];
59304+} __packed;
59305+
59306+#define ISCSI_RESERVED_TAG_CPU32 (0xffffffffU)
59307+#define ISCSI_RESERVED_TAG (__constant_cpu_to_be32(ISCSI_RESERVED_TAG_CPU32))
59308+
59309+#define cmnd_hdr(cmnd) ((struct iscsi_scsi_cmd_hdr *) (&((cmnd)->pdu.bhs)))
59310+#define cmnd_opcode(cmnd) ((cmnd)->pdu.bhs.opcode & ISCSI_OPCODE_MASK)
59311+#define cmnd_scsicode(cmnd) (cmnd_hdr((cmnd))->scb[0])
59312+
59313+#endif /* __ISCSI_HDR_H__ */
59314diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/nthread.c linux-2.6.35/drivers/scst/iscsi-scst/nthread.c
59315--- orig/linux-2.6.35/drivers/scst/iscsi-scst/nthread.c
59316+++ linux-2.6.35/drivers/scst/iscsi-scst/nthread.c
59317@@ -0,0 +1,1838 @@
59318+/*
59319+ * Network threads.
59320+ *
59321+ * Copyright (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
59322+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
59323+ * Copyright (C) 2007 - 2010 ID7 Ltd.
59324+ *
59325+ * This program is free software; you can redistribute it and/or
59326+ * modify it under the terms of the GNU General Public License
59327+ * as published by the Free Software Foundation.
59328+ *
59329+ * This program is distributed in the hope that it will be useful,
59330+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
59331+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59332+ * GNU General Public License for more details.
59333+ */
59334+
59335+#include <linux/sched.h>
59336+#include <linux/file.h>
59337+#include <linux/kthread.h>
59338+#include <asm/ioctls.h>
59339+#include <linux/delay.h>
59340+#include <net/tcp.h>
59341+
59342+#include "iscsi.h"
59343+#include "digest.h"
59344+
59345+enum rx_state {
59346+ RX_INIT_BHS, /* Must be zero for better "switch" optimization. */
59347+ RX_BHS,
59348+ RX_CMD_START,
59349+ RX_DATA,
59350+ RX_END,
59351+
59352+ RX_CMD_CONTINUE,
59353+ RX_INIT_HDIGEST,
59354+ RX_CHECK_HDIGEST,
59355+ RX_INIT_DDIGEST,
59356+ RX_CHECK_DDIGEST,
59357+ RX_AHS,
59358+ RX_PADDING,
59359+};
59360+
59361+enum tx_state {
59362+ TX_INIT = 0, /* Must be zero for better "switch" optimization. */
59363+ TX_BHS_DATA,
59364+ TX_INIT_PADDING,
59365+ TX_PADDING,
59366+ TX_INIT_DDIGEST,
59367+ TX_DDIGEST,
59368+ TX_END,
59369+};
59370+
59371+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
59372+static void iscsi_check_closewait(struct iscsi_conn *conn)
59373+{
59374+ struct iscsi_cmnd *cmnd;
59375+
59376+ TRACE_ENTRY();
59377+
59378+ TRACE_CONN_CLOSE_DBG("conn %p, sk_state %d", conn,
59379+ conn->sock->sk->sk_state);
59380+
59381+ if (conn->sock->sk->sk_state != TCP_CLOSE) {
59382+ TRACE_CONN_CLOSE_DBG("conn %p, skipping", conn);
59383+ goto out;
59384+ }
59385+
59386+ /*
59387+ * No data are going to be sent, so all queued buffers can be freed
59388+ * now. In many cases TCP does that only in close(), but we can't rely
59389+ * on user space on calling it.
59390+ */
59391+
59392+again:
59393+ spin_lock_bh(&conn->cmd_list_lock);
59394+ list_for_each_entry(cmnd, &conn->cmd_list, cmd_list_entry) {
59395+ struct iscsi_cmnd *rsp;
59396+ int restart = 0;
59397+
59398+ TRACE_CONN_CLOSE_DBG("cmd %p, scst_state %x, "
59399+ "r2t_len_to_receive %d, ref_cnt %d, parent_req %p, "
59400+ "net_ref_cnt %d, sg %p", cmnd, cmnd->scst_state,
59401+ cmnd->r2t_len_to_receive, atomic_read(&cmnd->ref_cnt),
59402+ cmnd->parent_req, atomic_read(&cmnd->net_ref_cnt),
59403+ cmnd->sg);
59404+
59405+ BUG_ON(cmnd->parent_req != NULL);
59406+
59407+ if (cmnd->sg != NULL) {
59408+ int i;
59409+
59410+ if (cmnd_get_check(cmnd))
59411+ continue;
59412+
59413+ for (i = 0; i < cmnd->sg_cnt; i++) {
59414+ struct page *page = sg_page(&cmnd->sg[i]);
59415+ TRACE_CONN_CLOSE_DBG("page %p, net_priv %p, "
59416+ "_count %d", page, page->net_priv,
59417+ atomic_read(&page->_count));
59418+
59419+ if (page->net_priv != NULL) {
59420+ if (restart == 0) {
59421+ spin_unlock_bh(&conn->cmd_list_lock);
59422+ restart = 1;
59423+ }
59424+ while (page->net_priv != NULL)
59425+ iscsi_put_page_callback(page);
59426+ }
59427+ }
59428+ cmnd_put(cmnd);
59429+
59430+ if (restart)
59431+ goto again;
59432+ }
59433+
59434+ list_for_each_entry(rsp, &cmnd->rsp_cmd_list,
59435+ rsp_cmd_list_entry) {
59436+ TRACE_CONN_CLOSE_DBG(" rsp %p, ref_cnt %d, "
59437+ "net_ref_cnt %d, sg %p",
59438+ rsp, atomic_read(&rsp->ref_cnt),
59439+ atomic_read(&rsp->net_ref_cnt), rsp->sg);
59440+
59441+ if ((rsp->sg != cmnd->sg) && (rsp->sg != NULL)) {
59442+ int i;
59443+
59444+ if (cmnd_get_check(rsp))
59445+ continue;
59446+
59447+ for (i = 0; i < rsp->sg_cnt; i++) {
59448+ struct page *page =
59449+ sg_page(&rsp->sg[i]);
59450+ TRACE_CONN_CLOSE_DBG(
59451+ " page %p, net_priv %p, "
59452+ "_count %d",
59453+ page, page->net_priv,
59454+ atomic_read(&page->_count));
59455+
59456+ if (page->net_priv != NULL) {
59457+ if (restart == 0) {
59458+ spin_unlock_bh(&conn->cmd_list_lock);
59459+ restart = 1;
59460+ }
59461+ while (page->net_priv != NULL)
59462+ iscsi_put_page_callback(page);
59463+ }
59464+ }
59465+ cmnd_put(rsp);
59466+
59467+ if (restart)
59468+ goto again;
59469+ }
59470+ }
59471+ }
59472+ spin_unlock_bh(&conn->cmd_list_lock);
59473+
59474+out:
59475+ TRACE_EXIT();
59476+ return;
59477+}
59478+#else
59479+static inline void iscsi_check_closewait(struct iscsi_conn *conn) {};
59480+#endif
59481+
59482+static void free_pending_commands(struct iscsi_conn *conn)
59483+{
59484+ struct iscsi_session *session = conn->session;
59485+ struct list_head *pending_list = &session->pending_list;
59486+ int req_freed;
59487+ struct iscsi_cmnd *cmnd;
59488+
59489+ spin_lock(&session->sn_lock);
59490+ do {
59491+ req_freed = 0;
59492+ list_for_each_entry(cmnd, pending_list, pending_list_entry) {
59493+ TRACE_CONN_CLOSE_DBG("Pending cmd %p"
59494+ "(conn %p, cmd_sn %u, exp_cmd_sn %u)",
59495+ cmnd, conn, cmnd->pdu.bhs.sn,
59496+ session->exp_cmd_sn);
59497+ if ((cmnd->conn == conn) &&
59498+ (session->exp_cmd_sn == cmnd->pdu.bhs.sn)) {
59499+ TRACE_MGMT_DBG("Freeing pending cmd %p "
59500+ "(cmd_sn %u, exp_cmd_sn %u)",
59501+ cmnd, cmnd->pdu.bhs.sn,
59502+ session->exp_cmd_sn);
59503+
59504+ list_del(&cmnd->pending_list_entry);
59505+ cmnd->pending = 0;
59506+
59507+ session->exp_cmd_sn++;
59508+
59509+ spin_unlock(&session->sn_lock);
59510+
59511+ req_cmnd_release_force(cmnd);
59512+
59513+ req_freed = 1;
59514+ spin_lock(&session->sn_lock);
59515+ break;
59516+ }
59517+ }
59518+ } while (req_freed);
59519+ spin_unlock(&session->sn_lock);
59520+
59521+ return;
59522+}
59523+
59524+static void free_orphaned_pending_commands(struct iscsi_conn *conn)
59525+{
59526+ struct iscsi_session *session = conn->session;
59527+ struct list_head *pending_list = &session->pending_list;
59528+ int req_freed;
59529+ struct iscsi_cmnd *cmnd;
59530+
59531+ spin_lock(&session->sn_lock);
59532+ do {
59533+ req_freed = 0;
59534+ list_for_each_entry(cmnd, pending_list, pending_list_entry) {
59535+ TRACE_CONN_CLOSE_DBG("Pending cmd %p"
59536+ "(conn %p, cmd_sn %u, exp_cmd_sn %u)",
59537+ cmnd, conn, cmnd->pdu.bhs.sn,
59538+ session->exp_cmd_sn);
59539+ if (cmnd->conn == conn) {
59540+ TRACE_MGMT_DBG("Freeing orphaned pending "
59541+ "cmnd %p (cmd_sn %u, exp_cmd_sn %u)",
59542+ cmnd, cmnd->pdu.bhs.sn,
59543+ session->exp_cmd_sn);
59544+
59545+ list_del(&cmnd->pending_list_entry);
59546+ cmnd->pending = 0;
59547+
59548+ if (session->exp_cmd_sn == cmnd->pdu.bhs.sn)
59549+ session->exp_cmd_sn++;
59550+
59551+ spin_unlock(&session->sn_lock);
59552+
59553+ req_cmnd_release_force(cmnd);
59554+
59555+ req_freed = 1;
59556+ spin_lock(&session->sn_lock);
59557+ break;
59558+ }
59559+ }
59560+ } while (req_freed);
59561+ spin_unlock(&session->sn_lock);
59562+
59563+ return;
59564+}
59565+
59566+#ifdef CONFIG_SCST_DEBUG
59567+static void trace_conn_close(struct iscsi_conn *conn)
59568+{
59569+ struct iscsi_cmnd *cmnd;
59570+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
59571+ struct iscsi_cmnd *rsp;
59572+#endif
59573+
59574+#if 0
59575+ if (time_after(jiffies, start_waiting + 10*HZ))
59576+ trace_flag |= TRACE_CONN_OC_DBG;
59577+#endif
59578+
59579+ spin_lock_bh(&conn->cmd_list_lock);
59580+ list_for_each_entry(cmnd, &conn->cmd_list,
59581+ cmd_list_entry) {
59582+ TRACE_CONN_CLOSE_DBG(
59583+ "cmd %p, scst_cmd %p, scst_state %x, scst_cmd state "
59584+ "%d, r2t_len_to_receive %d, ref_cnt %d, sn %u, "
59585+ "parent_req %p, pending %d",
59586+ cmnd, cmnd->scst_cmd, cmnd->scst_state,
59587+ ((cmnd->parent_req == NULL) && cmnd->scst_cmd) ?
59588+ cmnd->scst_cmd->state : -1,
59589+ cmnd->r2t_len_to_receive, atomic_read(&cmnd->ref_cnt),
59590+ cmnd->pdu.bhs.sn, cmnd->parent_req, cmnd->pending);
59591+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
59592+ TRACE_CONN_CLOSE_DBG("net_ref_cnt %d, sg %p",
59593+ atomic_read(&cmnd->net_ref_cnt),
59594+ cmnd->sg);
59595+ if (cmnd->sg != NULL) {
59596+ int i;
59597+ for (i = 0; i < cmnd->sg_cnt; i++) {
59598+ struct page *page = sg_page(&cmnd->sg[i]);
59599+ TRACE_CONN_CLOSE_DBG("page %p, "
59600+ "net_priv %p, _count %d",
59601+ page, page->net_priv,
59602+ atomic_read(&page->_count));
59603+ }
59604+ }
59605+
59606+ BUG_ON(cmnd->parent_req != NULL);
59607+
59608+ list_for_each_entry(rsp, &cmnd->rsp_cmd_list,
59609+ rsp_cmd_list_entry) {
59610+ TRACE_CONN_CLOSE_DBG(" rsp %p, "
59611+ "ref_cnt %d, net_ref_cnt %d, sg %p",
59612+ rsp, atomic_read(&rsp->ref_cnt),
59613+ atomic_read(&rsp->net_ref_cnt), rsp->sg);
59614+ if (rsp->sg != cmnd->sg && rsp->sg) {
59615+ int i;
59616+ for (i = 0; i < rsp->sg_cnt; i++) {
59617+ TRACE_CONN_CLOSE_DBG(" page %p, "
59618+ "net_priv %p, _count %d",
59619+ sg_page(&rsp->sg[i]),
59620+ sg_page(&rsp->sg[i])->net_priv,
59621+ atomic_read(&sg_page(&rsp->sg[i])->
59622+ _count));
59623+ }
59624+ }
59625+ }
59626+#endif /* CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION */
59627+ }
59628+ spin_unlock_bh(&conn->cmd_list_lock);
59629+ return;
59630+}
59631+#else /* CONFIG_SCST_DEBUG */
59632+static void trace_conn_close(struct iscsi_conn *conn) {}
59633+#endif /* CONFIG_SCST_DEBUG */
59634+
59635+void iscsi_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *scst_mcmd)
59636+{
59637+ int fn = scst_mgmt_cmd_get_fn(scst_mcmd);
59638+ void *priv = scst_mgmt_cmd_get_tgt_priv(scst_mcmd);
59639+
59640+ TRACE_MGMT_DBG("scst_mcmd %p, fn %d, priv %p", scst_mcmd, fn, priv);
59641+
59642+ switch (fn) {
59643+ case SCST_NEXUS_LOSS_SESS:
59644+ case SCST_ABORT_ALL_TASKS_SESS:
59645+ {
59646+ struct iscsi_conn *conn = (struct iscsi_conn *)priv;
59647+ struct iscsi_session *sess = conn->session;
59648+ struct iscsi_conn *c;
59649+
59650+ if (sess->sess_reinst_successor != NULL)
59651+ scst_reassign_persistent_sess_states(
59652+ sess->sess_reinst_successor->scst_sess,
59653+ sess->scst_sess);
59654+
59655+ mutex_lock(&sess->target->target_mutex);
59656+
59657+ /*
59658+ * We can't mark sess as shutting down earlier, because until
59659+ * now it might have pending commands. Otherwise, in case of
59660+ * reinstatement, it might lead to data corruption, because
59661+ * commands in being reinstated session can be executed
59662+ * after commands in the new session.
59663+ */
59664+ sess->sess_shutting_down = 1;
59665+ list_for_each_entry(c, &sess->conn_list, conn_list_entry) {
59666+ if (!test_bit(ISCSI_CONN_SHUTTINGDOWN, &c->conn_aflags)) {
59667+ sess->sess_shutting_down = 0;
59668+ break;
59669+ }
59670+ }
59671+
59672+ if (conn->conn_reinst_successor != NULL) {
59673+ BUG_ON(!test_bit(ISCSI_CONN_REINSTATING,
59674+ &conn->conn_reinst_successor->conn_aflags));
59675+ conn_reinst_finished(conn->conn_reinst_successor);
59676+ conn->conn_reinst_successor = NULL;
59677+ } else if (sess->sess_reinst_successor != NULL) {
59678+ sess_reinst_finished(sess->sess_reinst_successor);
59679+ sess->sess_reinst_successor = NULL;
59680+ }
59681+ mutex_unlock(&sess->target->target_mutex);
59682+
59683+ complete_all(&conn->ready_to_free);
59684+ break;
59685+ }
59686+ default:
59687+ /* Nothing to do */
59688+ break;
59689+ }
59690+
59691+ return;
59692+}
59693+
59694+/* No locks */
59695+static void close_conn(struct iscsi_conn *conn)
59696+{
59697+ struct iscsi_session *session = conn->session;
59698+ struct iscsi_target *target = conn->target;
59699+ typeof(jiffies) start_waiting = jiffies;
59700+ typeof(jiffies) shut_start_waiting = start_waiting;
59701+ bool pending_reported = 0, wait_expired = 0, shut_expired = 0;
59702+ bool reinst;
59703+ uint32_t tid, cid;
59704+ uint64_t sid;
59705+
59706+#define CONN_PENDING_TIMEOUT ((typeof(jiffies))10*HZ)
59707+#define CONN_WAIT_TIMEOUT ((typeof(jiffies))10*HZ)
59708+#define CONN_REG_SHUT_TIMEOUT ((typeof(jiffies))125*HZ)
59709+#define CONN_DEL_SHUT_TIMEOUT ((typeof(jiffies))10*HZ)
59710+
59711+ TRACE_ENTRY();
59712+
59713+ TRACE_MGMT_DBG("Closing connection %p (conn_ref_cnt=%d)", conn,
59714+ atomic_read(&conn->conn_ref_cnt));
59715+
59716+ iscsi_extracheck_is_rd_thread(conn);
59717+
59718+ BUG_ON(!conn->closing);
59719+
59720+ if (conn->active_close) {
59721+ /* We want all our already send operations to complete */
59722+ conn->sock->ops->shutdown(conn->sock, RCV_SHUTDOWN);
59723+ } else {
59724+ conn->sock->ops->shutdown(conn->sock,
59725+ RCV_SHUTDOWN|SEND_SHUTDOWN);
59726+ }
59727+
59728+ mutex_lock(&session->target->target_mutex);
59729+
59730+ set_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags);
59731+ reinst = (conn->conn_reinst_successor != NULL);
59732+
59733+ mutex_unlock(&session->target->target_mutex);
59734+
59735+ if (reinst) {
59736+ int rc;
59737+ int lun = 0;
59738+
59739+ /* Abort all outstanding commands */
59740+ rc = scst_rx_mgmt_fn_lun(session->scst_sess,
59741+ SCST_ABORT_ALL_TASKS_SESS, (uint8_t *)&lun, sizeof(lun),
59742+ SCST_NON_ATOMIC, conn);
59743+ if (rc != 0)
59744+ PRINT_ERROR("SCST_ABORT_ALL_TASKS_SESS failed %d", rc);
59745+ } else {
59746+ int rc;
59747+ int lun = 0;
59748+
59749+ rc = scst_rx_mgmt_fn_lun(session->scst_sess,
59750+ SCST_NEXUS_LOSS_SESS, (uint8_t *)&lun, sizeof(lun),
59751+ SCST_NON_ATOMIC, conn);
59752+ if (rc != 0)
59753+ PRINT_ERROR("SCST_NEXUS_LOSS_SESS failed %d", rc);
59754+ }
59755+
59756+ if (conn->read_state != RX_INIT_BHS) {
59757+ struct iscsi_cmnd *cmnd = conn->read_cmnd;
59758+
59759+ if (cmnd->scst_state == ISCSI_CMD_STATE_RX_CMD) {
59760+ TRACE_CONN_CLOSE_DBG("Going to wait for cmnd %p to "
59761+ "change state from RX_CMD", cmnd);
59762+ }
59763+ wait_event(conn->read_state_waitQ,
59764+ cmnd->scst_state != ISCSI_CMD_STATE_RX_CMD);
59765+
59766+ TRACE_CONN_CLOSE_DBG("Releasing conn->read_cmnd %p (conn %p)",
59767+ conn->read_cmnd, conn);
59768+
59769+ conn->read_cmnd = NULL;
59770+ conn->read_state = RX_INIT_BHS;
59771+ req_cmnd_release_force(cmnd);
59772+ }
59773+
59774+ conn_abort(conn);
59775+
59776+ /* ToDo: not the best way to wait */
59777+ while (atomic_read(&conn->conn_ref_cnt) != 0) {
59778+ if (conn->conn_tm_active)
59779+ iscsi_check_tm_data_wait_timeouts(conn, true);
59780+
59781+ mutex_lock(&target->target_mutex);
59782+ spin_lock(&session->sn_lock);
59783+ if (session->tm_rsp && session->tm_rsp->conn == conn) {
59784+ struct iscsi_cmnd *tm_rsp = session->tm_rsp;
59785+ TRACE_MGMT_DBG("Dropping delayed TM rsp %p", tm_rsp);
59786+ session->tm_rsp = NULL;
59787+ session->tm_active--;
59788+ WARN_ON(session->tm_active < 0);
59789+ spin_unlock(&session->sn_lock);
59790+ mutex_unlock(&target->target_mutex);
59791+
59792+ rsp_cmnd_release(tm_rsp);
59793+ } else {
59794+ spin_unlock(&session->sn_lock);
59795+ mutex_unlock(&target->target_mutex);
59796+ }
59797+
59798+ /* It's safe to check it without sn_lock */
59799+ if (!list_empty(&session->pending_list)) {
59800+ TRACE_CONN_CLOSE_DBG("Disposing pending commands on "
59801+ "connection %p (conn_ref_cnt=%d)", conn,
59802+ atomic_read(&conn->conn_ref_cnt));
59803+
59804+ free_pending_commands(conn);
59805+
59806+ if (time_after(jiffies,
59807+ start_waiting + CONN_PENDING_TIMEOUT)) {
59808+ if (!pending_reported) {
59809+ TRACE_CONN_CLOSE("%s",
59810+ "Pending wait time expired");
59811+ pending_reported = 1;
59812+ }
59813+ free_orphaned_pending_commands(conn);
59814+ }
59815+ }
59816+
59817+ iscsi_make_conn_wr_active(conn);
59818+
59819+ /* That's for active close only, actually */
59820+ if (time_after(jiffies, start_waiting + CONN_WAIT_TIMEOUT) &&
59821+ !wait_expired) {
59822+ TRACE_CONN_CLOSE("Wait time expired (conn %p, "
59823+ "sk_state %d)",
59824+ conn, conn->sock->sk->sk_state);
59825+ conn->sock->ops->shutdown(conn->sock, SEND_SHUTDOWN);
59826+ wait_expired = 1;
59827+ shut_start_waiting = jiffies;
59828+ }
59829+
59830+ if (wait_expired && !shut_expired &&
59831+ time_after(jiffies, shut_start_waiting +
59832+ conn->deleting ? CONN_DEL_SHUT_TIMEOUT :
59833+ CONN_REG_SHUT_TIMEOUT)) {
59834+ TRACE_CONN_CLOSE("Wait time after shutdown expired "
59835+ "(conn %p, sk_state %d)", conn,
59836+ conn->sock->sk->sk_state);
59837+ conn->sock->sk->sk_prot->disconnect(conn->sock->sk, 0);
59838+ shut_expired = 1;
59839+ }
59840+
59841+ if (conn->deleting)
59842+ msleep(200);
59843+ else
59844+ msleep(1000);
59845+
59846+ TRACE_CONN_CLOSE_DBG("conn %p, conn_ref_cnt %d left, "
59847+ "wr_state %d, exp_cmd_sn %u",
59848+ conn, atomic_read(&conn->conn_ref_cnt),
59849+ conn->wr_state, session->exp_cmd_sn);
59850+
59851+ trace_conn_close(conn);
59852+
59853+ /* It might never be called for being closed conn */
59854+ __iscsi_write_space_ready(conn);
59855+
59856+ iscsi_check_closewait(conn);
59857+ }
59858+
59859+ write_lock_bh(&conn->sock->sk->sk_callback_lock);
59860+ conn->sock->sk->sk_state_change = conn->old_state_change;
59861+ conn->sock->sk->sk_data_ready = conn->old_data_ready;
59862+ conn->sock->sk->sk_write_space = conn->old_write_space;
59863+ write_unlock_bh(&conn->sock->sk->sk_callback_lock);
59864+
59865+ while (1) {
59866+ bool t;
59867+
59868+ spin_lock_bh(&iscsi_wr_lock);
59869+ t = (conn->wr_state == ISCSI_CONN_WR_STATE_IDLE);
59870+ spin_unlock_bh(&iscsi_wr_lock);
59871+
59872+ if (t && (atomic_read(&conn->conn_ref_cnt) == 0))
59873+ break;
59874+
59875+ TRACE_CONN_CLOSE_DBG("Waiting for wr thread (conn %p), "
59876+ "wr_state %x", conn, conn->wr_state);
59877+ msleep(50);
59878+ }
59879+
59880+ wait_for_completion(&conn->ready_to_free);
59881+
59882+ tid = target->tid;
59883+ sid = session->sid;
59884+ cid = conn->cid;
59885+
59886+ mutex_lock(&target->target_mutex);
59887+ conn_free(conn);
59888+ mutex_unlock(&target->target_mutex);
59889+
59890+ /*
59891+ * We can't send E_CONN_CLOSE earlier, because otherwise we would have
59892+ * a race, when the user space tried to destroy session, which still
59893+ * has connections.
59894+ *
59895+ * !! All target, session and conn can be already dead here !!
59896+ */
59897+ TRACE_CONN_CLOSE("Notifying user space about closing connection %p",
59898+ conn);
59899+ event_send(tid, sid, cid, 0, E_CONN_CLOSE, NULL, NULL);
59900+
59901+ TRACE_EXIT();
59902+ return;
59903+}
59904+
59905+static int close_conn_thr(void *arg)
59906+{
59907+ struct iscsi_conn *conn = (struct iscsi_conn *)arg;
59908+
59909+ TRACE_ENTRY();
59910+
59911+#ifdef CONFIG_SCST_EXTRACHECKS
59912+ /*
59913+ * To satisfy iscsi_extracheck_is_rd_thread() in functions called
59914+ * on the connection close. It is safe, because at this point conn
59915+ * can't be used by any other thread.
59916+ */
59917+ conn->rd_task = current;
59918+#endif
59919+ close_conn(conn);
59920+
59921+ TRACE_EXIT();
59922+ return 0;
59923+}
59924+
59925+/* No locks */
59926+static void start_close_conn(struct iscsi_conn *conn)
59927+{
59928+ struct task_struct *t;
59929+
59930+ TRACE_ENTRY();
59931+
59932+ t = kthread_run(close_conn_thr, conn, "iscsi_conn_cleanup");
59933+ if (IS_ERR(t)) {
59934+ PRINT_ERROR("kthread_run() failed (%ld), closing conn %p "
59935+ "directly", PTR_ERR(t), conn);
59936+ close_conn(conn);
59937+ }
59938+
59939+ TRACE_EXIT();
59940+ return;
59941+}
59942+
59943+static inline void iscsi_conn_init_read(struct iscsi_conn *conn,
59944+ void __user *data, size_t len)
59945+{
59946+ conn->read_iov[0].iov_base = data;
59947+ conn->read_iov[0].iov_len = len;
59948+ conn->read_msg.msg_iov = conn->read_iov;
59949+ conn->read_msg.msg_iovlen = 1;
59950+ conn->read_size = len;
59951+ return;
59952+}
59953+
59954+static void iscsi_conn_prepare_read_ahs(struct iscsi_conn *conn,
59955+ struct iscsi_cmnd *cmnd)
59956+{
59957+ int asize = (cmnd->pdu.ahssize + 3) & -4;
59958+
59959+ /* ToDo: __GFP_NOFAIL ?? */
59960+ cmnd->pdu.ahs = kmalloc(asize, __GFP_NOFAIL|GFP_KERNEL);
59961+ BUG_ON(cmnd->pdu.ahs == NULL);
59962+ iscsi_conn_init_read(conn, (void __force __user *)cmnd->pdu.ahs, asize);
59963+ return;
59964+}
59965+
59966+static struct iscsi_cmnd *iscsi_get_send_cmnd(struct iscsi_conn *conn)
59967+{
59968+ struct iscsi_cmnd *cmnd = NULL;
59969+
59970+ spin_lock_bh(&conn->write_list_lock);
59971+ if (!list_empty(&conn->write_list)) {
59972+ cmnd = list_entry(conn->write_list.next, struct iscsi_cmnd,
59973+ write_list_entry);
59974+ cmd_del_from_write_list(cmnd);
59975+ cmnd->write_processing_started = 1;
59976+ } else {
59977+ spin_unlock_bh(&conn->write_list_lock);
59978+ goto out;
59979+ }
59980+ spin_unlock_bh(&conn->write_list_lock);
59981+
59982+ if (unlikely(test_bit(ISCSI_CMD_ABORTED,
59983+ &cmnd->parent_req->prelim_compl_flags))) {
59984+ TRACE_MGMT_DBG("Going to send acmd %p (scst cmd %p, "
59985+ "state %d, parent_req %p)", cmnd, cmnd->scst_cmd,
59986+ cmnd->scst_state, cmnd->parent_req);
59987+ }
59988+
59989+ if (unlikely(cmnd_opcode(cmnd) == ISCSI_OP_SCSI_TASK_MGT_RSP)) {
59990+#ifdef CONFIG_SCST_DEBUG
59991+ struct iscsi_task_mgt_hdr *req_hdr =
59992+ (struct iscsi_task_mgt_hdr *)&cmnd->parent_req->pdu.bhs;
59993+ struct iscsi_task_rsp_hdr *rsp_hdr =
59994+ (struct iscsi_task_rsp_hdr *)&cmnd->pdu.bhs;
59995+ TRACE_MGMT_DBG("Going to send TM response %p (status %d, "
59996+ "fn %d, parent_req %p)", cmnd, rsp_hdr->response,
59997+ req_hdr->function & ISCSI_FUNCTION_MASK,
59998+ cmnd->parent_req);
59999+#endif
60000+ }
60001+
60002+out:
60003+ return cmnd;
60004+}
60005+
60006+/* Returns number of bytes left to receive or <0 for error */
60007+static int do_recv(struct iscsi_conn *conn)
60008+{
60009+ int res;
60010+ mm_segment_t oldfs;
60011+ struct msghdr msg;
60012+ int first_len;
60013+
60014+ EXTRACHECKS_BUG_ON(conn->read_cmnd == NULL);
60015+
60016+ if (unlikely(conn->closing)) {
60017+ res = -EIO;
60018+ goto out;
60019+ }
60020+
60021+ /*
60022+ * We suppose that if sock_recvmsg() returned less data than requested,
60023+ * then next time it will return -EAGAIN, so there's no point to call
60024+ * it again.
60025+ */
60026+
60027+restart:
60028+ memset(&msg, 0, sizeof(msg));
60029+ msg.msg_iov = conn->read_msg.msg_iov;
60030+ msg.msg_iovlen = conn->read_msg.msg_iovlen;
60031+ first_len = msg.msg_iov->iov_len;
60032+
60033+ oldfs = get_fs();
60034+ set_fs(get_ds());
60035+ res = sock_recvmsg(conn->sock, &msg, conn->read_size,
60036+ MSG_DONTWAIT | MSG_NOSIGNAL);
60037+ set_fs(oldfs);
60038+
60039+ TRACE_DBG("msg_iovlen %zd, first_len %d, read_size %d, res %d",
60040+ msg.msg_iovlen, first_len, conn->read_size, res);
60041+
60042+ if (res > 0) {
60043+ /*
60044+ * To save some considerable effort and CPU power we
60045+ * suppose that TCP functions adjust
60046+ * conn->read_msg.msg_iov and conn->read_msg.msg_iovlen
60047+ * on amount of copied data. This BUG_ON is intended
60048+ * to catch if it is changed in the future.
60049+ */
60050+ BUG_ON((res >= first_len) &&
60051+ (conn->read_msg.msg_iov->iov_len != 0));
60052+ conn->read_size -= res;
60053+ if (conn->read_size != 0) {
60054+ if (res >= first_len) {
60055+ int done = 1 + ((res - first_len) >> PAGE_SHIFT);
60056+ TRACE_DBG("done %d", done);
60057+ conn->read_msg.msg_iov += done;
60058+ conn->read_msg.msg_iovlen -= done;
60059+ }
60060+ }
60061+ res = conn->read_size;
60062+ } else {
60063+ switch (res) {
60064+ case -EAGAIN:
60065+ TRACE_DBG("EAGAIN received for conn %p", conn);
60066+ res = conn->read_size;
60067+ break;
60068+ case -ERESTARTSYS:
60069+ TRACE_DBG("ERESTARTSYS received for conn %p", conn);
60070+ goto restart;
60071+ default:
60072+ if (!conn->closing) {
60073+ PRINT_ERROR("sock_recvmsg() failed: %d", res);
60074+ mark_conn_closed(conn);
60075+ }
60076+ if (res == 0)
60077+ res = -EIO;
60078+ break;
60079+ }
60080+ }
60081+
60082+out:
60083+ TRACE_EXIT_RES(res);
60084+ return res;
60085+}
60086+
60087+static int iscsi_rx_check_ddigest(struct iscsi_conn *conn)
60088+{
60089+ struct iscsi_cmnd *cmnd = conn->read_cmnd;
60090+ int res;
60091+
60092+ res = do_recv(conn);
60093+ if (res == 0) {
60094+ conn->read_state = RX_END;
60095+
60096+ if (cmnd->pdu.datasize <= 16*1024) {
60097+ /*
60098+ * It's cache hot, so let's compute it inline. The
60099+ * choice here about what will expose more latency:
60100+ * possible cache misses or the digest calculation.
60101+ */
60102+ TRACE_DBG("cmnd %p, opcode %x: checking RX "
60103+ "ddigest inline", cmnd, cmnd_opcode(cmnd));
60104+ cmnd->ddigest_checked = 1;
60105+ res = digest_rx_data(cmnd);
60106+ if (unlikely(res != 0)) {
60107+ struct iscsi_cmnd *orig_req;
60108+ if (cmnd_opcode(cmnd) == ISCSI_OP_SCSI_DATA_OUT)
60109+ orig_req = cmnd->cmd_req;
60110+ else
60111+ orig_req = cmnd;
60112+ if (unlikely(orig_req->scst_cmd == NULL)) {
60113+ /* Just drop it */
60114+ iscsi_preliminary_complete(cmnd, orig_req, false);
60115+ } else {
60116+ set_scst_preliminary_status_rsp(orig_req, false,
60117+ SCST_LOAD_SENSE(iscsi_sense_crc_error));
60118+ /*
60119+ * Let's prelim complete cmnd too to
60120+ * handle the DATA OUT case
60121+ */
60122+ iscsi_preliminary_complete(cmnd, orig_req, false);
60123+ }
60124+ res = 0;
60125+ }
60126+ } else if (cmnd_opcode(cmnd) == ISCSI_OP_SCSI_CMD) {
60127+ cmd_add_on_rx_ddigest_list(cmnd, cmnd);
60128+ cmnd_get(cmnd);
60129+ } else if (cmnd_opcode(cmnd) != ISCSI_OP_SCSI_DATA_OUT) {
60130+ /*
60131+ * We could get here only for Nop-Out. ISCSI RFC
60132+ * doesn't specify how to deal with digest errors in
60133+ * this case. Let's just drop the command.
60134+ */
60135+ TRACE_DBG("cmnd %p, opcode %x: checking NOP RX "
60136+ "ddigest", cmnd, cmnd_opcode(cmnd));
60137+ res = digest_rx_data(cmnd);
60138+ if (unlikely(res != 0)) {
60139+ iscsi_preliminary_complete(cmnd, cmnd, false);
60140+ res = 0;
60141+ }
60142+ }
60143+ }
60144+
60145+ return res;
60146+}
60147+
60148+/* No locks, conn is rd processing */
60149+static int process_read_io(struct iscsi_conn *conn, int *closed)
60150+{
60151+ struct iscsi_cmnd *cmnd = conn->read_cmnd;
60152+ int res;
60153+
60154+ TRACE_ENTRY();
60155+
60156+ /* In case of error cmnd will be freed in close_conn() */
60157+
60158+ do {
60159+ switch (conn->read_state) {
60160+ case RX_INIT_BHS:
60161+ EXTRACHECKS_BUG_ON(conn->read_cmnd != NULL);
60162+ cmnd = cmnd_alloc(conn, NULL);
60163+ conn->read_cmnd = cmnd;
60164+ iscsi_conn_init_read(cmnd->conn,
60165+ (void __force __user *)&cmnd->pdu.bhs,
60166+ sizeof(cmnd->pdu.bhs));
60167+ conn->read_state = RX_BHS;
60168+ /* go through */
60169+
60170+ case RX_BHS:
60171+ res = do_recv(conn);
60172+ if (res == 0) {
60173+ iscsi_cmnd_get_length(&cmnd->pdu);
60174+ if (cmnd->pdu.ahssize == 0) {
60175+ if ((conn->hdigest_type & DIGEST_NONE) == 0)
60176+ conn->read_state = RX_INIT_HDIGEST;
60177+ else
60178+ conn->read_state = RX_CMD_START;
60179+ } else {
60180+ iscsi_conn_prepare_read_ahs(conn, cmnd);
60181+ conn->read_state = RX_AHS;
60182+ }
60183+ }
60184+ break;
60185+
60186+ case RX_CMD_START:
60187+ res = cmnd_rx_start(cmnd);
60188+ if (res == 0) {
60189+ if (cmnd->pdu.datasize == 0)
60190+ conn->read_state = RX_END;
60191+ else
60192+ conn->read_state = RX_DATA;
60193+ } else if (res > 0)
60194+ conn->read_state = RX_CMD_CONTINUE;
60195+ else
60196+ BUG_ON(!conn->closing);
60197+ break;
60198+
60199+ case RX_CMD_CONTINUE:
60200+ if (cmnd->scst_state == ISCSI_CMD_STATE_RX_CMD) {
60201+ TRACE_DBG("cmnd %p is still in RX_CMD state",
60202+ cmnd);
60203+ res = 1;
60204+ break;
60205+ }
60206+ res = cmnd_rx_continue(cmnd);
60207+ if (unlikely(res != 0))
60208+ BUG_ON(!conn->closing);
60209+ else {
60210+ if (cmnd->pdu.datasize == 0)
60211+ conn->read_state = RX_END;
60212+ else
60213+ conn->read_state = RX_DATA;
60214+ }
60215+ break;
60216+
60217+ case RX_DATA:
60218+ res = do_recv(conn);
60219+ if (res == 0) {
60220+ int psz = ((cmnd->pdu.datasize + 3) & -4) - cmnd->pdu.datasize;
60221+ if (psz != 0) {
60222+ TRACE_DBG("padding %d bytes", psz);
60223+ iscsi_conn_init_read(conn,
60224+ (void __force __user *)&conn->rpadding, psz);
60225+ conn->read_state = RX_PADDING;
60226+ } else if ((conn->ddigest_type & DIGEST_NONE) != 0)
60227+ conn->read_state = RX_END;
60228+ else
60229+ conn->read_state = RX_INIT_DDIGEST;
60230+ }
60231+ break;
60232+
60233+ case RX_END:
60234+ if (unlikely(conn->read_size != 0)) {
60235+ PRINT_CRIT_ERROR("conn read_size !=0 on RX_END "
60236+ "(conn %p, op %x, read_size %d)", conn,
60237+ cmnd_opcode(cmnd), conn->read_size);
60238+ BUG();
60239+ }
60240+ conn->read_cmnd = NULL;
60241+ conn->read_state = RX_INIT_BHS;
60242+
60243+ cmnd_rx_end(cmnd);
60244+
60245+ EXTRACHECKS_BUG_ON(conn->read_size != 0);
60246+
60247+ /*
60248+ * To maintain fairness. Res must be 0 here anyway, the
60249+ * assignment is only to remove compiler warning about
60250+ * uninitialized variable.
60251+ */
60252+ res = 0;
60253+ goto out;
60254+
60255+ case RX_INIT_HDIGEST:
60256+ iscsi_conn_init_read(conn,
60257+ (void __force __user *)&cmnd->hdigest, sizeof(u32));
60258+ conn->read_state = RX_CHECK_HDIGEST;
60259+ /* go through */
60260+
60261+ case RX_CHECK_HDIGEST:
60262+ res = do_recv(conn);
60263+ if (res == 0) {
60264+ res = digest_rx_header(cmnd);
60265+ if (unlikely(res != 0)) {
60266+ PRINT_ERROR("rx header digest for "
60267+ "initiator %s failed (%d)",
60268+ conn->session->initiator_name,
60269+ res);
60270+ mark_conn_closed(conn);
60271+ } else
60272+ conn->read_state = RX_CMD_START;
60273+ }
60274+ break;
60275+
60276+ case RX_INIT_DDIGEST:
60277+ iscsi_conn_init_read(conn,
60278+ (void __force __user *)&cmnd->ddigest,
60279+ sizeof(u32));
60280+ conn->read_state = RX_CHECK_DDIGEST;
60281+ /* go through */
60282+
60283+ case RX_CHECK_DDIGEST:
60284+ res = iscsi_rx_check_ddigest(conn);
60285+ break;
60286+
60287+ case RX_AHS:
60288+ res = do_recv(conn);
60289+ if (res == 0) {
60290+ if ((conn->hdigest_type & DIGEST_NONE) == 0)
60291+ conn->read_state = RX_INIT_HDIGEST;
60292+ else
60293+ conn->read_state = RX_CMD_START;
60294+ }
60295+ break;
60296+
60297+ case RX_PADDING:
60298+ res = do_recv(conn);
60299+ if (res == 0) {
60300+ if ((conn->ddigest_type & DIGEST_NONE) == 0)
60301+ conn->read_state = RX_INIT_DDIGEST;
60302+ else
60303+ conn->read_state = RX_END;
60304+ }
60305+ break;
60306+
60307+ default:
60308+ PRINT_CRIT_ERROR("%d %x", conn->read_state, cmnd_opcode(cmnd));
60309+ res = -1; /* to keep compiler happy */
60310+ BUG();
60311+ }
60312+ } while (res == 0);
60313+
60314+ if (unlikely(conn->closing)) {
60315+ start_close_conn(conn);
60316+ *closed = 1;
60317+ }
60318+
60319+out:
60320+ TRACE_EXIT_RES(res);
60321+ return res;
60322+}
60323+
60324+/*
60325+ * Called under iscsi_rd_lock and BHs disabled, but will drop it inside,
60326+ * then reaquire.
60327+ */
60328+static void scst_do_job_rd(void)
60329+ __acquires(&iscsi_rd_lock)
60330+ __releases(&iscsi_rd_lock)
60331+{
60332+ TRACE_ENTRY();
60333+
60334+ /*
60335+ * We delete/add to tail connections to maintain fairness between them.
60336+ */
60337+
60338+ while (!list_empty(&iscsi_rd_list)) {
60339+ int closed = 0, rc;
60340+ struct iscsi_conn *conn = list_entry(iscsi_rd_list.next,
60341+ typeof(*conn), rd_list_entry);
60342+
60343+ list_del(&conn->rd_list_entry);
60344+
60345+ BUG_ON(conn->rd_state == ISCSI_CONN_RD_STATE_PROCESSING);
60346+ conn->rd_data_ready = 0;
60347+ conn->rd_state = ISCSI_CONN_RD_STATE_PROCESSING;
60348+#ifdef CONFIG_SCST_EXTRACHECKS
60349+ conn->rd_task = current;
60350+#endif
60351+ spin_unlock_bh(&iscsi_rd_lock);
60352+
60353+ rc = process_read_io(conn, &closed);
60354+
60355+ spin_lock_bh(&iscsi_rd_lock);
60356+
60357+ if (unlikely(closed))
60358+ continue;
60359+
60360+ if (unlikely(conn->conn_tm_active)) {
60361+ spin_unlock_bh(&iscsi_rd_lock);
60362+ iscsi_check_tm_data_wait_timeouts(conn, false);
60363+ spin_lock_bh(&iscsi_rd_lock);
60364+ }
60365+
60366+#ifdef CONFIG_SCST_EXTRACHECKS
60367+ conn->rd_task = NULL;
60368+#endif
60369+ if ((rc == 0) || conn->rd_data_ready) {
60370+ list_add_tail(&conn->rd_list_entry, &iscsi_rd_list);
60371+ conn->rd_state = ISCSI_CONN_RD_STATE_IN_LIST;
60372+ } else
60373+ conn->rd_state = ISCSI_CONN_RD_STATE_IDLE;
60374+ }
60375+
60376+ TRACE_EXIT();
60377+ return;
60378+}
60379+
60380+static inline int test_rd_list(void)
60381+{
60382+ int res = !list_empty(&iscsi_rd_list) ||
60383+ unlikely(kthread_should_stop());
60384+ return res;
60385+}
60386+
60387+int istrd(void *arg)
60388+{
60389+ TRACE_ENTRY();
60390+
60391+ PRINT_INFO("Read thread started, PID %d", current->pid);
60392+
60393+ current->flags |= PF_NOFREEZE;
60394+
60395+ spin_lock_bh(&iscsi_rd_lock);
60396+ while (!kthread_should_stop()) {
60397+ wait_queue_t wait;
60398+ init_waitqueue_entry(&wait, current);
60399+
60400+ if (!test_rd_list()) {
60401+ add_wait_queue_exclusive_head(&iscsi_rd_waitQ, &wait);
60402+ for (;;) {
60403+ set_current_state(TASK_INTERRUPTIBLE);
60404+ if (test_rd_list())
60405+ break;
60406+ spin_unlock_bh(&iscsi_rd_lock);
60407+ schedule();
60408+ spin_lock_bh(&iscsi_rd_lock);
60409+ }
60410+ set_current_state(TASK_RUNNING);
60411+ remove_wait_queue(&iscsi_rd_waitQ, &wait);
60412+ }
60413+ scst_do_job_rd();
60414+ }
60415+ spin_unlock_bh(&iscsi_rd_lock);
60416+
60417+ /*
60418+ * If kthread_should_stop() is true, we are guaranteed to be
60419+ * on the module unload, so iscsi_rd_list must be empty.
60420+ */
60421+ BUG_ON(!list_empty(&iscsi_rd_list));
60422+
60423+ PRINT_INFO("Read thread PID %d finished", current->pid);
60424+
60425+ TRACE_EXIT();
60426+ return 0;
60427+}
60428+
60429+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
60430+static inline void __iscsi_get_page_callback(struct iscsi_cmnd *cmd)
60431+{
60432+ int v;
60433+
60434+ TRACE_NET_PAGE("cmd %p, new net_ref_cnt %d",
60435+ cmd, atomic_read(&cmd->net_ref_cnt)+1);
60436+
60437+ v = atomic_inc_return(&cmd->net_ref_cnt);
60438+ if (v == 1) {
60439+ TRACE_NET_PAGE("getting cmd %p", cmd);
60440+ cmnd_get(cmd);
60441+ }
60442+ return;
60443+}
60444+
60445+void iscsi_get_page_callback(struct page *page)
60446+{
60447+ struct iscsi_cmnd *cmd = (struct iscsi_cmnd *)page->net_priv;
60448+
60449+ TRACE_NET_PAGE("page %p, _count %d", page,
60450+ atomic_read(&page->_count));
60451+
60452+ __iscsi_get_page_callback(cmd);
60453+ return;
60454+}
60455+
60456+static inline void __iscsi_put_page_callback(struct iscsi_cmnd *cmd)
60457+{
60458+ TRACE_NET_PAGE("cmd %p, new net_ref_cnt %d", cmd,
60459+ atomic_read(&cmd->net_ref_cnt)-1);
60460+
60461+ if (atomic_dec_and_test(&cmd->net_ref_cnt)) {
60462+ int i, sg_cnt = cmd->sg_cnt;
60463+ for (i = 0; i < sg_cnt; i++) {
60464+ struct page *page = sg_page(&cmd->sg[i]);
60465+ TRACE_NET_PAGE("Clearing page %p", page);
60466+ if (page->net_priv == cmd)
60467+ page->net_priv = NULL;
60468+ }
60469+ cmnd_put(cmd);
60470+ }
60471+ return;
60472+}
60473+
60474+void iscsi_put_page_callback(struct page *page)
60475+{
60476+ struct iscsi_cmnd *cmd = (struct iscsi_cmnd *)page->net_priv;
60477+
60478+ TRACE_NET_PAGE("page %p, _count %d", page,
60479+ atomic_read(&page->_count));
60480+
60481+ __iscsi_put_page_callback(cmd);
60482+ return;
60483+}
60484+
60485+static void check_net_priv(struct iscsi_cmnd *cmd, struct page *page)
60486+{
60487+ if ((atomic_read(&cmd->net_ref_cnt) == 1) && (page->net_priv == cmd)) {
60488+ TRACE_DBG("sendpage() not called get_page(), zeroing net_priv "
60489+ "%p (page %p)", page->net_priv, page);
60490+ page->net_priv = NULL;
60491+ }
60492+ return;
60493+}
60494+#else
60495+static inline void check_net_priv(struct iscsi_cmnd *cmd, struct page *page) {}
60496+static inline void __iscsi_get_page_callback(struct iscsi_cmnd *cmd) {}
60497+static inline void __iscsi_put_page_callback(struct iscsi_cmnd *cmd) {}
60498+#endif
60499+
60500+void req_add_to_write_timeout_list(struct iscsi_cmnd *req)
60501+{
60502+ struct iscsi_conn *conn;
60503+ bool set_conn_tm_active = false;
60504+
60505+ TRACE_ENTRY();
60506+
60507+ if (req->on_write_timeout_list)
60508+ goto out;
60509+
60510+ conn = req->conn;
60511+
60512+ TRACE_DBG("Adding req %p to conn %p write_timeout_list",
60513+ req, conn);
60514+
60515+ spin_lock_bh(&conn->write_list_lock);
60516+
60517+ /* Recheck, since it can be changed behind us */
60518+ if (unlikely(req->on_write_timeout_list)) {
60519+ spin_unlock_bh(&conn->write_list_lock);
60520+ goto out;
60521+ }
60522+
60523+ req->on_write_timeout_list = 1;
60524+ req->write_start = jiffies;
60525+
60526+ list_add_tail(&req->write_timeout_list_entry,
60527+ &conn->write_timeout_list);
60528+
60529+ if (!timer_pending(&conn->rsp_timer)) {
60530+ unsigned long timeout_time;
60531+ if (unlikely(conn->conn_tm_active ||
60532+ test_bit(ISCSI_CMD_ABORTED,
60533+ &req->prelim_compl_flags))) {
60534+ set_conn_tm_active = true;
60535+ timeout_time = req->write_start +
60536+ ISCSI_TM_DATA_WAIT_TIMEOUT +
60537+ ISCSI_ADD_SCHED_TIME;
60538+ } else
60539+ timeout_time = req->write_start +
60540+ conn->rsp_timeout + ISCSI_ADD_SCHED_TIME;
60541+
60542+ TRACE_DBG("Starting timer on %ld (con %p, write_start %ld)",
60543+ timeout_time, conn, req->write_start);
60544+
60545+ conn->rsp_timer.expires = timeout_time;
60546+ add_timer(&conn->rsp_timer);
60547+ } else if (unlikely(test_bit(ISCSI_CMD_ABORTED,
60548+ &req->prelim_compl_flags))) {
60549+ unsigned long timeout_time = jiffies +
60550+ ISCSI_TM_DATA_WAIT_TIMEOUT + ISCSI_ADD_SCHED_TIME;
60551+ set_conn_tm_active = true;
60552+ if (time_after(conn->rsp_timer.expires, timeout_time)) {
60553+ TRACE_MGMT_DBG("Mod timer on %ld (conn %p)",
60554+ timeout_time, conn);
60555+ mod_timer(&conn->rsp_timer, timeout_time);
60556+ }
60557+ }
60558+
60559+ spin_unlock_bh(&conn->write_list_lock);
60560+
60561+ /*
60562+ * conn_tm_active can be already cleared by
60563+ * iscsi_check_tm_data_wait_timeouts(). write_list_lock is an inner
60564+ * lock for iscsi_rd_lock.
60565+ */
60566+ if (unlikely(set_conn_tm_active)) {
60567+ spin_lock_bh(&iscsi_rd_lock);
60568+ TRACE_MGMT_DBG("Setting conn_tm_active for conn %p", conn);
60569+ conn->conn_tm_active = 1;
60570+ spin_unlock_bh(&iscsi_rd_lock);
60571+ }
60572+
60573+out:
60574+ TRACE_EXIT();
60575+ return;
60576+}
60577+
60578+static int write_data(struct iscsi_conn *conn)
60579+{
60580+ mm_segment_t oldfs;
60581+ struct file *file;
60582+ struct iovec *iop;
60583+ struct socket *sock;
60584+ ssize_t (*sock_sendpage)(struct socket *, struct page *, int, size_t,
60585+ int);
60586+ ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
60587+ struct iscsi_cmnd *write_cmnd = conn->write_cmnd;
60588+ struct iscsi_cmnd *ref_cmd;
60589+ struct page *page;
60590+ struct scatterlist *sg;
60591+ int saved_size, size, sendsize;
60592+ int length, offset, idx;
60593+ int flags, res, count, sg_size;
60594+ bool do_put = false, ref_cmd_to_parent;
60595+
60596+ TRACE_ENTRY();
60597+
60598+ iscsi_extracheck_is_wr_thread(conn);
60599+
60600+ if (!write_cmnd->own_sg) {
60601+ ref_cmd = write_cmnd->parent_req;
60602+ ref_cmd_to_parent = true;
60603+ } else {
60604+ ref_cmd = write_cmnd;
60605+ ref_cmd_to_parent = false;
60606+ }
60607+
60608+ req_add_to_write_timeout_list(write_cmnd->parent_req);
60609+
60610+ file = conn->file;
60611+ size = conn->write_size;
60612+ saved_size = size;
60613+ iop = conn->write_iop;
60614+ count = conn->write_iop_used;
60615+
60616+ if (iop) {
60617+ while (1) {
60618+ loff_t off = 0;
60619+ int rest;
60620+
60621+ BUG_ON(count > (signed)(sizeof(conn->write_iov) /
60622+ sizeof(conn->write_iov[0])));
60623+retry:
60624+ oldfs = get_fs();
60625+ set_fs(KERNEL_DS);
60626+ res = vfs_writev(file,
60627+ (struct iovec __force __user *)iop,
60628+ count, &off);
60629+ set_fs(oldfs);
60630+ TRACE_WRITE("sid %#Lx, cid %u, res %d, iov_len %ld",
60631+ (long long unsigned int)conn->session->sid,
60632+ conn->cid, res, (long)iop->iov_len);
60633+ if (unlikely(res <= 0)) {
60634+ if (res == -EAGAIN) {
60635+ conn->write_iop = iop;
60636+ conn->write_iop_used = count;
60637+ goto out_iov;
60638+ } else if (res == -EINTR)
60639+ goto retry;
60640+ goto out_err;
60641+ }
60642+
60643+ rest = res;
60644+ size -= res;
60645+ while ((typeof(rest))iop->iov_len <= rest && rest) {
60646+ rest -= iop->iov_len;
60647+ iop++;
60648+ count--;
60649+ }
60650+ if (count == 0) {
60651+ conn->write_iop = NULL;
60652+ conn->write_iop_used = 0;
60653+ if (size)
60654+ break;
60655+ goto out_iov;
60656+ }
60657+ BUG_ON(iop > conn->write_iov + sizeof(conn->write_iov)
60658+ /sizeof(conn->write_iov[0]));
60659+ iop->iov_base += rest;
60660+ iop->iov_len -= rest;
60661+ }
60662+ }
60663+
60664+ sg = write_cmnd->sg;
60665+ if (unlikely(sg == NULL)) {
60666+ PRINT_INFO("WARNING: Data missed (cmd %p)!", write_cmnd);
60667+ res = 0;
60668+ goto out;
60669+ }
60670+
60671+ /* To protect from too early transfer completion race */
60672+ __iscsi_get_page_callback(ref_cmd);
60673+ do_put = true;
60674+
60675+ sock = conn->sock;
60676+
60677+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
60678+ sock_sendpage = sock->ops->sendpage;
60679+#else
60680+ if ((write_cmnd->parent_req->scst_cmd != NULL) &&
60681+ scst_cmd_get_dh_data_buff_alloced(write_cmnd->parent_req->scst_cmd))
60682+ sock_sendpage = sock_no_sendpage;
60683+ else
60684+ sock_sendpage = sock->ops->sendpage;
60685+#endif
60686+
60687+ flags = MSG_DONTWAIT;
60688+ sg_size = size;
60689+
60690+ if (sg != write_cmnd->rsp_sg) {
60691+ offset = conn->write_offset + sg[0].offset;
60692+ idx = offset >> PAGE_SHIFT;
60693+ offset &= ~PAGE_MASK;
60694+ length = min(size, (int)PAGE_SIZE - offset);
60695+ TRACE_WRITE("write_offset %d, sg_size %d, idx %d, offset %d, "
60696+ "length %d", conn->write_offset, sg_size, idx, offset,
60697+ length);
60698+ } else {
60699+ idx = 0;
60700+ offset = conn->write_offset;
60701+ while (offset >= sg[idx].length) {
60702+ offset -= sg[idx].length;
60703+ idx++;
60704+ }
60705+ length = sg[idx].length - offset;
60706+ offset += sg[idx].offset;
60707+ sock_sendpage = sock_no_sendpage;
60708+ TRACE_WRITE("rsp_sg: write_offset %d, sg_size %d, idx %d, "
60709+ "offset %d, length %d", conn->write_offset, sg_size,
60710+ idx, offset, length);
60711+ }
60712+ page = sg_page(&sg[idx]);
60713+
60714+ while (1) {
60715+ sendpage = sock_sendpage;
60716+
60717+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
60718+ {
60719+ static DEFINE_SPINLOCK(net_priv_lock);
60720+ spin_lock(&net_priv_lock);
60721+ if (unlikely(page->net_priv != NULL)) {
60722+ if (page->net_priv != ref_cmd) {
60723+ /*
60724+ * This might happen if user space
60725+ * supplies to scst_user the same
60726+ * pages in different commands or in
60727+ * case of zero-copy FILEIO, when
60728+ * several initiators request the same
60729+ * data simultaneously.
60730+ */
60731+ TRACE_DBG("net_priv isn't NULL and != "
60732+ "ref_cmd (write_cmnd %p, ref_cmd "
60733+ "%p, sg %p, idx %d, page %p, "
60734+ "net_priv %p)",
60735+ write_cmnd, ref_cmd, sg, idx,
60736+ page, page->net_priv);
60737+ sendpage = sock_no_sendpage;
60738+ }
60739+ } else
60740+ page->net_priv = ref_cmd;
60741+ spin_unlock(&net_priv_lock);
60742+ }
60743+#endif
60744+ sendsize = min(size, length);
60745+ if (size <= sendsize) {
60746+retry2:
60747+ res = sendpage(sock, page, offset, size, flags);
60748+ TRACE_WRITE("Final %s sid %#Lx, cid %u, res %d (page "
60749+ "index %lu, offset %u, size %u, cmd %p, "
60750+ "page %p)", (sendpage != sock_no_sendpage) ?
60751+ "sendpage" : "sock_no_sendpage",
60752+ (long long unsigned int)conn->session->sid,
60753+ conn->cid, res, page->index,
60754+ offset, size, write_cmnd, page);
60755+ if (unlikely(res <= 0)) {
60756+ if (res == -EINTR)
60757+ goto retry2;
60758+ else
60759+ goto out_res;
60760+ }
60761+
60762+ check_net_priv(ref_cmd, page);
60763+ if (res == size) {
60764+ conn->write_size = 0;
60765+ res = saved_size;
60766+ goto out_put;
60767+ }
60768+
60769+ offset += res;
60770+ size -= res;
60771+ goto retry2;
60772+ }
60773+
60774+retry1:
60775+ res = sendpage(sock, page, offset, sendsize, flags | MSG_MORE);
60776+ TRACE_WRITE("%s sid %#Lx, cid %u, res %d (page index %lu, "
60777+ "offset %u, sendsize %u, size %u, cmd %p, page %p)",
60778+ (sendpage != sock_no_sendpage) ? "sendpage" :
60779+ "sock_no_sendpage",
60780+ (unsigned long long)conn->session->sid, conn->cid,
60781+ res, page->index, offset, sendsize, size,
60782+ write_cmnd, page);
60783+ if (unlikely(res <= 0)) {
60784+ if (res == -EINTR)
60785+ goto retry1;
60786+ else
60787+ goto out_res;
60788+ }
60789+
60790+ check_net_priv(ref_cmd, page);
60791+
60792+ size -= res;
60793+
60794+ if (res == sendsize) {
60795+ idx++;
60796+ EXTRACHECKS_BUG_ON(idx >= ref_cmd->sg_cnt);
60797+ page = sg_page(&sg[idx]);
60798+ length = sg[idx].length;
60799+ offset = sg[idx].offset;
60800+ } else {
60801+ offset += res;
60802+ sendsize -= res;
60803+ goto retry1;
60804+ }
60805+ }
60806+
60807+out_off:
60808+ conn->write_offset += sg_size - size;
60809+
60810+out_iov:
60811+ conn->write_size = size;
60812+ if ((saved_size == size) && res == -EAGAIN)
60813+ goto out_put;
60814+
60815+ res = saved_size - size;
60816+
60817+out_put:
60818+ if (do_put)
60819+ __iscsi_put_page_callback(ref_cmd);
60820+
60821+out:
60822+ TRACE_EXIT_RES(res);
60823+ return res;
60824+
60825+out_res:
60826+ check_net_priv(ref_cmd, page);
60827+ if (res == -EAGAIN)
60828+ goto out_off;
60829+ /* else go through */
60830+
60831+out_err:
60832+#ifndef CONFIG_SCST_DEBUG
60833+ if (!conn->closing)
60834+#endif
60835+ {
60836+ PRINT_ERROR("error %d at sid:cid %#Lx:%u, cmnd %p", res,
60837+ (long long unsigned int)conn->session->sid,
60838+ conn->cid, conn->write_cmnd);
60839+ }
60840+ if (ref_cmd_to_parent &&
60841+ ((ref_cmd->scst_cmd != NULL) || (ref_cmd->scst_aen != NULL))) {
60842+ if (ref_cmd->scst_state == ISCSI_CMD_STATE_AEN)
60843+ scst_set_aen_delivery_status(ref_cmd->scst_aen,
60844+ SCST_AEN_RES_FAILED);
60845+ else
60846+ scst_set_delivery_status(ref_cmd->scst_cmd,
60847+ SCST_CMD_DELIVERY_FAILED);
60848+ }
60849+ goto out_put;
60850+}
60851+
60852+static int exit_tx(struct iscsi_conn *conn, int res)
60853+{
60854+ iscsi_extracheck_is_wr_thread(conn);
60855+
60856+ switch (res) {
60857+ case -EAGAIN:
60858+ case -ERESTARTSYS:
60859+ break;
60860+ default:
60861+#ifndef CONFIG_SCST_DEBUG
60862+ if (!conn->closing)
60863+#endif
60864+ {
60865+ PRINT_ERROR("Sending data failed: initiator %s, "
60866+ "write_size %d, write_state %d, res %d",
60867+ conn->session->initiator_name,
60868+ conn->write_size,
60869+ conn->write_state, res);
60870+ }
60871+ conn->write_state = TX_END;
60872+ conn->write_size = 0;
60873+ mark_conn_closed(conn);
60874+ break;
60875+ }
60876+ return res;
60877+}
60878+
60879+static int tx_ddigest(struct iscsi_cmnd *cmnd, int state)
60880+{
60881+ int res, rest = cmnd->conn->write_size;
60882+ struct msghdr msg = {.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT};
60883+ struct kvec iov;
60884+
60885+ iscsi_extracheck_is_wr_thread(cmnd->conn);
60886+
60887+ TRACE_DBG("Sending data digest %x (cmd %p)", cmnd->ddigest, cmnd);
60888+
60889+ iov.iov_base = (char *)(&cmnd->ddigest) + (sizeof(u32) - rest);
60890+ iov.iov_len = rest;
60891+
60892+ res = kernel_sendmsg(cmnd->conn->sock, &msg, &iov, 1, rest);
60893+ if (res > 0) {
60894+ cmnd->conn->write_size -= res;
60895+ if (!cmnd->conn->write_size)
60896+ cmnd->conn->write_state = state;
60897+ } else
60898+ res = exit_tx(cmnd->conn, res);
60899+
60900+ return res;
60901+}
60902+
60903+static void init_tx_hdigest(struct iscsi_cmnd *cmnd)
60904+{
60905+ struct iscsi_conn *conn = cmnd->conn;
60906+ struct iovec *iop;
60907+
60908+ iscsi_extracheck_is_wr_thread(conn);
60909+
60910+ digest_tx_header(cmnd);
60911+
60912+ BUG_ON(conn->write_iop_used >=
60913+ (signed)(sizeof(conn->write_iov)/sizeof(conn->write_iov[0])));
60914+
60915+ iop = &conn->write_iop[conn->write_iop_used];
60916+ conn->write_iop_used++;
60917+ iop->iov_base = (void __force __user *)&(cmnd->hdigest);
60918+ iop->iov_len = sizeof(u32);
60919+ conn->write_size += sizeof(u32);
60920+
60921+ return;
60922+}
60923+
60924+static int tx_padding(struct iscsi_cmnd *cmnd, int state)
60925+{
60926+ int res, rest = cmnd->conn->write_size;
60927+ struct msghdr msg = {.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT};
60928+ struct kvec iov;
60929+ static const uint32_t padding;
60930+
60931+ iscsi_extracheck_is_wr_thread(cmnd->conn);
60932+
60933+ TRACE_DBG("Sending %d padding bytes (cmd %p)", rest, cmnd);
60934+
60935+ iov.iov_base = (char *)(&padding) + (sizeof(uint32_t) - rest);
60936+ iov.iov_len = rest;
60937+
60938+ res = kernel_sendmsg(cmnd->conn->sock, &msg, &iov, 1, rest);
60939+ if (res > 0) {
60940+ cmnd->conn->write_size -= res;
60941+ if (!cmnd->conn->write_size)
60942+ cmnd->conn->write_state = state;
60943+ } else
60944+ res = exit_tx(cmnd->conn, res);
60945+
60946+ return res;
60947+}
60948+
60949+static int iscsi_do_send(struct iscsi_conn *conn, int state)
60950+{
60951+ int res;
60952+
60953+ iscsi_extracheck_is_wr_thread(conn);
60954+
60955+ res = write_data(conn);
60956+ if (res > 0) {
60957+ if (!conn->write_size)
60958+ conn->write_state = state;
60959+ } else
60960+ res = exit_tx(conn, res);
60961+
60962+ return res;
60963+}
60964+
60965+/*
60966+ * No locks, conn is wr processing.
60967+ *
60968+ * IMPORTANT! Connection conn must be protected by additional conn_get()
60969+ * upon entrance in this function, because otherwise it could be destroyed
60970+ * inside as a result of cmnd release.
60971+ */
60972+int iscsi_send(struct iscsi_conn *conn)
60973+{
60974+ struct iscsi_cmnd *cmnd = conn->write_cmnd;
60975+ int ddigest, res = 0;
60976+
60977+ TRACE_ENTRY();
60978+
60979+ TRACE_DBG("conn %p, write_cmnd %p", conn, cmnd);
60980+
60981+ iscsi_extracheck_is_wr_thread(conn);
60982+
60983+ ddigest = conn->ddigest_type != DIGEST_NONE ? 1 : 0;
60984+
60985+ switch (conn->write_state) {
60986+ case TX_INIT:
60987+ BUG_ON(cmnd != NULL);
60988+ cmnd = conn->write_cmnd = iscsi_get_send_cmnd(conn);
60989+ if (!cmnd)
60990+ goto out;
60991+ cmnd_tx_start(cmnd);
60992+ if (!(conn->hdigest_type & DIGEST_NONE))
60993+ init_tx_hdigest(cmnd);
60994+ conn->write_state = TX_BHS_DATA;
60995+ case TX_BHS_DATA:
60996+ res = iscsi_do_send(conn, cmnd->pdu.datasize ?
60997+ TX_INIT_PADDING : TX_END);
60998+ if (res <= 0 || conn->write_state != TX_INIT_PADDING)
60999+ break;
61000+ case TX_INIT_PADDING:
61001+ cmnd->conn->write_size = ((cmnd->pdu.datasize + 3) & -4) -
61002+ cmnd->pdu.datasize;
61003+ if (cmnd->conn->write_size != 0)
61004+ conn->write_state = TX_PADDING;
61005+ else if (ddigest)
61006+ conn->write_state = TX_INIT_DDIGEST;
61007+ else
61008+ conn->write_state = TX_END;
61009+ break;
61010+ case TX_PADDING:
61011+ res = tx_padding(cmnd, ddigest ? TX_INIT_DDIGEST : TX_END);
61012+ if (res <= 0 || conn->write_state != TX_INIT_DDIGEST)
61013+ break;
61014+ case TX_INIT_DDIGEST:
61015+ cmnd->conn->write_size = sizeof(u32);
61016+ conn->write_state = TX_DDIGEST;
61017+ case TX_DDIGEST:
61018+ res = tx_ddigest(cmnd, TX_END);
61019+ break;
61020+ default:
61021+ PRINT_CRIT_ERROR("%d %d %x", res, conn->write_state,
61022+ cmnd_opcode(cmnd));
61023+ BUG();
61024+ }
61025+
61026+ if (res == 0)
61027+ goto out;
61028+
61029+ if (conn->write_state != TX_END)
61030+ goto out;
61031+
61032+ if (unlikely(conn->write_size)) {
61033+ PRINT_CRIT_ERROR("%d %x %u", res, cmnd_opcode(cmnd),
61034+ conn->write_size);
61035+ BUG();
61036+ }
61037+ cmnd_tx_end(cmnd);
61038+
61039+ rsp_cmnd_release(cmnd);
61040+
61041+ conn->write_cmnd = NULL;
61042+ conn->write_state = TX_INIT;
61043+
61044+out:
61045+ TRACE_EXIT_RES(res);
61046+ return res;
61047+}
61048+
61049+/*
61050+ * Called under iscsi_wr_lock and BHs disabled, but will drop it inside,
61051+ * then reaquire.
61052+ */
61053+static void scst_do_job_wr(void)
61054+ __acquires(&iscsi_wr_lock)
61055+ __releases(&iscsi_wr_lock)
61056+{
61057+ TRACE_ENTRY();
61058+
61059+ /*
61060+ * We delete/add to tail connections to maintain fairness between them.
61061+ */
61062+
61063+ while (!list_empty(&iscsi_wr_list)) {
61064+ int rc;
61065+ struct iscsi_conn *conn = list_entry(iscsi_wr_list.next,
61066+ typeof(*conn), wr_list_entry);
61067+
61068+ TRACE_DBG("conn %p, wr_state %x, wr_space_ready %d, "
61069+ "write ready %d", conn, conn->wr_state,
61070+ conn->wr_space_ready, test_write_ready(conn));
61071+
61072+ list_del(&conn->wr_list_entry);
61073+
61074+ BUG_ON(conn->wr_state == ISCSI_CONN_WR_STATE_PROCESSING);
61075+
61076+ conn->wr_state = ISCSI_CONN_WR_STATE_PROCESSING;
61077+ conn->wr_space_ready = 0;
61078+#ifdef CONFIG_SCST_EXTRACHECKS
61079+ conn->wr_task = current;
61080+#endif
61081+ spin_unlock_bh(&iscsi_wr_lock);
61082+
61083+ conn_get(conn);
61084+
61085+ rc = iscsi_send(conn);
61086+
61087+ spin_lock_bh(&iscsi_wr_lock);
61088+#ifdef CONFIG_SCST_EXTRACHECKS
61089+ conn->wr_task = NULL;
61090+#endif
61091+ if ((rc == -EAGAIN) && !conn->wr_space_ready) {
61092+ TRACE_DBG("EAGAIN, setting WR_STATE_SPACE_WAIT "
61093+ "(conn %p)", conn);
61094+ conn->wr_state = ISCSI_CONN_WR_STATE_SPACE_WAIT;
61095+ } else if (test_write_ready(conn)) {
61096+ list_add_tail(&conn->wr_list_entry, &iscsi_wr_list);
61097+ conn->wr_state = ISCSI_CONN_WR_STATE_IN_LIST;
61098+ } else
61099+ conn->wr_state = ISCSI_CONN_WR_STATE_IDLE;
61100+
61101+ conn_put(conn);
61102+ }
61103+
61104+ TRACE_EXIT();
61105+ return;
61106+}
61107+
61108+static inline int test_wr_list(void)
61109+{
61110+ int res = !list_empty(&iscsi_wr_list) ||
61111+ unlikely(kthread_should_stop());
61112+ return res;
61113+}
61114+
61115+int istwr(void *arg)
61116+{
61117+ TRACE_ENTRY();
61118+
61119+ PRINT_INFO("Write thread started, PID %d", current->pid);
61120+
61121+ current->flags |= PF_NOFREEZE;
61122+
61123+ spin_lock_bh(&iscsi_wr_lock);
61124+ while (!kthread_should_stop()) {
61125+ wait_queue_t wait;
61126+ init_waitqueue_entry(&wait, current);
61127+
61128+ if (!test_wr_list()) {
61129+ add_wait_queue_exclusive_head(&iscsi_wr_waitQ, &wait);
61130+ for (;;) {
61131+ set_current_state(TASK_INTERRUPTIBLE);
61132+ if (test_wr_list())
61133+ break;
61134+ spin_unlock_bh(&iscsi_wr_lock);
61135+ schedule();
61136+ spin_lock_bh(&iscsi_wr_lock);
61137+ }
61138+ set_current_state(TASK_RUNNING);
61139+ remove_wait_queue(&iscsi_wr_waitQ, &wait);
61140+ }
61141+ scst_do_job_wr();
61142+ }
61143+ spin_unlock_bh(&iscsi_wr_lock);
61144+
61145+ /*
61146+ * If kthread_should_stop() is true, we are guaranteed to be
61147+ * on the module unload, so iscsi_wr_list must be empty.
61148+ */
61149+ BUG_ON(!list_empty(&iscsi_wr_list));
61150+
61151+ PRINT_INFO("Write thread PID %d finished", current->pid);
61152+
61153+ TRACE_EXIT();
61154+ return 0;
61155+}
61156diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/param.c linux-2.6.35/drivers/scst/iscsi-scst/param.c
61157--- orig/linux-2.6.35/drivers/scst/iscsi-scst/param.c
61158+++ linux-2.6.35/drivers/scst/iscsi-scst/param.c
61159@@ -0,0 +1,306 @@
61160+/*
61161+ * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org>
61162+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
61163+ * Copyright (C) 2007 - 2010 ID7 Ltd.
61164+ *
61165+ * This program is free software; you can redistribute it and/or
61166+ * modify it under the terms of the GNU General Public License
61167+ * as published by the Free Software Foundation.
61168+ *
61169+ * This program is distributed in the hope that it will be useful,
61170+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
61171+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61172+ * GNU General Public License for more details.
61173+ */
61174+
61175+#include "iscsi.h"
61176+#include "digest.h"
61177+
61178+#define CHECK_PARAM(info, iparams, word, min, max) \
61179+do { \
61180+ if (!(info)->partial || ((info)->partial & 1 << key_##word)) { \
61181+ TRACE_DBG("%s: %u", #word, (iparams)[key_##word]); \
61182+ if ((iparams)[key_##word] < (min) || \
61183+ (iparams)[key_##word] > (max)) { \
61184+ if ((iparams)[key_##word] < (min)) { \
61185+ (iparams)[key_##word] = (min); \
61186+ PRINT_WARNING("%s: %u is too small, resetting " \
61187+ "it to allowed min %u", \
61188+ #word, (iparams)[key_##word], (min)); \
61189+ } else { \
61190+ PRINT_WARNING("%s: %u is too big, resetting " \
61191+ "it to allowed max %u", \
61192+ #word, (iparams)[key_##word], (max)); \
61193+ (iparams)[key_##word] = (max); \
61194+ } \
61195+ } \
61196+ } \
61197+} while (0)
61198+
61199+#define SET_PARAM(params, info, iparams, word) \
61200+({ \
61201+ int changed = 0; \
61202+ if (!(info)->partial || ((info)->partial & 1 << key_##word)) { \
61203+ if ((params)->word != (iparams)[key_##word]) \
61204+ changed = 1; \
61205+ (params)->word = (iparams)[key_##word]; \
61206+ TRACE_DBG("%s set to %u", #word, (params)->word); \
61207+ } \
61208+ changed; \
61209+})
61210+
61211+#define GET_PARAM(params, info, iparams, word) \
61212+do { \
61213+ (iparams)[key_##word] = (params)->word; \
61214+} while (0)
61215+
61216+const char *iscsi_get_bool_value(int val)
61217+{
61218+ if (val)
61219+ return "Yes";
61220+ else
61221+ return "No";
61222+}
61223+
61224+const char *iscsi_get_digest_name(int val, char *res)
61225+{
61226+ int pos = 0;
61227+
61228+ if (val & DIGEST_NONE)
61229+ pos = sprintf(&res[pos], "%s", "None");
61230+
61231+ if (val & DIGEST_CRC32C)
61232+ pos += sprintf(&res[pos], "%s%s", (pos != 0) ? ", " : "",
61233+ "CRC32C");
61234+
61235+ if (pos == 0)
61236+ sprintf(&res[pos], "%s", "Unknown");
61237+
61238+ return res;
61239+}
61240+
61241+static void log_params(struct iscsi_sess_params *params)
61242+{
61243+ char digest_name[64];
61244+
61245+ PRINT_INFO("Negotiated parameters: InitialR2T %s, ImmediateData %s, "
61246+ "MaxConnections %d, MaxRecvDataSegmentLength %d, "
61247+ "MaxXmitDataSegmentLength %d, ",
61248+ iscsi_get_bool_value(params->initial_r2t),
61249+ iscsi_get_bool_value(params->immediate_data), params->max_connections,
61250+ params->max_recv_data_length, params->max_xmit_data_length);
61251+ PRINT_INFO(" MaxBurstLength %d, FirstBurstLength %d, "
61252+ "DefaultTime2Wait %d, DefaultTime2Retain %d, ",
61253+ params->max_burst_length, params->first_burst_length,
61254+ params->default_wait_time, params->default_retain_time);
61255+ PRINT_INFO(" MaxOutstandingR2T %d, DataPDUInOrder %s, "
61256+ "DataSequenceInOrder %s, ErrorRecoveryLevel %d, ",
61257+ params->max_outstanding_r2t,
61258+ iscsi_get_bool_value(params->data_pdu_inorder),
61259+ iscsi_get_bool_value(params->data_sequence_inorder),
61260+ params->error_recovery_level);
61261+ PRINT_INFO(" HeaderDigest %s, DataDigest %s, OFMarker %s, "
61262+ "IFMarker %s, OFMarkInt %d, IFMarkInt %d",
61263+ iscsi_get_digest_name(params->header_digest, digest_name),
61264+ iscsi_get_digest_name(params->data_digest, digest_name),
61265+ iscsi_get_bool_value(params->ofmarker),
61266+ iscsi_get_bool_value(params->ifmarker),
61267+ params->ofmarkint, params->ifmarkint);
61268+}
61269+
61270+/* target_mutex supposed to be locked */
61271+static void sess_params_check(struct iscsi_kern_params_info *info)
61272+{
61273+ int32_t *iparams = info->session_params;
61274+ const int max_len = ISCSI_CONN_IOV_MAX * PAGE_SIZE;
61275+
61276+ CHECK_PARAM(info, iparams, initial_r2t, 0, 1);
61277+ CHECK_PARAM(info, iparams, immediate_data, 0, 1);
61278+ CHECK_PARAM(info, iparams, max_connections, 1, 1);
61279+ CHECK_PARAM(info, iparams, max_recv_data_length, 512, max_len);
61280+ CHECK_PARAM(info, iparams, max_xmit_data_length, 512, max_len);
61281+ CHECK_PARAM(info, iparams, max_burst_length, 512, max_len);
61282+ CHECK_PARAM(info, iparams, first_burst_length, 512, max_len);
61283+ CHECK_PARAM(info, iparams, max_outstanding_r2t, 1, 65535);
61284+ CHECK_PARAM(info, iparams, error_recovery_level, 0, 0);
61285+ CHECK_PARAM(info, iparams, data_pdu_inorder, 0, 1);
61286+ CHECK_PARAM(info, iparams, data_sequence_inorder, 0, 1);
61287+
61288+ digest_alg_available(&iparams[key_header_digest]);
61289+ digest_alg_available(&iparams[key_data_digest]);
61290+
61291+ CHECK_PARAM(info, iparams, ofmarker, 0, 0);
61292+ CHECK_PARAM(info, iparams, ifmarker, 0, 0);
61293+
61294+ return;
61295+}
61296+
61297+/* target_mutex supposed to be locked */
61298+static void sess_params_set(struct iscsi_sess_params *params,
61299+ struct iscsi_kern_params_info *info)
61300+{
61301+ int32_t *iparams = info->session_params;
61302+
61303+ SET_PARAM(params, info, iparams, initial_r2t);
61304+ SET_PARAM(params, info, iparams, immediate_data);
61305+ SET_PARAM(params, info, iparams, max_connections);
61306+ SET_PARAM(params, info, iparams, max_recv_data_length);
61307+ SET_PARAM(params, info, iparams, max_xmit_data_length);
61308+ SET_PARAM(params, info, iparams, max_burst_length);
61309+ SET_PARAM(params, info, iparams, first_burst_length);
61310+ SET_PARAM(params, info, iparams, default_wait_time);
61311+ SET_PARAM(params, info, iparams, default_retain_time);
61312+ SET_PARAM(params, info, iparams, max_outstanding_r2t);
61313+ SET_PARAM(params, info, iparams, data_pdu_inorder);
61314+ SET_PARAM(params, info, iparams, data_sequence_inorder);
61315+ SET_PARAM(params, info, iparams, error_recovery_level);
61316+ SET_PARAM(params, info, iparams, header_digest);
61317+ SET_PARAM(params, info, iparams, data_digest);
61318+ SET_PARAM(params, info, iparams, ofmarker);
61319+ SET_PARAM(params, info, iparams, ifmarker);
61320+ SET_PARAM(params, info, iparams, ofmarkint);
61321+ SET_PARAM(params, info, iparams, ifmarkint);
61322+ return;
61323+}
61324+
61325+static void sess_params_get(struct iscsi_sess_params *params,
61326+ struct iscsi_kern_params_info *info)
61327+{
61328+ int32_t *iparams = info->session_params;
61329+
61330+ GET_PARAM(params, info, iparams, initial_r2t);
61331+ GET_PARAM(params, info, iparams, immediate_data);
61332+ GET_PARAM(params, info, iparams, max_connections);
61333+ GET_PARAM(params, info, iparams, max_recv_data_length);
61334+ GET_PARAM(params, info, iparams, max_xmit_data_length);
61335+ GET_PARAM(params, info, iparams, max_burst_length);
61336+ GET_PARAM(params, info, iparams, first_burst_length);
61337+ GET_PARAM(params, info, iparams, default_wait_time);
61338+ GET_PARAM(params, info, iparams, default_retain_time);
61339+ GET_PARAM(params, info, iparams, max_outstanding_r2t);
61340+ GET_PARAM(params, info, iparams, data_pdu_inorder);
61341+ GET_PARAM(params, info, iparams, data_sequence_inorder);
61342+ GET_PARAM(params, info, iparams, error_recovery_level);
61343+ GET_PARAM(params, info, iparams, header_digest);
61344+ GET_PARAM(params, info, iparams, data_digest);
61345+ GET_PARAM(params, info, iparams, ofmarker);
61346+ GET_PARAM(params, info, iparams, ifmarker);
61347+ GET_PARAM(params, info, iparams, ofmarkint);
61348+ GET_PARAM(params, info, iparams, ifmarkint);
61349+ return;
61350+}
61351+
61352+/* target_mutex supposed to be locked */
61353+static void tgt_params_check(struct iscsi_session *session,
61354+ struct iscsi_kern_params_info *info)
61355+{
61356+ int32_t *iparams = info->target_params;
61357+
61358+ CHECK_PARAM(info, iparams, queued_cmnds, MIN_NR_QUEUED_CMNDS,
61359+ min_t(int, MAX_NR_QUEUED_CMNDS,
61360+ scst_get_max_lun_commands(session->scst_sess, NO_SUCH_LUN)));
61361+ CHECK_PARAM(info, iparams, rsp_timeout, MIN_RSP_TIMEOUT,
61362+ MAX_RSP_TIMEOUT);
61363+ CHECK_PARAM(info, iparams, nop_in_interval, MIN_NOP_IN_INTERVAL,
61364+ MAX_NOP_IN_INTERVAL);
61365+ return;
61366+}
61367+
61368+/* target_mutex supposed to be locked */
61369+static int iscsi_tgt_params_set(struct iscsi_session *session,
61370+ struct iscsi_kern_params_info *info, int set)
61371+{
61372+ struct iscsi_tgt_params *params = &session->tgt_params;
61373+ int32_t *iparams = info->target_params;
61374+
61375+ if (set) {
61376+ struct iscsi_conn *conn;
61377+
61378+ tgt_params_check(session, info);
61379+
61380+ SET_PARAM(params, info, iparams, queued_cmnds);
61381+ SET_PARAM(params, info, iparams, rsp_timeout);
61382+ SET_PARAM(params, info, iparams, nop_in_interval);
61383+
61384+ PRINT_INFO("Target parameters set for session %llx: "
61385+ "QueuedCommands %d, Response timeout %d, Nop-In "
61386+ "interval %d", session->sid, params->queued_cmnds,
61387+ params->rsp_timeout, params->nop_in_interval);
61388+
61389+ list_for_each_entry(conn, &session->conn_list,
61390+ conn_list_entry) {
61391+ conn->rsp_timeout = session->tgt_params.rsp_timeout * HZ;
61392+ conn->nop_in_interval = session->tgt_params.nop_in_interval * HZ;
61393+ spin_lock_bh(&iscsi_rd_lock);
61394+ if (!conn->closing && (conn->nop_in_interval > 0)) {
61395+ TRACE_DBG("Schedule Nop-In work for conn %p", conn);
61396+ schedule_delayed_work(&conn->nop_in_delayed_work,
61397+ conn->nop_in_interval + ISCSI_ADD_SCHED_TIME);
61398+ }
61399+ spin_unlock_bh(&iscsi_rd_lock);
61400+ }
61401+ } else {
61402+ GET_PARAM(params, info, iparams, queued_cmnds);
61403+ GET_PARAM(params, info, iparams, rsp_timeout);
61404+ GET_PARAM(params, info, iparams, nop_in_interval);
61405+ }
61406+
61407+ return 0;
61408+}
61409+
61410+/* target_mutex supposed to be locked */
61411+static int iscsi_sess_params_set(struct iscsi_session *session,
61412+ struct iscsi_kern_params_info *info, int set)
61413+{
61414+ struct iscsi_sess_params *params;
61415+
61416+ if (set)
61417+ sess_params_check(info);
61418+
61419+ params = &session->sess_params;
61420+
61421+ if (set) {
61422+ sess_params_set(params, info);
61423+ log_params(params);
61424+ } else
61425+ sess_params_get(params, info);
61426+
61427+ return 0;
61428+}
61429+
61430+/* target_mutex supposed to be locked */
61431+int iscsi_params_set(struct iscsi_target *target,
61432+ struct iscsi_kern_params_info *info, int set)
61433+{
61434+ int err;
61435+ struct iscsi_session *session;
61436+
61437+ if (info->sid == 0) {
61438+ PRINT_ERROR("sid must not be %d", 0);
61439+ err = -EINVAL;
61440+ goto out;
61441+ }
61442+
61443+ session = session_lookup(target, info->sid);
61444+ if (session == NULL) {
61445+ PRINT_ERROR("Session for sid %llx not found", info->sid);
61446+ err = -ENOENT;
61447+ goto out;
61448+ }
61449+
61450+ if (set && !list_empty(&session->conn_list) &&
61451+ (info->params_type != key_target)) {
61452+ err = -EBUSY;
61453+ goto out;
61454+ }
61455+
61456+ if (info->params_type == key_session)
61457+ err = iscsi_sess_params_set(session, info, set);
61458+ else if (info->params_type == key_target)
61459+ err = iscsi_tgt_params_set(session, info, set);
61460+ else
61461+ err = -EINVAL;
61462+
61463+out:
61464+ return err;
61465+}
61466diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/session.c linux-2.6.35/drivers/scst/iscsi-scst/session.c
61467--- orig/linux-2.6.35/drivers/scst/iscsi-scst/session.c
61468+++ linux-2.6.35/drivers/scst/iscsi-scst/session.c
61469@@ -0,0 +1,499 @@
61470+/*
61471+ * Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
61472+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
61473+ * Copyright (C) 2007 - 2010 ID7 Ltd.
61474+ *
61475+ * This program is free software; you can redistribute it and/or
61476+ * modify it under the terms of the GNU General Public License
61477+ * as published by the Free Software Foundation, version 2
61478+ * of the License.
61479+ *
61480+ * This program is distributed in the hope that it will be useful,
61481+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
61482+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61483+ * GNU General Public License for more details.
61484+ */
61485+
61486+#include "iscsi.h"
61487+
61488+/* target_mutex supposed to be locked */
61489+struct iscsi_session *session_lookup(struct iscsi_target *target, u64 sid)
61490+{
61491+ struct iscsi_session *session;
61492+
61493+ list_for_each_entry(session, &target->session_list,
61494+ session_list_entry) {
61495+ if (session->sid == sid)
61496+ return session;
61497+ }
61498+ return NULL;
61499+}
61500+
61501+/* target_mgmt_mutex supposed to be locked */
61502+static int iscsi_session_alloc(struct iscsi_target *target,
61503+ struct iscsi_kern_session_info *info, struct iscsi_session **result)
61504+{
61505+ int err;
61506+ unsigned int i;
61507+ struct iscsi_session *session;
61508+ char *name = NULL;
61509+
61510+ session = kzalloc(sizeof(*session), GFP_KERNEL);
61511+ if (!session)
61512+ return -ENOMEM;
61513+
61514+ session->target = target;
61515+ session->sid = info->sid;
61516+ atomic_set(&session->active_cmds, 0);
61517+ session->exp_cmd_sn = info->exp_cmd_sn;
61518+
61519+ session->initiator_name = kstrdup(info->initiator_name, GFP_KERNEL);
61520+ if (!session->initiator_name) {
61521+ err = -ENOMEM;
61522+ goto err;
61523+ }
61524+
61525+ name = info->full_initiator_name;
61526+
61527+ INIT_LIST_HEAD(&session->conn_list);
61528+ INIT_LIST_HEAD(&session->pending_list);
61529+
61530+ spin_lock_init(&session->sn_lock);
61531+
61532+ spin_lock_init(&session->cmnd_data_wait_hash_lock);
61533+ for (i = 0; i < ARRAY_SIZE(session->cmnd_data_wait_hash); i++)
61534+ INIT_LIST_HEAD(&session->cmnd_data_wait_hash[i]);
61535+
61536+ session->next_ttt = 1;
61537+
61538+ session->scst_sess = scst_register_session(target->scst_tgt, 0,
61539+ name, session, NULL, NULL);
61540+ if (session->scst_sess == NULL) {
61541+ PRINT_ERROR("%s", "scst_register_session() failed");
61542+ err = -ENOMEM;
61543+ goto err;
61544+ }
61545+
61546+ TRACE_MGMT_DBG("Session %p created: target %p, tid %u, sid %#Lx",
61547+ session, target, target->tid, info->sid);
61548+
61549+ *result = session;
61550+ return 0;
61551+
61552+err:
61553+ if (session) {
61554+ kfree(session->initiator_name);
61555+ kfree(session);
61556+ }
61557+ return err;
61558+}
61559+
61560+/* target_mutex supposed to be locked */
61561+void sess_reinst_finished(struct iscsi_session *sess)
61562+{
61563+ struct iscsi_conn *c;
61564+
61565+ TRACE_ENTRY();
61566+
61567+ TRACE_MGMT_DBG("Enabling reinstate successor sess %p", sess);
61568+
61569+ BUG_ON(!sess->sess_reinstating);
61570+
61571+ list_for_each_entry(c, &sess->conn_list, conn_list_entry) {
61572+ conn_reinst_finished(c);
61573+ }
61574+ sess->sess_reinstating = 0;
61575+
61576+ TRACE_EXIT();
61577+ return;
61578+}
61579+
61580+/* target_mgmt_mutex supposed to be locked */
61581+int __add_session(struct iscsi_target *target,
61582+ struct iscsi_kern_session_info *info)
61583+{
61584+ struct iscsi_session *new_sess = NULL, *sess, *old_sess;
61585+ int err = 0, i;
61586+ union iscsi_sid sid;
61587+ bool reinstatement = false;
61588+ struct iscsi_kern_params_info *params_info;
61589+
61590+ TRACE_MGMT_DBG("Adding session SID %llx", info->sid);
61591+
61592+ err = iscsi_session_alloc(target, info, &new_sess);
61593+ if (err != 0)
61594+ goto out;
61595+
61596+ mutex_lock(&target->target_mutex);
61597+
61598+ sess = session_lookup(target, info->sid);
61599+ if (sess != NULL) {
61600+ PRINT_ERROR("Attempt to add session with existing SID %llx",
61601+ info->sid);
61602+ err = -EEXIST;
61603+ goto out_err_unlock;
61604+ }
61605+
61606+ params_info = kmalloc(sizeof(*params_info), GFP_KERNEL);
61607+ if (params_info == NULL) {
61608+ PRINT_ERROR("Unable to allocate params info (size %zd)",
61609+ sizeof(*params_info));
61610+ err = -ENOMEM;
61611+ goto out_err_unlock;
61612+ }
61613+
61614+ sid = *(union iscsi_sid *)&info->sid;
61615+ sid.id.tsih = 0;
61616+ old_sess = NULL;
61617+
61618+ /*
61619+ * We need to find the latest session to correctly handle
61620+ * multi-reinstatements
61621+ */
61622+ list_for_each_entry_reverse(sess, &target->session_list,
61623+ session_list_entry) {
61624+ union iscsi_sid s = *(union iscsi_sid *)&sess->sid;
61625+ s.id.tsih = 0;
61626+ if ((sid.id64 == s.id64) &&
61627+ (strcmp(info->initiator_name, sess->initiator_name) == 0)) {
61628+ if (!sess->sess_shutting_down) {
61629+ /* session reinstatement */
61630+ old_sess = sess;
61631+ }
61632+ break;
61633+ }
61634+ }
61635+ sess = NULL;
61636+
61637+ list_add_tail(&new_sess->session_list_entry, &target->session_list);
61638+
61639+ memset(params_info, 0, sizeof(*params_info));
61640+ params_info->tid = target->tid;
61641+ params_info->sid = info->sid;
61642+ params_info->params_type = key_session;
61643+ for (i = 0; i < session_key_last; i++)
61644+ params_info->session_params[i] = info->session_params[i];
61645+
61646+ err = iscsi_params_set(target, params_info, 1);
61647+ if (err != 0)
61648+ goto out_del;
61649+
61650+ memset(params_info, 0, sizeof(*params_info));
61651+ params_info->tid = target->tid;
61652+ params_info->sid = info->sid;
61653+ params_info->params_type = key_target;
61654+ for (i = 0; i < target_key_last; i++)
61655+ params_info->target_params[i] = info->target_params[i];
61656+
61657+ err = iscsi_params_set(target, params_info, 1);
61658+ if (err != 0)
61659+ goto out_del;
61660+
61661+ kfree(params_info);
61662+ params_info = NULL;
61663+
61664+ if (old_sess != NULL) {
61665+ reinstatement = true;
61666+
61667+ TRACE_MGMT_DBG("Reinstating sess %p with SID %llx (old %p, "
61668+ "SID %llx)", new_sess, new_sess->sid, old_sess,
61669+ old_sess->sid);
61670+
61671+ new_sess->sess_reinstating = 1;
61672+ old_sess->sess_reinst_successor = new_sess;
61673+
61674+ target_del_session(old_sess->target, old_sess, 0);
61675+ }
61676+
61677+ mutex_unlock(&target->target_mutex);
61678+
61679+ if (reinstatement) {
61680+ /*
61681+ * Mutex target_mgmt_mutex won't allow to add connections to
61682+ * the new session after target_mutex was dropped, so it's safe
61683+ * to replace the initial UA without it. We can't do it under
61684+ * target_mutex, because otherwise we can establish a
61685+ * circular locking dependency between target_mutex and
61686+ * scst_mutex in SCST core (iscsi_report_aen() called by
61687+ * SCST core under scst_mutex).
61688+ */
61689+ scst_set_initial_UA(new_sess->scst_sess,
61690+ SCST_LOAD_SENSE(scst_sense_nexus_loss_UA));
61691+ }
61692+
61693+out:
61694+ return err;
61695+
61696+out_del:
61697+ list_del(&new_sess->session_list_entry);
61698+ kfree(params_info);
61699+
61700+out_err_unlock:
61701+ mutex_unlock(&target->target_mutex);
61702+
61703+ scst_unregister_session(new_sess->scst_sess, 1, NULL);
61704+ new_sess->scst_sess = NULL;
61705+
61706+ mutex_lock(&target->target_mutex);
61707+ session_free(new_sess, false);
61708+ mutex_unlock(&target->target_mutex);
61709+ goto out;
61710+}
61711+
61712+static void __session_free(struct iscsi_session *session)
61713+{
61714+ kfree(session->initiator_name);
61715+ kfree(session);
61716+}
61717+
61718+static void iscsi_unreg_sess_done(struct scst_session *scst_sess)
61719+{
61720+ struct iscsi_session *session;
61721+
61722+ TRACE_ENTRY();
61723+
61724+ session = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
61725+
61726+ session->scst_sess = NULL;
61727+ __session_free(session);
61728+
61729+ TRACE_EXIT();
61730+ return;
61731+}
61732+
61733+/* target_mutex supposed to be locked */
61734+int session_free(struct iscsi_session *session, bool del)
61735+{
61736+ unsigned int i;
61737+
61738+ TRACE_MGMT_DBG("Freeing session %p (SID %llx)",
61739+ session, session->sid);
61740+
61741+ BUG_ON(!list_empty(&session->conn_list));
61742+ if (unlikely(atomic_read(&session->active_cmds) != 0)) {
61743+ PRINT_CRIT_ERROR("active_cmds not 0 (%d)!!",
61744+ atomic_read(&session->active_cmds));
61745+ BUG();
61746+ }
61747+
61748+ for (i = 0; i < ARRAY_SIZE(session->cmnd_data_wait_hash); i++)
61749+ BUG_ON(!list_empty(&session->cmnd_data_wait_hash[i]));
61750+
61751+ if (session->sess_reinst_successor != NULL)
61752+ sess_reinst_finished(session->sess_reinst_successor);
61753+
61754+ if (session->sess_reinstating) {
61755+ struct iscsi_session *s;
61756+ TRACE_MGMT_DBG("Freeing being reinstated sess %p", session);
61757+ list_for_each_entry(s, &session->target->session_list,
61758+ session_list_entry) {
61759+ if (s->sess_reinst_successor == session) {
61760+ s->sess_reinst_successor = NULL;
61761+ break;
61762+ }
61763+ }
61764+ }
61765+
61766+ if (del)
61767+ list_del(&session->session_list_entry);
61768+
61769+ if (session->scst_sess != NULL) {
61770+ /*
61771+ * We must NOT call scst_unregister_session() in the waiting
61772+ * mode, since we are under target_mutex. Otherwise we can
61773+ * establish a circular locking dependency between target_mutex
61774+ * and scst_mutex in SCST core (iscsi_report_aen() called by
61775+ * SCST core under scst_mutex).
61776+ */
61777+ scst_unregister_session(session->scst_sess, 0,
61778+ iscsi_unreg_sess_done);
61779+ } else
61780+ __session_free(session);
61781+
61782+ return 0;
61783+}
61784+
61785+/* target_mutex supposed to be locked */
61786+int __del_session(struct iscsi_target *target, u64 sid)
61787+{
61788+ struct iscsi_session *session;
61789+
61790+ session = session_lookup(target, sid);
61791+ if (!session)
61792+ return -ENOENT;
61793+
61794+ if (!list_empty(&session->conn_list)) {
61795+ PRINT_ERROR("%llx still have connections",
61796+ (long long unsigned int)session->sid);
61797+ return -EBUSY;
61798+ }
61799+
61800+ return session_free(session, true);
61801+}
61802+
61803+#define ISCSI_SESS_BOOL_PARAM_ATTR(name, exported_name) \
61804+static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
61805+ struct kobj_attribute *attr, char *buf) \
61806+{ \
61807+ int pos; \
61808+ struct scst_session *scst_sess; \
61809+ struct iscsi_session *sess; \
61810+ \
61811+ scst_sess = container_of(kobj, struct scst_session, sess_kobj); \
61812+ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess); \
61813+ \
61814+ pos = sprintf(buf, "%s\n", \
61815+ iscsi_get_bool_value(sess->sess_params.name)); \
61816+ \
61817+ return pos; \
61818+} \
61819+ \
61820+static struct kobj_attribute iscsi_sess_attr_##name = \
61821+ __ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL);
61822+
61823+#define ISCSI_SESS_INT_PARAM_ATTR(name, exported_name) \
61824+static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
61825+ struct kobj_attribute *attr, char *buf) \
61826+{ \
61827+ int pos; \
61828+ struct scst_session *scst_sess; \
61829+ struct iscsi_session *sess; \
61830+ \
61831+ scst_sess = container_of(kobj, struct scst_session, sess_kobj); \
61832+ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess); \
61833+ \
61834+ pos = sprintf(buf, "%d\n", sess->sess_params.name); \
61835+ \
61836+ return pos; \
61837+} \
61838+ \
61839+static struct kobj_attribute iscsi_sess_attr_##name = \
61840+ __ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL);
61841+
61842+#define ISCSI_SESS_DIGEST_PARAM_ATTR(name, exported_name) \
61843+static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
61844+ struct kobj_attribute *attr, char *buf) \
61845+{ \
61846+ int pos; \
61847+ struct scst_session *scst_sess; \
61848+ struct iscsi_session *sess; \
61849+ char digest_name[64]; \
61850+ \
61851+ scst_sess = container_of(kobj, struct scst_session, sess_kobj); \
61852+ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess); \
61853+ \
61854+ pos = sprintf(buf, "%s\n", iscsi_get_digest_name( \
61855+ sess->sess_params.name, digest_name)); \
61856+ \
61857+ return pos; \
61858+} \
61859+ \
61860+static struct kobj_attribute iscsi_sess_attr_##name = \
61861+ __ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL);
61862+
61863+ISCSI_SESS_BOOL_PARAM_ATTR(initial_r2t, InitialR2T);
61864+ISCSI_SESS_BOOL_PARAM_ATTR(immediate_data, ImmediateData);
61865+ISCSI_SESS_INT_PARAM_ATTR(max_recv_data_length, MaxRecvDataSegmentLength);
61866+ISCSI_SESS_INT_PARAM_ATTR(max_xmit_data_length, MaxXmitDataSegmentLength);
61867+ISCSI_SESS_INT_PARAM_ATTR(max_burst_length, MaxBurstLength);
61868+ISCSI_SESS_INT_PARAM_ATTR(first_burst_length, FirstBurstLength);
61869+ISCSI_SESS_INT_PARAM_ATTR(max_outstanding_r2t, MaxOutstandingR2T);
61870+ISCSI_SESS_DIGEST_PARAM_ATTR(header_digest, HeaderDigest);
61871+ISCSI_SESS_DIGEST_PARAM_ATTR(data_digest, DataDigest);
61872+
61873+static ssize_t iscsi_sess_sid_show(struct kobject *kobj,
61874+ struct kobj_attribute *attr, char *buf)
61875+{
61876+ int pos;
61877+ struct scst_session *scst_sess;
61878+ struct iscsi_session *sess;
61879+
61880+ TRACE_ENTRY();
61881+
61882+ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
61883+ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
61884+
61885+ pos = sprintf(buf, "%llx\n", sess->sid);
61886+
61887+ TRACE_EXIT_RES(pos);
61888+ return pos;
61889+}
61890+
61891+static struct kobj_attribute iscsi_attr_sess_sid =
61892+ __ATTR(sid, S_IRUGO, iscsi_sess_sid_show, NULL);
61893+
61894+static ssize_t iscsi_sess_reinstating_show(struct kobject *kobj,
61895+ struct kobj_attribute *attr, char *buf)
61896+{
61897+ int pos;
61898+ struct scst_session *scst_sess;
61899+ struct iscsi_session *sess;
61900+
61901+ TRACE_ENTRY();
61902+
61903+ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
61904+ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
61905+
61906+ pos = sprintf(buf, "%d\n", sess->sess_reinstating ? 1 : 0);
61907+
61908+ TRACE_EXIT_RES(pos);
61909+ return pos;
61910+}
61911+
61912+static struct kobj_attribute iscsi_sess_attr_reinstating =
61913+ __ATTR(reinstating, S_IRUGO, iscsi_sess_reinstating_show, NULL);
61914+
61915+static ssize_t iscsi_sess_force_close_store(struct kobject *kobj,
61916+ struct kobj_attribute *attr, const char *buf, size_t count)
61917+{
61918+ int res;
61919+ struct scst_session *scst_sess;
61920+ struct iscsi_session *sess;
61921+ struct iscsi_conn *conn;
61922+
61923+ TRACE_ENTRY();
61924+
61925+ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
61926+ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
61927+
61928+ if (mutex_lock_interruptible(&sess->target->target_mutex) != 0) {
61929+ res = -EINTR;
61930+ goto out;
61931+ }
61932+
61933+ PRINT_INFO("Deleting session %llx with initiator %s (%p)",
61934+ (long long unsigned int)sess->sid, sess->initiator_name, sess);
61935+
61936+ list_for_each_entry(conn, &sess->conn_list, conn_list_entry) {
61937+ TRACE_MGMT_DBG("Deleting connection with initiator %p", conn);
61938+ __mark_conn_closed(conn, ISCSI_CONN_ACTIVE_CLOSE|ISCSI_CONN_DELETING);
61939+ }
61940+
61941+ mutex_unlock(&sess->target->target_mutex);
61942+
61943+ res = count;
61944+
61945+out:
61946+ TRACE_EXIT_RES(res);
61947+ return res;
61948+}
61949+
61950+static struct kobj_attribute iscsi_sess_attr_force_close =
61951+ __ATTR(force_close, S_IWUSR, NULL, iscsi_sess_force_close_store);
61952+
61953+const struct attribute *iscsi_sess_attrs[] = {
61954+ &iscsi_sess_attr_initial_r2t.attr,
61955+ &iscsi_sess_attr_immediate_data.attr,
61956+ &iscsi_sess_attr_max_recv_data_length.attr,
61957+ &iscsi_sess_attr_max_xmit_data_length.attr,
61958+ &iscsi_sess_attr_max_burst_length.attr,
61959+ &iscsi_sess_attr_first_burst_length.attr,
61960+ &iscsi_sess_attr_max_outstanding_r2t.attr,
61961+ &iscsi_sess_attr_header_digest.attr,
61962+ &iscsi_sess_attr_data_digest.attr,
61963+ &iscsi_attr_sess_sid.attr,
61964+ &iscsi_sess_attr_reinstating.attr,
61965+ &iscsi_sess_attr_force_close.attr,
61966+ NULL,
61967+};
61968+
61969diff -uprN orig/linux-2.6.35/drivers/scst/iscsi-scst/target.c linux-2.6.35/drivers/scst/iscsi-scst/target.c
61970--- orig/linux-2.6.35/drivers/scst/iscsi-scst/target.c
61971+++ linux-2.6.35/drivers/scst/iscsi-scst/target.c
61972@@ -0,0 +1,533 @@
61973+/*
61974+ * Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
61975+ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
61976+ * Copyright (C) 2007 - 2010 ID7 Ltd.
61977+ *
61978+ * This program is free software; you can redistribute it and/or
61979+ * modify it under the terms of the GNU General Public License
61980+ * as published by the Free Software Foundation, version 2
61981+ * of the License.
61982+ *
61983+ * This program is distributed in the hope that it will be useful,
61984+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
61985+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61986+ * GNU General Public License for more details.
61987+ */
61988+
61989+#include <linux/delay.h>
61990+
61991+#include "iscsi.h"
61992+#include "digest.h"
61993+
61994+#define MAX_NR_TARGETS (1UL << 30)
61995+
61996+DEFINE_MUTEX(target_mgmt_mutex);
61997+
61998+/* All 3 protected by target_mgmt_mutex */
61999+static LIST_HEAD(target_list);
62000+static u32 next_target_id;
62001+static u32 nr_targets;
62002+
62003+/* target_mgmt_mutex supposed to be locked */
62004+struct iscsi_target *target_lookup_by_id(u32 id)
62005+{
62006+ struct iscsi_target *target;
62007+
62008+ list_for_each_entry(target, &target_list, target_list_entry) {
62009+ if (target->tid == id)
62010+ return target;
62011+ }
62012+ return NULL;
62013+}
62014+
62015+/* target_mgmt_mutex supposed to be locked */
62016+static struct iscsi_target *target_lookup_by_name(const char *name)
62017+{
62018+ struct iscsi_target *target;
62019+
62020+ list_for_each_entry(target, &target_list, target_list_entry) {
62021+ if (!strcmp(target->name, name))
62022+ return target;
62023+ }
62024+ return NULL;
62025+}
62026+
62027+/* target_mgmt_mutex supposed to be locked */
62028+static int iscsi_target_create(struct iscsi_kern_target_info *info, u32 tid,
62029+ struct iscsi_target **out_target)
62030+{
62031+ int err = -EINVAL, len;
62032+ char *name = info->name;
62033+ struct iscsi_target *target;
62034+
62035+ TRACE_MGMT_DBG("Creating target tid %u, name %s", tid, name);
62036+
62037+ len = strlen(name);
62038+ if (!len) {
62039+ PRINT_ERROR("The length of the target name is zero %u", tid);
62040+ goto out;
62041+ }
62042+
62043+ if (!try_module_get(THIS_MODULE)) {
62044+ PRINT_ERROR("Fail to get module %u", tid);
62045+ goto out;
62046+ }
62047+
62048+ target = kzalloc(sizeof(*target), GFP_KERNEL);
62049+ if (!target) {
62050+ err = -ENOMEM;
62051+ goto out_put;
62052+ }
62053+
62054+ target->tid = info->tid = tid;
62055+
62056+ strlcpy(target->name, name, sizeof(target->name));
62057+
62058+ mutex_init(&target->target_mutex);
62059+ INIT_LIST_HEAD(&target->session_list);
62060+ INIT_LIST_HEAD(&target->attrs_list);
62061+
62062+ target->scst_tgt = scst_register_target(&iscsi_template, target->name);
62063+ if (!target->scst_tgt) {
62064+ PRINT_ERROR("%s", "scst_register_target() failed");
62065+ err = -EBUSY;
62066+ goto out_free;
62067+ }
62068+
62069+ scst_tgt_set_tgt_priv(target->scst_tgt, target);
62070+
62071+ list_add_tail(&target->target_list_entry, &target_list);
62072+
62073+ *out_target = target;
62074+
62075+ return 0;
62076+
62077+out_free:
62078+ kfree(target);
62079+
62080+out_put:
62081+ module_put(THIS_MODULE);
62082+
62083+out:
62084+ return err;
62085+}
62086+
62087+/* target_mgmt_mutex supposed to be locked */
62088+int __add_target(struct iscsi_kern_target_info *info)
62089+{
62090+ int err;
62091+ u32 tid = info->tid;
62092+ struct iscsi_target *target = NULL; /* to calm down sparse */
62093+ struct iscsi_kern_params_info *params_info;
62094+ struct iscsi_kern_attr *attr_info;
62095+ union add_info_union {
62096+ struct iscsi_kern_params_info params_info;
62097+ struct iscsi_kern_attr attr_info;
62098+ } *add_info;
62099+ int i, rc;
62100+ unsigned long attrs_ptr_long;
62101+ struct iscsi_kern_attr __user *attrs_ptr;
62102+
62103+ if (nr_targets > MAX_NR_TARGETS) {
62104+ err = -EBUSY;
62105+ goto out;
62106+ }
62107+
62108+ if (target_lookup_by_name(info->name)) {
62109+ PRINT_ERROR("Target %s already exist!", info->name);
62110+ err = -EEXIST;
62111+ goto out;
62112+ }
62113+
62114+ if (tid && target_lookup_by_id(tid)) {
62115+ PRINT_ERROR("Target %u already exist!", tid);
62116+ err = -EEXIST;
62117+ goto out;
62118+ }
62119+
62120+ add_info = kmalloc(sizeof(*add_info), GFP_KERNEL);
62121+ if (add_info == NULL) {
62122+ PRINT_ERROR("Unable to allocate additional info (size %zd)",
62123+ sizeof(*add_info));
62124+ err = -ENOMEM;
62125+ goto out;
62126+ }
62127+ params_info = (struct iscsi_kern_params_info *)add_info;
62128+ attr_info = (struct iscsi_kern_attr *)add_info;
62129+
62130+ if (tid == 0) {
62131+ do {
62132+ if (!++next_target_id)
62133+ ++next_target_id;
62134+ } while (target_lookup_by_id(next_target_id));
62135+
62136+ tid = next_target_id;
62137+ }
62138+
62139+ err = iscsi_target_create(info, tid, &target);
62140+ if (err != 0)
62141+ goto out_free;
62142+
62143+ nr_targets++;
62144+
62145+ mutex_lock(&target->target_mutex);
62146+
62147+ attrs_ptr_long = info->attrs_ptr;
62148+ attrs_ptr = (struct iscsi_kern_attr __user *)attrs_ptr_long;
62149+ for (i = 0; i < info->attrs_num; i++) {
62150+ memset(attr_info, 0, sizeof(*attr_info));
62151+
62152+ rc = copy_from_user(attr_info, attrs_ptr, sizeof(*attr_info));
62153+ if (rc != 0) {
62154+ PRINT_ERROR("Failed to copy users of target %s "
62155+ "failed", info->name);
62156+ err = -EFAULT;
62157+ goto out_del_unlock;
62158+ }
62159+
62160+ attr_info->name[sizeof(attr_info->name)-1] = '\0';
62161+
62162+ err = iscsi_add_attr(target, attr_info);
62163+ if (err != 0)
62164+ goto out_del_unlock;
62165+
62166+ attrs_ptr++;
62167+ }
62168+
62169+ mutex_unlock(&target->target_mutex);
62170+
62171+ err = tid;
62172+
62173+out_free:
62174+ kfree(add_info);
62175+
62176+out:
62177+ return err;
62178+
62179+out_del_unlock:
62180+ mutex_unlock(&target->target_mutex);
62181+ __del_target(tid);
62182+ goto out_free;
62183+}
62184+
62185+static void target_destroy(struct iscsi_target *target)
62186+{
62187+ struct iscsi_attr *attr, *t;
62188+
62189+ TRACE_MGMT_DBG("Destroying target tid %u", target->tid);
62190+
62191+ list_for_each_entry_safe(attr, t, &target->attrs_list,
62192+ attrs_list_entry) {
62193+ __iscsi_del_attr(target, attr);
62194+ }
62195+
62196+ scst_unregister_target(target->scst_tgt);
62197+
62198+ kfree(target);
62199+
62200+ module_put(THIS_MODULE);
62201+ return;
62202+}
62203+
62204+/* target_mgmt_mutex supposed to be locked */
62205+int __del_target(u32 id)
62206+{
62207+ struct iscsi_target *target;
62208+ int err;
62209+
62210+ target = target_lookup_by_id(id);
62211+ if (!target) {
62212+ err = -ENOENT;
62213+ goto out;
62214+ }
62215+
62216+ mutex_lock(&target->target_mutex);
62217+
62218+ if (!list_empty(&target->session_list)) {
62219+ err = -EBUSY;
62220+ goto out_unlock;
62221+ }
62222+
62223+ list_del(&target->target_list_entry);
62224+ nr_targets--;
62225+
62226+ mutex_unlock(&target->target_mutex);
62227+
62228+ target_destroy(target);
62229+ return 0;
62230+
62231+out_unlock:
62232+ mutex_unlock(&target->target_mutex);
62233+
62234+out:
62235+ return err;
62236+}
62237+
62238+/* target_mutex supposed to be locked */
62239+void target_del_session(struct iscsi_target *target,
62240+ struct iscsi_session *session, int flags)
62241+{
62242+ TRACE_ENTRY();
62243+
62244+ TRACE_MGMT_DBG("Deleting session %p", session);
62245+
62246+ if (!list_empty(&session->conn_list)) {
62247+ struct iscsi_conn *conn, *tc;
62248+ list_for_each_entry_safe(conn, tc, &session->conn_list,
62249+ conn_list_entry) {
62250+ TRACE_MGMT_DBG("Mark conn %p closing", conn);
62251+ __mark_conn_closed(conn, flags);
62252+ }
62253+ } else {
62254+ TRACE_MGMT_DBG("Freeing session %p without connections",
62255+ session);
62256+ __del_session(target, session->sid);
62257+ }
62258+
62259+ TRACE_EXIT();
62260+ return;
62261+}
62262+
62263+/* target_mutex supposed to be locked */
62264+void target_del_all_sess(struct iscsi_target *target, int flags)
62265+{
62266+ struct iscsi_session *session, *ts;
62267+
62268+ TRACE_ENTRY();
62269+
62270+ if (!list_empty(&target->session_list)) {
62271+ TRACE_MGMT_DBG("Deleting all sessions from target %p", target);
62272+ list_for_each_entry_safe(session, ts, &target->session_list,
62273+ session_list_entry) {
62274+ target_del_session(target, session, flags);
62275+ }
62276+ }
62277+
62278+ TRACE_EXIT();
62279+ return;
62280+}
62281+
62282+void target_del_all(void)
62283+{
62284+ struct iscsi_target *target, *t;
62285+ bool first = true;
62286+
62287+ TRACE_ENTRY();
62288+
62289+ TRACE_MGMT_DBG("%s", "Deleting all targets");
62290+
62291+ /* Not the best, ToDo */
62292+ while (1) {
62293+ mutex_lock(&target_mgmt_mutex);
62294+
62295+ if (list_empty(&target_list))
62296+ break;
62297+
62298+ /*
62299+ * In the first iteration we won't delete targets to go at
62300+ * first through all sessions of all targets and close their
62301+ * connections. Otherwise we can stuck for noticeable time
62302+ * waiting during a target's unregistration for the activities
62303+ * suspending over active connection. This can especially got
62304+ * bad if any being wait connection itself stuck waiting for
62305+ * something and can be recovered only by connection close.
62306+ * Let's for such cases not wait while such connection recover
62307+ * theyself, but act in advance.
62308+ */
62309+
62310+ list_for_each_entry_safe(target, t, &target_list,
62311+ target_list_entry) {
62312+ mutex_lock(&target->target_mutex);
62313+
62314+ if (!list_empty(&target->session_list)) {
62315+ target_del_all_sess(target,
62316+ ISCSI_CONN_ACTIVE_CLOSE |
62317+ ISCSI_CONN_DELETING);
62318+ } else if (!first) {
62319+ TRACE_MGMT_DBG("Deleting target %p", target);
62320+ list_del(&target->target_list_entry);
62321+ nr_targets--;
62322+ mutex_unlock(&target->target_mutex);
62323+ target_destroy(target);
62324+ continue;
62325+ }
62326+
62327+ mutex_unlock(&target->target_mutex);
62328+ }
62329+ mutex_unlock(&target_mgmt_mutex);
62330+ msleep(100);
62331+
62332+ first = false;
62333+ }
62334+
62335+ mutex_unlock(&target_mgmt_mutex);
62336+
62337+ TRACE_MGMT_DBG("%s", "Deleting all targets finished");
62338+
62339+ TRACE_EXIT();
62340+ return;
62341+}
62342+
62343+static ssize_t iscsi_tgt_tid_show(struct kobject *kobj,
62344+ struct kobj_attribute *attr, char *buf)
62345+{
62346+ int pos;
62347+ struct scst_tgt *scst_tgt;
62348+ struct iscsi_target *tgt;
62349+
62350+ TRACE_ENTRY();
62351+
62352+ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
62353+ tgt = (struct iscsi_target *)scst_tgt_get_tgt_priv(scst_tgt);
62354+
62355+ pos = sprintf(buf, "%u\n", tgt->tid);
62356+
62357+ TRACE_EXIT_RES(pos);
62358+ return pos;
62359+}
62360+
62361+static struct kobj_attribute iscsi_tgt_attr_tid =
62362+ __ATTR(tid, S_IRUGO, iscsi_tgt_tid_show, NULL);
62363+
62364+const struct attribute *iscsi_tgt_attrs[] = {
62365+ &iscsi_tgt_attr_tid.attr,
62366+ NULL,
62367+};
62368+
62369+ssize_t iscsi_sysfs_send_event(uint32_t tid, enum iscsi_kern_event_code code,
62370+ const char *param1, const char *param2, void **data)
62371+{
62372+ int res;
62373+ struct scst_sysfs_user_info *info;
62374+
62375+ TRACE_ENTRY();
62376+
62377+ if (ctr_open_state != ISCSI_CTR_OPEN_STATE_OPEN) {
62378+ PRINT_ERROR("%s", "User space process not connected");
62379+ res = -EPERM;
62380+ goto out;
62381+ }
62382+
62383+ res = scst_sysfs_user_add_info(&info);
62384+ if (res != 0)
62385+ goto out;
62386+
62387+ TRACE_DBG("Sending event %d (tid %d, param1 %s, param2 %s, cookie %d, "
62388+ "info %p)", tid, code, param1, param2, info->info_cookie, info);
62389+
62390+ res = event_send(tid, 0, 0, info->info_cookie, code, param1, param2);
62391+ if (res <= 0) {
62392+ PRINT_ERROR("event_send() failed: %d", res);
62393+ if (res == 0)
62394+ res = -EFAULT;
62395+ goto out_free;
62396+ }
62397+
62398+ /*
62399+ * It may wait 30 secs in blocking connect to an unreacheable
62400+ * iSNS server. It must be fixed, but not now. ToDo.
62401+ */
62402+ res = scst_wait_info_completion(info, 31 * HZ);
62403+
62404+ if (data != NULL)
62405+ *data = info->data;
62406+
62407+out_free:
62408+ scst_sysfs_user_del_info(info);
62409+
62410+out:
62411+ TRACE_EXIT_RES(res);
62412+ return res;
62413+}
62414+
62415+int iscsi_enable_target(struct scst_tgt *scst_tgt, bool enable)
62416+{
62417+ struct iscsi_target *tgt =
62418+ (struct iscsi_target *)scst_tgt_get_tgt_priv(scst_tgt);
62419+ int res;
62420+ uint32_t type;
62421+
62422+ TRACE_ENTRY();
62423+
62424+ if (enable)
62425+ type = E_ENABLE_TARGET;
62426+ else
62427+ type = E_DISABLE_TARGET;
62428+
62429+ TRACE_DBG("%s target %d", enable ? "Enabling" : "Disabling", tgt->tid);
62430+
62431+ res = iscsi_sysfs_send_event(tgt->tid, type, NULL, NULL, NULL);
62432+
62433+ TRACE_EXIT_RES(res);
62434+ return res;
62435+}
62436+
62437+bool iscsi_is_target_enabled(struct scst_tgt *scst_tgt)
62438+{
62439+ struct iscsi_target *tgt =
62440+ (struct iscsi_target *)scst_tgt_get_tgt_priv(scst_tgt);
62441+
62442+ return tgt->tgt_enabled;
62443+}
62444+
62445+ssize_t iscsi_sysfs_add_target(const char *target_name, char *params)
62446+{
62447+ int res;
62448+
62449+ TRACE_ENTRY();
62450+
62451+ res = iscsi_sysfs_send_event(0, E_ADD_TARGET, target_name,
62452+ params, NULL);
62453+ if (res > 0) {
62454+ /* It's tid */
62455+ res = 0;
62456+ }
62457+
62458+ TRACE_EXIT_RES(res);
62459+ return res;
62460+}
62461+
62462+ssize_t iscsi_sysfs_del_target(const char *target_name)
62463+{
62464+ int res = 0, tid;
62465+
62466+ TRACE_ENTRY();
62467+
62468+ /* We don't want to have tgt visible after the mutex unlock */
62469+ {
62470+ struct iscsi_target *tgt;
62471+ mutex_lock(&target_mgmt_mutex);
62472+ tgt = target_lookup_by_name(target_name);
62473+ if (tgt == NULL) {
62474+ PRINT_ERROR("Target %s not found", target_name);
62475+ mutex_unlock(&target_mgmt_mutex);
62476+ res = -ENOENT;
62477+ goto out;
62478+ }
62479+ tid = tgt->tid;
62480+ mutex_unlock(&target_mgmt_mutex);
62481+ }
62482+
62483+ TRACE_DBG("Deleting target %s (tid %d)", target_name, tid);
62484+
62485+ res = iscsi_sysfs_send_event(tid, E_DEL_TARGET, NULL, NULL, NULL);
62486+
62487+out:
62488+ TRACE_EXIT_RES(res);
62489+ return res;
62490+}
62491+
62492+ssize_t iscsi_sysfs_mgmt_cmd(char *cmd)
62493+{
62494+ int res;
62495+
62496+ TRACE_ENTRY();
62497+
62498+ TRACE_DBG("Sending mgmt cmd %s", cmd);
62499+
62500+ res = iscsi_sysfs_send_event(0, E_MGMT_CMD, cmd, NULL, NULL);
62501+
62502+ TRACE_EXIT_RES(res);
62503+ return res;
62504+}
62505+
62506diff -uprN orig/linux-2.6.35/Documentation/scst/README.iscsi linux-2.6.35/Documentation/scst/README.iscsi
62507--- orig/linux-2.6.35/Documentation/scst/README.iscsi
62508+++ linux-2.6.35/Documentation/scst/README.iscsi
62509@@ -0,0 +1,741 @@
62510+iSCSI SCST target driver
62511+========================
62512+
62513+ISCSI-SCST is a deeply reworked fork of iSCSI Enterprise Target (IET)
62514+(http://iscsitarget.sourceforge.net). Reasons of the fork were:
62515+
62516+ - To be able to use full power of SCST core.
62517+
62518+ - To fix all the problems, corner cases issues and iSCSI standard
62519+ violations which IET has.
62520+
62521+See for more info http://iscsi-scst.sourceforge.net.
62522+
62523+Usage
62524+-----
62525+
62526+See in http://iscsi-scst.sourceforge.net/iscsi-scst-howto.txt how to
62527+configure iSCSI-SCST.
62528+
62529+If you want to use Intel CRC32 offload and have corresponding hardware,
62530+you should load crc32c-intel module. Then iSCSI-SCST will do all digest
62531+calculations using this facility.
62532+
62533+In 2.0.0 usage of iscsi-scstd.conf as well as iscsi-scst-adm utility is
62534+obsolete. Use the sysfs interface facilities instead.
62535+
62536+The flow of iSCSI-SCST inialization should be as the following:
62537+
62538+1. Load of SCST and iSCSI-SCST kernel modules with necessary module
62539+parameters, if needed.
62540+
62541+2. Start iSCSI-SCST service.
62542+
62543+3. Configure targets, devices, LUNs, etc. either using scstadmin
62544+(recommended), or using the sysfs interface directly as described below.
62545+
62546+It is recommended to use TEST UNIT READY ("tur") command to check if
62547+iSCSI-SCST target is alive in MPIO configurations.
62548+
62549+Also see SCST README file how to tune for the best performance.
62550+
62551+CAUTION: Working of target and initiator on the same host isn't fully
62552+======= supported. See SCST README file for details.
62553+
62554+Sysfs interface
62555+---------------
62556+
62557+Root of SCST sysfs interface is /sys/kernel/scst_tgt. Root of iSCSI-SCST
62558+is /sys/kernel/scst_tgt/targets/iscsi. It has the following entries:
62559+
62560+ - None, one or more subdirectories for targets with name equal to names
62561+ of the corresponding targets.
62562+
62563+ - IncomingUser[num] - optional one or more attributes containing user
62564+ name and password for incoming discovery user name. Not exist by
62565+ default and can be added through "mgmt" entry, see below.
62566+
62567+ - OutgoingUser - optional attribute containing user name and password
62568+ for outgoing discovery user name. Not exist by default and can be
62569+ added through "mgmt" entry, see below.
62570+
62571+ - iSNSServer - contains name or IP address of iSNS server with optional
62572+ "AccessControl" attribute, which allows to enable iSNS access
62573+ control. Empty by default.
62574+
62575+ - allowed_portal[num] - optional attribute, which specifies, on which
62576+ portals (target's IP addresses) this target will be available. If not
62577+ specified (default) the target will be available on all all portals.
62578+ As soon as at least one allowed_portal specified, the target will be
62579+ accessible for initiators only on the specified portals. There might
62580+ be any number of the allowed_portal attributes. The portals
62581+ specification in the allowed_portal attributes can be a simple
62582+ DOS-type patterns, containing '*' and '?' symbols. '*' means match
62583+ all any symbols, '?' means match only any single symbol. For
62584+ instance, "10.170.77.2" will match "10.170.7?.*". Additionally, you
62585+ can use negative sign '!' to revert the value of the pattern. For
62586+ instance, "10.170.67.2" will match "!10.170.7?.*". See examples
62587+ below.
62588+
62589+ - enabled - using this attribute you can enable or disable iSCSI-SCST
62590+ accept new connections. It allows to finish configuring global
62591+ iSCSI-SCST attributes before it starts accepting new connections. 0
62592+ by default.
62593+
62594+ - open_state - read-only attribute, which allows to see if the user
62595+ space part of iSCSI-SCST connected to the kernel part.
62596+
62597+ - per_portal_acl - if set, makes iSCSI-SCST work in the per-portal
62598+ access control mode. In this mode iSCSI-SCST registers all initiators
62599+ in SCST core as "initiator_name#portal_IP_address" pattern, like
62600+ "iqn.2006-10.net.vlnb:ini#10.170.77.2" for initiator
62601+ iqn.2006-10.net.vlnb connected through portal 10.170.77.2. This mode
62602+ allows to make particular initiators be able to use only particular
62603+ portals on the target and don't see/be able to connect through
62604+ others. See below for more details.
62605+
62606+ - trace_level - allows to enable and disable various tracing
62607+ facilities. See content of this file for help how to use it.
62608+
62609+ - version - read-only attribute, which allows to see version of
62610+ iSCSI-SCST and enabled optional features.
62611+
62612+ - mgmt - main management entry, which allows to configure iSCSI-SCST.
62613+ Namely, add/delete targets as well as add/delete optional global and
62614+ per-target attributes. See content of this file for help how to use
62615+ it.
62616+
62617+Each iSCSI-SCST sysfs file (attribute) can contain in the last line mark
62618+"[key]". It is automatically added mark used to allow scstadmin to see
62619+which attributes it should save in the config file. You can ignore it.
62620+
62621+Each target subdirectory contains the following entries:
62622+
62623+ - ini_groups - subdirectory defining initiator groups for this target,
62624+ used to define per-initiator access control. See SCST core README for
62625+ more details.
62626+
62627+ - luns - subdirectory defining LUNs of this target. See SCST core
62628+ README for more details.
62629+
62630+ - sessions - subdirectory containing connected to this target sessions.
62631+
62632+ - IncomingUser[num] - optional one or more attributes containing user
62633+ name and password for incoming user name. Not exist by default and can
62634+ be added through the "mgmt" entry, see above.
62635+
62636+ - OutgoingUser - optional attribute containing user name and password
62637+ for outgoing user name. Not exist by default and can be added through
62638+ the "mgmt" entry, see above.
62639+
62640+ - Entries defining default iSCSI parameters values used during iSCSI
62641+ parameters negotiation. Only entries which can be changed or make
62642+ sense are listed there.
62643+
62644+ - QueuedCommands - defines maximum number of commands queued to any
62645+ session of this target. Default is 32 commands.
62646+
62647+ - RspTimeout - defines the maximum time in seconds a command can wait for
62648+ response from initiator, otherwise the corresponding connection will
62649+ be closed. For performance reasons it is implemented as a timer,
62650+ which once in RspTimeout time checks the oldest command waiting for
62651+ response and, if it's older than RspTimeout, then it closes the
62652+ connection. Hence, a stalled connection will be closed in time
62653+ between RspTimeout and 2*RspTimeout. Default is 30 seconds.
62654+
62655+ - NopInInterval - defines interval between NOP-In requests, which the
62656+ target will send on idle connections to check if the initiator is
62657+ still alive. If there is no NOP-Out reply from the initiator in
62658+ RspTimeout time, the corresponding connection will be closed. Default
62659+ is 30 seconds. If it's set to 0, then NOP-In requests are disabled.
62660+
62661+ - enabled - using this attribute you can enable or disable iSCSI-SCST
62662+ accept new connections to this target. It allows to finish
62663+ configuring it before it starts accepting new connections. 0 by
62664+ default.
62665+
62666+ - rel_tgt_id - allows to read or write SCSI Relative Target Port
62667+ Identifier attribute. This identifier is used to identify SCSI Target
62668+ Ports by some SCSI commands, mainly by Persistent Reservations
62669+ commands. This identifier must be unique among all SCST targets, but
62670+ for convenience SCST allows disabled targets to have not unique
62671+ rel_tgt_id. In this case SCST will not allow to enable this target
62672+ until rel_tgt_id becomes unique. This attribute initialized unique by
62673+ SCST by default.
62674+
62675+ - redirect - allows to temporarily or permanently redirect login to the
62676+ target to another portal. Discovery sessions will not be impacted,
62677+ but normal sessions will be redirected before security negotiation.
62678+ The destination should be specified using format "<ip_addr>[:port] temp|perm".
62679+ IPv6 addresses need to be enclosed in [] brackets. To remove
62680+ redirection, provide an empty string. For example:
62681+ echo "10.170.77.2:32600 temp" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/redirect
62682+ will temporarily redirect login to portal 10.170.77.2 and port 32600.
62683+
62684+ - tid - TID of this target.
62685+
62686+Subdirectory "sessions" contains one subdirectory for each connected
62687+session with name equal to name of the connected initiator.
62688+
62689+Each session subdirectory contains the following entries:
62690+
62691+ - One subdirectory for each TCP connection in this session. ISCSI-SCST
62692+ supports 1 connection per session, but the session subdirectory can
62693+ contain several connections: one active and other being closed.
62694+
62695+ - Entries defining negotiated iSCSI parameters. Only parameters which
62696+ can be changed or make sense are listed there.
62697+
62698+ - initiator_name - contains initiator name
62699+
62700+ - sid - contains SID of this session
62701+
62702+ - reinstating - contains reinstatement state of this session
62703+
62704+ - force_close - write-only attribute, which allows to force close this
62705+ session. This is the only writable session attribute.
62706+
62707+ - active_commands - contains number of active, i.e. not yet or being
62708+ executed, SCSI commands in this session.
62709+
62710+ - commands - contains overall number of SCSI commands in this session.
62711+
62712+Each connection subdirectory contains the following entries:
62713+
62714+ - cid - contains CID of this connection.
62715+
62716+ - ip - contains IP address of the connected initiator.
62717+
62718+ - state - contains processing state of this connection.
62719+
62720+Below is a sample script, which configures 1 virtual disk "disk1" using
62721+/disk1 image and one target iqn.2006-10.net.vlnb:tgt with all default
62722+parameters:
62723+
62724+#!/bin/bash
62725+
62726+modprobe scst
62727+modprobe scst_vdisk
62728+
62729+echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
62730+
62731+service iscsi-scst start
62732+
62733+echo "add_target iqn.2006-10.net.vlnb:tgt" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
62734+echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
62735+
62736+echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
62737+echo 1 >/sys/kernel/scst_tgt/targets/iscsi/enabled
62738+
62739+Below is another sample script, which configures 1 real local SCSI disk
62740+0:0:1:0 and one target iqn.2006-10.net.vlnb:tgt with all default parameters:
62741+
62742+#!/bin/bash
62743+
62744+modprobe scst
62745+modprobe scst_disk
62746+
62747+echo "add_device 0:0:1:0" >/sys/kernel/scst_tgt/handlers/dev_disk/mgmt
62748+
62749+service iscsi-scst start
62750+
62751+echo "add_target iqn.2006-10.net.vlnb:tgt" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
62752+echo "add 0:0:1:0 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
62753+
62754+echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
62755+echo 1 >/sys/kernel/scst_tgt/targets/iscsi/enabled
62756+
62757+Below is an advanced sample script, which configures more virtual
62758+devices of various types, including virtual CDROM and 2 targets, one
62759+with all default parameters, another one with some not default
62760+parameters, incoming and outgoing user names for CHAP authentification,
62761+and special permissions for initiator iqn.2005-03.org.open-iscsi:cacdcd2520,
62762+which will see another set of devices. Also this sample configures CHAP
62763+authentication for discovery sessions and iSNS server with access
62764+control.
62765+
62766+#!/bin/bash
62767+
62768+modprobe scst
62769+modprobe scst_vdisk
62770+
62771+echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
62772+echo "add_device disk2 filename=/disk2; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
62773+echo "add_device blockio filename=/dev/sda5" >/sys/kernel/scst_tgt/handlers/vdisk_blockio/mgmt
62774+echo "add_device nullio" >/sys/kernel/scst_tgt/handlers/vdisk_nullio/mgmt
62775+echo "add_device cdrom" >/sys/kernel/scst_tgt/handlers/vcdrom/mgmt
62776+
62777+service iscsi-scst start
62778+
62779+echo "192.168.1.16 AccessControl" >/sys/kernel/scst_tgt/targets/iscsi/iSNSServer
62780+echo "add_attribute IncomingUser joeD 12charsecret" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
62781+echo "add_attribute OutgoingUser jackD 12charsecret1" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
62782+
62783+echo "add_target iqn.2006-10.net.vlnb:tgt" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
62784+
62785+echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
62786+echo "add cdrom 1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
62787+
62788+echo "add_target iqn.2006-10.net.vlnb:tgt1" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
62789+echo "add_target_attribute iqn.2006-10.net.vlnb:tgt1 IncomingUser1 joe2 12charsecret2" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
62790+echo "add_target_attribute iqn.2006-10.net.vlnb:tgt1 IncomingUser joe 12charsecret" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
62791+echo "add_target_attribute iqn.2006-10.net.vlnb:tgt1 OutgoingUser jim1 12charpasswd" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
62792+echo "No" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/InitialR2T
62793+echo "Yes" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ImmediateData
62794+echo "8192" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxRecvDataSegmentLength
62795+echo "8192" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxXmitDataSegmentLength
62796+echo "131072" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxBurstLength
62797+echo "32768" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/FirstBurstLength
62798+echo "1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxOutstandingR2T
62799+echo "CRC32C,None" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/HeaderDigest
62800+echo "CRC32C,None" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/DataDigest
62801+echo "32" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/QueuedCommands
62802+
62803+echo "add disk2 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/mgmt
62804+echo "add nullio 26" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/mgmt
62805+
62806+echo "create special_ini" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/mgmt
62807+echo "add blockio 0 read_only=1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/special_ini/luns/mgmt
62808+echo "add iqn.2005-03.org.open-iscsi:cacdcd2520" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/special_ini/initiators/mgmt
62809+
62810+echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
62811+echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/enabled
62812+
62813+echo 1 >/sys/kernel/scst_tgt/targets/iscsi/enabled
62814+
62815+The resulting overall SCST sysfs hierarchy with an initiator connected to
62816+both iSCSI-SCST targets will look like:
62817+
62818+/sys/kernel/scst_tgt
62819+|-- devices
62820+| |-- blockio
62821+| | |-- blocksize
62822+| | |-- exported
62823+| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/special_ini/luns/0
62824+| | |-- filename
62825+| | |-- handler -> ../../handlers/vdisk_blockio
62826+| | |-- nv_cache
62827+| | |-- read_only
62828+| | |-- removable
62829+| | |-- resync_size
62830+| | |-- size_mb
62831+| | |-- t10_dev_id
62832+| | |-- threads_num
62833+| | |-- threads_pool_type
62834+| | |-- type
62835+| | `-- usn
62836+| |-- cdrom
62837+| | |-- exported
62838+| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/1
62839+| | |-- filename
62840+| | |-- handler -> ../../handlers/vcdrom
62841+| | |-- size_mb
62842+| | |-- t10_dev_id
62843+| | |-- threads_num
62844+| | |-- threads_pool_type
62845+| | |-- type
62846+| | `-- usn
62847+| |-- disk1
62848+| | |-- blocksize
62849+| | |-- exported
62850+| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/0
62851+| | |-- filename
62852+| | |-- handler -> ../../handlers/vdisk_fileio
62853+| | |-- nv_cache
62854+| | |-- o_direct
62855+| | |-- read_only
62856+| | |-- removable
62857+| | |-- resync_size
62858+| | |-- size_mb
62859+| | |-- t10_dev_id
62860+| | |-- type
62861+| | |-- usn
62862+| | `-- write_through
62863+| |-- disk2
62864+| | |-- blocksize
62865+| | |-- exported
62866+| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/0
62867+| | |-- filename
62868+| | |-- handler -> ../../handlers/vdisk_fileio
62869+| | |-- nv_cache
62870+| | |-- o_direct
62871+| | |-- read_only
62872+| | |-- removable
62873+| | |-- resync_size
62874+| | |-- size_mb
62875+| | |-- t10_dev_id
62876+| | |-- threads_num
62877+| | |-- threads_pool_type
62878+| | |-- threads_num
62879+| | |-- threads_pool_type
62880+| | |-- type
62881+| | |-- usn
62882+| | `-- write_through
62883+| `-- nullio
62884+| |-- blocksize
62885+| |-- exported
62886+| | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/26
62887+| |-- handler -> ../../handlers/vdisk_nullio
62888+| |-- read_only
62889+| |-- removable
62890+| |-- size_mb
62891+| |-- t10_dev_id
62892+| |-- threads_num
62893+| |-- threads_pool_type
62894+| |-- type
62895+| `-- usn
62896+|-- handlers
62897+| |-- vcdrom
62898+| | |-- cdrom -> ../../devices/cdrom
62899+| | |-- mgmt
62900+| | |-- trace_level
62901+| | `-- type
62902+| |-- vdisk_blockio
62903+| | |-- blockio -> ../../devices/blockio
62904+| | |-- mgmt
62905+| | |-- trace_level
62906+| | `-- type
62907+| |-- vdisk_fileio
62908+| | |-- disk1 -> ../../devices/disk1
62909+| | |-- disk2 -> ../../devices/disk2
62910+| | |-- mgmt
62911+| | |-- trace_level
62912+| | `-- type
62913+| `-- vdisk_nullio
62914+| |-- mgmt
62915+| |-- nullio -> ../../devices/nullio
62916+| |-- trace_level
62917+| `-- type
62918+|-- sgv
62919+| |-- global_stats
62920+| |-- sgv
62921+| | `-- stats
62922+| |-- sgv-clust
62923+| | `-- stats
62924+| `-- sgv-dma
62925+| `-- stats
62926+|-- targets
62927+| `-- iscsi
62928+| |-- IncomingUser
62929+| |-- OutgoingUser
62930+| |-- enabled
62931+| |-- iSNSServer
62932+| |-- iqn.2006-10.net.vlnb:tgt
62933+| | |-- DataDigest
62934+| | |-- FirstBurstLength
62935+| | |-- HeaderDigest
62936+| | |-- ImmediateData
62937+| | |-- InitialR2T
62938+| | |-- MaxBurstLength
62939+| | |-- MaxOutstandingR2T
62940+| | |-- MaxRecvDataSegmentLength
62941+| | |-- MaxXmitDataSegmentLength
62942+| | |-- NopInInterval
62943+| | |-- QueuedCommands
62944+| | |-- RspTimeout
62945+| | |-- enabled
62946+| | |-- ini_groups
62947+| | | `-- mgmt
62948+| | |-- luns
62949+| | | |-- 0
62950+| | | | |-- device -> ../../../../../devices/disk1
62951+| | | | `-- read_only
62952+| | | |-- 1
62953+| | | | |-- device -> ../../../../../devices/cdrom
62954+| | | | `-- read_only
62955+| | | `-- mgmt
62956+| | |-- per_portal_acl
62957+| | |-- redirect
62958+| | |-- rel_tgt_id
62959+| | |-- sessions
62960+| | | `-- iqn.2005-03.org.open-iscsi:cacdcd2520
62961+| | | |-- 10.170.75.2
62962+| | | | |-- cid
62963+| | | | |-- ip
62964+| | | | `-- state
62965+| | | |-- DataDigest
62966+| | | |-- FirstBurstLength
62967+| | | |-- HeaderDigest
62968+| | | |-- ImmediateData
62969+| | | |-- InitialR2T
62970+| | | |-- MaxBurstLength
62971+| | | |-- MaxOutstandingR2T
62972+| | | |-- MaxRecvDataSegmentLength
62973+| | | |-- MaxXmitDataSegmentLength
62974+| | | |-- active_commands
62975+| | | |-- commands
62976+| | | |-- force_close
62977+| | | |-- initiator_name
62978+| | | |-- luns -> ../../luns
62979+| | | |-- reinstating
62980+| | | `-- sid
62981+| | `-- tid
62982+| |-- iqn.2006-10.net.vlnb:tgt1
62983+| | |-- DataDigest
62984+| | |-- FirstBurstLength
62985+| | |-- HeaderDigest
62986+| | |-- ImmediateData
62987+| | |-- IncomingUser
62988+| | |-- IncomingUser1
62989+| | |-- InitialR2T
62990+| | |-- MaxBurstLength
62991+| | |-- MaxOutstandingR2T
62992+| | |-- MaxRecvDataSegmentLength
62993+| | |-- MaxXmitDataSegmentLength
62994+| | |-- OutgoingUser
62995+| | |-- NopInInterval
62996+| | |-- QueuedCommands
62997+| | |-- RspTimeout
62998+| | |-- enabled
62999+| | |-- ini_groups
63000+| | | |-- mgmt
63001+| | | `-- special_ini
63002+| | | |-- initiators
63003+| | | | |-- iqn.2005-03.org.open-iscsi:cacdcd2520
63004+| | | | `-- mgmt
63005+| | | `-- luns
63006+| | | |-- 0
63007+| | | | |-- device -> ../../../../../../../devices/blockio
63008+| | | | `-- read_only
63009+| | | `-- mgmt
63010+| | |-- luns
63011+| | | |-- 0
63012+| | | | |-- device -> ../../../../../devices/disk2
63013+| | | | `-- read_only
63014+| | | |-- 26
63015+| | | | |-- device -> ../../../../../devices/nullio
63016+| | | | `-- read_only
63017+| | | `-- mgmt
63018+| | |-- per_portal_acl
63019+| | |-- redirect
63020+| | |-- rel_tgt_id
63021+| | |-- sessions
63022+| | | `-- iqn.2005-03.org.open-iscsi:cacdcd2520
63023+| | | |-- 10.170.75.2
63024+| | | | |-- cid
63025+| | | | |-- ip
63026+| | | | `-- state
63027+| | | |-- DataDigest
63028+| | | |-- FirstBurstLength
63029+| | | |-- HeaderDigest
63030+| | | |-- ImmediateData
63031+| | | |-- InitialR2T
63032+| | | |-- MaxBurstLength
63033+| | | |-- MaxOutstandingR2T
63034+| | | |-- MaxRecvDataSegmentLength
63035+| | | |-- MaxXmitDataSegmentLength
63036+| | | |-- active_commands
63037+| | | |-- commands
63038+| | | |-- force_close
63039+| | | |-- initiator_name
63040+| | | |-- luns -> ../../ini_groups/special_ini/luns
63041+| | | |-- reinstating
63042+| | | `-- sid
63043+| | `-- tid
63044+| |-- mgmt
63045+| |-- open_state
63046+| |-- trace_level
63047+| `-- version
63048+|-- threads
63049+|-- trace_level
63050+`-- version
63051+
63052+Advanced initiators access control
63053+----------------------------------
63054+
63055+ISCSI-SCST allows you to optionally control visibility and accessibility
63056+of your target and its portals (IP addresses) to remote initiators. This
63057+control includes both the target's portals SendTargets discovery as well
63058+as regular LUNs access.
63059+
63060+This facility supersedes the obsolete initiators.[allow,deny] method,
63061+which is going to be removed in one of the future versions.
63062+
63063+This facility is available only in the sysfs build of iSCSI-SCST.
63064+
63065+By default, all portals are available for the initiators.
63066+
63067+1. If you want to enable/disable one or more target's portals for all
63068+initiators, you should define one ore more allowed_portal attributes.
63069+For example:
63070+
63071+echo 'add_target_attribute iqn.2006-10.net.vlnb:tgt allowed_portal 10.170.77.2' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
63072+
63073+will enable only portal 10.170.77.2 and disable all other portals
63074+
63075+echo 'add_target_attribute iqn.2006-10.net.vlnb:tgt allowed_portal 10.170.77.2' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
63076+echo 'add_target_attribute iqn.2006-10.net.vlnb:tgt allowed_portal 10.170.75.2' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
63077+
63078+will enable only portals 10.170.77.2 and 10.170.75.2 and disable all
63079+other portals.
63080+
63081+echo 'add_target_attribute iqn.2006-10.net.vlnb:tgt allowed_portal 10.170.7?.2' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
63082+
63083+will enable only portals 10.170.7x.2 and disable all other portals.
63084+
63085+echo 'add_target_attribute iqn.2006-10.net.vlnb:tgt allowed_portal !*' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
63086+
63087+will disable all portals.
63088+
63089+2. If you want to want to allow only only specific set of initiators be
63090+able to connect to your target, you should don't add any default LUNs
63091+for the target and create for allowed initiators a security group to
63092+which they will be assigned.
63093+
63094+For example, we want initiator iqn.2005-03.org.vlnb:cacdcd2520 and only
63095+it be able to access target iqn.2006-10.net.vlnb:tgt:
63096+
63097+echo 'add_target iqn.2006-10.net.vlnb:tgt' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
63098+echo 'create allowed_ini' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/mgmt
63099+echo 'add dev1 0' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/allowed_ini/luns/mgmt
63100+echo 'add iqn.2005-03.org.vlnb:cacdcd2520' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/allowed_ini/initiators/mgmt
63101+echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
63102+
63103+Since there will be no default LUNs for the target, all initiators other
63104+than iqn.2005-03.org.vlnb:cacdcd2520 will be blocked from accessing it.
63105+
63106+Alternatively, you can create an empty security group and filter out in
63107+it all initiators except the allowed one:
63108+
63109+echo 'add_target iqn.2006-10.net.vlnb:tgt' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
63110+echo 'add dev1 0' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
63111+echo 'create denied_inis' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/mgmt
63112+echo 'add !iqn.2005-03.org.vlnb:cacdcd2520' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/denied_inis/initiators/mgmt
63113+echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
63114+
63115+3. If you want to enable/disable one or more target's portals for
63116+particular initiators, you should set per_portal_acl attribute to 1 and
63117+specify SCST access control to those initiators. If an SCST security
63118+group doesn't have any LUNs, all the initiator, which should be assigned
63119+to it, will not see this target and/or its portal. For example:
63120+
63121+(We assume that an empty group "BLOCKING_GROUP" is already created by for
63122+target iqn.2006-10.net.vlnb:tgt by command (see above for more information):
63123+"echo 'create BLOCKING_GROUP' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/mgmt)
63124+
63125+echo 'add iqn.2005-03.org.vlnb:cacdcd2520#10.170.77.2' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/BLOCKING_GROUP/initiators/mgmt
63126+
63127+will block access of initiator iqn.2005-03.org.vlnb:cacdcd2520 to
63128+target iqn.2006-10.net.vlnb:tgt portal 10.170.77.2.
63129+
63130+Another example:
63131+
63132+echo 'add iqn.2005-03.org.vlnb:cacdcd2520*' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/BLOCKING_GROUP/initiators/mgmt
63133+
63134+will block access of initiator iqn.2005-03.org.vlnb:cacdcd2520 to
63135+all target iqn.2006-10.net.vlnb:tgt portals.
63136+
63137+Troubleshooting
63138+---------------
63139+
63140+If you have any problems, start troubleshooting from looking at the
63141+kernel and system logs. In the kernel log iSCSI-SCST and SCST core send
63142+their messages, in the system log iscsi-scstd sends its messages. In
63143+most Linux distributions both those logs are put to /var/log/messages
63144+file.
63145+
63146+Then, it might be helpful to increase level of logging. For kernel
63147+modules you should make the debug build by enabling CONFIG_SCST_DEBUG.
63148+
63149+If after looking on the logs the reason of your problem is still unclear
63150+for you, report to SCST mailing list scst-devel@lists.sourceforge.net.
63151+
63152+Work if target's backstorage or link is too slow
63153+------------------------------------------------
63154+
63155+In some cases you can experience I/O stalls or see in the kernel log
63156+abort or reset messages. It can happen under high I/O load, when your
63157+target's backstorage gets overloaded, or working over a slow link, when
63158+the link can't serve all the queued commands on time,
63159+
63160+To workaround it you can reduce QueuedCommands parameter for the
63161+corresponding target to some lower value, like 8 (default is 32).
63162+
63163+Also see SCST README file for more details about that issue and ways to
63164+prevent it.
63165+
63166+Performance advices
63167+-------------------
63168+
63169+1. If you use Windows XP or Windows 2003+ as initiators, you can
63170+consider to decrease TcpAckFrequency parameter to 1. See
63171+http://support.microsoft.com/kb/328890/ or google for "TcpAckFrequency"
63172+for more details.
63173+
63174+2. See how to get the maximum throughput from iSCSI, for instance, at
63175+http://virtualgeek.typepad.com/virtual_geek/2009/01/a-multivendor-post-to-help-our-mutual-iscsi-customers-using-vmware.html.
63176+It's about VMware, but its recommendations apply to other environments
63177+as well.
63178+
63179+3. ISCSI initiators built in pre-CentOS/RHEL 5 reported to have some
63180+performance problems. If you use it, it is strongly advised to upgrade.
63181+
63182+4. If you are going to use your target in an VM environment, for
63183+instance as a shared storage with VMware, make sure all your VMs
63184+connected to the target via *separate* sessions, i.e. each VM has own
63185+connection to the target, not all VMs connected using a single
63186+connection. You can check it using SCST sysfs interface. If you
63187+miss it, you can greatly loose performance of parallel access to your
63188+target from different VMs. This isn't related to the case if your VMs
63189+are using the same shared storage, like with VMFS, for instance. In this
63190+case all your VM hosts will be connected to the target via separate
63191+sessions, which is enough.
63192+
63193+5. Many dual port network adapters are not able to transfer data
63194+simultaneously on both ports, i.e. they transfer data via both ports on
63195+the same speed as via any single port. Thus, using such adapters in MPIO
63196+configuration can't improve performance. To allow MPIO to have double
63197+performance you should either use separate network adapters, or find a
63198+dual-port adapter capable to to transfer data simultaneously on both
63199+ports. You can check it by running 2 iperf's through both ports in
63200+parallel.
63201+
63202+6. Since network offload works much better in the write direction, than
63203+for reading (simplifying, in the read direction often there's additional
63204+data copy) in many cases with 10GbE in a single initiator-target pair
63205+the initiator's CPU is a bottleneck, so you can see the initiator can
63206+read data on much slower rate, than write. You can check it by watching
63207+*each particular* CPU load to find out if any of them is close to 100%
63208+load, including IRQ processing load. Note, many tools like vmstat give
63209+aggregate load on all CPUs, so with 4 cores 25% corresponds to 100% load
63210+of any single CPU.
63211+
63212+7. See SCST core's README for more advices. Especially pay attention to
63213+have io_grouping_type option set correctly.
63214+
63215+Compilation options
63216+-------------------
63217+
63218+There are the following compilation options, that could be commented
63219+in/out in the kernel's module Makefile:
63220+
63221+ - CONFIG_SCST_DEBUG - turns on some debugging code, including some logging.
63222+ Makes the driver considerably bigger and slower, producing large amount of
63223+ log data.
63224+
63225+ - CONFIG_SCST_TRACING - turns on ability to log events. Makes the driver
63226+ considerably bigger and leads to some performance loss.
63227+
63228+ - CONFIG_SCST_EXTRACHECKS - adds extra validity checks in the various places.
63229+
63230+ - CONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES - simulates digest failures in
63231+ random places.
63232+
63233+Credits
63234+-------
63235+
63236+Thanks to:
63237+
63238+ * Ming Zhang <blackmagic02881@gmail.com> for fixes
63239+
63240+ * Krzysztof Blaszkowski <kb@sysmikro.com.pl> for many fixes
63241+
63242+ * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> for comments and help in
63243+ debugging
63244+
63245+ * Tomasz Chmielewski <mangoo@wpkg.org> for testing and suggestions
63246+
63247+ * Bart Van Assche <bart.vanassche@gmail.com> for a lot of help
63248+
63249+Vladislav Bolkhovitin <vst@vlnb.net>, http://scst.sourceforge.net
63250+
63251diff -uprN orig/linux-2.6.35/drivers/scsi/qla2xxx/qla2x_tgt.h linux-2.6.35/drivers/scsi/qla2xxx/qla2x_tgt.h
63252--- orig/linux-2.6.35/drivers/scsi/qla2xxx/qla2x_tgt.h
63253+++ linux-2.6.35/drivers/scsi/qla2xxx/qla2x_tgt.h
63254@@ -0,0 +1,131 @@
63255+/*
63256+ * qla2x_tgt.h
63257+ *
63258+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
63259+ * Copyright (C) 2004 - 2005 Leonid Stoljar
63260+ * Copyright (C) 2006 Nathaniel Clark <nate@misrule.us>
63261+ * Copyright (C) 2007 - 2010 ID7 Ltd.
63262+ *
63263+ * Additional file for the target driver support.
63264+ *
63265+ * This program is free software; you can redistribute it and/or
63266+ * modify it under the terms of the GNU General Public License
63267+ * as published by the Free Software Foundation; either version 2
63268+ * of the License, or (at your option) any later version.
63269+ *
63270+ * This program is distributed in the hope that it will be useful,
63271+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
63272+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63273+ * GNU General Public License for more details.
63274+ */
63275+/*
63276+ * This should be included only from within qla2xxx module.
63277+ */
63278+
63279+#ifndef __QLA2X_TGT_H
63280+#define __QLA2X_TGT_H
63281+
63282+extern request_t *qla2x00_req_pkt(scsi_qla_host_t *ha);
63283+
63284+#ifdef CONFIG_SCSI_QLA2XXX_TARGET
63285+
63286+#include "qla2x_tgt_def.h"
63287+
63288+extern struct qla_tgt_data qla_target;
63289+
63290+void qla_set_tgt_mode(scsi_qla_host_t *ha);
63291+void qla_clear_tgt_mode(scsi_qla_host_t *ha);
63292+
63293+static inline bool qla_tgt_mode_enabled(scsi_qla_host_t *ha)
63294+{
63295+ return ha->host->active_mode & MODE_TARGET;
63296+}
63297+
63298+static inline bool qla_ini_mode_enabled(scsi_qla_host_t *ha)
63299+{
63300+ return ha->host->active_mode & MODE_INITIATOR;
63301+}
63302+
63303+static inline void qla_reverse_ini_mode(scsi_qla_host_t *ha)
63304+{
63305+ if (ha->host->active_mode & MODE_INITIATOR)
63306+ ha->host->active_mode &= ~MODE_INITIATOR;
63307+ else
63308+ ha->host->active_mode |= MODE_INITIATOR;
63309+}
63310+
63311+/********************************************************************\
63312+ * ISP Queue types left out of new QLogic driver (from old version)
63313+\********************************************************************/
63314+
63315+/*
63316+ * qla2x00_do_en_dis_lun
63317+ * Issue enable or disable LUN entry IOCB.
63318+ *
63319+ * Input:
63320+ * ha = adapter block pointer.
63321+ *
63322+ * Caller MUST have hardware lock held. This function might release it,
63323+ * then reaquire.
63324+ */
63325+static inline void
63326+__qla2x00_send_enable_lun(scsi_qla_host_t *ha, int enable)
63327+{
63328+ elun_entry_t *pkt;
63329+
63330+ BUG_ON(IS_FWI2_CAPABLE(ha));
63331+
63332+ pkt = (elun_entry_t *)qla2x00_req_pkt(ha);
63333+ if (pkt != NULL) {
63334+ pkt->entry_type = ENABLE_LUN_TYPE;
63335+ if (enable) {
63336+ pkt->command_count = QLA2X00_COMMAND_COUNT_INIT;
63337+ pkt->immed_notify_count = QLA2X00_IMMED_NOTIFY_COUNT_INIT;
63338+ pkt->timeout = 0xffff;
63339+ } else {
63340+ pkt->command_count = 0;
63341+ pkt->immed_notify_count = 0;
63342+ pkt->timeout = 0;
63343+ }
63344+ DEBUG2(printk(KERN_DEBUG
63345+ "scsi%lu:ENABLE_LUN IOCB imm %u cmd %u timeout %u\n",
63346+ ha->host_no, pkt->immed_notify_count,
63347+ pkt->command_count, pkt->timeout));
63348+
63349+ /* Issue command to ISP */
63350+ qla2x00_isp_cmd(ha);
63351+
63352+ } else
63353+ qla_clear_tgt_mode(ha);
63354+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
63355+ if (!pkt)
63356+ printk(KERN_ERR "%s: **** FAILED ****\n", __func__);
63357+#endif
63358+
63359+ return;
63360+}
63361+
63362+/*
63363+ * qla2x00_send_enable_lun
63364+ * Issue enable LUN entry IOCB.
63365+ *
63366+ * Input:
63367+ * ha = adapter block pointer.
63368+ * enable = enable/disable flag.
63369+ */
63370+static inline void
63371+qla2x00_send_enable_lun(scsi_qla_host_t *ha, bool enable)
63372+{
63373+ if (!IS_FWI2_CAPABLE(ha)) {
63374+ unsigned long flags;
63375+ spin_lock_irqsave(&ha->hardware_lock, flags);
63376+ __qla2x00_send_enable_lun(ha, enable);
63377+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
63378+ }
63379+}
63380+
63381+extern void qla2xxx_add_targets(void);
63382+
63383+#endif /* CONFIG_SCSI_QLA2XXX_TARGET */
63384+
63385+#endif /* __QLA2X_TGT_H */
63386diff -uprN orig/linux-2.6.35/drivers/scsi/qla2xxx/qla2x_tgt_def.h linux-2.6.35/drivers/scsi/qla2xxx/qla2x_tgt_def.h
63387--- orig/linux-2.6.35/drivers/scsi/qla2xxx/qla2x_tgt_def.h
63388+++ linux-2.6.35/drivers/scsi/qla2xxx/qla2x_tgt_def.h
63389@@ -0,0 +1,729 @@
63390+/*
63391+ * qla2x_tgt_def.h
63392+ *
63393+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
63394+ * Copyright (C) 2004 - 2005 Leonid Stoljar
63395+ * Copyright (C) 2006 Nathaniel Clark <nate@misrule.us>
63396+ * Copyright (C) 2007 - 2010 ID7 Ltd.
63397+ *
63398+ * Additional file for the target driver support.
63399+ *
63400+ * This program is free software; you can redistribute it and/or
63401+ * modify it under the terms of the GNU General Public License
63402+ * as published by the Free Software Foundation; either version 2
63403+ * of the License, or (at your option) any later version.
63404+ *
63405+ * This program is distributed in the hope that it will be useful,
63406+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
63407+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63408+ * GNU General Public License for more details.
63409+ */
63410+/*
63411+ * This is the global def file that is useful for including from the
63412+ * target portion.
63413+ */
63414+
63415+#ifndef __QLA2X_TGT_DEF_H
63416+#define __QLA2X_TGT_DEF_H
63417+
63418+#include "qla_def.h"
63419+
63420+#ifndef CONFIG_SCSI_QLA2XXX_TARGET
63421+#error __FILE__ " included without CONFIG_SCSI_QLA2XXX_TARGET"
63422+#endif
63423+
63424+#ifndef ENTER
63425+#define ENTER(a)
63426+#endif
63427+
63428+#ifndef LEAVE
63429+#define LEAVE(a)
63430+#endif
63431+
63432+/*
63433+ * Must be changed on any change in any initiator visible interfaces or
63434+ * data in the target add-on
63435+ */
63436+#define QLA2X_TARGET_MAGIC 267
63437+
63438+/*
63439+ * Must be changed on any change in any target visible interfaces or
63440+ * data in the initiator
63441+ */
63442+#define QLA2X_INITIATOR_MAGIC 57319
63443+
63444+#define QLA2X_INI_MODE_STR_EXCLUSIVE "exclusive"
63445+#define QLA2X_INI_MODE_STR_DISABLED "disabled"
63446+#define QLA2X_INI_MODE_STR_ENABLED "enabled"
63447+
63448+#define QLA2X_INI_MODE_EXCLUSIVE 0
63449+#define QLA2X_INI_MODE_DISABLED 1
63450+#define QLA2X_INI_MODE_ENABLED 2
63451+
63452+#define QLA2X00_COMMAND_COUNT_INIT 250
63453+#define QLA2X00_IMMED_NOTIFY_COUNT_INIT 250
63454+
63455+/*
63456+ * Used to mark which completion handles (for RIO Status's) are for CTIO's
63457+ * vs. regular (non-target) info. This is checked for in
63458+ * qla2x00_process_response_queue() to see if a handle coming back in a
63459+ * multi-complete should come to the tgt driver or be handled there by qla2xxx
63460+ */
63461+#define CTIO_COMPLETION_HANDLE_MARK BIT_29
63462+#if (CTIO_COMPLETION_HANDLE_MARK <= MAX_OUTSTANDING_COMMANDS)
63463+#error "Hackish CTIO_COMPLETION_HANDLE_MARK no longer larger than MAX_OUTSTANDING_COMMANDS"
63464+#endif
63465+#define HANDLE_IS_CTIO_COMP(h) (h & CTIO_COMPLETION_HANDLE_MARK)
63466+
63467+/* Used to mark CTIO as intermediate */
63468+#define CTIO_INTERMEDIATE_HANDLE_MARK BIT_30
63469+
63470+#ifndef OF_SS_MODE_0
63471+/*
63472+ * ISP target entries - Flags bit definitions.
63473+ */
63474+#define OF_SS_MODE_0 0
63475+#define OF_SS_MODE_1 1
63476+#define OF_SS_MODE_2 2
63477+#define OF_SS_MODE_3 3
63478+
63479+#define OF_EXPL_CONF BIT_5 /* Explicit Confirmation Requested */
63480+#define OF_DATA_IN BIT_6 /* Data in to initiator */
63481+ /* (data from target to initiator) */
63482+#define OF_DATA_OUT BIT_7 /* Data out from initiator */
63483+ /* (data from initiator to target) */
63484+#define OF_NO_DATA (BIT_7 | BIT_6)
63485+#define OF_INC_RC BIT_8 /* Increment command resource count */
63486+#define OF_FAST_POST BIT_9 /* Enable mailbox fast posting. */
63487+#define OF_CONF_REQ BIT_13 /* Confirmation Requested */
63488+#define OF_TERM_EXCH BIT_14 /* Terminate exchange */
63489+#define OF_SSTS BIT_15 /* Send SCSI status */
63490+#endif
63491+
63492+#ifndef DATASEGS_PER_COMMAND32
63493+#define DATASEGS_PER_COMMAND32 3
63494+#define DATASEGS_PER_CONT32 7
63495+#define QLA_MAX_SG32(ql) \
63496+ (((ql) > 0) ? (DATASEGS_PER_COMMAND32 + DATASEGS_PER_CONT32*((ql) - 1)) : 0)
63497+
63498+#define DATASEGS_PER_COMMAND64 2
63499+#define DATASEGS_PER_CONT64 5
63500+#define QLA_MAX_SG64(ql) \
63501+ (((ql) > 0) ? (DATASEGS_PER_COMMAND64 + DATASEGS_PER_CONT64*((ql) - 1)) : 0)
63502+#endif
63503+
63504+#ifndef DATASEGS_PER_COMMAND_24XX
63505+#define DATASEGS_PER_COMMAND_24XX 1
63506+#define DATASEGS_PER_CONT_24XX 5
63507+#define QLA_MAX_SG_24XX(ql) \
63508+ (min(1270, ((ql) > 0) ? (DATASEGS_PER_COMMAND_24XX + DATASEGS_PER_CONT_24XX*((ql) - 1)) : 0))
63509+#endif
63510+
63511+/********************************************************************\
63512+ * ISP Queue types left out of new QLogic driver (from old version)
63513+\********************************************************************/
63514+
63515+#ifndef ENABLE_LUN_TYPE
63516+#define ENABLE_LUN_TYPE 0x0B /* Enable LUN entry. */
63517+/*
63518+ * ISP queue - enable LUN entry structure definition.
63519+ */
63520+typedef struct {
63521+ uint8_t entry_type; /* Entry type. */
63522+ uint8_t entry_count; /* Entry count. */
63523+ uint8_t sys_define; /* System defined. */
63524+ uint8_t entry_status; /* Entry Status. */
63525+ uint32_t sys_define_2; /* System defined. */
63526+ uint8_t reserved_8;
63527+ uint8_t reserved_1;
63528+ uint16_t reserved_2;
63529+ uint32_t reserved_3;
63530+ uint8_t status;
63531+ uint8_t reserved_4;
63532+ uint8_t command_count; /* Number of ATIOs allocated. */
63533+ uint8_t immed_notify_count; /* Number of Immediate Notify entries allocated. */
63534+ uint16_t reserved_5;
63535+ uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
63536+ uint16_t reserved_6[20];
63537+} __attribute__((packed)) elun_entry_t;
63538+#define ENABLE_LUN_SUCCESS 0x01
63539+#define ENABLE_LUN_RC_NONZERO 0x04
63540+#define ENABLE_LUN_INVALID_REQUEST 0x06
63541+#define ENABLE_LUN_ALREADY_ENABLED 0x3E
63542+#endif
63543+
63544+#ifndef MODIFY_LUN_TYPE
63545+#define MODIFY_LUN_TYPE 0x0C /* Modify LUN entry. */
63546+/*
63547+ * ISP queue - modify LUN entry structure definition.
63548+ */
63549+typedef struct {
63550+ uint8_t entry_type; /* Entry type. */
63551+ uint8_t entry_count; /* Entry count. */
63552+ uint8_t sys_define; /* System defined. */
63553+ uint8_t entry_status; /* Entry Status. */
63554+ uint32_t sys_define_2; /* System defined. */
63555+ uint8_t reserved_8;
63556+ uint8_t reserved_1;
63557+ uint8_t operators;
63558+ uint8_t reserved_2;
63559+ uint32_t reserved_3;
63560+ uint8_t status;
63561+ uint8_t reserved_4;
63562+ uint8_t command_count; /* Number of ATIOs allocated. */
63563+ uint8_t immed_notify_count; /* Number of Immediate Notify */
63564+ /* entries allocated. */
63565+ uint16_t reserved_5;
63566+ uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
63567+ uint16_t reserved_7[20];
63568+} __attribute__((packed)) modify_lun_entry_t;
63569+#define MODIFY_LUN_SUCCESS 0x01
63570+#define MODIFY_LUN_CMD_ADD BIT_0
63571+#define MODIFY_LUN_CMD_SUB BIT_1
63572+#define MODIFY_LUN_IMM_ADD BIT_2
63573+#define MODIFY_LUN_IMM_SUB BIT_3
63574+#endif
63575+
63576+#define GET_TARGET_ID(ha, iocb) ((HAS_EXTENDED_IDS(ha)) \
63577+ ? le16_to_cpu((iocb)->target.extended) \
63578+ : (uint16_t)(iocb)->target.id.standard)
63579+
63580+#ifndef IMMED_NOTIFY_TYPE
63581+#define IMMED_NOTIFY_TYPE 0x0D /* Immediate notify entry. */
63582+/*
63583+ * ISP queue - immediate notify entry structure definition.
63584+ */
63585+typedef struct {
63586+ uint8_t entry_type; /* Entry type. */
63587+ uint8_t entry_count; /* Entry count. */
63588+ uint8_t sys_define; /* System defined. */
63589+ uint8_t entry_status; /* Entry Status. */
63590+ uint32_t sys_define_2; /* System defined. */
63591+ target_id_t target;
63592+ uint16_t lun;
63593+ uint8_t target_id;
63594+ uint8_t reserved_1;
63595+ uint16_t status_modifier;
63596+ uint16_t status;
63597+ uint16_t task_flags;
63598+ uint16_t seq_id;
63599+ uint16_t srr_rx_id;
63600+ uint32_t srr_rel_offs;
63601+ uint16_t srr_ui;
63602+#define SRR_IU_DATA_IN 0x1
63603+#define SRR_IU_DATA_OUT 0x5
63604+#define SRR_IU_STATUS 0x7
63605+ uint16_t srr_ox_id;
63606+ uint8_t reserved_2[30];
63607+ uint16_t ox_id;
63608+} __attribute__((packed)) notify_entry_t;
63609+#endif
63610+
63611+#ifndef NOTIFY_ACK_TYPE
63612+#define NOTIFY_ACK_TYPE 0x0E /* Notify acknowledge entry. */
63613+/*
63614+ * ISP queue - notify acknowledge entry structure definition.
63615+ */
63616+typedef struct {
63617+ uint8_t entry_type; /* Entry type. */
63618+ uint8_t entry_count; /* Entry count. */
63619+ uint8_t sys_define; /* System defined. */
63620+ uint8_t entry_status; /* Entry Status. */
63621+ uint32_t sys_define_2; /* System defined. */
63622+ target_id_t target;
63623+ uint8_t target_id;
63624+ uint8_t reserved_1;
63625+ uint16_t flags;
63626+ uint16_t resp_code;
63627+ uint16_t status;
63628+ uint16_t task_flags;
63629+ uint16_t seq_id;
63630+ uint16_t srr_rx_id;
63631+ uint32_t srr_rel_offs;
63632+ uint16_t srr_ui;
63633+ uint16_t srr_flags;
63634+ uint16_t srr_reject_code;
63635+ uint8_t srr_reject_vendor_uniq;
63636+ uint8_t srr_reject_code_expl;
63637+ uint8_t reserved_2[26];
63638+ uint16_t ox_id;
63639+} __attribute__((packed)) nack_entry_t;
63640+#define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0
63641+#define NOTIFY_ACK_SRR_FLAGS_REJECT 1
63642+
63643+#define NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM 0x9
63644+
63645+#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL 0
63646+#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_UNABLE_TO_SUPPLY_DATA 0x2a
63647+
63648+#define NOTIFY_ACK_SUCCESS 0x01
63649+#endif
63650+
63651+#ifndef ACCEPT_TGT_IO_TYPE
63652+#define ACCEPT_TGT_IO_TYPE 0x16 /* Accept target I/O entry. */
63653+/*
63654+ * ISP queue - Accept Target I/O (ATIO) entry structure definition.
63655+ */
63656+typedef struct {
63657+ uint8_t entry_type; /* Entry type. */
63658+ uint8_t entry_count; /* Entry count. */
63659+ uint8_t sys_define; /* System defined. */
63660+ uint8_t entry_status; /* Entry Status. */
63661+ uint32_t sys_define_2; /* System defined. */
63662+ target_id_t target;
63663+ uint16_t rx_id;
63664+ uint16_t flags;
63665+ uint16_t status;
63666+ uint8_t command_ref;
63667+ uint8_t task_codes;
63668+ uint8_t task_flags;
63669+ uint8_t execution_codes;
63670+ uint8_t cdb[MAX_CMDSZ];
63671+ uint32_t data_length;
63672+ uint16_t lun;
63673+ uint8_t initiator_port_name[WWN_SIZE]; /* on qla23xx */
63674+ uint16_t reserved_32[6];
63675+ uint16_t ox_id;
63676+} __attribute__((packed)) atio_entry_t;
63677+#endif
63678+
63679+#ifndef CONTINUE_TGT_IO_TYPE
63680+#define CONTINUE_TGT_IO_TYPE 0x17
63681+/*
63682+ * ISP queue - Continue Target I/O (CTIO) entry for status mode 0
63683+ * structure definition.
63684+ */
63685+typedef struct {
63686+ uint8_t entry_type; /* Entry type. */
63687+ uint8_t entry_count; /* Entry count. */
63688+ uint8_t sys_define; /* System defined. */
63689+ uint8_t entry_status; /* Entry Status. */
63690+ uint32_t handle; /* System defined handle */
63691+ target_id_t target;
63692+ uint16_t rx_id;
63693+ uint16_t flags;
63694+ uint16_t status;
63695+ uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
63696+ uint16_t dseg_count; /* Data segment count. */
63697+ uint32_t relative_offset;
63698+ uint32_t residual;
63699+ uint16_t reserved_1[3];
63700+ uint16_t scsi_status;
63701+ uint32_t transfer_length;
63702+ uint32_t dseg_0_address[0];
63703+} __attribute__((packed)) ctio_common_entry_t;
63704+#define ATIO_PATH_INVALID 0x07
63705+#define ATIO_CANT_PROV_CAP 0x16
63706+#define ATIO_CDB_VALID 0x3D
63707+
63708+#define ATIO_EXEC_READ BIT_1
63709+#define ATIO_EXEC_WRITE BIT_0
63710+#endif
63711+
63712+#ifndef CTIO_A64_TYPE
63713+#define CTIO_A64_TYPE 0x1F
63714+typedef struct {
63715+ ctio_common_entry_t common;
63716+ uint32_t dseg_0_address; /* Data segment 0 address. */
63717+ uint32_t dseg_0_length; /* Data segment 0 length. */
63718+ uint32_t dseg_1_address; /* Data segment 1 address. */
63719+ uint32_t dseg_1_length; /* Data segment 1 length. */
63720+ uint32_t dseg_2_address; /* Data segment 2 address. */
63721+ uint32_t dseg_2_length; /* Data segment 2 length. */
63722+} __attribute__((packed)) ctio_entry_t;
63723+#define CTIO_SUCCESS 0x01
63724+#define CTIO_ABORTED 0x02
63725+#define CTIO_INVALID_RX_ID 0x08
63726+#define CTIO_TIMEOUT 0x0B
63727+#define CTIO_LIP_RESET 0x0E
63728+#define CTIO_TARGET_RESET 0x17
63729+#define CTIO_PORT_UNAVAILABLE 0x28
63730+#define CTIO_PORT_LOGGED_OUT 0x29
63731+#define CTIO_PORT_CONF_CHANGED 0x2A
63732+#define CTIO_SRR_RECEIVED 0x45
63733+
63734+#endif
63735+
63736+#ifndef CTIO_RET_TYPE
63737+#define CTIO_RET_TYPE 0x17 /* CTIO return entry */
63738+/*
63739+ * ISP queue - CTIO returned entry structure definition.
63740+ */
63741+typedef struct {
63742+ uint8_t entry_type; /* Entry type. */
63743+ uint8_t entry_count; /* Entry count. */
63744+ uint8_t sys_define; /* System defined. */
63745+ uint8_t entry_status; /* Entry Status. */
63746+ uint32_t handle; /* System defined handle. */
63747+ target_id_t target;
63748+ uint16_t rx_id;
63749+ uint16_t flags;
63750+ uint16_t status;
63751+ uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
63752+ uint16_t dseg_count; /* Data segment count. */
63753+ uint32_t relative_offset;
63754+ uint32_t residual;
63755+ uint16_t reserved_1[2];
63756+ uint16_t sense_length;
63757+ uint16_t scsi_status;
63758+ uint16_t response_length;
63759+ uint8_t sense_data[26];
63760+} __attribute__((packed)) ctio_ret_entry_t;
63761+#endif
63762+
63763+#define ATIO_TYPE7 0x06 /* Accept target I/O entry for 24xx */
63764+
63765+typedef struct {
63766+ uint8_t r_ctl;
63767+ uint8_t d_id[3];
63768+ uint8_t cs_ctl;
63769+ uint8_t s_id[3];
63770+ uint8_t type;
63771+ uint8_t f_ctl[3];
63772+ uint8_t seq_id;
63773+ uint8_t df_ctl;
63774+ uint16_t seq_cnt;
63775+ uint16_t ox_id;
63776+ uint16_t rx_id;
63777+ uint32_t parameter;
63778+} __attribute__((packed)) fcp_hdr_t;
63779+
63780+typedef struct {
63781+ uint8_t d_id[3];
63782+ uint8_t r_ctl;
63783+ uint8_t s_id[3];
63784+ uint8_t cs_ctl;
63785+ uint8_t f_ctl[3];
63786+ uint8_t type;
63787+ uint16_t seq_cnt;
63788+ uint8_t df_ctl;
63789+ uint8_t seq_id;
63790+ uint16_t rx_id;
63791+ uint16_t ox_id;
63792+ uint32_t parameter;
63793+} __attribute__((packed)) fcp_hdr_le_t;
63794+
63795+#define F_CTL_EXCH_CONTEXT_RESP BIT_23
63796+#define F_CTL_SEQ_CONTEXT_RESIP BIT_22
63797+#define F_CTL_LAST_SEQ BIT_20
63798+#define F_CTL_END_SEQ BIT_19
63799+#define F_CTL_SEQ_INITIATIVE BIT_16
63800+
63801+#define R_CTL_BASIC_LINK_SERV 0x80
63802+#define R_CTL_B_ACC 0x4
63803+#define R_CTL_B_RJT 0x5
63804+
63805+typedef struct {
63806+ uint64_t lun;
63807+ uint8_t cmnd_ref;
63808+ uint8_t task_attr:3;
63809+ uint8_t reserved:5;
63810+ uint8_t task_mgmt_flags;
63811+#define FCP_CMND_TASK_MGMT_CLEAR_ACA 6
63812+#define FCP_CMND_TASK_MGMT_TARGET_RESET 5
63813+#define FCP_CMND_TASK_MGMT_LU_RESET 4
63814+#define FCP_CMND_TASK_MGMT_CLEAR_TASK_SET 2
63815+#define FCP_CMND_TASK_MGMT_ABORT_TASK_SET 1
63816+ uint8_t wrdata:1;
63817+ uint8_t rddata:1;
63818+ uint8_t add_cdb_len:6;
63819+ uint8_t cdb[16];
63820+ /* Valid only if add_cdb_len=0, otherwise this is additional CDB data */
63821+ uint32_t data_length;
63822+} __attribute__((packed)) fcp_cmnd_t;
63823+
63824+/*
63825+ * ISP queue - Accept Target I/O (ATIO) type 7 entry for 24xx structure
63826+ * definition.
63827+ */
63828+typedef struct {
63829+ uint8_t entry_type; /* Entry type. */
63830+ uint8_t entry_count; /* Entry count. */
63831+ uint8_t fcp_cmnd_len_low;
63832+ uint8_t fcp_cmnd_len_high:4;
63833+ uint8_t attr:4;
63834+ uint32_t exchange_addr;
63835+#define ATIO_EXCHANGE_ADDRESS_UNKNOWN 0xFFFFFFFF
63836+ fcp_hdr_t fcp_hdr;
63837+ fcp_cmnd_t fcp_cmnd;
63838+} __attribute__((packed)) atio7_entry_t;
63839+
63840+#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */
63841+
63842+/*
63843+ * ISP queue - Continue Target I/O (ATIO) type 7 entry (for 24xx) structure
63844+ * definition.
63845+ */
63846+
63847+typedef struct {
63848+ uint8_t entry_type; /* Entry type. */
63849+ uint8_t entry_count; /* Entry count. */
63850+ uint8_t sys_define; /* System defined. */
63851+ uint8_t entry_status; /* Entry Status. */
63852+ uint32_t handle; /* System defined handle */
63853+ uint16_t nport_handle;
63854+#define CTIO7_NHANDLE_UNRECOGNIZED 0xFFFF
63855+ uint16_t timeout;
63856+ uint16_t dseg_count; /* Data segment count. */
63857+ uint8_t vp_index;
63858+ uint8_t add_flags;
63859+ uint8_t initiator_id[3];
63860+ uint8_t reserved;
63861+ uint32_t exchange_addr;
63862+} __attribute__((packed)) ctio7_common_entry_t;
63863+
63864+typedef struct {
63865+ ctio7_common_entry_t common;
63866+ uint16_t reserved1;
63867+ uint16_t flags;
63868+ uint32_t residual;
63869+ uint16_t ox_id;
63870+ uint16_t scsi_status;
63871+ uint32_t relative_offset;
63872+ uint32_t reserved2;
63873+ uint32_t transfer_length;
63874+ uint32_t reserved3;
63875+ uint32_t dseg_0_address[2]; /* Data segment 0 address. */
63876+ uint32_t dseg_0_length; /* Data segment 0 length. */
63877+} __attribute__((packed)) ctio7_status0_entry_t;
63878+
63879+typedef struct {
63880+ ctio7_common_entry_t common;
63881+ uint16_t sense_length;
63882+ uint16_t flags;
63883+ uint32_t residual;
63884+ uint16_t ox_id;
63885+ uint16_t scsi_status;
63886+ uint16_t response_len;
63887+ uint16_t reserved;
63888+ uint8_t sense_data[24];
63889+} __attribute__((packed)) ctio7_status1_entry_t;
63890+
63891+typedef struct {
63892+ uint8_t entry_type; /* Entry type. */
63893+ uint8_t entry_count; /* Entry count. */
63894+ uint8_t sys_define; /* System defined. */
63895+ uint8_t entry_status; /* Entry Status. */
63896+ uint32_t handle; /* System defined handle */
63897+ uint16_t status;
63898+ uint16_t timeout;
63899+ uint16_t dseg_count; /* Data segment count. */
63900+ uint8_t reserved1[6];
63901+ uint32_t exchange_address;
63902+ uint16_t reserved2;
63903+ uint16_t flags;
63904+ uint32_t residual;
63905+ uint16_t ox_id;
63906+ uint16_t reserved3;
63907+ uint32_t relative_offset;
63908+ uint8_t reserved4[24];
63909+} __attribute__((packed)) ctio7_fw_entry_t;
63910+
63911+/* CTIO7 flags values */
63912+#define CTIO7_FLAGS_SEND_STATUS BIT_15
63913+#define CTIO7_FLAGS_TERMINATE BIT_14
63914+#define CTIO7_FLAGS_CONFORM_REQ BIT_13
63915+#define CTIO7_FLAGS_DONT_RET_CTIO BIT_8
63916+#define CTIO7_FLAGS_STATUS_MODE_0 0
63917+#define CTIO7_FLAGS_STATUS_MODE_1 BIT_6
63918+#define CTIO7_FLAGS_EXPLICIT_CONFORM BIT_5
63919+#define CTIO7_FLAGS_CONFIRM_SATISF BIT_4
63920+#define CTIO7_FLAGS_DSD_PTR BIT_2
63921+#define CTIO7_FLAGS_DATA_IN BIT_1
63922+#define CTIO7_FLAGS_DATA_OUT BIT_0
63923+
63924+/*
63925+ * ISP queue - immediate notify entry structure definition for 24xx.
63926+ */
63927+typedef struct {
63928+ uint8_t entry_type; /* Entry type. */
63929+ uint8_t entry_count; /* Entry count. */
63930+ uint8_t sys_define; /* System defined. */
63931+ uint8_t entry_status; /* Entry Status. */
63932+ uint32_t reserved;
63933+ uint16_t nport_handle;
63934+ uint16_t reserved_2;
63935+ uint16_t flags;
63936+#define NOTIFY24XX_FLAGS_GLOBAL_TPRLO BIT_1
63937+#define NOTIFY24XX_FLAGS_PUREX_IOCB BIT_0
63938+ uint16_t srr_rx_id;
63939+ uint16_t status;
63940+ uint8_t status_subcode;
63941+ uint8_t reserved_3;
63942+ uint32_t exchange_address;
63943+ uint32_t srr_rel_offs;
63944+ uint16_t srr_ui;
63945+ uint16_t srr_ox_id;
63946+ uint8_t reserved_4[19];
63947+ uint8_t vp_index;
63948+ uint32_t reserved_5;
63949+ uint8_t port_id[3];
63950+ uint8_t reserved_6;
63951+ uint16_t reserved_7;
63952+ uint16_t ox_id;
63953+} __attribute__((packed)) notify24xx_entry_t;
63954+
63955+#define ELS_PLOGI 0x3
63956+#define ELS_FLOGI 0x4
63957+#define ELS_LOGO 0x5
63958+#define ELS_PRLI 0x20
63959+#define ELS_PRLO 0x21
63960+#define ELS_TPRLO 0x24
63961+#define ELS_PDISC 0x50
63962+#define ELS_ADISC 0x52
63963+
63964+/*
63965+ * ISP queue - notify acknowledge entry structure definition for 24xx.
63966+ */
63967+typedef struct {
63968+ uint8_t entry_type; /* Entry type. */
63969+ uint8_t entry_count; /* Entry count. */
63970+ uint8_t sys_define; /* System defined. */
63971+ uint8_t entry_status; /* Entry Status. */
63972+ uint32_t handle;
63973+ uint16_t nport_handle;
63974+ uint16_t reserved_1;
63975+ uint16_t flags;
63976+ uint16_t srr_rx_id;
63977+ uint16_t status;
63978+ uint8_t status_subcode;
63979+ uint8_t reserved_3;
63980+ uint32_t exchange_address;
63981+ uint32_t srr_rel_offs;
63982+ uint16_t srr_ui;
63983+ uint16_t srr_flags;
63984+ uint8_t reserved_4[19];
63985+ uint8_t vp_index;
63986+ uint8_t srr_reject_vendor_uniq;
63987+ uint8_t srr_reject_code_expl;
63988+ uint8_t srr_reject_code;
63989+ uint8_t reserved_5[7];
63990+ uint16_t ox_id;
63991+} __attribute__((packed)) nack24xx_entry_t;
63992+
63993+/*
63994+ * ISP queue - ABTS received/response entries structure definition for 24xx.
63995+ */
63996+#define ABTS_RECV_24XX 0x54 /* ABTS received (for 24xx) */
63997+#define ABTS_RESP_24XX 0x55 /* ABTS responce (for 24xx) */
63998+
63999+typedef struct {
64000+ uint8_t entry_type; /* Entry type. */
64001+ uint8_t entry_count; /* Entry count. */
64002+ uint8_t sys_define; /* System defined. */
64003+ uint8_t entry_status; /* Entry Status. */
64004+ uint8_t reserved_1[6];
64005+ uint16_t nport_handle;
64006+ uint8_t reserved_2[3];
64007+ uint8_t reserved_3:4;
64008+ uint8_t sof_type:4;
64009+ uint32_t exchange_address;
64010+ fcp_hdr_le_t fcp_hdr_le;
64011+ uint8_t reserved_4[16];
64012+ uint32_t exchange_addr_to_abort;
64013+} __attribute__((packed)) abts24_recv_entry_t;
64014+
64015+#define ABTS_PARAM_ABORT_SEQ BIT_0
64016+
64017+typedef struct {
64018+ uint16_t reserved;
64019+ uint8_t seq_id_last;
64020+ uint8_t seq_id_valid;
64021+#define SEQ_ID_VALID 0x80
64022+#define SEQ_ID_INVALID 0x00
64023+ uint16_t rx_id;
64024+ uint16_t ox_id;
64025+ uint16_t high_seq_cnt;
64026+ uint16_t low_seq_cnt;
64027+} __attribute__((packed)) ba_acc_le_t;
64028+
64029+typedef struct {
64030+ uint8_t vendor_uniq;
64031+ uint8_t reason_expl;
64032+ uint8_t reason_code;
64033+#define BA_RJT_REASON_CODE_INVALID_COMMAND 0x1
64034+#define BA_RJT_REASON_CODE_UNABLE_TO_PERFORM 0x9
64035+ uint8_t reserved;
64036+} __attribute__((packed)) ba_rjt_le_t;
64037+
64038+typedef struct {
64039+ uint8_t entry_type; /* Entry type. */
64040+ uint8_t entry_count; /* Entry count. */
64041+ uint8_t sys_define; /* System defined. */
64042+ uint8_t entry_status; /* Entry Status. */
64043+ uint32_t handle;
64044+ uint16_t reserved_1;
64045+ uint16_t nport_handle;
64046+ uint16_t control_flags;
64047+#define ABTS_CONTR_FLG_TERM_EXCHG BIT_0
64048+ uint8_t reserved_2;
64049+ uint8_t reserved_3:4;
64050+ uint8_t sof_type:4;
64051+ uint32_t exchange_address;
64052+ fcp_hdr_le_t fcp_hdr_le;
64053+ union {
64054+ ba_acc_le_t ba_acct;
64055+ ba_rjt_le_t ba_rjt;
64056+ } __attribute__((packed)) payload;
64057+ uint32_t reserved_4;
64058+ uint32_t exchange_addr_to_abort;
64059+} __attribute__((packed)) abts24_resp_entry_t;
64060+
64061+typedef struct {
64062+ uint8_t entry_type; /* Entry type. */
64063+ uint8_t entry_count; /* Entry count. */
64064+ uint8_t sys_define; /* System defined. */
64065+ uint8_t entry_status; /* Entry Status. */
64066+ uint32_t handle;
64067+ uint16_t compl_status;
64068+#define ABTS_RESP_COMPL_SUCCESS 0
64069+#define ABTS_RESP_COMPL_SUBCODE_ERROR 0x31
64070+ uint16_t nport_handle;
64071+ uint16_t reserved_1;
64072+ uint8_t reserved_2;
64073+ uint8_t reserved_3:4;
64074+ uint8_t sof_type:4;
64075+ uint32_t exchange_address;
64076+ fcp_hdr_le_t fcp_hdr_le;
64077+ uint8_t reserved_4[8];
64078+ uint32_t error_subcode1;
64079+#define ABTS_RESP_SUBCODE_ERR_ABORTED_EXCH_NOT_TERM 0x1E
64080+ uint32_t error_subcode2;
64081+ uint32_t exchange_addr_to_abort;
64082+} __attribute__((packed)) abts24_resp_fw_entry_t;
64083+
64084+/********************************************************************\
64085+ * Type Definitions used by initiator & target halves
64086+\********************************************************************/
64087+
64088+typedef enum {
64089+ ADD_TARGET = 0,
64090+ REMOVE_TARGET,
64091+ DISABLE_TARGET_MODE,
64092+ ENABLE_TARGET_MODE,
64093+} qla2x_tgt_host_action_t;
64094+
64095+/* Changing it don't forget to change QLA2X_TARGET_MAGIC! */
64096+struct qla_tgt_data {
64097+ int magic;
64098+
64099+ /* Callbacks */
64100+ void (*tgt24_atio_pkt)(scsi_qla_host_t *ha, atio7_entry_t *pkt);
64101+ void (*tgt_response_pkt)(scsi_qla_host_t *ha, response_t *pkt);
64102+ void (*tgt2x_ctio_completion)(scsi_qla_host_t *ha, uint32_t handle);
64103+ void (*tgt_async_event)(uint16_t code, scsi_qla_host_t *ha,
64104+ uint16_t *mailbox);
64105+ int (*tgt_host_action)(scsi_qla_host_t *ha, qla2x_tgt_host_action_t
64106+ action);
64107+ void (*tgt_fc_port_added)(scsi_qla_host_t *ha, fc_port_t *fcport);
64108+ void (*tgt_fc_port_deleted)(scsi_qla_host_t *ha, fc_port_t *fcport);
64109+};
64110+
64111+int qla2xxx_tgt_register_driver(struct qla_tgt_data *tgt);
64112+
64113+void qla2xxx_tgt_unregister_driver(void);
64114+
64115+int qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha);
64116+int qla2x00_wait_for_hba_online(scsi_qla_host_t *ha);
64117+
64118+#endif /* __QLA2X_TGT_DEF_H */
64119diff -uprN orig/linux-2.6.35/drivers/scst/qla2xxx-target/Makefile linux-2.6.35/drivers/scst/qla2xxx-target/Makefile
64120--- orig/linux-2.6.35/drivers/scst/qla2xxx-target/Makefile
64121+++ linux-2.6.35/drivers/scst/qla2xxx-target/Makefile
64122@@ -0,0 +1,5 @@
64123+ccflags-y += -Idrivers/scsi/qla2xxx
64124+
64125+qla2x00tgt-y := qla2x00t.o
64126+
64127+obj-$(CONFIG_SCST_QLA_TGT_ADDON) += qla2x00tgt.o
64128diff -uprN orig/linux-2.6.35/drivers/scst/qla2xxx-target/Kconfig linux-2.6.35/drivers/scst/qla2xxx-target/Kconfig
64129--- orig/linux-2.6.35/drivers/scst/qla2xxx-target/Kconfig
64130+++ linux-2.6.35/drivers/scst/qla2xxx-target/Kconfig
64131@@ -0,0 +1,30 @@
64132+config SCST_QLA_TGT_ADDON
64133+ tristate "QLogic 2XXX Target Mode Add-On"
64134+ depends on SCST && SCSI_QLA_FC && SCSI_QLA2XXX_TARGET
64135+ default SCST
64136+ help
64137+ Target mode add-on driver for QLogic 2xxx Fibre Channel host adapters.
64138+ Visit http://scst.sourceforge.net for more info about this driver.
64139+
64140+config QLA_TGT_DEBUG_WORK_IN_THREAD
64141+ bool "Use threads context only"
64142+ depends on SCST_QLA_TGT_ADDON
64143+ help
64144+ Makes SCST process incoming commands from the qla2x00t target
64145+ driver and call the driver's callbacks in internal SCST
64146+ threads context instead of SIRQ context, where thise commands
64147+ were received. Useful for debugging and lead to some
64148+ performance loss.
64149+
64150+ If unsure, say "N".
64151+
64152+config QLA_TGT_DEBUG_SRR
64153+ bool "SRR debugging"
64154+ depends on SCST_QLA_TGT_ADDON
64155+ help
64156+ Turns on retransmitting packets (SRR)
64157+ debugging. In this mode some CTIOs will be "broken" to force the
64158+ initiator to issue a retransmit request. Useful for debugging and lead to big
64159+ performance loss.
64160+
64161+ If unsure, say "N".
64162diff -uprN orig/linux-2.6.35/drivers/scst/qla2xxx-target/qla2x00t.c linux-2.6.35/drivers/scst/qla2xxx-target/qla2x00t.c
64163--- orig/linux-2.6.35/drivers/scst/qla2xxx-target/qla2x00t.c
64164+++ linux-2.6.35/drivers/scst/qla2xxx-target/qla2x00t.c
64165@@ -0,0 +1,5486 @@
64166+/*
64167+ * qla2x00t.c
64168+ *
64169+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
64170+ * Copyright (C) 2004 - 2005 Leonid Stoljar
64171+ * Copyright (C) 2006 Nathaniel Clark <nate@misrule.us>
64172+ * Copyright (C) 2006 - 2010 ID7 Ltd.
64173+ *
64174+ * QLogic 22xx/23xx/24xx/25xx FC target driver.
64175+ *
64176+ * This program is free software; you can redistribute it and/or
64177+ * modify it under the terms of the GNU General Public License
64178+ * as published by the Free Software Foundation, version 2
64179+ * of the License.
64180+ *
64181+ * This program is distributed in the hope that it will be useful,
64182+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
64183+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
64184+ * GNU General Public License for more details.
64185+ */
64186+
64187+#include <linux/module.h>
64188+#include <linux/init.h>
64189+#include <linux/types.h>
64190+#include <linux/version.h>
64191+#include <linux/blkdev.h>
64192+#include <linux/interrupt.h>
64193+#include <scsi/scsi.h>
64194+#include <scsi/scsi_host.h>
64195+#include <linux/pci.h>
64196+#include <linux/delay.h>
64197+#include <linux/list.h>
64198+
64199+#include <scst/scst.h>
64200+
64201+#include "qla2x00t.h"
64202+
64203+/*
64204+ * This driver calls qla2x00_req_pkt() and qla2x00_issue_marker(), which
64205+ * must be called under HW lock and could unlock/lock it inside.
64206+ * It isn't an issue, since in the current implementation on the time when
64207+ * those functions are called:
64208+ *
64209+ * - Either context is IRQ and only IRQ handler can modify HW data,
64210+ * including rings related fields,
64211+ *
64212+ * - Or access to target mode variables from struct q2t_tgt doesn't
64213+ * cross those functions boundaries, except tgt_stop, which
64214+ * additionally protected by irq_cmd_count.
64215+ */
64216+
64217+#ifndef CONFIG_SCSI_QLA2XXX_TARGET
64218+#error "CONFIG_SCSI_QLA2XXX_TARGET is NOT DEFINED"
64219+#endif
64220+
64221+#ifdef CONFIG_SCST_DEBUG
64222+#define Q2T_DEFAULT_LOG_FLAGS (TRACE_FUNCTION | TRACE_LINE | TRACE_PID | \
64223+ TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MGMT_DEBUG | \
64224+ TRACE_MINOR | TRACE_SPECIAL)
64225+#else
64226+# ifdef CONFIG_SCST_TRACING
64227+#define Q2T_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
64228+ TRACE_SPECIAL)
64229+# endif
64230+#endif
64231+
64232+static int q2t_target_detect(struct scst_tgt_template *templ);
64233+static int q2t_target_release(struct scst_tgt *scst_tgt);
64234+static int q2x_xmit_response(struct scst_cmd *scst_cmd);
64235+static int __q24_xmit_response(struct q2t_cmd *cmd, int xmit_type);
64236+static int q2t_rdy_to_xfer(struct scst_cmd *scst_cmd);
64237+static void q2t_on_free_cmd(struct scst_cmd *scst_cmd);
64238+static void q2t_task_mgmt_fn_done(struct scst_mgmt_cmd *mcmd);
64239+static int q2t_get_initiator_port_transport_id(struct scst_session *scst_sess,
64240+ uint8_t **transport_id);
64241+
64242+/* Predefs for callbacks handed to qla2xxx(target) */
64243+static void q24_atio_pkt(scsi_qla_host_t *ha, atio7_entry_t *pkt);
64244+static void q2t_response_pkt(scsi_qla_host_t *ha, response_t *pkt);
64245+static void q2t_async_event(uint16_t code, scsi_qla_host_t *ha,
64246+ uint16_t *mailbox);
64247+static void q2x_ctio_completion(scsi_qla_host_t *ha, uint32_t handle);
64248+static int q2t_host_action(scsi_qla_host_t *ha,
64249+ qla2x_tgt_host_action_t action);
64250+static void q2t_fc_port_added(scsi_qla_host_t *ha, fc_port_t *fcport);
64251+static void q2t_fc_port_deleted(scsi_qla_host_t *ha, fc_port_t *fcport);
64252+static int q2t_issue_task_mgmt(struct q2t_sess *sess, uint8_t *lun,
64253+ int lun_size, int fn, void *iocb, int flags);
64254+static void q2x_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
64255+ atio_entry_t *atio, int ha_locked);
64256+static void q24_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
64257+ atio7_entry_t *atio, int ha_locked);
64258+static void q2t_reject_free_srr_imm(scsi_qla_host_t *ha, struct srr_imm *imm,
64259+ int ha_lock);
64260+static int q2t_cut_cmd_data_head(struct q2t_cmd *cmd, unsigned int offset);
64261+static void q2t_clear_tgt_db(struct q2t_tgt *tgt, bool local_only);
64262+static void q2t_on_hw_pending_cmd_timeout(struct scst_cmd *scst_cmd);
64263+static int q2t_unreg_sess(struct q2t_sess *sess);
64264+static uint16_t q2t_get_scsi_transport_version(struct scst_tgt *scst_tgt);
64265+static uint16_t q2t_get_phys_transport_version(struct scst_tgt *scst_tgt);
64266+
64267+/** SYSFS **/
64268+
64269+static ssize_t q2t_version_show(struct kobject *kobj,
64270+ struct kobj_attribute *attr, char *buf);
64271+
64272+struct kobj_attribute q2t_version_attr =
64273+ __ATTR(version, S_IRUGO, q2t_version_show, NULL);
64274+
64275+static const struct attribute *q2t_attrs[] = {
64276+ &q2t_version_attr.attr,
64277+ NULL,
64278+};
64279+
64280+static ssize_t q2t_show_expl_conf_enabled(struct kobject *kobj,
64281+ struct kobj_attribute *attr, char *buffer);
64282+static ssize_t q2t_store_expl_conf_enabled(struct kobject *kobj,
64283+ struct kobj_attribute *attr, const char *buffer, size_t size);
64284+
64285+struct kobj_attribute q2t_expl_conf_attr =
64286+ __ATTR(explicit_confirmation, S_IRUGO|S_IWUSR,
64287+ q2t_show_expl_conf_enabled, q2t_store_expl_conf_enabled);
64288+
64289+static ssize_t q2t_abort_isp_store(struct kobject *kobj,
64290+ struct kobj_attribute *attr, const char *buffer, size_t size);
64291+
64292+struct kobj_attribute q2t_abort_isp_attr =
64293+ __ATTR(abort_isp, S_IWUSR, NULL, q2t_abort_isp_store);
64294+
64295+static const struct attribute *q2t_tgt_attrs[] = {
64296+ &q2t_expl_conf_attr.attr,
64297+ &q2t_abort_isp_attr.attr,
64298+ NULL,
64299+};
64300+
64301+static int q2t_enable_tgt(struct scst_tgt *tgt, bool enable);
64302+static bool q2t_is_tgt_enabled(struct scst_tgt *tgt);
64303+
64304+/*
64305+ * Global Variables
64306+ */
64307+
64308+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
64309+#define trace_flag q2t_trace_flag
64310+static unsigned long q2t_trace_flag = Q2T_DEFAULT_LOG_FLAGS;
64311+#endif
64312+
64313+static struct scst_tgt_template tgt2x_template = {
64314+ .name = "qla2x00t",
64315+ .sg_tablesize = 0,
64316+ .use_clustering = 1,
64317+#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
64318+ .xmit_response_atomic = 0,
64319+ .rdy_to_xfer_atomic = 0,
64320+#else
64321+ .xmit_response_atomic = 1,
64322+ .rdy_to_xfer_atomic = 1,
64323+#endif
64324+ .max_hw_pending_time = Q2T_MAX_HW_PENDING_TIME,
64325+ .detect = q2t_target_detect,
64326+ .release = q2t_target_release,
64327+ .xmit_response = q2x_xmit_response,
64328+ .rdy_to_xfer = q2t_rdy_to_xfer,
64329+ .on_free_cmd = q2t_on_free_cmd,
64330+ .task_mgmt_fn_done = q2t_task_mgmt_fn_done,
64331+ .get_initiator_port_transport_id = q2t_get_initiator_port_transport_id,
64332+ .get_scsi_transport_version = q2t_get_scsi_transport_version,
64333+ .get_phys_transport_version = q2t_get_phys_transport_version,
64334+ .on_hw_pending_cmd_timeout = q2t_on_hw_pending_cmd_timeout,
64335+ .enable_target = q2t_enable_tgt,
64336+ .is_target_enabled = q2t_is_tgt_enabled,
64337+ .tgtt_attrs = q2t_attrs,
64338+ .tgt_attrs = q2t_tgt_attrs,
64339+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
64340+ .default_trace_flags = Q2T_DEFAULT_LOG_FLAGS,
64341+ .trace_flags = &trace_flag,
64342+#endif
64343+};
64344+
64345+static struct kmem_cache *q2t_cmd_cachep;
64346+static struct kmem_cache *q2t_mgmt_cmd_cachep;
64347+static mempool_t *q2t_mgmt_cmd_mempool;
64348+
64349+static DECLARE_RWSEM(q2t_unreg_rwsem);
64350+
64351+/* It's not yet supported */
64352+static inline int scst_cmd_get_ppl_offset(struct scst_cmd *scst_cmd)
64353+{
64354+ return 0;
64355+}
64356+
64357+/* ha->hardware_lock supposed to be held on entry */
64358+static inline void q2t_sess_get(struct q2t_sess *sess)
64359+{
64360+ sess->sess_ref++;
64361+ TRACE_DBG("sess %p, new sess_ref %d", sess, sess->sess_ref);
64362+}
64363+
64364+/* ha->hardware_lock supposed to be held on entry */
64365+static inline void q2t_sess_put(struct q2t_sess *sess)
64366+{
64367+ TRACE_DBG("sess %p, new sess_ref %d", sess, sess->sess_ref-1);
64368+ BUG_ON(sess->sess_ref == 0);
64369+
64370+ sess->sess_ref--;
64371+ if (sess->sess_ref == 0)
64372+ q2t_unreg_sess(sess);
64373+}
64374+
64375+/* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */
64376+static inline struct q2t_sess *q2t_find_sess_by_loop_id(struct q2t_tgt *tgt,
64377+ uint16_t lid)
64378+{
64379+ struct q2t_sess *sess;
64380+ BUG_ON(tgt == NULL);
64381+ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
64382+ if (lid == (sess->loop_id))
64383+ return sess;
64384+ }
64385+ return NULL;
64386+}
64387+
64388+/* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */
64389+static inline struct q2t_sess *q2t_find_sess_by_s_id(struct q2t_tgt *tgt,
64390+ const uint8_t *s_id)
64391+{
64392+ struct q2t_sess *sess;
64393+ BUG_ON(tgt == NULL);
64394+ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
64395+ if ((sess->s_id.b.al_pa == s_id[2]) &&
64396+ (sess->s_id.b.area == s_id[1]) &&
64397+ (sess->s_id.b.domain == s_id[0]))
64398+ return sess;
64399+ }
64400+ return NULL;
64401+}
64402+
64403+/* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */
64404+static inline struct q2t_sess *q2t_find_sess_by_s_id_le(struct q2t_tgt *tgt,
64405+ const uint8_t *s_id)
64406+{
64407+ struct q2t_sess *sess;
64408+ BUG_ON(tgt == NULL);
64409+ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
64410+ if ((sess->s_id.b.al_pa == s_id[0]) &&
64411+ (sess->s_id.b.area == s_id[1]) &&
64412+ (sess->s_id.b.domain == s_id[2]))
64413+ return sess;
64414+ }
64415+ return NULL;
64416+}
64417+
64418+/* ha->hardware_lock supposed to be held on entry */
64419+static inline void q2t_exec_queue(scsi_qla_host_t *ha)
64420+{
64421+ qla2x00_isp_cmd(ha);
64422+}
64423+
64424+/* Might release hw lock, then reaquire!! */
64425+static inline int q2t_issue_marker(scsi_qla_host_t *ha, int ha_locked)
64426+{
64427+ /* Send marker if required */
64428+ if (unlikely(ha->marker_needed != 0)) {
64429+ int rc = qla2x00_issue_marker(ha, ha_locked);
64430+ if (rc != QLA_SUCCESS) {
64431+ PRINT_ERROR("qla2x00t(%ld): issue_marker() "
64432+ "failed", ha->instance);
64433+ }
64434+ return rc;
64435+ }
64436+ return QLA_SUCCESS;
64437+}
64438+
64439+/*
64440+ * Registers with initiator driver (but target mode isn't enabled till
64441+ * it's turned on via sysfs)
64442+ */
64443+static int q2t_target_detect(struct scst_tgt_template *tgtt)
64444+{
64445+ int res, rc;
64446+ struct qla_tgt_data t = {
64447+ .magic = QLA2X_TARGET_MAGIC,
64448+ .tgt24_atio_pkt = q24_atio_pkt,
64449+ .tgt_response_pkt = q2t_response_pkt,
64450+ .tgt2x_ctio_completion = q2x_ctio_completion,
64451+ .tgt_async_event = q2t_async_event,
64452+ .tgt_host_action = q2t_host_action,
64453+ .tgt_fc_port_added = q2t_fc_port_added,
64454+ .tgt_fc_port_deleted = q2t_fc_port_deleted,
64455+ };
64456+
64457+ TRACE_ENTRY();
64458+
64459+ rc = qla2xxx_tgt_register_driver(&t);
64460+ if (rc < 0) {
64461+ res = rc;
64462+ PRINT_ERROR("qla2x00t: Unable to register driver: %d", res);
64463+ goto out;
64464+ }
64465+
64466+ if (rc != QLA2X_INITIATOR_MAGIC) {
64467+ PRINT_ERROR("qla2x00t: Wrong version of the initiator part: "
64468+ "%d", rc);
64469+ res = -EINVAL;
64470+ goto out;
64471+ }
64472+
64473+ qla2xxx_add_targets();
64474+
64475+ res = 0;
64476+
64477+ PRINT_INFO("qla2x00t: %s", "Target mode driver for QLogic 2x00 controller "
64478+ "registered successfully");
64479+
64480+out:
64481+ TRACE_EXIT();
64482+ return res;
64483+}
64484+
64485+static void q2t_free_session_done(struct scst_session *scst_sess)
64486+{
64487+ struct q2t_sess *sess;
64488+ struct q2t_tgt *tgt;
64489+ scsi_qla_host_t *ha;
64490+ unsigned long flags;
64491+
64492+ TRACE_ENTRY();
64493+
64494+ BUG_ON(scst_sess == NULL);
64495+ sess = (struct q2t_sess *)scst_sess_get_tgt_priv(scst_sess);
64496+ BUG_ON(sess == NULL);
64497+ tgt = sess->tgt;
64498+
64499+ TRACE_MGMT_DBG("Unregistration of sess %p finished", sess);
64500+
64501+ kfree(sess);
64502+
64503+ if (tgt == NULL)
64504+ goto out;
64505+
64506+ TRACE_DBG("empty(sess_list) %d sess_count %d",
64507+ list_empty(&tgt->sess_list), tgt->sess_count);
64508+
64509+ ha = tgt->ha;
64510+
64511+ /*
64512+ * We need to protect against race, when tgt is freed before or
64513+ * inside wake_up()
64514+ */
64515+ spin_lock_irqsave(&ha->hardware_lock, flags);
64516+ tgt->sess_count--;
64517+ if (tgt->sess_count == 0)
64518+ wake_up_all(&tgt->waitQ);
64519+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
64520+
64521+out:
64522+ TRACE_EXIT();
64523+ return;
64524+}
64525+
64526+/* ha->hardware_lock supposed to be held on entry */
64527+static int q2t_unreg_sess(struct q2t_sess *sess)
64528+{
64529+ int res = 1;
64530+
64531+ TRACE_ENTRY();
64532+
64533+ BUG_ON(sess == NULL);
64534+ BUG_ON(sess->sess_ref != 0);
64535+
64536+ TRACE_MGMT_DBG("Deleting sess %p from tgt %p", sess, sess->tgt);
64537+ list_del(&sess->sess_list_entry);
64538+
64539+ if (sess->deleted)
64540+ list_del(&sess->del_list_entry);
64541+
64542+ PRINT_INFO("qla2x00t(%ld): %ssession for loop_id %d deleted",
64543+ sess->tgt->ha->instance, sess->local ? "local " : "",
64544+ sess->loop_id);
64545+
64546+ scst_unregister_session(sess->scst_sess, 0, q2t_free_session_done);
64547+
64548+ TRACE_EXIT_RES(res);
64549+ return res;
64550+}
64551+
64552+/* ha->hardware_lock supposed to be held on entry */
64553+static int q2t_reset(scsi_qla_host_t *ha, void *iocb, int mcmd)
64554+{
64555+ struct q2t_sess *sess;
64556+ int loop_id;
64557+ uint16_t lun = 0;
64558+ int res = 0;
64559+
64560+ TRACE_ENTRY();
64561+
64562+ if (IS_FWI2_CAPABLE(ha)) {
64563+ notify24xx_entry_t *n = (notify24xx_entry_t *)iocb;
64564+ loop_id = le16_to_cpu(n->nport_handle);
64565+ } else
64566+ loop_id = GET_TARGET_ID(ha, (notify_entry_t *)iocb);
64567+
64568+ if (loop_id == 0xFFFF) {
64569+ /* Global event */
64570+ q2t_clear_tgt_db(ha->tgt, 1);
64571+ if (!list_empty(&ha->tgt->sess_list)) {
64572+ sess = list_entry(ha->tgt->sess_list.next,
64573+ typeof(*sess), sess_list_entry);
64574+ switch (mcmd) {
64575+ case Q2T_NEXUS_LOSS_SESS:
64576+ mcmd = Q2T_NEXUS_LOSS;
64577+ break;
64578+
64579+ case Q2T_ABORT_ALL_SESS:
64580+ mcmd = Q2T_ABORT_ALL;
64581+ break;
64582+
64583+ case Q2T_NEXUS_LOSS:
64584+ case Q2T_ABORT_ALL:
64585+ break;
64586+
64587+ default:
64588+ PRINT_ERROR("qla2x00t(%ld): Not allowed "
64589+ "command %x in %s", ha->instance,
64590+ mcmd, __func__);
64591+ sess = NULL;
64592+ break;
64593+ }
64594+ } else
64595+ sess = NULL;
64596+ } else
64597+ sess = q2t_find_sess_by_loop_id(ha->tgt, loop_id);
64598+
64599+ if (sess == NULL) {
64600+ res = -ESRCH;
64601+ ha->tgt->tm_to_unknown = 1;
64602+ goto out;
64603+ }
64604+
64605+ TRACE_MGMT_DBG("scsi(%ld): resetting (session %p from port "
64606+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, "
64607+ "mcmd %x, loop_id %d)", ha->host_no, sess,
64608+ sess->port_name[0], sess->port_name[1],
64609+ sess->port_name[2], sess->port_name[3],
64610+ sess->port_name[4], sess->port_name[5],
64611+ sess->port_name[6], sess->port_name[7],
64612+ mcmd, loop_id);
64613+
64614+ res = q2t_issue_task_mgmt(sess, (uint8_t *)&lun, sizeof(lun),
64615+ mcmd, iocb, Q24_MGMT_SEND_NACK);
64616+
64617+out:
64618+ TRACE_EXIT_RES(res);
64619+ return res;
64620+}
64621+
64622+/* ha->hardware_lock supposed to be held on entry */
64623+static void q2t_clear_tgt_db(struct q2t_tgt *tgt, bool local_only)
64624+{
64625+ struct q2t_sess *sess, *sess_tmp;
64626+
64627+ TRACE_ENTRY();
64628+
64629+ TRACE(TRACE_MGMT, "qla2x00t: Clearing targets DB %p", tgt);
64630+
64631+ list_for_each_entry_safe(sess, sess_tmp, &tgt->sess_list,
64632+ sess_list_entry) {
64633+ if (local_only && !sess->local)
64634+ continue;
64635+ if (local_only && sess->local)
64636+ TRACE_MGMT_DBG("Putting local session %p from port "
64637+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
64638+ sess, sess->port_name[0], sess->port_name[1],
64639+ sess->port_name[2], sess->port_name[3],
64640+ sess->port_name[4], sess->port_name[5],
64641+ sess->port_name[6], sess->port_name[7]);
64642+ q2t_sess_put(sess);
64643+ }
64644+
64645+ /* At this point tgt could be already dead */
64646+
64647+ TRACE_MGMT_DBG("Finished clearing tgt %p DB", tgt);
64648+
64649+ TRACE_EXIT();
64650+ return;
64651+}
64652+
64653+/* Called in a thread context */
64654+static void q2t_alloc_session_done(struct scst_session *scst_sess,
64655+ void *data, int result)
64656+{
64657+ TRACE_ENTRY();
64658+
64659+ if (result != 0) {
64660+ struct q2t_sess *sess = (struct q2t_sess *)data;
64661+ struct q2t_tgt *tgt = sess->tgt;
64662+ scsi_qla_host_t *ha = tgt->ha;
64663+ unsigned long flags;
64664+
64665+ PRINT_INFO("qla2x00t(%ld): Session initialization failed",
64666+ ha->instance);
64667+
64668+ spin_lock_irqsave(&ha->hardware_lock, flags);
64669+ q2t_sess_put(sess);
64670+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
64671+ }
64672+
64673+ TRACE_EXIT();
64674+ return;
64675+}
64676+
64677+static void q2t_del_sess_timer_fn(unsigned long arg)
64678+{
64679+ struct q2t_tgt *tgt = (struct q2t_tgt *)arg;
64680+ scsi_qla_host_t *ha = tgt->ha;
64681+ struct q2t_sess *sess;
64682+ unsigned long flags;
64683+
64684+ TRACE_ENTRY();
64685+
64686+ spin_lock_irqsave(&ha->hardware_lock, flags);
64687+ while (!list_empty(&tgt->del_sess_list)) {
64688+ sess = list_entry(tgt->del_sess_list.next, typeof(*sess),
64689+ del_list_entry);
64690+ if (time_after_eq(jiffies, sess->expires)) {
64691+ /*
64692+ * sess will be deleted from del_sess_list in
64693+ * q2t_unreg_sess()
64694+ */
64695+ TRACE_MGMT_DBG("Timeout: sess %p about to be deleted",
64696+ sess);
64697+ q2t_sess_put(sess);
64698+ } else {
64699+ tgt->sess_del_timer.expires = sess->expires;
64700+ add_timer(&tgt->sess_del_timer);
64701+ break;
64702+ }
64703+ }
64704+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
64705+
64706+ TRACE_EXIT();
64707+ return;
64708+}
64709+
64710+/* pha->hardware_lock supposed to be held on entry */
64711+static void q2t_undelete_sess(struct q2t_sess *sess)
64712+{
64713+ list_del(&sess->del_list_entry);
64714+ sess->deleted = 0;
64715+}
64716+
64717+/*
64718+ * Must be called under tgt_mutex.
64719+ *
64720+ * Adds an extra ref to allow to drop hw lock after adding sess to the list.
64721+ * Caller must put it.
64722+ */
64723+static struct q2t_sess *q2t_create_sess(scsi_qla_host_t *ha, fc_port_t *fcport,
64724+ bool local)
64725+{
64726+ char *wwn_str;
64727+ const int wwn_str_len = 3*WWN_SIZE+2;
64728+ struct q2t_tgt *tgt = ha->tgt;
64729+ struct q2t_sess *sess;
64730+
64731+ TRACE_ENTRY();
64732+
64733+ /* Check to avoid double sessions */
64734+ spin_lock_irq(&ha->hardware_lock);
64735+ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
64736+ if ((sess->port_name[0] == fcport->port_name[0]) &&
64737+ (sess->port_name[1] == fcport->port_name[1]) &&
64738+ (sess->port_name[2] == fcport->port_name[2]) &&
64739+ (sess->port_name[3] == fcport->port_name[3]) &&
64740+ (sess->port_name[4] == fcport->port_name[4]) &&
64741+ (sess->port_name[5] == fcport->port_name[5]) &&
64742+ (sess->port_name[6] == fcport->port_name[6]) &&
64743+ (sess->port_name[7] == fcport->port_name[7])) {
64744+ TRACE_MGMT_DBG("Double sess %p found (s_id %x:%x:%x, "
64745+ "loop_id %d), updating to d_id %x:%x:%x, "
64746+ "loop_id %d", sess, sess->s_id.b.domain,
64747+ sess->s_id.b.al_pa, sess->s_id.b.area,
64748+ sess->loop_id, fcport->d_id.b.domain,
64749+ fcport->d_id.b.al_pa, fcport->d_id.b.area,
64750+ fcport->loop_id);
64751+
64752+ if (sess->deleted)
64753+ q2t_undelete_sess(sess);
64754+
64755+ q2t_sess_get(sess);
64756+ sess->s_id = fcport->d_id;
64757+ sess->loop_id = fcport->loop_id;
64758+ sess->conf_compl_supported = fcport->conf_compl_supported;
64759+ if (sess->local && !local)
64760+ sess->local = 0;
64761+ spin_unlock_irq(&ha->hardware_lock);
64762+ goto out;
64763+ }
64764+ }
64765+ spin_unlock_irq(&ha->hardware_lock);
64766+
64767+ /* We are under tgt_mutex, so a new sess can't be added behind us */
64768+
64769+ sess = kzalloc(sizeof(*sess), GFP_KERNEL);
64770+ if (sess == NULL) {
64771+ PRINT_ERROR("qla2x00t(%ld): session allocation failed, "
64772+ "all commands from port %02x:%02x:%02x:%02x:"
64773+ "%02x:%02x:%02x:%02x will be refused", ha->instance,
64774+ fcport->port_name[0], fcport->port_name[1],
64775+ fcport->port_name[2], fcport->port_name[3],
64776+ fcport->port_name[4], fcport->port_name[5],
64777+ fcport->port_name[6], fcport->port_name[7]);
64778+ goto out;
64779+ }
64780+
64781+ sess->sess_ref = 2; /* plus 1 extra ref, see above */
64782+ sess->tgt = ha->tgt;
64783+ sess->s_id = fcport->d_id;
64784+ sess->loop_id = fcport->loop_id;
64785+ sess->conf_compl_supported = fcport->conf_compl_supported;
64786+ sess->local = local;
64787+ BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
64788+ memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
64789+
64790+ wwn_str = kmalloc(wwn_str_len, GFP_KERNEL);
64791+ if (wwn_str == NULL) {
64792+ PRINT_ERROR("qla2x00t(%ld): Allocation of wwn_str failed. "
64793+ "All commands from port %02x:%02x:%02x:%02x:%02x:%02x:"
64794+ "%02x:%02x will be refused", ha->instance,
64795+ fcport->port_name[0], fcport->port_name[1],
64796+ fcport->port_name[2], fcport->port_name[3],
64797+ fcport->port_name[4], fcport->port_name[5],
64798+ fcport->port_name[6], fcport->port_name[7]);
64799+ goto out_free_sess;
64800+ }
64801+
64802+ sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
64803+ fcport->port_name[0], fcport->port_name[1],
64804+ fcport->port_name[2], fcport->port_name[3],
64805+ fcport->port_name[4], fcport->port_name[5],
64806+ fcport->port_name[6], fcport->port_name[7]);
64807+
64808+ /* Let's do the session creation async'ly */
64809+ sess->scst_sess = scst_register_session(tgt->scst_tgt, 1, wwn_str,
64810+ sess, sess, q2t_alloc_session_done);
64811+ if (sess->scst_sess == NULL) {
64812+ PRINT_ERROR("qla2x00t(%ld): scst_register_session() "
64813+ "failed for host %ld (wwn %s, loop_id %d), all "
64814+ "commands from it will be refused", ha->instance,
64815+ ha->host_no, wwn_str, fcport->loop_id);
64816+ goto out_free_sess_wwn;
64817+ }
64818+
64819+ spin_lock_irq(&ha->hardware_lock);
64820+ TRACE_MGMT_DBG("Adding sess %p to tgt %p", sess, tgt);
64821+ list_add_tail(&sess->sess_list_entry, &tgt->sess_list);
64822+ tgt->sess_count++;
64823+ spin_unlock_irq(&ha->hardware_lock);
64824+
64825+ PRINT_INFO("qla2x00t(%ld): %ssession for wwn %s (loop_id %d, "
64826+ "s_id %x:%x:%x, confirmed completion %ssupported) added",
64827+ ha->instance, local ? "local " : "", wwn_str, fcport->loop_id,
64828+ sess->s_id.b.domain, sess->s_id.b.al_pa, sess->s_id.b.area,
64829+ sess->conf_compl_supported ? "" : "not ");
64830+
64831+ kfree(wwn_str);
64832+
64833+out:
64834+ TRACE_EXIT_HRES(sess);
64835+ return sess;
64836+
64837+out_free_sess_wwn:
64838+ kfree(wwn_str);
64839+ /* go through */
64840+
64841+out_free_sess:
64842+ kfree(sess);
64843+ sess = NULL;
64844+ goto out;
64845+}
64846+
64847+/* pha->hardware_lock supposed to be held on entry */
64848+static void q2t_reappear_sess(struct q2t_sess *sess, const char *reason)
64849+{
64850+ q2t_undelete_sess(sess);
64851+
64852+ PRINT_INFO("qla2x00t(%ld): %ssession for port %02x:"
64853+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x (loop ID %d) "
64854+ "reappeared%s", sess->tgt->ha->instance,
64855+ sess->local ? "local " : "", sess->port_name[0],
64856+ sess->port_name[1], sess->port_name[2], sess->port_name[3],
64857+ sess->port_name[4], sess->port_name[5], sess->port_name[6],
64858+ sess->port_name[7], sess->loop_id, reason);
64859+ TRACE_MGMT_DBG("Appeared sess %p", sess);
64860+}
64861+
64862+static void q2t_fc_port_added(scsi_qla_host_t *ha, fc_port_t *fcport)
64863+{
64864+ struct q2t_tgt *tgt;
64865+ struct q2t_sess *sess;
64866+
64867+ TRACE_ENTRY();
64868+
64869+ mutex_lock(&ha->tgt_mutex);
64870+
64871+ tgt = ha->tgt;
64872+
64873+ if ((tgt == NULL) || (fcport->port_type != FCT_INITIATOR))
64874+ goto out_unlock;
64875+
64876+ if (tgt->tgt_stop)
64877+ goto out_unlock;
64878+
64879+ spin_lock_irq(&ha->hardware_lock);
64880+
64881+ sess = q2t_find_sess_by_loop_id(tgt, fcport->loop_id);
64882+ if (sess == NULL) {
64883+ spin_unlock_irq(&ha->hardware_lock);
64884+ sess = q2t_create_sess(ha, fcport, false);
64885+ spin_lock_irq(&ha->hardware_lock);
64886+ if (sess != NULL)
64887+ q2t_sess_put(sess); /* put the extra creation ref */
64888+ } else {
64889+ if (sess->deleted)
64890+ q2t_reappear_sess(sess, "");
64891+ }
64892+
64893+ if (sess->local) {
64894+ TRACE(TRACE_MGMT, "qla2x00t(%ld): local session for "
64895+ "port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
64896+ "(loop ID %d) became global", ha->instance,
64897+ fcport->port_name[0], fcport->port_name[1],
64898+ fcport->port_name[2], fcport->port_name[3],
64899+ fcport->port_name[4], fcport->port_name[5],
64900+ fcport->port_name[6], fcport->port_name[7],
64901+ sess->loop_id);
64902+ sess->local = 0;
64903+ }
64904+
64905+ spin_unlock_irq(&ha->hardware_lock);
64906+
64907+out_unlock:
64908+ mutex_unlock(&ha->tgt_mutex);
64909+
64910+ TRACE_EXIT();
64911+ return;
64912+}
64913+
64914+static void q2t_fc_port_deleted(scsi_qla_host_t *ha, fc_port_t *fcport)
64915+{
64916+ struct q2t_tgt *tgt;
64917+ struct q2t_sess *sess;
64918+ uint32_t dev_loss_tmo;
64919+
64920+ TRACE_ENTRY();
64921+
64922+ mutex_lock(&ha->tgt_mutex);
64923+
64924+ tgt = ha->tgt;
64925+
64926+ if ((tgt == NULL) || (fcport->port_type != FCT_INITIATOR))
64927+ goto out_unlock;
64928+
64929+ dev_loss_tmo = ha->port_down_retry_count + 5;
64930+
64931+ if (tgt->tgt_stop)
64932+ goto out_unlock;
64933+
64934+ spin_lock_irq(&ha->hardware_lock);
64935+
64936+ sess = q2t_find_sess_by_loop_id(tgt, fcport->loop_id);
64937+ if (sess == NULL)
64938+ goto out_unlock_ha;
64939+
64940+ if (!sess->deleted) {
64941+ int add_tmr;
64942+
64943+ add_tmr = list_empty(&tgt->del_sess_list);
64944+
64945+ TRACE_MGMT_DBG("Scheduling sess %p to deletion", sess);
64946+ list_add_tail(&sess->del_list_entry, &tgt->del_sess_list);
64947+ sess->deleted = 1;
64948+
64949+ PRINT_INFO("qla2x00t(%ld): %ssession for port %02x:%02x:%02x:"
64950+ "%02x:%02x:%02x:%02x:%02x (loop ID %d) scheduled for "
64951+ "deletion in %d secs", ha->instance,
64952+ sess->local ? "local " : "",
64953+ fcport->port_name[0], fcport->port_name[1],
64954+ fcport->port_name[2], fcport->port_name[3],
64955+ fcport->port_name[4], fcport->port_name[5],
64956+ fcport->port_name[6], fcport->port_name[7],
64957+ sess->loop_id, dev_loss_tmo);
64958+
64959+ sess->expires = jiffies + dev_loss_tmo * HZ;
64960+ if (add_tmr)
64961+ mod_timer(&tgt->sess_del_timer, sess->expires);
64962+ }
64963+
64964+out_unlock_ha:
64965+ spin_unlock_irq(&ha->hardware_lock);
64966+
64967+out_unlock:
64968+ mutex_unlock(&ha->tgt_mutex);
64969+
64970+ TRACE_EXIT();
64971+ return;
64972+}
64973+
64974+static inline int test_tgt_sess_count(struct q2t_tgt *tgt)
64975+{
64976+ unsigned long flags;
64977+ int res;
64978+
64979+ /*
64980+ * We need to protect against race, when tgt is freed before or
64981+ * inside wake_up()
64982+ */
64983+ spin_lock_irqsave(&tgt->ha->hardware_lock, flags);
64984+ TRACE_DBG("tgt %p, empty(sess_list)=%d sess_count=%d",
64985+ tgt, list_empty(&tgt->sess_list), tgt->sess_count);
64986+ res = (tgt->sess_count == 0);
64987+ spin_unlock_irqrestore(&tgt->ha->hardware_lock, flags);
64988+
64989+ return res;
64990+}
64991+
64992+/* Must be called under tgt_host_action_mutex or q2t_unreg_rwsem write locked */
64993+static void q2t_target_stop(struct scst_tgt *scst_tgt)
64994+{
64995+ struct q2t_tgt *tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
64996+ scsi_qla_host_t *ha = tgt->ha;
64997+
64998+ TRACE_ENTRY();
64999+
65000+ TRACE_DBG("Stopping target for host %ld(%p)", ha->host_no, ha);
65001+
65002+ /*
65003+ * Mutex needed to sync with q2t_fc_port_[added,deleted].
65004+ * Lock is needed, because we still can get an incoming packet.
65005+ */
65006+
65007+ mutex_lock(&ha->tgt_mutex);
65008+ spin_lock_irq(&ha->hardware_lock);
65009+ tgt->tgt_stop = 1;
65010+ q2t_clear_tgt_db(tgt, false);
65011+ spin_unlock_irq(&ha->hardware_lock);
65012+ mutex_unlock(&ha->tgt_mutex);
65013+
65014+ del_timer_sync(&tgt->sess_del_timer);
65015+
65016+ TRACE_MGMT_DBG("Waiting for sess works (tgt %p)", tgt);
65017+ spin_lock_irq(&tgt->sess_work_lock);
65018+ while (!list_empty(&tgt->sess_works_list)) {
65019+ spin_unlock_irq(&tgt->sess_work_lock);
65020+ flush_scheduled_work();
65021+ spin_lock_irq(&tgt->sess_work_lock);
65022+ }
65023+ spin_unlock_irq(&tgt->sess_work_lock);
65024+
65025+ TRACE_MGMT_DBG("Waiting for tgt %p: list_empty(sess_list)=%d "
65026+ "sess_count=%d", tgt, list_empty(&tgt->sess_list),
65027+ tgt->sess_count);
65028+
65029+ wait_event(tgt->waitQ, test_tgt_sess_count(tgt));
65030+
65031+ /* Big hammer */
65032+ if (!ha->host_shutting_down && qla_tgt_mode_enabled(ha))
65033+ qla2x00_disable_tgt_mode(ha);
65034+
65035+ /* Wait for sessions to clear out (just in case) */
65036+ wait_event(tgt->waitQ, test_tgt_sess_count(tgt));
65037+
65038+ TRACE_MGMT_DBG("Waiting for %d IRQ commands to complete (tgt %p)",
65039+ tgt->irq_cmd_count, tgt);
65040+
65041+ mutex_lock(&ha->tgt_mutex);
65042+ spin_lock_irq(&ha->hardware_lock);
65043+ while (tgt->irq_cmd_count != 0) {
65044+ spin_unlock_irq(&ha->hardware_lock);
65045+ udelay(2);
65046+ spin_lock_irq(&ha->hardware_lock);
65047+ }
65048+ ha->tgt = NULL;
65049+ spin_unlock_irq(&ha->hardware_lock);
65050+ mutex_unlock(&ha->tgt_mutex);
65051+
65052+ TRACE_MGMT_DBG("Stop of tgt %p finished", tgt);
65053+
65054+ TRACE_EXIT();
65055+ return;
65056+}
65057+
65058+/* Must be called under tgt_host_action_mutex or q2t_unreg_rwsem write locked */
65059+static int q2t_target_release(struct scst_tgt *scst_tgt)
65060+{
65061+ struct q2t_tgt *tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
65062+ scsi_qla_host_t *ha = tgt->ha;
65063+
65064+ TRACE_ENTRY();
65065+
65066+ q2t_target_stop(scst_tgt);
65067+
65068+ ha->q2t_tgt = NULL;
65069+ scst_tgt_set_tgt_priv(scst_tgt, NULL);
65070+
65071+ TRACE_MGMT_DBG("Release of tgt %p finished", tgt);
65072+
65073+ kfree(tgt);
65074+
65075+ TRACE_EXIT();
65076+ return 0;
65077+}
65078+
65079+/*
65080+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
65081+ */
65082+static void q2x_modify_command_count(scsi_qla_host_t *ha, int cmd_count,
65083+ int imm_count)
65084+{
65085+ modify_lun_entry_t *pkt;
65086+
65087+ TRACE_ENTRY();
65088+
65089+ TRACE_DBG("Sending MODIFY_LUN (ha=%p, cmd=%d, imm=%d)",
65090+ ha, cmd_count, imm_count);
65091+
65092+ /* Sending marker isn't necessary, since we called from ISR */
65093+
65094+ pkt = (modify_lun_entry_t *)qla2x00_req_pkt(ha);
65095+ if (pkt == NULL) {
65096+ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
65097+ "request packet", ha->instance, __func__);
65098+ goto out;
65099+ }
65100+
65101+ ha->tgt->modify_lun_expected++;
65102+
65103+ pkt->entry_type = MODIFY_LUN_TYPE;
65104+ pkt->entry_count = 1;
65105+ if (cmd_count < 0) {
65106+ pkt->operators = MODIFY_LUN_CMD_SUB; /* Subtract from command count */
65107+ pkt->command_count = -cmd_count;
65108+ } else if (cmd_count > 0) {
65109+ pkt->operators = MODIFY_LUN_CMD_ADD; /* Add to command count */
65110+ pkt->command_count = cmd_count;
65111+ }
65112+
65113+ if (imm_count < 0) {
65114+ pkt->operators |= MODIFY_LUN_IMM_SUB;
65115+ pkt->immed_notify_count = -imm_count;
65116+ } else if (imm_count > 0) {
65117+ pkt->operators |= MODIFY_LUN_IMM_ADD;
65118+ pkt->immed_notify_count = imm_count;
65119+ }
65120+
65121+ pkt->timeout = 0; /* Use default */
65122+
65123+ TRACE_BUFFER("MODIFY LUN packet data", pkt, REQUEST_ENTRY_SIZE);
65124+
65125+ q2t_exec_queue(ha);
65126+
65127+out:
65128+ TRACE_EXIT();
65129+ return;
65130+}
65131+
65132+/*
65133+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
65134+ */
65135+static void q2x_send_notify_ack(scsi_qla_host_t *ha, notify_entry_t *iocb,
65136+ uint32_t add_flags, uint16_t resp_code, int resp_code_valid,
65137+ uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan)
65138+{
65139+ nack_entry_t *ntfy;
65140+
65141+ TRACE_ENTRY();
65142+
65143+ TRACE_DBG("Sending NOTIFY_ACK (ha=%p)", ha);
65144+
65145+ /* Send marker if required */
65146+ if (q2t_issue_marker(ha, 1) != QLA_SUCCESS)
65147+ goto out;
65148+
65149+ ntfy = (nack_entry_t *)qla2x00_req_pkt(ha);
65150+ if (ntfy == NULL) {
65151+ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
65152+ "request packet", ha->instance, __func__);
65153+ goto out;
65154+ }
65155+
65156+ if (ha->tgt != NULL)
65157+ ha->tgt->notify_ack_expected++;
65158+
65159+ ntfy->entry_type = NOTIFY_ACK_TYPE;
65160+ ntfy->entry_count = 1;
65161+ SET_TARGET_ID(ha, ntfy->target, GET_TARGET_ID(ha, iocb));
65162+ ntfy->status = iocb->status;
65163+ ntfy->task_flags = iocb->task_flags;
65164+ ntfy->seq_id = iocb->seq_id;
65165+ /* Do not increment here, the chip isn't decrementing */
65166+ /* ntfy->flags = __constant_cpu_to_le16(NOTIFY_ACK_RES_COUNT); */
65167+ ntfy->flags |= cpu_to_le16(add_flags);
65168+ ntfy->srr_rx_id = iocb->srr_rx_id;
65169+ ntfy->srr_rel_offs = iocb->srr_rel_offs;
65170+ ntfy->srr_ui = iocb->srr_ui;
65171+ ntfy->srr_flags = cpu_to_le16(srr_flags);
65172+ ntfy->srr_reject_code = cpu_to_le16(srr_reject_code);
65173+ ntfy->srr_reject_code_expl = srr_explan;
65174+ ntfy->ox_id = iocb->ox_id;
65175+
65176+ if (resp_code_valid) {
65177+ ntfy->resp_code = cpu_to_le16(resp_code);
65178+ ntfy->flags |= __constant_cpu_to_le16(
65179+ NOTIFY_ACK_TM_RESP_CODE_VALID);
65180+ }
65181+
65182+ TRACE(TRACE_SCSI, "qla2x00t(%ld): Sending Notify Ack Seq %#x -> I %#x "
65183+ "St %#x RC %#x", ha->instance,
65184+ le16_to_cpu(iocb->seq_id), GET_TARGET_ID(ha, iocb),
65185+ le16_to_cpu(iocb->status), le16_to_cpu(ntfy->resp_code));
65186+ TRACE_BUFFER("Notify Ack packet data", ntfy, REQUEST_ENTRY_SIZE);
65187+
65188+ q2t_exec_queue(ha);
65189+
65190+out:
65191+ TRACE_EXIT();
65192+ return;
65193+}
65194+
65195+/*
65196+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
65197+ */
65198+static void q24_send_abts_resp(scsi_qla_host_t *ha,
65199+ const abts24_recv_entry_t *abts, uint32_t status, bool ids_reversed)
65200+{
65201+ abts24_resp_entry_t *resp;
65202+ uint32_t f_ctl;
65203+ uint8_t *p;
65204+
65205+ TRACE_ENTRY();
65206+
65207+ TRACE_DBG("Sending task mgmt ABTS response (ha=%p, atio=%p, "
65208+ "status=%x", ha, abts, status);
65209+
65210+ /* Send marker if required */
65211+ if (q2t_issue_marker(ha, 1) != QLA_SUCCESS)
65212+ goto out;
65213+
65214+ resp = (abts24_resp_entry_t *)qla2x00_req_pkt(ha);
65215+ if (resp == NULL) {
65216+ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
65217+ "request packet", ha->instance, __func__);
65218+ goto out;
65219+ }
65220+
65221+ resp->entry_type = ABTS_RESP_24XX;
65222+ resp->entry_count = 1;
65223+ resp->nport_handle = abts->nport_handle;
65224+ resp->sof_type = abts->sof_type;
65225+ resp->exchange_address = abts->exchange_address;
65226+ resp->fcp_hdr_le = abts->fcp_hdr_le;
65227+ f_ctl = __constant_cpu_to_le32(F_CTL_EXCH_CONTEXT_RESP |
65228+ F_CTL_LAST_SEQ | F_CTL_END_SEQ |
65229+ F_CTL_SEQ_INITIATIVE);
65230+ p = (uint8_t *)&f_ctl;
65231+ resp->fcp_hdr_le.f_ctl[0] = *p++;
65232+ resp->fcp_hdr_le.f_ctl[1] = *p++;
65233+ resp->fcp_hdr_le.f_ctl[2] = *p;
65234+ if (ids_reversed) {
65235+ resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.d_id[0];
65236+ resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.d_id[1];
65237+ resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.d_id[2];
65238+ resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.s_id[0];
65239+ resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.s_id[1];
65240+ resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.s_id[2];
65241+ } else {
65242+ resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.s_id[0];
65243+ resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.s_id[1];
65244+ resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.s_id[2];
65245+ resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.d_id[0];
65246+ resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.d_id[1];
65247+ resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.d_id[2];
65248+ }
65249+ resp->exchange_addr_to_abort = abts->exchange_addr_to_abort;
65250+ if (status == SCST_MGMT_STATUS_SUCCESS) {
65251+ resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_ACC;
65252+ resp->payload.ba_acct.seq_id_valid = SEQ_ID_INVALID;
65253+ resp->payload.ba_acct.low_seq_cnt = 0x0000;
65254+ resp->payload.ba_acct.high_seq_cnt = 0xFFFF;
65255+ resp->payload.ba_acct.ox_id = abts->fcp_hdr_le.ox_id;
65256+ resp->payload.ba_acct.rx_id = abts->fcp_hdr_le.rx_id;
65257+ } else {
65258+ resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_RJT;
65259+ resp->payload.ba_rjt.reason_code =
65260+ BA_RJT_REASON_CODE_UNABLE_TO_PERFORM;
65261+ /* Other bytes are zero */
65262+ }
65263+
65264+ TRACE_BUFFER("ABTS RESP packet data", resp, REQUEST_ENTRY_SIZE);
65265+
65266+ ha->tgt->abts_resp_expected++;
65267+
65268+ q2t_exec_queue(ha);
65269+
65270+out:
65271+ TRACE_EXIT();
65272+ return;
65273+}
65274+
65275+/*
65276+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
65277+ */
65278+static void q24_retry_term_exchange(scsi_qla_host_t *ha,
65279+ abts24_resp_fw_entry_t *entry)
65280+{
65281+ ctio7_status1_entry_t *ctio;
65282+
65283+ TRACE_ENTRY();
65284+
65285+ TRACE_DBG("Sending retry TERM EXCH CTIO7 (ha=%p)", ha);
65286+
65287+ /* Send marker if required */
65288+ if (q2t_issue_marker(ha, 1) != QLA_SUCCESS)
65289+ goto out;
65290+
65291+ ctio = (ctio7_status1_entry_t *)qla2x00_req_pkt(ha);
65292+ if (ctio == NULL) {
65293+ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
65294+ "request packet", ha->instance, __func__);
65295+ goto out;
65296+ }
65297+
65298+ /*
65299+ * We've got on entrance firmware's response on by us generated
65300+ * ABTS response. So, in it ID fields are reversed.
65301+ */
65302+
65303+ ctio->common.entry_type = CTIO_TYPE7;
65304+ ctio->common.entry_count = 1;
65305+ ctio->common.nport_handle = entry->nport_handle;
65306+ ctio->common.handle = Q2T_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
65307+ ctio->common.timeout = __constant_cpu_to_le16(Q2T_TIMEOUT);
65308+ ctio->common.initiator_id[0] = entry->fcp_hdr_le.d_id[0];
65309+ ctio->common.initiator_id[1] = entry->fcp_hdr_le.d_id[1];
65310+ ctio->common.initiator_id[2] = entry->fcp_hdr_le.d_id[2];
65311+ ctio->common.exchange_addr = entry->exchange_addr_to_abort;
65312+ ctio->flags = __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_TERMINATE);
65313+ ctio->ox_id = entry->fcp_hdr_le.ox_id;
65314+
65315+ TRACE_BUFFER("CTIO7 retry TERM EXCH packet data", ctio, REQUEST_ENTRY_SIZE);
65316+
65317+ q2t_exec_queue(ha);
65318+
65319+ q24_send_abts_resp(ha, (abts24_recv_entry_t *)entry,
65320+ SCST_MGMT_STATUS_SUCCESS, true);
65321+
65322+out:
65323+ TRACE_EXIT();
65324+ return;
65325+}
65326+
65327+/*
65328+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
65329+ */
65330+static void q24_handle_abts(scsi_qla_host_t *ha, abts24_recv_entry_t *abts)
65331+{
65332+ uint32_t tag;
65333+ int rc;
65334+ struct q2t_mgmt_cmd *mcmd;
65335+ struct q2t_sess *sess;
65336+
65337+ TRACE_ENTRY();
65338+
65339+ if (le32_to_cpu(abts->fcp_hdr_le.parameter) & ABTS_PARAM_ABORT_SEQ) {
65340+ PRINT_ERROR("qla2x00t(%ld): ABTS: Abort Sequence not "
65341+ "supported", ha->instance);
65342+ goto out_err;
65343+ }
65344+
65345+ tag = abts->exchange_addr_to_abort;
65346+
65347+ if (tag == ATIO_EXCHANGE_ADDRESS_UNKNOWN) {
65348+ TRACE_MGMT_DBG("qla2x00t(%ld): ABTS: Unknown Exchange "
65349+ "Address received", ha->instance);
65350+ goto out_err;
65351+ }
65352+
65353+ TRACE(TRACE_MGMT, "qla2x00t(%ld): task abort (s_id=%x:%x:%x, "
65354+ "tag=%d, param=%x)", ha->instance, abts->fcp_hdr_le.s_id[2],
65355+ abts->fcp_hdr_le.s_id[1], abts->fcp_hdr_le.s_id[0], tag,
65356+ le32_to_cpu(abts->fcp_hdr_le.parameter));
65357+
65358+ sess = q2t_find_sess_by_s_id_le(ha->tgt, abts->fcp_hdr_le.s_id);
65359+ if (sess == NULL) {
65360+ TRACE(TRACE_MGMT, "qla2x00t(%ld): task abort for unexisting "
65361+ "session", ha->instance);
65362+ ha->tgt->tm_to_unknown = 1;
65363+ goto out_err;
65364+ }
65365+
65366+ mcmd = mempool_alloc(q2t_mgmt_cmd_mempool, GFP_ATOMIC);
65367+ if (mcmd == NULL) {
65368+ PRINT_ERROR("qla2x00t(%ld): %s: Allocation of ABORT cmd failed",
65369+ ha->instance, __func__);
65370+ goto out_err;
65371+ }
65372+ memset(mcmd, 0, sizeof(*mcmd));
65373+
65374+ mcmd->sess = sess;
65375+ memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts));
65376+
65377+ rc = scst_rx_mgmt_fn_tag(sess->scst_sess, SCST_ABORT_TASK, tag,
65378+ SCST_ATOMIC, mcmd);
65379+ if (rc != 0) {
65380+ PRINT_ERROR("qla2x00t(%ld): scst_rx_mgmt_fn_tag() failed: %d",
65381+ ha->instance, rc);
65382+ goto out_err_free;
65383+ }
65384+
65385+out:
65386+ TRACE_EXIT();
65387+ return;
65388+
65389+out_err_free:
65390+ mempool_free(mcmd, q2t_mgmt_cmd_mempool);
65391+
65392+out_err:
65393+ q24_send_abts_resp(ha, abts, SCST_MGMT_STATUS_REJECTED, false);
65394+ goto out;
65395+}
65396+
65397+/*
65398+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
65399+ */
65400+static void q24_send_task_mgmt_ctio(scsi_qla_host_t *ha,
65401+ struct q2t_mgmt_cmd *mcmd, uint32_t resp_code)
65402+{
65403+ const atio7_entry_t *atio = &mcmd->orig_iocb.atio7;
65404+ ctio7_status1_entry_t *ctio;
65405+
65406+ TRACE_ENTRY();
65407+
65408+ TRACE_DBG("Sending task mgmt CTIO7 (ha=%p, atio=%p, resp_code=%x",
65409+ ha, atio, resp_code);
65410+
65411+ /* Send marker if required */
65412+ if (q2t_issue_marker(ha, 1) != QLA_SUCCESS)
65413+ goto out;
65414+
65415+ ctio = (ctio7_status1_entry_t *)qla2x00_req_pkt(ha);
65416+ if (ctio == NULL) {
65417+ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
65418+ "request packet", ha->instance, __func__);
65419+ goto out;
65420+ }
65421+
65422+ ctio->common.entry_type = CTIO_TYPE7;
65423+ ctio->common.entry_count = 1;
65424+ ctio->common.handle = Q2T_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
65425+ ctio->common.nport_handle = mcmd->sess->loop_id;
65426+ ctio->common.timeout = __constant_cpu_to_le16(Q2T_TIMEOUT);
65427+ ctio->common.initiator_id[0] = atio->fcp_hdr.s_id[2];
65428+ ctio->common.initiator_id[1] = atio->fcp_hdr.s_id[1];
65429+ ctio->common.initiator_id[2] = atio->fcp_hdr.s_id[0];
65430+ ctio->common.exchange_addr = atio->exchange_addr;
65431+ ctio->flags = (atio->attr << 9) | __constant_cpu_to_le16(
65432+ CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS);
65433+ ctio->ox_id = swab16(atio->fcp_hdr.ox_id);
65434+ ctio->scsi_status = __constant_cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID);
65435+ ctio->response_len = __constant_cpu_to_le16(8);
65436+ ((uint32_t *)ctio->sense_data)[0] = cpu_to_be32(resp_code);
65437+
65438+ TRACE_BUFFER("CTIO7 TASK MGMT packet data", ctio, REQUEST_ENTRY_SIZE);
65439+
65440+ q2t_exec_queue(ha);
65441+
65442+out:
65443+ TRACE_EXIT();
65444+ return;
65445+}
65446+
65447+/*
65448+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
65449+ */
65450+static void q24_send_notify_ack(scsi_qla_host_t *ha,
65451+ notify24xx_entry_t *iocb, uint16_t srr_flags,
65452+ uint8_t srr_reject_code, uint8_t srr_explan)
65453+{
65454+ nack24xx_entry_t *nack;
65455+
65456+ TRACE_ENTRY();
65457+
65458+ TRACE_DBG("Sending NOTIFY_ACK24 (ha=%p)", ha);
65459+
65460+ /* Send marker if required */
65461+ if (q2t_issue_marker(ha, 1) != QLA_SUCCESS)
65462+ goto out;
65463+
65464+ if (ha->tgt != NULL)
65465+ ha->tgt->notify_ack_expected++;
65466+
65467+ nack = (nack24xx_entry_t *)qla2x00_req_pkt(ha);
65468+ if (nack == NULL) {
65469+ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
65470+ "request packet", ha->instance, __func__);
65471+ goto out;
65472+ }
65473+
65474+ nack->entry_type = NOTIFY_ACK_TYPE;
65475+ nack->entry_count = 1;
65476+ nack->nport_handle = iocb->nport_handle;
65477+ if (le16_to_cpu(iocb->status) == IMM_NTFY_ELS) {
65478+ nack->flags = iocb->flags &
65479+ __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
65480+ }
65481+ nack->srr_rx_id = iocb->srr_rx_id;
65482+ nack->status = iocb->status;
65483+ nack->status_subcode = iocb->status_subcode;
65484+ nack->exchange_address = iocb->exchange_address;
65485+ nack->srr_rel_offs = iocb->srr_rel_offs;
65486+ nack->srr_ui = iocb->srr_ui;
65487+ nack->srr_flags = cpu_to_le16(srr_flags);
65488+ nack->srr_reject_code = srr_reject_code;
65489+ nack->srr_reject_code_expl = srr_explan;
65490+ nack->ox_id = iocb->ox_id;
65491+
65492+ TRACE(TRACE_SCSI, "qla2x00t(%ld): Sending 24xx Notify Ack %d",
65493+ ha->instance, nack->status);
65494+ TRACE_BUFFER("24xx Notify Ack packet data", nack, sizeof(*nack));
65495+
65496+ q2t_exec_queue(ha);
65497+
65498+out:
65499+ TRACE_EXIT();
65500+ return;
65501+}
65502+
65503+static uint32_t q2t_convert_to_fc_tm_status(int scst_mstatus)
65504+{
65505+ uint32_t res;
65506+
65507+ switch (scst_mstatus) {
65508+ case SCST_MGMT_STATUS_SUCCESS:
65509+ res = FC_TM_SUCCESS;
65510+ break;
65511+ case SCST_MGMT_STATUS_TASK_NOT_EXIST:
65512+ res = FC_TM_BAD_CMD;
65513+ break;
65514+ case SCST_MGMT_STATUS_FN_NOT_SUPPORTED:
65515+ case SCST_MGMT_STATUS_REJECTED:
65516+ res = FC_TM_REJECT;
65517+ break;
65518+ case SCST_MGMT_STATUS_LUN_NOT_EXIST:
65519+ case SCST_MGMT_STATUS_FAILED:
65520+ default:
65521+ res = FC_TM_FAILED;
65522+ break;
65523+ }
65524+
65525+ TRACE_EXIT_RES(res);
65526+ return res;
65527+}
65528+
65529+/* SCST Callback */
65530+static void q2t_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd)
65531+{
65532+ struct q2t_mgmt_cmd *mcmd;
65533+ unsigned long flags;
65534+ scsi_qla_host_t *ha;
65535+
65536+ TRACE_ENTRY();
65537+
65538+ TRACE_MGMT_DBG("scst_mcmd (%p) status %#x state %#x", scst_mcmd,
65539+ scst_mcmd->status, scst_mcmd->state);
65540+
65541+ mcmd = scst_mgmt_cmd_get_tgt_priv(scst_mcmd);
65542+ if (unlikely(mcmd == NULL)) {
65543+ PRINT_ERROR("qla2x00t: scst_mcmd %p tgt_spec is NULL", mcmd);
65544+ goto out;
65545+ }
65546+
65547+ ha = mcmd->sess->tgt->ha;
65548+
65549+ spin_lock_irqsave(&ha->hardware_lock, flags);
65550+ if (IS_FWI2_CAPABLE(ha)) {
65551+ if (mcmd->flags == Q24_MGMT_SEND_NACK) {
65552+ q24_send_notify_ack(ha,
65553+ &mcmd->orig_iocb.notify_entry24, 0, 0, 0);
65554+ } else {
65555+ if (scst_mcmd->fn == SCST_ABORT_TASK)
65556+ q24_send_abts_resp(ha, &mcmd->orig_iocb.abts,
65557+ scst_mgmt_cmd_get_status(scst_mcmd),
65558+ false);
65559+ else
65560+ q24_send_task_mgmt_ctio(ha, mcmd,
65561+ q2t_convert_to_fc_tm_status(
65562+ scst_mgmt_cmd_get_status(scst_mcmd)));
65563+ }
65564+ } else {
65565+ uint32_t resp_code = q2t_convert_to_fc_tm_status(
65566+ scst_mgmt_cmd_get_status(scst_mcmd));
65567+ q2x_send_notify_ack(ha, &mcmd->orig_iocb.notify_entry, 0,
65568+ resp_code, 1, 0, 0, 0);
65569+ }
65570+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
65571+
65572+ scst_mgmt_cmd_set_tgt_priv(scst_mcmd, NULL);
65573+ mempool_free(mcmd, q2t_mgmt_cmd_mempool);
65574+
65575+out:
65576+ TRACE_EXIT();
65577+ return;
65578+}
65579+
65580+/* No locks */
65581+static int q2t_pci_map_calc_cnt(struct q2t_prm *prm)
65582+{
65583+ int res = 0;
65584+
65585+ BUG_ON(prm->cmd->sg_cnt == 0);
65586+
65587+ prm->sg = (struct scatterlist *)prm->cmd->sg;
65588+ prm->seg_cnt = pci_map_sg(prm->tgt->ha->pdev, prm->cmd->sg,
65589+ prm->cmd->sg_cnt, prm->cmd->dma_data_direction);
65590+ if (unlikely(prm->seg_cnt == 0))
65591+ goto out_err;
65592+
65593+ prm->cmd->sg_mapped = 1;
65594+
65595+ /*
65596+ * If greater than four sg entries then we need to allocate
65597+ * the continuation entries
65598+ */
65599+ if (prm->seg_cnt > prm->tgt->datasegs_per_cmd) {
65600+ prm->req_cnt += (uint16_t)(prm->seg_cnt -
65601+ prm->tgt->datasegs_per_cmd) /
65602+ prm->tgt->datasegs_per_cont;
65603+ if (((uint16_t)(prm->seg_cnt - prm->tgt->datasegs_per_cmd)) %
65604+ prm->tgt->datasegs_per_cont)
65605+ prm->req_cnt++;
65606+ }
65607+
65608+out:
65609+ TRACE_DBG("seg_cnt=%d, req_cnt=%d, res=%d", prm->seg_cnt,
65610+ prm->req_cnt, res);
65611+ return res;
65612+
65613+out_err:
65614+ PRINT_ERROR("qla2x00t(%ld): PCI mapping failed: sg_cnt=%d",
65615+ prm->tgt->ha->instance, prm->cmd->sg_cnt);
65616+ res = -1;
65617+ goto out;
65618+}
65619+
65620+static inline void q2t_unmap_sg(scsi_qla_host_t *ha, struct q2t_cmd *cmd)
65621+{
65622+ EXTRACHECKS_BUG_ON(!cmd->sg_mapped);
65623+ pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction);
65624+ cmd->sg_mapped = 0;
65625+}
65626+
65627+static int q2t_check_reserve_free_req(scsi_qla_host_t *ha, uint32_t req_cnt)
65628+{
65629+ int res = SCST_TGT_RES_SUCCESS;
65630+ device_reg_t __iomem *reg = ha->iobase;
65631+ uint32_t cnt;
65632+
65633+ TRACE_ENTRY();
65634+
65635+ if (ha->req_q_cnt < (req_cnt + 2)) {
65636+ if (IS_FWI2_CAPABLE(ha))
65637+ cnt = (uint16_t)RD_REG_DWORD(
65638+ &reg->isp24.req_q_out);
65639+ else
65640+ cnt = qla2x00_debounce_register(
65641+ ISP_REQ_Q_OUT(ha, &reg->isp));
65642+ TRACE_DBG("Request ring circled: cnt=%d, "
65643+ "ha->req_ring_index=%d, ha->req_q_cnt=%d, req_cnt=%d",
65644+ cnt, ha->req_ring_index, ha->req_q_cnt, req_cnt);
65645+ if (ha->req_ring_index < cnt)
65646+ ha->req_q_cnt = cnt - ha->req_ring_index;
65647+ else
65648+ ha->req_q_cnt = ha->request_q_length -
65649+ (ha->req_ring_index - cnt);
65650+ }
65651+
65652+ if (unlikely(ha->req_q_cnt < (req_cnt + 2))) {
65653+ TRACE(TRACE_OUT_OF_MEM, "qla2x00t(%ld): There is no room in the "
65654+ "request ring: ha->req_ring_index=%d, ha->req_q_cnt=%d, "
65655+ "req_cnt=%d", ha->instance, ha->req_ring_index,
65656+ ha->req_q_cnt, req_cnt);
65657+ res = SCST_TGT_RES_QUEUE_FULL;
65658+ goto out;
65659+ }
65660+
65661+ ha->req_q_cnt -= req_cnt;
65662+
65663+out:
65664+ TRACE_EXIT_RES(res);
65665+ return res;
65666+}
65667+
65668+/*
65669+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
65670+ */
65671+static inline void *q2t_get_req_pkt(scsi_qla_host_t *ha)
65672+{
65673+ /* Adjust ring index. */
65674+ ha->req_ring_index++;
65675+ if (ha->req_ring_index == ha->request_q_length) {
65676+ ha->req_ring_index = 0;
65677+ ha->request_ring_ptr = ha->request_ring;
65678+ } else {
65679+ ha->request_ring_ptr++;
65680+ }
65681+ return (cont_entry_t *)ha->request_ring_ptr;
65682+}
65683+
65684+/* ha->hardware_lock supposed to be held on entry */
65685+static inline uint32_t q2t_make_handle(scsi_qla_host_t *ha)
65686+{
65687+ uint32_t h;
65688+
65689+ h = ha->current_handle;
65690+ /* always increment cmd handle */
65691+ do {
65692+ ++h;
65693+ if (h > MAX_OUTSTANDING_COMMANDS)
65694+ h = 1; /* 0 is Q2T_NULL_HANDLE */
65695+ if (h == ha->current_handle) {
65696+ TRACE(TRACE_OUT_OF_MEM, "qla2x00t(%ld): Ran out of "
65697+ "empty cmd slots in ha %p", ha->instance, ha);
65698+ h = Q2T_NULL_HANDLE;
65699+ break;
65700+ }
65701+ } while ((h == Q2T_NULL_HANDLE) ||
65702+ (h == Q2T_SKIP_HANDLE) ||
65703+ (ha->cmds[h-1] != NULL));
65704+
65705+ if (h != Q2T_NULL_HANDLE)
65706+ ha->current_handle = h;
65707+
65708+ return h;
65709+}
65710+
65711+/* ha->hardware_lock supposed to be held on entry */
65712+static void q2x_build_ctio_pkt(struct q2t_prm *prm)
65713+{
65714+ uint32_t h;
65715+ ctio_entry_t *pkt;
65716+ scsi_qla_host_t *ha = prm->tgt->ha;
65717+
65718+ pkt = (ctio_entry_t *)ha->request_ring_ptr;
65719+ prm->pkt = pkt;
65720+ memset(pkt, 0, sizeof(*pkt));
65721+
65722+ if (prm->tgt->tgt_enable_64bit_addr)
65723+ pkt->common.entry_type = CTIO_A64_TYPE;
65724+ else
65725+ pkt->common.entry_type = CONTINUE_TGT_IO_TYPE;
65726+
65727+ pkt->common.entry_count = (uint8_t)prm->req_cnt;
65728+
65729+ h = q2t_make_handle(ha);
65730+ if (h != Q2T_NULL_HANDLE)
65731+ ha->cmds[h-1] = prm->cmd;
65732+
65733+ pkt->common.handle = h | CTIO_COMPLETION_HANDLE_MARK;
65734+ pkt->common.timeout = __constant_cpu_to_le16(Q2T_TIMEOUT);
65735+
65736+ /* Set initiator ID */
65737+ h = GET_TARGET_ID(ha, &prm->cmd->atio.atio2x);
65738+ SET_TARGET_ID(ha, pkt->common.target, h);
65739+
65740+ pkt->common.rx_id = prm->cmd->atio.atio2x.rx_id;
65741+ pkt->common.relative_offset = cpu_to_le32(prm->cmd->offset);
65742+
65743+ TRACE(TRACE_DEBUG|TRACE_SCSI, "qla2x00t(%ld): handle(scst_cmd) -> %08x, "
65744+ "timeout %d L %#x -> I %#x E %#x", ha->instance,
65745+ pkt->common.handle, Q2T_TIMEOUT,
65746+ le16_to_cpu(prm->cmd->atio.atio2x.lun),
65747+ GET_TARGET_ID(ha, &pkt->common), pkt->common.rx_id);
65748+}
65749+
65750+/* ha->hardware_lock supposed to be held on entry */
65751+static int q24_build_ctio_pkt(struct q2t_prm *prm)
65752+{
65753+ uint32_t h;
65754+ ctio7_status0_entry_t *pkt;
65755+ scsi_qla_host_t *ha = prm->tgt->ha;
65756+ atio7_entry_t *atio = &prm->cmd->atio.atio7;
65757+ int res = SCST_TGT_RES_SUCCESS;
65758+
65759+ TRACE_ENTRY();
65760+
65761+ pkt = (ctio7_status0_entry_t *)ha->request_ring_ptr;
65762+ prm->pkt = pkt;
65763+ memset(pkt, 0, sizeof(*pkt));
65764+
65765+ pkt->common.entry_type = CTIO_TYPE7;
65766+ pkt->common.entry_count = (uint8_t)prm->req_cnt;
65767+
65768+ h = q2t_make_handle(ha);
65769+ if (unlikely(h == Q2T_NULL_HANDLE)) {
65770+ /*
65771+ * CTIO type 7 from the firmware doesn't provide a way to
65772+ * know the initiator's LOOP ID, hence we can't find
65773+ * the session and, so, the command.
65774+ */
65775+ res = SCST_TGT_RES_QUEUE_FULL;
65776+ goto out;
65777+ } else
65778+ ha->cmds[h-1] = prm->cmd;
65779+
65780+ pkt->common.handle = h | CTIO_COMPLETION_HANDLE_MARK;
65781+ pkt->common.nport_handle = prm->cmd->loop_id;
65782+ pkt->common.timeout = __constant_cpu_to_le16(Q2T_TIMEOUT);
65783+ pkt->common.initiator_id[0] = atio->fcp_hdr.s_id[2];
65784+ pkt->common.initiator_id[1] = atio->fcp_hdr.s_id[1];
65785+ pkt->common.initiator_id[2] = atio->fcp_hdr.s_id[0];
65786+ pkt->common.exchange_addr = atio->exchange_addr;
65787+ pkt->flags |= (atio->attr << 9);
65788+ pkt->ox_id = swab16(atio->fcp_hdr.ox_id);
65789+ pkt->relative_offset = cpu_to_le32(prm->cmd->offset);
65790+
65791+out:
65792+ TRACE(TRACE_DEBUG|TRACE_SCSI, "qla2x00t(%ld): handle(scst_cmd) -> %08x, "
65793+ "timeout %d, ox_id %#x", ha->instance, pkt->common.handle,
65794+ Q2T_TIMEOUT, le16_to_cpu(pkt->ox_id));
65795+ TRACE_EXIT_RES(res);
65796+ return res;
65797+}
65798+
65799+/*
65800+ * ha->hardware_lock supposed to be held on entry. We have already made sure
65801+ * that there is sufficient amount of request entries to not drop it.
65802+ */
65803+static void q2t_load_cont_data_segments(struct q2t_prm *prm)
65804+{
65805+ int cnt;
65806+ uint32_t *dword_ptr;
65807+ int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr;
65808+
65809+ TRACE_ENTRY();
65810+
65811+ /* Build continuation packets */
65812+ while (prm->seg_cnt > 0) {
65813+ cont_a64_entry_t *cont_pkt64 =
65814+ (cont_a64_entry_t *)q2t_get_req_pkt(prm->tgt->ha);
65815+
65816+ /*
65817+ * Make sure that from cont_pkt64 none of
65818+ * 64-bit specific fields used for 32-bit
65819+ * addressing. Cast to (cont_entry_t *) for
65820+ * that.
65821+ */
65822+
65823+ memset(cont_pkt64, 0, sizeof(*cont_pkt64));
65824+
65825+ cont_pkt64->entry_count = 1;
65826+ cont_pkt64->sys_define = 0;
65827+
65828+ if (enable_64bit_addressing) {
65829+ cont_pkt64->entry_type = CONTINUE_A64_TYPE;
65830+ dword_ptr =
65831+ (uint32_t *)&cont_pkt64->dseg_0_address;
65832+ } else {
65833+ cont_pkt64->entry_type = CONTINUE_TYPE;
65834+ dword_ptr =
65835+ (uint32_t *)&((cont_entry_t *)
65836+ cont_pkt64)->dseg_0_address;
65837+ }
65838+
65839+ /* Load continuation entry data segments */
65840+ for (cnt = 0;
65841+ cnt < prm->tgt->datasegs_per_cont && prm->seg_cnt;
65842+ cnt++, prm->seg_cnt--) {
65843+ *dword_ptr++ =
65844+ cpu_to_le32(pci_dma_lo32
65845+ (sg_dma_address(prm->sg)));
65846+ if (enable_64bit_addressing) {
65847+ *dword_ptr++ =
65848+ cpu_to_le32(pci_dma_hi32
65849+ (sg_dma_address
65850+ (prm->sg)));
65851+ }
65852+ *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg));
65853+
65854+ TRACE_SG("S/G Segment Cont. phys_addr=%llx:%llx, len=%d",
65855+ (long long unsigned int)pci_dma_hi32(sg_dma_address(prm->sg)),
65856+ (long long unsigned int)pci_dma_lo32(sg_dma_address(prm->sg)),
65857+ (int)sg_dma_len(prm->sg));
65858+
65859+ prm->sg++;
65860+ }
65861+
65862+ TRACE_BUFFER("Continuation packet data",
65863+ cont_pkt64, REQUEST_ENTRY_SIZE);
65864+ }
65865+
65866+ TRACE_EXIT();
65867+ return;
65868+}
65869+
65870+/*
65871+ * ha->hardware_lock supposed to be held on entry. We have already made sure
65872+ * that there is sufficient amount of request entries to not drop it.
65873+ */
65874+static void q2x_load_data_segments(struct q2t_prm *prm)
65875+{
65876+ int cnt;
65877+ uint32_t *dword_ptr;
65878+ int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr;
65879+ ctio_common_entry_t *pkt = (ctio_common_entry_t *)prm->pkt;
65880+
65881+ TRACE_DBG("iocb->scsi_status=%x, iocb->flags=%x",
65882+ le16_to_cpu(pkt->scsi_status), le16_to_cpu(pkt->flags));
65883+
65884+ pkt->transfer_length = cpu_to_le32(prm->cmd->bufflen);
65885+
65886+ /* Setup packet address segment pointer */
65887+ dword_ptr = pkt->dseg_0_address;
65888+
65889+ if (prm->seg_cnt == 0) {
65890+ /* No data transfer */
65891+ *dword_ptr++ = 0;
65892+ *dword_ptr = 0;
65893+
65894+ TRACE_BUFFER("No data, CTIO packet data", pkt,
65895+ REQUEST_ENTRY_SIZE);
65896+ goto out;
65897+ }
65898+
65899+ /* Set total data segment count */
65900+ pkt->dseg_count = cpu_to_le16(prm->seg_cnt);
65901+
65902+ /* If scatter gather */
65903+ TRACE_SG("%s", "Building S/G data segments...");
65904+ /* Load command entry data segments */
65905+ for (cnt = 0;
65906+ (cnt < prm->tgt->datasegs_per_cmd) && prm->seg_cnt;
65907+ cnt++, prm->seg_cnt--) {
65908+ *dword_ptr++ =
65909+ cpu_to_le32(pci_dma_lo32(sg_dma_address(prm->sg)));
65910+ if (enable_64bit_addressing) {
65911+ *dword_ptr++ =
65912+ cpu_to_le32(pci_dma_hi32
65913+ (sg_dma_address(prm->sg)));
65914+ }
65915+ *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg));
65916+
65917+ TRACE_SG("S/G Segment phys_addr=%llx:%llx, len=%d",
65918+ (long long unsigned int)pci_dma_hi32(sg_dma_address(prm->sg)),
65919+ (long long unsigned int)pci_dma_lo32(sg_dma_address(prm->sg)),
65920+ (int)sg_dma_len(prm->sg));
65921+
65922+ prm->sg++;
65923+ }
65924+
65925+ TRACE_BUFFER("Scatter/gather, CTIO packet data", pkt,
65926+ REQUEST_ENTRY_SIZE);
65927+
65928+ q2t_load_cont_data_segments(prm);
65929+
65930+out:
65931+ return;
65932+}
65933+
65934+/*
65935+ * ha->hardware_lock supposed to be held on entry. We have already made sure
65936+ * that there is sufficient amount of request entries to not drop it.
65937+ */
65938+static void q24_load_data_segments(struct q2t_prm *prm)
65939+{
65940+ int cnt;
65941+ uint32_t *dword_ptr;
65942+ int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr;
65943+ ctio7_status0_entry_t *pkt = (ctio7_status0_entry_t *)prm->pkt;
65944+
65945+ TRACE_DBG("iocb->scsi_status=%x, iocb->flags=%x",
65946+ le16_to_cpu(pkt->scsi_status), le16_to_cpu(pkt->flags));
65947+
65948+ pkt->transfer_length = cpu_to_le32(prm->cmd->bufflen);
65949+
65950+ /* Setup packet address segment pointer */
65951+ dword_ptr = pkt->dseg_0_address;
65952+
65953+ if (prm->seg_cnt == 0) {
65954+ /* No data transfer */
65955+ *dword_ptr++ = 0;
65956+ *dword_ptr = 0;
65957+
65958+ TRACE_BUFFER("No data, CTIO7 packet data", pkt,
65959+ REQUEST_ENTRY_SIZE);
65960+ goto out;
65961+ }
65962+
65963+ /* Set total data segment count */
65964+ pkt->common.dseg_count = cpu_to_le16(prm->seg_cnt);
65965+
65966+ /* If scatter gather */
65967+ TRACE_SG("%s", "Building S/G data segments...");
65968+ /* Load command entry data segments */
65969+ for (cnt = 0;
65970+ (cnt < prm->tgt->datasegs_per_cmd) && prm->seg_cnt;
65971+ cnt++, prm->seg_cnt--) {
65972+ *dword_ptr++ =
65973+ cpu_to_le32(pci_dma_lo32(sg_dma_address(prm->sg)));
65974+ if (enable_64bit_addressing) {
65975+ *dword_ptr++ =
65976+ cpu_to_le32(pci_dma_hi32(
65977+ sg_dma_address(prm->sg)));
65978+ }
65979+ *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg));
65980+
65981+ TRACE_SG("S/G Segment phys_addr=%llx:%llx, len=%d",
65982+ (long long unsigned int)pci_dma_hi32(sg_dma_address(
65983+ prm->sg)),
65984+ (long long unsigned int)pci_dma_lo32(sg_dma_address(
65985+ prm->sg)),
65986+ (int)sg_dma_len(prm->sg));
65987+
65988+ prm->sg++;
65989+ }
65990+
65991+ q2t_load_cont_data_segments(prm);
65992+
65993+out:
65994+ return;
65995+}
65996+
65997+static inline int q2t_has_data(struct q2t_cmd *cmd)
65998+{
65999+ return cmd->bufflen > 0;
66000+}
66001+
66002+static int q2t_pre_xmit_response(struct q2t_cmd *cmd,
66003+ struct q2t_prm *prm, int xmit_type, unsigned long *flags)
66004+{
66005+ int res;
66006+ struct q2t_tgt *tgt = cmd->tgt;
66007+ scsi_qla_host_t *ha = tgt->ha;
66008+ uint16_t full_req_cnt;
66009+ struct scst_cmd *scst_cmd = cmd->scst_cmd;
66010+
66011+ TRACE_ENTRY();
66012+
66013+ if (unlikely(cmd->aborted)) {
66014+ TRACE_MGMT_DBG("qla2x00t(%ld): terminating exchange "
66015+ "for aborted cmd=%p (scst_cmd=%p, tag=%d)",
66016+ ha->instance, cmd, scst_cmd, cmd->tag);
66017+
66018+ cmd->state = Q2T_STATE_ABORTED;
66019+ scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_ABORTED);
66020+
66021+ if (IS_FWI2_CAPABLE(ha))
66022+ q24_send_term_exchange(ha, cmd, &cmd->atio.atio7, 0);
66023+ else
66024+ q2x_send_term_exchange(ha, cmd, &cmd->atio.atio2x, 0);
66025+ /* !! At this point cmd could be already freed !! */
66026+ res = Q2T_PRE_XMIT_RESP_CMD_ABORTED;
66027+ goto out;
66028+ }
66029+
66030+ TRACE(TRACE_SCSI, "qla2x00t(%ld): tag=%lld", ha->instance,
66031+ scst_cmd_get_tag(scst_cmd));
66032+
66033+ prm->cmd = cmd;
66034+ prm->tgt = tgt;
66035+ prm->rq_result = scst_cmd_get_status(scst_cmd);
66036+ prm->sense_buffer = scst_cmd_get_sense_buffer(scst_cmd);
66037+ prm->sense_buffer_len = scst_cmd_get_sense_buffer_len(scst_cmd);
66038+ prm->sg = NULL;
66039+ prm->seg_cnt = -1;
66040+ prm->req_cnt = 1;
66041+ prm->add_status_pkt = 0;
66042+
66043+ TRACE_DBG("rq_result=%x, xmit_type=%x", prm->rq_result, xmit_type);
66044+ if (prm->rq_result != 0)
66045+ TRACE_BUFFER("Sense", prm->sense_buffer, prm->sense_buffer_len);
66046+
66047+ /* Send marker if required */
66048+ if (q2t_issue_marker(ha, 0) != QLA_SUCCESS) {
66049+ res = SCST_TGT_RES_FATAL_ERROR;
66050+ goto out;
66051+ }
66052+
66053+ TRACE_DBG("CTIO start: ha(%d)", (int)ha->instance);
66054+
66055+ if ((xmit_type & Q2T_XMIT_DATA) && q2t_has_data(cmd)) {
66056+ if (q2t_pci_map_calc_cnt(prm) != 0) {
66057+ res = SCST_TGT_RES_QUEUE_FULL;
66058+ goto out;
66059+ }
66060+ }
66061+
66062+ full_req_cnt = prm->req_cnt;
66063+
66064+ if (xmit_type & Q2T_XMIT_STATUS) {
66065+ /* Bidirectional transfers not supported (yet) */
66066+ if (unlikely(scst_get_resid(scst_cmd, &prm->residual, NULL))) {
66067+ if (prm->residual > 0) {
66068+ TRACE_DBG("Residual underflow: %d (tag %lld, "
66069+ "op %x, bufflen %d, rq_result %x)",
66070+ prm->residual, scst_cmd->tag,
66071+ scst_cmd->cdb[0], cmd->bufflen,
66072+ prm->rq_result);
66073+ prm->rq_result |= SS_RESIDUAL_UNDER;
66074+ } else if (prm->residual < 0) {
66075+ TRACE_DBG("Residual overflow: %d (tag %lld, "
66076+ "op %x, bufflen %d, rq_result %x)",
66077+ prm->residual, scst_cmd->tag,
66078+ scst_cmd->cdb[0], cmd->bufflen,
66079+ prm->rq_result);
66080+ prm->rq_result |= SS_RESIDUAL_OVER;
66081+ prm->residual = -prm->residual;
66082+ }
66083+ }
66084+
66085+ /*
66086+ * If Q2T_XMIT_DATA is not set, add_status_pkt will be ignored
66087+ * in *xmit_response() below
66088+ */
66089+ if (q2t_has_data(cmd)) {
66090+ if (SCST_SENSE_VALID(prm->sense_buffer) ||
66091+ (IS_FWI2_CAPABLE(ha) &&
66092+ (prm->rq_result != 0))) {
66093+ prm->add_status_pkt = 1;
66094+ full_req_cnt++;
66095+ }
66096+ }
66097+ }
66098+
66099+ TRACE_DBG("req_cnt=%d, full_req_cnt=%d, add_status_pkt=%d",
66100+ prm->req_cnt, full_req_cnt, prm->add_status_pkt);
66101+
66102+ /* Acquire ring specific lock */
66103+ spin_lock_irqsave(&ha->hardware_lock, *flags);
66104+
66105+ /* Does F/W have an IOCBs for this request */
66106+ res = q2t_check_reserve_free_req(ha, full_req_cnt);
66107+ if (unlikely(res != SCST_TGT_RES_SUCCESS) &&
66108+ (xmit_type & Q2T_XMIT_DATA))
66109+ goto out_unlock_free_unmap;
66110+
66111+out:
66112+ TRACE_EXIT_RES(res);
66113+ return res;
66114+
66115+out_unlock_free_unmap:
66116+ if (cmd->sg_mapped)
66117+ q2t_unmap_sg(ha, cmd);
66118+
66119+ /* Release ring specific lock */
66120+ spin_unlock_irqrestore(&ha->hardware_lock, *flags);
66121+ goto out;
66122+}
66123+
66124+static inline int q2t_need_explicit_conf(scsi_qla_host_t *ha,
66125+ struct q2t_cmd *cmd, int sending_sense)
66126+{
66127+ if (ha->enable_class_2)
66128+ return 0;
66129+
66130+ if (sending_sense)
66131+ return cmd->conf_compl_supported;
66132+ else
66133+ return ha->enable_explicit_conf && cmd->conf_compl_supported;
66134+}
66135+
66136+static void q2x_init_ctio_ret_entry(ctio_ret_entry_t *ctio_m1,
66137+ struct q2t_prm *prm)
66138+{
66139+ TRACE_ENTRY();
66140+
66141+ prm->sense_buffer_len = min((uint32_t)prm->sense_buffer_len,
66142+ (uint32_t)sizeof(ctio_m1->sense_data));
66143+
66144+ ctio_m1->flags = __constant_cpu_to_le16(OF_SSTS | OF_FAST_POST |
66145+ OF_NO_DATA | OF_SS_MODE_1);
66146+ ctio_m1->flags |= __constant_cpu_to_le16(OF_INC_RC);
66147+ if (q2t_need_explicit_conf(prm->tgt->ha, prm->cmd, 0)) {
66148+ ctio_m1->flags |= __constant_cpu_to_le16(OF_EXPL_CONF |
66149+ OF_CONF_REQ);
66150+ }
66151+ ctio_m1->scsi_status = cpu_to_le16(prm->rq_result);
66152+ ctio_m1->residual = cpu_to_le32(prm->residual);
66153+ if (SCST_SENSE_VALID(prm->sense_buffer)) {
66154+ if (q2t_need_explicit_conf(prm->tgt->ha, prm->cmd, 1)) {
66155+ ctio_m1->flags |= __constant_cpu_to_le16(OF_EXPL_CONF |
66156+ OF_CONF_REQ);
66157+ }
66158+ ctio_m1->scsi_status |= __constant_cpu_to_le16(
66159+ SS_SENSE_LEN_VALID);
66160+ ctio_m1->sense_length = cpu_to_le16(prm->sense_buffer_len);
66161+ memcpy(ctio_m1->sense_data, prm->sense_buffer,
66162+ prm->sense_buffer_len);
66163+ } else {
66164+ memset(ctio_m1->sense_data, 0, sizeof(ctio_m1->sense_data));
66165+ ctio_m1->sense_length = 0;
66166+ }
66167+
66168+ /* Sense with len > 26, is it possible ??? */
66169+
66170+ TRACE_EXIT();
66171+ return;
66172+}
66173+
66174+static int __q2x_xmit_response(struct q2t_cmd *cmd, int xmit_type)
66175+{
66176+ int res;
66177+ unsigned long flags;
66178+ scsi_qla_host_t *ha;
66179+ struct q2t_prm prm;
66180+ ctio_common_entry_t *pkt;
66181+
66182+ TRACE_ENTRY();
66183+
66184+ memset(&prm, 0, sizeof(prm));
66185+
66186+ res = q2t_pre_xmit_response(cmd, &prm, xmit_type, &flags);
66187+ if (unlikely(res != SCST_TGT_RES_SUCCESS)) {
66188+ if (res == Q2T_PRE_XMIT_RESP_CMD_ABORTED)
66189+ res = SCST_TGT_RES_SUCCESS;
66190+ goto out;
66191+ }
66192+
66193+ /* Here ha->hardware_lock already locked */
66194+
66195+ ha = prm.tgt->ha;
66196+
66197+ q2x_build_ctio_pkt(&prm);
66198+ pkt = (ctio_common_entry_t *)prm.pkt;
66199+
66200+ if (q2t_has_data(cmd) && (xmit_type & Q2T_XMIT_DATA)) {
66201+ pkt->flags |= __constant_cpu_to_le16(OF_FAST_POST | OF_DATA_IN);
66202+ pkt->flags |= __constant_cpu_to_le16(OF_INC_RC);
66203+
66204+ q2x_load_data_segments(&prm);
66205+
66206+ if (prm.add_status_pkt == 0) {
66207+ if (xmit_type & Q2T_XMIT_STATUS) {
66208+ pkt->scsi_status = cpu_to_le16(prm.rq_result);
66209+ pkt->residual = cpu_to_le32(prm.residual);
66210+ pkt->flags |= __constant_cpu_to_le16(OF_SSTS);
66211+ if (q2t_need_explicit_conf(ha, cmd, 0)) {
66212+ pkt->flags |= __constant_cpu_to_le16(
66213+ OF_EXPL_CONF |
66214+ OF_CONF_REQ);
66215+ }
66216+ }
66217+ } else {
66218+ /*
66219+ * We have already made sure that there is sufficient
66220+ * amount of request entries to not drop HW lock in
66221+ * req_pkt().
66222+ */
66223+ ctio_ret_entry_t *ctio_m1 =
66224+ (ctio_ret_entry_t *)q2t_get_req_pkt(ha);
66225+
66226+ TRACE_DBG("%s", "Building additional status packet");
66227+
66228+ memcpy(ctio_m1, pkt, sizeof(*ctio_m1));
66229+ ctio_m1->entry_count = 1;
66230+ ctio_m1->dseg_count = 0;
66231+
66232+ /* Real finish is ctio_m1's finish */
66233+ pkt->handle |= CTIO_INTERMEDIATE_HANDLE_MARK;
66234+ pkt->flags &= ~__constant_cpu_to_le16(OF_INC_RC);
66235+
66236+ q2x_init_ctio_ret_entry(ctio_m1, &prm);
66237+ TRACE_BUFFER("Status CTIO packet data", ctio_m1,
66238+ REQUEST_ENTRY_SIZE);
66239+ }
66240+ } else
66241+ q2x_init_ctio_ret_entry((ctio_ret_entry_t *)pkt, &prm);
66242+
66243+ cmd->state = Q2T_STATE_PROCESSED; /* Mid-level is done processing */
66244+
66245+ TRACE_BUFFER("Xmitting", pkt, REQUEST_ENTRY_SIZE);
66246+
66247+ q2t_exec_queue(ha);
66248+
66249+ /* Release ring specific lock */
66250+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
66251+
66252+out:
66253+ TRACE_EXIT_RES(res);
66254+ return res;
66255+}
66256+
66257+#ifdef CONFIG_QLA_TGT_DEBUG_SRR
66258+static void q2t_check_srr_debug(struct q2t_cmd *cmd, int *xmit_type)
66259+{
66260+#if 0 /* This is not a real status packets lost, so it won't lead to SRR */
66261+ if ((*xmit_type & Q2T_XMIT_STATUS) && (scst_random() % 200) == 50) {
66262+ *xmit_type &= ~Q2T_XMIT_STATUS;
66263+ TRACE_MGMT_DBG("Dropping cmd %p (tag %d) status", cmd,
66264+ cmd->tag);
66265+ }
66266+#endif
66267+
66268+ if (q2t_has_data(cmd) && (cmd->sg_cnt > 1) &&
66269+ ((scst_random() % 100) == 20)) {
66270+ int i, leave = 0;
66271+ unsigned int tot_len = 0;
66272+
66273+ while (leave == 0)
66274+ leave = scst_random() % cmd->sg_cnt;
66275+
66276+ for (i = 0; i < leave; i++)
66277+ tot_len += cmd->sg[i].length;
66278+
66279+ TRACE_MGMT_DBG("Cutting cmd %p (tag %d) buffer tail to len %d, "
66280+ "sg_cnt %d (cmd->bufflen %d, cmd->sg_cnt %d)", cmd,
66281+ cmd->tag, tot_len, leave, cmd->bufflen, cmd->sg_cnt);
66282+
66283+ cmd->bufflen = tot_len;
66284+ cmd->sg_cnt = leave;
66285+ }
66286+
66287+ if (q2t_has_data(cmd) && ((scst_random() % 100) == 70)) {
66288+ unsigned int offset = scst_random() % cmd->bufflen;
66289+
66290+ TRACE_MGMT_DBG("Cutting cmd %p (tag %d) buffer head "
66291+ "to offset %d (cmd->bufflen %d)", cmd, cmd->tag,
66292+ offset, cmd->bufflen);
66293+ if (offset == 0)
66294+ *xmit_type &= ~Q2T_XMIT_DATA;
66295+ else if (q2t_cut_cmd_data_head(cmd, offset)) {
66296+ TRACE_MGMT_DBG("q2t_cut_cmd_data_head() failed (tag %d)",
66297+ cmd->tag);
66298+ }
66299+ }
66300+}
66301+#else
66302+static inline void q2t_check_srr_debug(struct q2t_cmd *cmd, int *xmit_type) {}
66303+#endif
66304+
66305+static int q2x_xmit_response(struct scst_cmd *scst_cmd)
66306+{
66307+ int xmit_type = Q2T_XMIT_DATA, res;
66308+ int is_send_status = scst_cmd_get_is_send_status(scst_cmd);
66309+ struct q2t_cmd *cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
66310+
66311+#ifdef CONFIG_SCST_EXTRACHECKS
66312+ BUG_ON(!q2t_has_data(cmd) && !is_send_status);
66313+#endif
66314+
66315+#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
66316+ EXTRACHECKS_BUG_ON(scst_cmd_atomic(scst_cmd));
66317+#endif
66318+
66319+ if (is_send_status)
66320+ xmit_type |= Q2T_XMIT_STATUS;
66321+
66322+ cmd->bufflen = scst_cmd_get_adjusted_resp_data_len(scst_cmd);
66323+ cmd->sg = scst_cmd_get_sg(scst_cmd);
66324+ cmd->sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
66325+ cmd->data_direction = scst_cmd_get_data_direction(scst_cmd);
66326+ cmd->dma_data_direction = scst_to_tgt_dma_dir(cmd->data_direction);
66327+ cmd->offset = scst_cmd_get_ppl_offset(scst_cmd);
66328+ cmd->aborted = scst_cmd_aborted(scst_cmd);
66329+
66330+ q2t_check_srr_debug(cmd, &xmit_type);
66331+
66332+ TRACE_DBG("is_send_status=%x, cmd->bufflen=%d, cmd->sg_cnt=%d, "
66333+ "cmd->data_direction=%d", is_send_status, cmd->bufflen,
66334+ cmd->sg_cnt, cmd->data_direction);
66335+
66336+ if (IS_FWI2_CAPABLE(cmd->tgt->ha))
66337+ res = __q24_xmit_response(cmd, xmit_type);
66338+ else
66339+ res = __q2x_xmit_response(cmd, xmit_type);
66340+
66341+ return res;
66342+}
66343+
66344+static void q24_init_ctio_ret_entry(ctio7_status0_entry_t *ctio,
66345+ struct q2t_prm *prm)
66346+{
66347+ ctio7_status1_entry_t *ctio1;
66348+
66349+ TRACE_ENTRY();
66350+
66351+ prm->sense_buffer_len = min((uint32_t)prm->sense_buffer_len,
66352+ (uint32_t)sizeof(ctio1->sense_data));
66353+ ctio->flags |= __constant_cpu_to_le16(CTIO7_FLAGS_SEND_STATUS);
66354+ if (q2t_need_explicit_conf(prm->tgt->ha, prm->cmd, 0)) {
66355+ ctio->flags |= __constant_cpu_to_le16(
66356+ CTIO7_FLAGS_EXPLICIT_CONFORM |
66357+ CTIO7_FLAGS_CONFORM_REQ);
66358+ }
66359+ ctio->residual = cpu_to_le32(prm->residual);
66360+ ctio->scsi_status = cpu_to_le16(prm->rq_result);
66361+ if (SCST_SENSE_VALID(prm->sense_buffer)) {
66362+ int i;
66363+ ctio1 = (ctio7_status1_entry_t *)ctio;
66364+ if (q2t_need_explicit_conf(prm->tgt->ha, prm->cmd, 1)) {
66365+ ctio1->flags |= __constant_cpu_to_le16(
66366+ CTIO7_FLAGS_EXPLICIT_CONFORM |
66367+ CTIO7_FLAGS_CONFORM_REQ);
66368+ }
66369+ ctio1->flags &= ~__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0);
66370+ ctio1->flags |= __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1);
66371+ ctio1->scsi_status |= __constant_cpu_to_le16(SS_SENSE_LEN_VALID);
66372+ ctio1->sense_length = cpu_to_le16(prm->sense_buffer_len);
66373+ for (i = 0; i < prm->sense_buffer_len/4; i++)
66374+ ((uint32_t *)ctio1->sense_data)[i] =
66375+ cpu_to_be32(((uint32_t *)prm->sense_buffer)[i]);
66376+#if 0
66377+ if (unlikely((prm->sense_buffer_len % 4) != 0)) {
66378+ static int q;
66379+ if (q < 10) {
66380+ PRINT_INFO("qla2x00t(%ld): %d bytes of sense "
66381+ "lost", prm->tgt->ha->instance,
66382+ prm->sense_buffer_len % 4);
66383+ q++;
66384+ }
66385+ }
66386+#endif
66387+ } else {
66388+ ctio1 = (ctio7_status1_entry_t *)ctio;
66389+ ctio1->flags &= ~__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0);
66390+ ctio1->flags |= __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1);
66391+ ctio1->sense_length = 0;
66392+ memset(ctio1->sense_data, 0, sizeof(ctio1->sense_data));
66393+ }
66394+
66395+ /* Sense with len > 24, is it possible ??? */
66396+
66397+ TRACE_EXIT();
66398+ return;
66399+}
66400+
66401+static int __q24_xmit_response(struct q2t_cmd *cmd, int xmit_type)
66402+{
66403+ int res;
66404+ unsigned long flags;
66405+ scsi_qla_host_t *ha;
66406+ struct q2t_prm prm;
66407+ ctio7_status0_entry_t *pkt;
66408+
66409+ TRACE_ENTRY();
66410+
66411+ memset(&prm, 0, sizeof(prm));
66412+
66413+ res = q2t_pre_xmit_response(cmd, &prm, xmit_type, &flags);
66414+ if (unlikely(res != SCST_TGT_RES_SUCCESS)) {
66415+ if (res == Q2T_PRE_XMIT_RESP_CMD_ABORTED)
66416+ res = SCST_TGT_RES_SUCCESS;
66417+ goto out;
66418+ }
66419+
66420+ /* Here ha->hardware_lock already locked */
66421+
66422+ ha = prm.tgt->ha;
66423+
66424+ res = q24_build_ctio_pkt(&prm);
66425+ if (unlikely(res != SCST_TGT_RES_SUCCESS))
66426+ goto out_unmap_unlock;
66427+
66428+ pkt = (ctio7_status0_entry_t *)prm.pkt;
66429+
66430+ if (q2t_has_data(cmd) && (xmit_type & Q2T_XMIT_DATA)) {
66431+ pkt->flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_IN |
66432+ CTIO7_FLAGS_STATUS_MODE_0);
66433+
66434+ q24_load_data_segments(&prm);
66435+
66436+ if (prm.add_status_pkt == 0) {
66437+ if (xmit_type & Q2T_XMIT_STATUS) {
66438+ pkt->scsi_status = cpu_to_le16(prm.rq_result);
66439+ pkt->residual = cpu_to_le32(prm.residual);
66440+ pkt->flags |= __constant_cpu_to_le16(
66441+ CTIO7_FLAGS_SEND_STATUS);
66442+ if (q2t_need_explicit_conf(ha, cmd, 0)) {
66443+ pkt->flags |= __constant_cpu_to_le16(
66444+ CTIO7_FLAGS_EXPLICIT_CONFORM |
66445+ CTIO7_FLAGS_CONFORM_REQ);
66446+ }
66447+ }
66448+ } else {
66449+ /*
66450+ * We have already made sure that there is sufficient
66451+ * amount of request entries to not drop HW lock in
66452+ * req_pkt().
66453+ */
66454+ ctio7_status1_entry_t *ctio =
66455+ (ctio7_status1_entry_t *)q2t_get_req_pkt(ha);
66456+
66457+ TRACE_DBG("%s", "Building additional status packet");
66458+
66459+ memcpy(ctio, pkt, sizeof(*ctio));
66460+ ctio->common.entry_count = 1;
66461+ ctio->common.dseg_count = 0;
66462+ ctio->flags &= ~__constant_cpu_to_le16(
66463+ CTIO7_FLAGS_DATA_IN);
66464+
66465+ /* Real finish is ctio_m1's finish */
66466+ pkt->common.handle |= CTIO_INTERMEDIATE_HANDLE_MARK;
66467+ pkt->flags |= __constant_cpu_to_le16(
66468+ CTIO7_FLAGS_DONT_RET_CTIO);
66469+ q24_init_ctio_ret_entry((ctio7_status0_entry_t *)ctio,
66470+ &prm);
66471+ TRACE_BUFFER("Status CTIO7", ctio, REQUEST_ENTRY_SIZE);
66472+ }
66473+ } else
66474+ q24_init_ctio_ret_entry(pkt, &prm);
66475+
66476+ cmd->state = Q2T_STATE_PROCESSED; /* Mid-level is done processing */
66477+
66478+ TRACE_BUFFER("Xmitting CTIO7", pkt, REQUEST_ENTRY_SIZE);
66479+
66480+ q2t_exec_queue(ha);
66481+
66482+out_unlock:
66483+ /* Release ring specific lock */
66484+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
66485+
66486+out:
66487+ TRACE_EXIT_RES(res);
66488+ return res;
66489+
66490+out_unmap_unlock:
66491+ if (cmd->sg_mapped)
66492+ q2t_unmap_sg(ha, cmd);
66493+ goto out_unlock;
66494+}
66495+
66496+static int __q2t_rdy_to_xfer(struct q2t_cmd *cmd)
66497+{
66498+ int res = SCST_TGT_RES_SUCCESS;
66499+ unsigned long flags;
66500+ scsi_qla_host_t *ha;
66501+ struct q2t_tgt *tgt = cmd->tgt;
66502+ struct q2t_prm prm;
66503+ void *p;
66504+
66505+ TRACE_ENTRY();
66506+
66507+ memset(&prm, 0, sizeof(prm));
66508+ prm.cmd = cmd;
66509+ prm.tgt = tgt;
66510+ prm.sg = NULL;
66511+ prm.req_cnt = 1;
66512+ ha = tgt->ha;
66513+
66514+ /* Send marker if required */
66515+ if (q2t_issue_marker(ha, 0) != QLA_SUCCESS) {
66516+ res = SCST_TGT_RES_FATAL_ERROR;
66517+ goto out;
66518+ }
66519+
66520+ TRACE_DBG("CTIO_start: ha(%d)", (int)ha->instance);
66521+
66522+ /* Calculate number of entries and segments required */
66523+ if (q2t_pci_map_calc_cnt(&prm) != 0) {
66524+ res = SCST_TGT_RES_QUEUE_FULL;
66525+ goto out;
66526+ }
66527+
66528+ /* Acquire ring specific lock */
66529+ spin_lock_irqsave(&ha->hardware_lock, flags);
66530+
66531+ /* Does F/W have an IOCBs for this request */
66532+ res = q2t_check_reserve_free_req(ha, prm.req_cnt);
66533+ if (res != SCST_TGT_RES_SUCCESS)
66534+ goto out_unlock_free_unmap;
66535+
66536+ if (IS_FWI2_CAPABLE(ha)) {
66537+ ctio7_status0_entry_t *pkt;
66538+ res = q24_build_ctio_pkt(&prm);
66539+ if (unlikely(res != SCST_TGT_RES_SUCCESS))
66540+ goto out_unlock_free_unmap;
66541+ pkt = (ctio7_status0_entry_t *)prm.pkt;
66542+ pkt->flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_OUT |
66543+ CTIO7_FLAGS_STATUS_MODE_0);
66544+ q24_load_data_segments(&prm);
66545+ p = pkt;
66546+ } else {
66547+ ctio_common_entry_t *pkt;
66548+ q2x_build_ctio_pkt(&prm);
66549+ pkt = (ctio_common_entry_t *)prm.pkt;
66550+ pkt->flags = __constant_cpu_to_le16(OF_FAST_POST | OF_DATA_OUT);
66551+ q2x_load_data_segments(&prm);
66552+ p = pkt;
66553+ }
66554+
66555+ cmd->state = Q2T_STATE_NEED_DATA;
66556+
66557+ TRACE_BUFFER("Xfering", p, REQUEST_ENTRY_SIZE);
66558+
66559+ q2t_exec_queue(ha);
66560+
66561+out_unlock:
66562+ /* Release ring specific lock */
66563+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
66564+
66565+out:
66566+ TRACE_EXIT_RES(res);
66567+ return res;
66568+
66569+out_unlock_free_unmap:
66570+ if (cmd->sg_mapped)
66571+ q2t_unmap_sg(ha, cmd);
66572+ goto out_unlock;
66573+}
66574+
66575+static int q2t_rdy_to_xfer(struct scst_cmd *scst_cmd)
66576+{
66577+ int res;
66578+ struct q2t_cmd *cmd;
66579+
66580+ TRACE_ENTRY();
66581+
66582+ TRACE(TRACE_SCSI, "qla2x00t: tag=%lld", scst_cmd_get_tag(scst_cmd));
66583+
66584+ cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
66585+ cmd->bufflen = scst_cmd_get_write_fields(scst_cmd, &cmd->sg,
66586+ &cmd->sg_cnt);
66587+ cmd->data_direction = scst_cmd_get_data_direction(scst_cmd);
66588+ cmd->dma_data_direction = scst_to_tgt_dma_dir(cmd->data_direction);
66589+
66590+ res = __q2t_rdy_to_xfer(cmd);
66591+
66592+ TRACE_EXIT();
66593+ return res;
66594+}
66595+
66596+/* If hardware_lock held on entry, might drop it, then reaquire */
66597+static void q2x_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
66598+ atio_entry_t *atio, int ha_locked)
66599+{
66600+ ctio_ret_entry_t *ctio;
66601+ unsigned long flags = 0; /* to stop compiler's warning */
66602+ int do_tgt_cmd_done = 0;
66603+
66604+ TRACE_ENTRY();
66605+
66606+ TRACE_DBG("Sending TERM EXCH CTIO (ha=%p)", ha);
66607+
66608+ /* Send marker if required */
66609+ if (q2t_issue_marker(ha, ha_locked) != QLA_SUCCESS)
66610+ goto out;
66611+
66612+ if (!ha_locked)
66613+ spin_lock_irqsave(&ha->hardware_lock, flags);
66614+
66615+ ctio = (ctio_ret_entry_t *)qla2x00_req_pkt(ha);
66616+ if (ctio == NULL) {
66617+ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
66618+ "request packet", ha->instance, __func__);
66619+ goto out_unlock;
66620+ }
66621+
66622+ ctio->entry_type = CTIO_RET_TYPE;
66623+ ctio->entry_count = 1;
66624+ if (cmd != NULL) {
66625+ if (cmd->state < Q2T_STATE_PROCESSED) {
66626+ PRINT_ERROR("qla2x00t(%ld): Terminating cmd %p with "
66627+ "incorrect state %d", ha->instance, cmd,
66628+ cmd->state);
66629+ } else
66630+ do_tgt_cmd_done = 1;
66631+ }
66632+ ctio->handle = Q2T_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
66633+
66634+ /* Set IDs */
66635+ SET_TARGET_ID(ha, ctio->target, GET_TARGET_ID(ha, atio));
66636+ ctio->rx_id = atio->rx_id;
66637+
66638+ /* Most likely, it isn't needed */
66639+ ctio->residual = atio->data_length;
66640+ if (ctio->residual != 0)
66641+ ctio->scsi_status |= SS_RESIDUAL_UNDER;
66642+
66643+ ctio->flags = __constant_cpu_to_le16(OF_FAST_POST | OF_TERM_EXCH |
66644+ OF_NO_DATA | OF_SS_MODE_1);
66645+ ctio->flags |= __constant_cpu_to_le16(OF_INC_RC);
66646+
66647+ TRACE_BUFFER("CTIO TERM EXCH packet data", ctio, REQUEST_ENTRY_SIZE);
66648+
66649+ q2t_exec_queue(ha);
66650+
66651+out_unlock:
66652+ if (!ha_locked)
66653+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
66654+
66655+ if (do_tgt_cmd_done) {
66656+ if (!ha_locked && !in_interrupt()) {
66657+ msleep(250); /* just in case */
66658+ scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_DIRECT);
66659+ } else
66660+ scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_TASKLET);
66661+ /* !! At this point cmd could be already freed !! */
66662+ }
66663+
66664+out:
66665+ TRACE_EXIT();
66666+ return;
66667+}
66668+
66669+/* If hardware_lock held on entry, might drop it, then reaquire */
66670+static void q24_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
66671+ atio7_entry_t *atio, int ha_locked)
66672+{
66673+ ctio7_status1_entry_t *ctio;
66674+ unsigned long flags = 0; /* to stop compiler's warning */
66675+ int do_tgt_cmd_done = 0;
66676+
66677+ TRACE_ENTRY();
66678+
66679+ TRACE_DBG("Sending TERM EXCH CTIO7 (ha=%p)", ha);
66680+
66681+ /* Send marker if required */
66682+ if (q2t_issue_marker(ha, ha_locked) != QLA_SUCCESS)
66683+ goto out;
66684+
66685+ if (!ha_locked)
66686+ spin_lock_irqsave(&ha->hardware_lock, flags);
66687+
66688+ ctio = (ctio7_status1_entry_t *)qla2x00_req_pkt(ha);
66689+ if (ctio == NULL) {
66690+ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
66691+ "request packet", ha->instance, __func__);
66692+ goto out_unlock;
66693+ }
66694+
66695+ ctio->common.entry_type = CTIO_TYPE7;
66696+ ctio->common.entry_count = 1;
66697+ if (cmd != NULL) {
66698+ ctio->common.nport_handle = cmd->loop_id;
66699+ if (cmd->state < Q2T_STATE_PROCESSED) {
66700+ PRINT_ERROR("qla2x00t(%ld): Terminating cmd %p with "
66701+ "incorrect state %d", ha->instance, cmd,
66702+ cmd->state);
66703+ } else
66704+ do_tgt_cmd_done = 1;
66705+ } else
66706+ ctio->common.nport_handle = CTIO7_NHANDLE_UNRECOGNIZED;
66707+ ctio->common.handle = Q2T_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
66708+ ctio->common.timeout = __constant_cpu_to_le16(Q2T_TIMEOUT);
66709+ ctio->common.initiator_id[0] = atio->fcp_hdr.s_id[2];
66710+ ctio->common.initiator_id[1] = atio->fcp_hdr.s_id[1];
66711+ ctio->common.initiator_id[2] = atio->fcp_hdr.s_id[0];
66712+ ctio->common.exchange_addr = atio->exchange_addr;
66713+ ctio->flags = (atio->attr << 9) | __constant_cpu_to_le16(
66714+ CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_TERMINATE);
66715+ ctio->ox_id = swab16(atio->fcp_hdr.ox_id);
66716+
66717+ /* Most likely, it isn't needed */
66718+ ctio->residual = atio->fcp_cmnd.data_length;
66719+ if (ctio->residual != 0)
66720+ ctio->scsi_status |= SS_RESIDUAL_UNDER;
66721+
66722+ TRACE_BUFFER("CTIO7 TERM EXCH packet data", ctio, REQUEST_ENTRY_SIZE);
66723+
66724+ q2t_exec_queue(ha);
66725+
66726+out_unlock:
66727+ if (!ha_locked)
66728+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
66729+
66730+ if (do_tgt_cmd_done) {
66731+ if (!ha_locked && !in_interrupt()) {
66732+ msleep(250); /* just in case */
66733+ scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_DIRECT);
66734+ } else
66735+ scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_TASKLET);
66736+ /* !! At this point cmd could be already freed !! */
66737+ }
66738+
66739+out:
66740+ TRACE_EXIT();
66741+ return;
66742+}
66743+
66744+static inline void q2t_free_cmd(struct q2t_cmd *cmd)
66745+{
66746+ EXTRACHECKS_BUG_ON(cmd->sg_mapped);
66747+
66748+ if (unlikely(cmd->free_sg))
66749+ kfree(cmd->sg);
66750+ kmem_cache_free(q2t_cmd_cachep, cmd);
66751+}
66752+
66753+static void q2t_on_free_cmd(struct scst_cmd *scst_cmd)
66754+{
66755+ struct q2t_cmd *cmd;
66756+
66757+ TRACE_ENTRY();
66758+
66759+ TRACE(TRACE_SCSI, "qla2x00t: Freeing command %p, tag %lld",
66760+ scst_cmd, scst_cmd_get_tag(scst_cmd));
66761+
66762+ cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
66763+ scst_cmd_set_tgt_priv(scst_cmd, NULL);
66764+
66765+ q2t_free_cmd(cmd);
66766+
66767+ TRACE_EXIT();
66768+ return;
66769+}
66770+
66771+/* ha->hardware_lock supposed to be held on entry */
66772+static int q2t_prepare_srr_ctio(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
66773+ void *ctio)
66774+{
66775+ struct srr_ctio *sc;
66776+ struct q2t_tgt *tgt = ha->tgt;
66777+ int res = 0;
66778+ struct srr_imm *imm;
66779+
66780+ tgt->ctio_srr_id++;
66781+
66782+ TRACE_MGMT_DBG("qla2x00t(%ld): CTIO with SRR "
66783+ "status received", ha->instance);
66784+
66785+ if (ctio == NULL) {
66786+ PRINT_ERROR("qla2x00t(%ld): SRR CTIO, "
66787+ "but ctio is NULL", ha->instance);
66788+ res = -EINVAL;
66789+ goto out;
66790+ }
66791+
66792+ if (cmd->scst_cmd != NULL)
66793+ scst_update_hw_pending_start(cmd->scst_cmd);
66794+
66795+ sc = kzalloc(sizeof(*sc), GFP_ATOMIC);
66796+ if (sc != NULL) {
66797+ sc->cmd = cmd;
66798+ /* IRQ is already OFF */
66799+ spin_lock(&tgt->srr_lock);
66800+ sc->srr_id = tgt->ctio_srr_id;
66801+ list_add_tail(&sc->srr_list_entry,
66802+ &tgt->srr_ctio_list);
66803+ TRACE_MGMT_DBG("CTIO SRR %p added (id %d)",
66804+ sc, sc->srr_id);
66805+ if (tgt->imm_srr_id == tgt->ctio_srr_id) {
66806+ int found = 0;
66807+ list_for_each_entry(imm, &tgt->srr_imm_list,
66808+ srr_list_entry) {
66809+ if (imm->srr_id == sc->srr_id) {
66810+ found = 1;
66811+ break;
66812+ }
66813+ }
66814+ if (found) {
66815+ TRACE_MGMT_DBG("%s", "Scheduling srr work");
66816+ schedule_work(&tgt->srr_work);
66817+ } else {
66818+ PRINT_ERROR("qla2x00t(%ld): imm_srr_id "
66819+ "== ctio_srr_id (%d), but there is no "
66820+ "corresponding SRR IMM, deleting CTIO "
66821+ "SRR %p", ha->instance, tgt->ctio_srr_id,
66822+ sc);
66823+ list_del(&sc->srr_list_entry);
66824+ spin_unlock(&tgt->srr_lock);
66825+
66826+ kfree(sc);
66827+ res = -EINVAL;
66828+ goto out;
66829+ }
66830+ }
66831+ spin_unlock(&tgt->srr_lock);
66832+ } else {
66833+ struct srr_imm *ti;
66834+ PRINT_ERROR("qla2x00t(%ld): Unable to allocate SRR CTIO entry",
66835+ ha->instance);
66836+ spin_lock(&tgt->srr_lock);
66837+ list_for_each_entry_safe(imm, ti, &tgt->srr_imm_list,
66838+ srr_list_entry) {
66839+ if (imm->srr_id == tgt->ctio_srr_id) {
66840+ TRACE_MGMT_DBG("IMM SRR %p deleted "
66841+ "(id %d)", imm, imm->srr_id);
66842+ list_del(&imm->srr_list_entry);
66843+ q2t_reject_free_srr_imm(ha, imm, 1);
66844+ }
66845+ }
66846+ spin_unlock(&tgt->srr_lock);
66847+ res = -ENOMEM;
66848+ goto out;
66849+ }
66850+
66851+out:
66852+ TRACE_EXIT_RES(res);
66853+ return res;
66854+}
66855+
66856+/*
66857+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
66858+ */
66859+static int q2t_term_ctio_exchange(scsi_qla_host_t *ha, void *ctio,
66860+ struct q2t_cmd *cmd, uint32_t status)
66861+{
66862+ int term = 0;
66863+
66864+ if (IS_FWI2_CAPABLE(ha)) {
66865+ if (ctio != NULL) {
66866+ ctio7_fw_entry_t *c = (ctio7_fw_entry_t *)ctio;
66867+ term = !(c->flags &
66868+ __constant_cpu_to_le16(OF_TERM_EXCH));
66869+ } else
66870+ term = 1;
66871+ if (term) {
66872+ q24_send_term_exchange(ha, cmd,
66873+ &cmd->atio.atio7, 1);
66874+ }
66875+ } else {
66876+ if (status != CTIO_SUCCESS)
66877+ q2x_modify_command_count(ha, 1, 0);
66878+#if 0 /* seems, it isn't needed */
66879+ if (ctio != NULL) {
66880+ ctio_common_entry_t *c = (ctio_common_entry_t *)ctio;
66881+ term = !(c->flags &
66882+ __constant_cpu_to_le16(
66883+ CTIO7_FLAGS_TERMINATE));
66884+ } else
66885+ term = 1;
66886+ if (term) {
66887+ q2x_send_term_exchange(ha, cmd,
66888+ &cmd->atio.atio2x, 1);
66889+ }
66890+#endif
66891+ }
66892+ return term;
66893+}
66894+
66895+/* ha->hardware_lock supposed to be held on entry */
66896+static inline struct q2t_cmd *q2t_get_cmd(scsi_qla_host_t *ha, uint32_t handle)
66897+{
66898+ handle--;
66899+ if (ha->cmds[handle] != NULL) {
66900+ struct q2t_cmd *cmd = ha->cmds[handle];
66901+ ha->cmds[handle] = NULL;
66902+ return cmd;
66903+ } else
66904+ return NULL;
66905+}
66906+
66907+/* ha->hardware_lock supposed to be held on entry */
66908+static struct q2t_cmd *q2t_ctio_to_cmd(scsi_qla_host_t *ha, uint32_t handle,
66909+ void *ctio)
66910+{
66911+ struct q2t_cmd *cmd = NULL;
66912+
66913+ /* Clear out internal marks */
66914+ handle &= ~(CTIO_COMPLETION_HANDLE_MARK | CTIO_INTERMEDIATE_HANDLE_MARK);
66915+
66916+ if (handle != Q2T_NULL_HANDLE) {
66917+ if (unlikely(handle == Q2T_SKIP_HANDLE)) {
66918+ TRACE_DBG("%s", "SKIP_HANDLE CTIO");
66919+ goto out;
66920+ }
66921+ /* handle-1 is actually used */
66922+ if (unlikely(handle > MAX_OUTSTANDING_COMMANDS)) {
66923+ PRINT_ERROR("qla2x00t(%ld): Wrong handle %x "
66924+ "received", ha->instance, handle);
66925+ goto out;
66926+ }
66927+ cmd = q2t_get_cmd(ha, handle);
66928+ if (unlikely(cmd == NULL)) {
66929+ PRINT_WARNING("qla2x00t(%ld): Suspicious: unable to "
66930+ "find the command with handle %x",
66931+ ha->instance, handle);
66932+ goto out;
66933+ }
66934+ } else if (ctio != NULL) {
66935+ uint16_t loop_id;
66936+ int tag;
66937+ struct q2t_sess *sess;
66938+ struct scst_cmd *scst_cmd;
66939+
66940+ if (IS_FWI2_CAPABLE(ha)) {
66941+ /* We can't get loop ID from CTIO7 */
66942+ PRINT_ERROR("qla2x00t(%ld): Wrong CTIO received: "
66943+ "QLA24xx doesn't support NULL handles",
66944+ ha->instance);
66945+ goto out;
66946+ } else {
66947+ ctio_common_entry_t *c = (ctio_common_entry_t *)ctio;
66948+ loop_id = GET_TARGET_ID(ha, c);
66949+ tag = c->rx_id;
66950+ }
66951+
66952+ sess = q2t_find_sess_by_loop_id(ha->tgt, loop_id);
66953+ if (sess == NULL) {
66954+ PRINT_WARNING("qla2x00t(%ld): Suspicious: "
66955+ "ctio_completion for non-existing session "
66956+ "(loop_id %d, tag %d)",
66957+ ha->instance, loop_id, tag);
66958+ goto out;
66959+ }
66960+
66961+ scst_cmd = scst_find_cmd_by_tag(sess->scst_sess, tag);
66962+ if (scst_cmd == NULL) {
66963+ PRINT_WARNING("qla2x00t(%ld): Suspicious: unable to "
66964+ "find the command with tag %d (loop_id %d)",
66965+ ha->instance, tag, loop_id);
66966+ goto out;
66967+ }
66968+
66969+ cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
66970+ TRACE_DBG("Found q2t_cmd %p (tag %d)", cmd, tag);
66971+ }
66972+
66973+out:
66974+ return cmd;
66975+}
66976+
66977+/*
66978+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
66979+ */
66980+static void q2t_do_ctio_completion(scsi_qla_host_t *ha, uint32_t handle,
66981+ uint32_t status, void *ctio)
66982+{
66983+ struct scst_cmd *scst_cmd;
66984+ struct q2t_cmd *cmd;
66985+ enum scst_exec_context context;
66986+
66987+ TRACE_ENTRY();
66988+
66989+#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
66990+ context = SCST_CONTEXT_THREAD;
66991+#else
66992+ context = SCST_CONTEXT_TASKLET;
66993+#endif
66994+
66995+ TRACE(TRACE_DEBUG|TRACE_SCSI, "qla2x00t(%ld): handle(ctio %p "
66996+ "status %#x) <- %08x", ha->instance, ctio, status, handle);
66997+
66998+ if (handle & CTIO_INTERMEDIATE_HANDLE_MARK) {
66999+ /* That could happen only in case of an error/reset/abort */
67000+ if (status != CTIO_SUCCESS) {
67001+ TRACE_MGMT_DBG("Intermediate CTIO received (status %x)",
67002+ status);
67003+ }
67004+ goto out;
67005+ }
67006+
67007+ cmd = q2t_ctio_to_cmd(ha, handle, ctio);
67008+ if (cmd == NULL) {
67009+ if (status != CTIO_SUCCESS)
67010+ q2t_term_ctio_exchange(ha, ctio, NULL, status);
67011+ goto out;
67012+ }
67013+
67014+ scst_cmd = cmd->scst_cmd;
67015+
67016+ if (cmd->sg_mapped)
67017+ q2t_unmap_sg(ha, cmd);
67018+
67019+ if (unlikely(status != CTIO_SUCCESS)) {
67020+ switch (status & 0xFFFF) {
67021+ case CTIO_LIP_RESET:
67022+ case CTIO_TARGET_RESET:
67023+ case CTIO_ABORTED:
67024+ case CTIO_TIMEOUT:
67025+ case CTIO_INVALID_RX_ID:
67026+ /* They are OK */
67027+ TRACE(TRACE_MINOR_AND_MGMT_DBG,
67028+ "qla2x00t(%ld): CTIO with "
67029+ "status %#x received, state %x, scst_cmd %p, "
67030+ "op %x (LIP_RESET=e, ABORTED=2, TARGET_RESET=17, "
67031+ "TIMEOUT=b, INVALID_RX_ID=8)", ha->instance,
67032+ status, cmd->state, scst_cmd, scst_cmd->cdb[0]);
67033+ break;
67034+
67035+ case CTIO_PORT_LOGGED_OUT:
67036+ case CTIO_PORT_UNAVAILABLE:
67037+ PRINT_INFO("qla2x00t(%ld): CTIO with PORT LOGGED "
67038+ "OUT (29) or PORT UNAVAILABLE (28) status %x "
67039+ "received (state %x, scst_cmd %p, op %x)",
67040+ ha->instance, status, cmd->state, scst_cmd,
67041+ scst_cmd->cdb[0]);
67042+ break;
67043+
67044+ case CTIO_SRR_RECEIVED:
67045+ if (q2t_prepare_srr_ctio(ha, cmd, ctio) != 0)
67046+ break;
67047+ else
67048+ goto out;
67049+
67050+ default:
67051+ PRINT_ERROR("qla2x00t(%ld): CTIO with error status "
67052+ "0x%x received (state %x, scst_cmd %p, op %x)",
67053+ ha->instance, status, cmd->state, scst_cmd,
67054+ scst_cmd->cdb[0]);
67055+ break;
67056+ }
67057+
67058+ if (cmd->state != Q2T_STATE_NEED_DATA)
67059+ if (q2t_term_ctio_exchange(ha, ctio, cmd, status))
67060+ goto out;
67061+ }
67062+
67063+ if (cmd->state == Q2T_STATE_PROCESSED) {
67064+ TRACE_DBG("Command %p finished", cmd);
67065+ } else if (cmd->state == Q2T_STATE_NEED_DATA) {
67066+ int rx_status = SCST_RX_STATUS_SUCCESS;
67067+
67068+ cmd->state = Q2T_STATE_DATA_IN;
67069+
67070+ if (unlikely(status != CTIO_SUCCESS))
67071+ rx_status = SCST_RX_STATUS_ERROR;
67072+ else
67073+ cmd->write_data_transferred = 1;
67074+
67075+ TRACE_DBG("Data received, context %x, rx_status %d",
67076+ context, rx_status);
67077+
67078+ scst_rx_data(scst_cmd, rx_status, context);
67079+ goto out;
67080+ } else if (cmd->state == Q2T_STATE_ABORTED) {
67081+ TRACE_MGMT_DBG("Aborted command %p (tag %d) finished", cmd,
67082+ cmd->tag);
67083+ } else {
67084+ PRINT_ERROR("qla2x00t(%ld): A command in state (%d) should "
67085+ "not return a CTIO complete", ha->instance, cmd->state);
67086+ }
67087+
67088+ if (unlikely(status != CTIO_SUCCESS)) {
67089+ TRACE_MGMT_DBG("%s", "Finishing failed CTIO");
67090+ scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_FAILED);
67091+ }
67092+
67093+ scst_tgt_cmd_done(scst_cmd, context);
67094+
67095+out:
67096+ TRACE_EXIT();
67097+ return;
67098+}
67099+
67100+/* ha->hardware_lock supposed to be held on entry */
67101+/* called via callback from qla2xxx */
67102+static void q2x_ctio_completion(scsi_qla_host_t *ha, uint32_t handle)
67103+{
67104+ struct q2t_tgt *tgt = ha->tgt;
67105+
67106+ TRACE_ENTRY();
67107+
67108+ if (likely(tgt != NULL)) {
67109+ tgt->irq_cmd_count++;
67110+ q2t_do_ctio_completion(ha, handle, CTIO_SUCCESS, NULL);
67111+ tgt->irq_cmd_count--;
67112+ } else {
67113+ TRACE_DBG("CTIO, but target mode not enabled (ha %p handle "
67114+ "%#x)", ha, handle);
67115+ }
67116+
67117+ TRACE_EXIT();
67118+ return;
67119+}
67120+
67121+/* ha->hardware_lock is supposed to be held on entry */
67122+static int q2x_do_send_cmd_to_scst(struct q2t_cmd *cmd)
67123+{
67124+ int res = 0;
67125+ struct q2t_sess *sess = cmd->sess;
67126+ uint16_t lun;
67127+ atio_entry_t *atio = &cmd->atio.atio2x;
67128+ scst_data_direction dir;
67129+ int context;
67130+
67131+ TRACE_ENTRY();
67132+
67133+ /* make it be in network byte order */
67134+ lun = swab16(le16_to_cpu(atio->lun));
67135+ cmd->scst_cmd = scst_rx_cmd(sess->scst_sess, (uint8_t *)&lun,
67136+ sizeof(lun), atio->cdb, Q2T_MAX_CDB_LEN,
67137+ SCST_ATOMIC);
67138+
67139+ if (cmd->scst_cmd == NULL) {
67140+ PRINT_ERROR("%s", "qla2x00t: scst_rx_cmd() failed");
67141+ res = -EFAULT;
67142+ goto out;
67143+ }
67144+
67145+ cmd->tag = atio->rx_id;
67146+ scst_cmd_set_tag(cmd->scst_cmd, cmd->tag);
67147+ scst_cmd_set_tgt_priv(cmd->scst_cmd, cmd);
67148+
67149+ if ((atio->execution_codes & (ATIO_EXEC_READ | ATIO_EXEC_WRITE)) ==
67150+ (ATIO_EXEC_READ | ATIO_EXEC_WRITE))
67151+ dir = SCST_DATA_BIDI;
67152+ else if (atio->execution_codes & ATIO_EXEC_READ)
67153+ dir = SCST_DATA_READ;
67154+ else if (atio->execution_codes & ATIO_EXEC_WRITE)
67155+ dir = SCST_DATA_WRITE;
67156+ else
67157+ dir = SCST_DATA_NONE;
67158+ scst_cmd_set_expected(cmd->scst_cmd, dir,
67159+ le32_to_cpu(atio->data_length));
67160+
67161+ switch (atio->task_codes) {
67162+ case ATIO_SIMPLE_QUEUE:
67163+ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_SIMPLE);
67164+ break;
67165+ case ATIO_HEAD_OF_QUEUE:
67166+ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
67167+ break;
67168+ case ATIO_ORDERED_QUEUE:
67169+ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
67170+ break;
67171+ case ATIO_ACA_QUEUE:
67172+ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ACA);
67173+ break;
67174+ case ATIO_UNTAGGED:
67175+ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_UNTAGGED);
67176+ break;
67177+ default:
67178+ PRINT_ERROR("qla2x00t: unknown task code %x, use "
67179+ "ORDERED instead", atio->task_codes);
67180+ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
67181+ break;
67182+ }
67183+
67184+#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
67185+ context = SCST_CONTEXT_THREAD;
67186+#else
67187+ context = SCST_CONTEXT_TASKLET;
67188+#endif
67189+
67190+ TRACE_DBG("Context %x", context);
67191+ TRACE(TRACE_SCSI, "qla2x00t: START Command (tag %d, queue_type %d)",
67192+ cmd->tag, scst_cmd_get_queue_type(cmd->scst_cmd));
67193+ scst_cmd_init_done(cmd->scst_cmd, context);
67194+
67195+out:
67196+ TRACE_EXIT_RES(res);
67197+ return res;
67198+}
67199+
67200+/* ha->hardware_lock is supposed to be held on entry */
67201+static int q24_do_send_cmd_to_scst(struct q2t_cmd *cmd)
67202+{
67203+ int res = 0;
67204+ struct q2t_sess *sess = cmd->sess;
67205+ atio7_entry_t *atio = &cmd->atio.atio7;
67206+ scst_data_direction dir;
67207+ int context;
67208+
67209+ TRACE_ENTRY();
67210+
67211+ cmd->scst_cmd = scst_rx_cmd(sess->scst_sess,
67212+ (uint8_t *)&atio->fcp_cmnd.lun, sizeof(atio->fcp_cmnd.lun),
67213+ atio->fcp_cmnd.cdb, Q2T_MAX_CDB_LEN, SCST_ATOMIC);
67214+
67215+ if (cmd->scst_cmd == NULL) {
67216+ PRINT_ERROR("%s", "qla2x00t: scst_rx_cmd() failed");
67217+ res = -EFAULT;
67218+ goto out;
67219+ }
67220+
67221+ cmd->tag = atio->exchange_addr;
67222+ scst_cmd_set_tag(cmd->scst_cmd, cmd->tag);
67223+ scst_cmd_set_tgt_priv(cmd->scst_cmd, cmd);
67224+
67225+ if (atio->fcp_cmnd.rddata && atio->fcp_cmnd.wrdata)
67226+ dir = SCST_DATA_BIDI;
67227+ else if (atio->fcp_cmnd.rddata)
67228+ dir = SCST_DATA_READ;
67229+ else if (atio->fcp_cmnd.wrdata)
67230+ dir = SCST_DATA_WRITE;
67231+ else
67232+ dir = SCST_DATA_NONE;
67233+ scst_cmd_set_expected(cmd->scst_cmd, dir,
67234+ be32_to_cpu(atio->fcp_cmnd.data_length));
67235+
67236+ switch (atio->fcp_cmnd.task_attr) {
67237+ case ATIO_SIMPLE_QUEUE:
67238+ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_SIMPLE);
67239+ break;
67240+ case ATIO_HEAD_OF_QUEUE:
67241+ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
67242+ break;
67243+ case ATIO_ORDERED_QUEUE:
67244+ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
67245+ break;
67246+ case ATIO_ACA_QUEUE:
67247+ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ACA);
67248+ break;
67249+ case ATIO_UNTAGGED:
67250+ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_UNTAGGED);
67251+ break;
67252+ default:
67253+ PRINT_ERROR("qla2x00t: unknown task code %x, use "
67254+ "ORDERED instead", atio->fcp_cmnd.task_attr);
67255+ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
67256+ break;
67257+ }
67258+
67259+#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
67260+ context = SCST_CONTEXT_THREAD;
67261+#else
67262+ context = SCST_CONTEXT_TASKLET;
67263+#endif
67264+
67265+ TRACE_DBG("Context %x", context);
67266+ TRACE(TRACE_SCSI, "qla2x00t: START Command %p (tag %d, queue type %x)",
67267+ cmd, cmd->tag, scst_cmd_get_queue_type(cmd->scst_cmd));
67268+ scst_cmd_init_done(cmd->scst_cmd, context);
67269+
67270+out:
67271+ TRACE_EXIT_RES(res);
67272+ return res;
67273+}
67274+
67275+/* ha->hardware_lock supposed to be held on entry */
67276+static int q2t_do_send_cmd_to_scst(scsi_qla_host_t *ha,
67277+ struct q2t_cmd *cmd, struct q2t_sess *sess)
67278+{
67279+ int res;
67280+
67281+ TRACE_ENTRY();
67282+
67283+ cmd->sess = sess;
67284+ cmd->loop_id = sess->loop_id;
67285+ cmd->conf_compl_supported = sess->conf_compl_supported;
67286+
67287+ if (IS_FWI2_CAPABLE(ha))
67288+ res = q24_do_send_cmd_to_scst(cmd);
67289+ else
67290+ res = q2x_do_send_cmd_to_scst(cmd);
67291+
67292+ TRACE_EXIT_RES(res);
67293+ return res;
67294+}
67295+
67296+/* ha->hardware_lock supposed to be held on entry */
67297+static int q2t_send_cmd_to_scst(scsi_qla_host_t *ha, atio_t *atio)
67298+{
67299+ int res = 0;
67300+ struct q2t_tgt *tgt = ha->tgt;
67301+ struct q2t_sess *sess;
67302+ struct q2t_cmd *cmd;
67303+
67304+ TRACE_ENTRY();
67305+
67306+ if (unlikely(tgt->tgt_stop)) {
67307+ TRACE_MGMT_DBG("New command while device %p is shutting "
67308+ "down", tgt);
67309+ res = -EFAULT;
67310+ goto out;
67311+ }
67312+
67313+ cmd = kmem_cache_zalloc(q2t_cmd_cachep, GFP_ATOMIC);
67314+ if (cmd == NULL) {
67315+ TRACE(TRACE_OUT_OF_MEM, "qla2x00t(%ld): Allocation of cmd "
67316+ "failed", ha->instance);
67317+ res = -ENOMEM;
67318+ goto out;
67319+ }
67320+
67321+ memcpy(&cmd->atio.atio2x, atio, sizeof(*atio));
67322+ cmd->state = Q2T_STATE_NEW;
67323+ cmd->tgt = ha->tgt;
67324+
67325+ if (IS_FWI2_CAPABLE(ha)) {
67326+ atio7_entry_t *a = (atio7_entry_t *)atio;
67327+ sess = q2t_find_sess_by_s_id(tgt, a->fcp_hdr.s_id);
67328+ if (unlikely(sess == NULL)) {
67329+ TRACE_MGMT_DBG("qla2x00t(%ld): Unable to find "
67330+ "wwn login (s_id %x:%x:%x), trying to create "
67331+ "it manually", ha->instance,
67332+ a->fcp_hdr.s_id[0], a->fcp_hdr.s_id[1],
67333+ a->fcp_hdr.s_id[2]);
67334+ goto out_sched;
67335+ }
67336+ } else {
67337+ sess = q2t_find_sess_by_loop_id(tgt,
67338+ GET_TARGET_ID(ha, (atio_entry_t *)atio));
67339+ if (unlikely(sess == NULL)) {
67340+ TRACE_MGMT_DBG("qla2x00t(%ld): Unable to find "
67341+ "wwn login (loop_id=%d), trying to create it "
67342+ "manually", ha->instance,
67343+ GET_TARGET_ID(ha, (atio_entry_t *)atio));
67344+ goto out_sched;
67345+ }
67346+ }
67347+
67348+ if (unlikely(sess->deleted))
67349+ q2t_reappear_sess(sess, " by new commands");
67350+
67351+ res = q2t_do_send_cmd_to_scst(ha, cmd, sess);
67352+ if (unlikely(res != 0))
67353+ goto out_free_cmd;
67354+
67355+out:
67356+ TRACE_EXIT_RES(res);
67357+ return res;
67358+
67359+out_free_cmd:
67360+ q2t_free_cmd(cmd);
67361+ goto out;
67362+
67363+out_sched:
67364+ {
67365+ struct q2t_sess_work_param *prm;
67366+ unsigned long flags;
67367+
67368+ prm = kzalloc(sizeof(*prm), GFP_ATOMIC);
67369+ if (prm == NULL) {
67370+ PRINT_ERROR("qla2x00t(%ld): Unable to create session "
67371+ "work, command will be refused", ha->instance);
67372+ res = -1;
67373+ goto out_free_cmd;
67374+ }
67375+
67376+ TRACE_MGMT_DBG("Scheduling work to find session for cmd %p",
67377+ cmd);
67378+
67379+ prm->cmd = cmd;
67380+
67381+ spin_lock_irqsave(&tgt->sess_work_lock, flags);
67382+ if (!tgt->sess_works_pending)
67383+ tgt->tm_to_unknown = 0;
67384+ list_add_tail(&prm->sess_works_list_entry, &tgt->sess_works_list);
67385+ tgt->sess_works_pending = 1;
67386+ spin_unlock_irqrestore(&tgt->sess_work_lock, flags);
67387+
67388+ schedule_work(&tgt->sess_work);
67389+ }
67390+ goto out;
67391+}
67392+
67393+/* ha->hardware_lock supposed to be held on entry */
67394+static int q2t_issue_task_mgmt(struct q2t_sess *sess, uint8_t *lun,
67395+ int lun_size, int fn, void *iocb, int flags)
67396+{
67397+ int res = 0, rc = -1;
67398+ struct q2t_mgmt_cmd *mcmd;
67399+
67400+ TRACE_ENTRY();
67401+
67402+ mcmd = mempool_alloc(q2t_mgmt_cmd_mempool, GFP_ATOMIC);
67403+ if (mcmd == NULL) {
67404+ PRINT_CRIT_ERROR("qla2x00t(%ld): Allocation of management "
67405+ "command failed, some commands and their data could "
67406+ "leak", sess->tgt->ha->instance);
67407+ res = -ENOMEM;
67408+ goto out;
67409+ }
67410+ memset(mcmd, 0, sizeof(*mcmd));
67411+
67412+ mcmd->sess = sess;
67413+ if (iocb) {
67414+ memcpy(&mcmd->orig_iocb.notify_entry, iocb,
67415+ sizeof(mcmd->orig_iocb.notify_entry));
67416+ }
67417+ mcmd->flags = flags;
67418+
67419+ switch (fn) {
67420+ case Q2T_CLEAR_ACA:
67421+ TRACE(TRACE_MGMT, "qla2x00t(%ld): CLEAR_ACA received",
67422+ sess->tgt->ha->instance);
67423+ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_CLEAR_ACA,
67424+ lun, lun_size, SCST_ATOMIC, mcmd);
67425+ break;
67426+
67427+ case Q2T_TARGET_RESET:
67428+ TRACE(TRACE_MGMT, "qla2x00t(%ld): TARGET_RESET received",
67429+ sess->tgt->ha->instance);
67430+ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_TARGET_RESET,
67431+ lun, lun_size, SCST_ATOMIC, mcmd);
67432+ break;
67433+
67434+ case Q2T_LUN_RESET:
67435+ TRACE(TRACE_MGMT, "qla2x00t(%ld): LUN_RESET received",
67436+ sess->tgt->ha->instance);
67437+ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_LUN_RESET,
67438+ lun, lun_size, SCST_ATOMIC, mcmd);
67439+ break;
67440+
67441+ case Q2T_CLEAR_TS:
67442+ TRACE(TRACE_MGMT, "qla2x00t(%ld): CLEAR_TS received",
67443+ sess->tgt->ha->instance);
67444+ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_CLEAR_TASK_SET,
67445+ lun, lun_size, SCST_ATOMIC, mcmd);
67446+ break;
67447+
67448+ case Q2T_ABORT_TS:
67449+ TRACE(TRACE_MGMT, "qla2x00t(%ld): ABORT_TS received",
67450+ sess->tgt->ha->instance);
67451+ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_ABORT_TASK_SET,
67452+ lun, lun_size, SCST_ATOMIC, mcmd);
67453+ break;
67454+
67455+ case Q2T_ABORT_ALL:
67456+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Doing ABORT_ALL_TASKS",
67457+ sess->tgt->ha->instance);
67458+ rc = scst_rx_mgmt_fn_lun(sess->scst_sess,
67459+ SCST_ABORT_ALL_TASKS,
67460+ lun, lun_size, SCST_ATOMIC, mcmd);
67461+ break;
67462+
67463+ case Q2T_ABORT_ALL_SESS:
67464+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Doing ABORT_ALL_TASKS_SESS",
67465+ sess->tgt->ha->instance);
67466+ rc = scst_rx_mgmt_fn_lun(sess->scst_sess,
67467+ SCST_ABORT_ALL_TASKS_SESS,
67468+ lun, lun_size, SCST_ATOMIC, mcmd);
67469+ break;
67470+
67471+ case Q2T_NEXUS_LOSS_SESS:
67472+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Doing NEXUS_LOSS_SESS",
67473+ sess->tgt->ha->instance);
67474+ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_NEXUS_LOSS_SESS,
67475+ lun, lun_size, SCST_ATOMIC, mcmd);
67476+ break;
67477+
67478+ case Q2T_NEXUS_LOSS:
67479+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Doing NEXUS_LOSS",
67480+ sess->tgt->ha->instance);
67481+ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_NEXUS_LOSS,
67482+ lun, lun_size, SCST_ATOMIC, mcmd);
67483+ break;
67484+
67485+ default:
67486+ PRINT_ERROR("qla2x00t(%ld): Unknown task mgmt fn 0x%x",
67487+ sess->tgt->ha->instance, fn);
67488+ rc = -1;
67489+ break;
67490+ }
67491+
67492+ if (rc != 0) {
67493+ PRINT_ERROR("qla2x00t(%ld): scst_rx_mgmt_fn_lun() failed: %d",
67494+ sess->tgt->ha->instance, rc);
67495+ res = -EFAULT;
67496+ goto out_free;
67497+ }
67498+
67499+out:
67500+ TRACE_EXIT_RES(res);
67501+ return res;
67502+
67503+out_free:
67504+ mempool_free(mcmd, q2t_mgmt_cmd_mempool);
67505+ goto out;
67506+}
67507+
67508+/* ha->hardware_lock supposed to be held on entry */
67509+static int q2t_handle_task_mgmt(scsi_qla_host_t *ha, void *iocb)
67510+{
67511+ int res = 0;
67512+ struct q2t_tgt *tgt;
67513+ struct q2t_sess *sess;
67514+ uint8_t *lun;
67515+ uint16_t lun_data;
67516+ int lun_size;
67517+ int fn;
67518+
67519+ TRACE_ENTRY();
67520+
67521+ tgt = ha->tgt;
67522+ if (IS_FWI2_CAPABLE(ha)) {
67523+ atio7_entry_t *a = (atio7_entry_t *)iocb;
67524+ lun = (uint8_t *)&a->fcp_cmnd.lun;
67525+ lun_size = sizeof(a->fcp_cmnd.lun);
67526+ fn = a->fcp_cmnd.task_mgmt_flags;
67527+ sess = q2t_find_sess_by_s_id(tgt, a->fcp_hdr.s_id);
67528+ if (sess != NULL) {
67529+ sess->s_id.b.al_pa = a->fcp_hdr.s_id[2];
67530+ sess->s_id.b.area = a->fcp_hdr.s_id[1];
67531+ sess->s_id.b.domain = a->fcp_hdr.s_id[0];
67532+ }
67533+ } else {
67534+ notify_entry_t *n = (notify_entry_t *)iocb;
67535+ /* make it be in network byte order */
67536+ lun_data = swab16(le16_to_cpu(n->lun));
67537+ lun = (uint8_t *)&lun_data;
67538+ lun_size = sizeof(lun_data);
67539+ fn = n->task_flags >> IMM_NTFY_TASK_MGMT_SHIFT;
67540+ sess = q2t_find_sess_by_loop_id(tgt, GET_TARGET_ID(ha, n));
67541+ }
67542+
67543+ if (sess == NULL) {
67544+ TRACE(TRACE_MGMT, "qla2x00t(%ld): task mgmt fn 0x%x for "
67545+ "non-existant session", ha->instance, fn);
67546+ tgt->tm_to_unknown = 1;
67547+ res = -ESRCH;
67548+ goto out;
67549+ }
67550+
67551+ res = q2t_issue_task_mgmt(sess, lun, lun_size, fn, iocb, 0);
67552+
67553+out:
67554+ TRACE_EXIT_RES(res);
67555+ return res;
67556+}
67557+
67558+/* ha->hardware_lock supposed to be held on entry */
67559+static int q2t_abort_task(scsi_qla_host_t *ha, notify_entry_t *iocb)
67560+{
67561+ int res = 0, rc;
67562+ struct q2t_mgmt_cmd *mcmd;
67563+ struct q2t_sess *sess;
67564+ int loop_id;
67565+ uint32_t tag;
67566+
67567+ TRACE_ENTRY();
67568+
67569+ loop_id = GET_TARGET_ID(ha, iocb);
67570+ tag = le16_to_cpu(iocb->seq_id);
67571+
67572+ sess = q2t_find_sess_by_loop_id(ha->tgt, loop_id);
67573+ if (sess == NULL) {
67574+ TRACE(TRACE_MGMT, "qla2x00t(%ld): task abort for unexisting "
67575+ "session", ha->instance);
67576+ ha->tgt->tm_to_unknown = 1;
67577+ res = -EFAULT;
67578+ goto out;
67579+ }
67580+
67581+ mcmd = mempool_alloc(q2t_mgmt_cmd_mempool, GFP_ATOMIC);
67582+ if (mcmd == NULL) {
67583+ PRINT_ERROR("qla2x00t(%ld): %s: Allocation of ABORT cmd failed",
67584+ ha->instance, __func__);
67585+ res = -ENOMEM;
67586+ goto out;
67587+ }
67588+ memset(mcmd, 0, sizeof(*mcmd));
67589+
67590+ mcmd->sess = sess;
67591+ memcpy(&mcmd->orig_iocb.notify_entry, iocb,
67592+ sizeof(mcmd->orig_iocb.notify_entry));
67593+
67594+ rc = scst_rx_mgmt_fn_tag(sess->scst_sess, SCST_ABORT_TASK, tag,
67595+ SCST_ATOMIC, mcmd);
67596+ if (rc != 0) {
67597+ PRINT_ERROR("qla2x00t(%ld): scst_rx_mgmt_fn_tag() failed: %d",
67598+ ha->instance, rc);
67599+ res = -EFAULT;
67600+ goto out_free;
67601+ }
67602+
67603+out:
67604+ TRACE_EXIT_RES(res);
67605+ return res;
67606+
67607+out_free:
67608+ mempool_free(mcmd, q2t_mgmt_cmd_mempool);
67609+ goto out;
67610+}
67611+
67612+/*
67613+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
67614+ */
67615+static int q24_handle_els(scsi_qla_host_t *ha, notify24xx_entry_t *iocb)
67616+{
67617+ int res = 0;
67618+
67619+ TRACE_ENTRY();
67620+
67621+ TRACE(TRACE_MGMT, "qla2x00t(%ld): ELS opcode %x", ha->instance,
67622+ iocb->status_subcode);
67623+
67624+ switch (iocb->status_subcode) {
67625+ case ELS_PLOGI:
67626+ case ELS_FLOGI:
67627+ case ELS_PRLI:
67628+ case ELS_LOGO:
67629+ case ELS_PRLO:
67630+ res = q2t_reset(ha, iocb, Q2T_NEXUS_LOSS_SESS);
67631+ break;
67632+
67633+ case ELS_PDISC:
67634+ case ELS_ADISC:
67635+ {
67636+ struct q2t_tgt *tgt = ha->tgt;
67637+ if (tgt->link_reinit_iocb_pending) {
67638+ q24_send_notify_ack(ha, &tgt->link_reinit_iocb, 0, 0, 0);
67639+ tgt->link_reinit_iocb_pending = 0;
67640+ }
67641+ res = 1; /* send notify ack */
67642+ break;
67643+ }
67644+
67645+ default:
67646+ PRINT_ERROR("qla2x00t(%ld): Unsupported ELS command %x "
67647+ "received", ha->instance, iocb->status_subcode);
67648+ res = q2t_reset(ha, iocb, Q2T_NEXUS_LOSS_SESS);
67649+ break;
67650+ }
67651+
67652+ TRACE_EXIT_RES(res);
67653+ return res;
67654+}
67655+
67656+static int q2t_cut_cmd_data_head(struct q2t_cmd *cmd, unsigned int offset)
67657+{
67658+ int res = 0;
67659+ int cnt, first_sg, first_page = 0, first_page_offs = 0, i;
67660+ unsigned int l;
67661+ int cur_dst, cur_src;
67662+ struct scatterlist *sg;
67663+ size_t bufflen = 0;
67664+
67665+ TRACE_ENTRY();
67666+
67667+ first_sg = -1;
67668+ cnt = 0;
67669+ l = 0;
67670+ for (i = 0; i < cmd->sg_cnt; i++) {
67671+ l += cmd->sg[i].length;
67672+ if (l > offset) {
67673+ int sg_offs = l - cmd->sg[i].length;
67674+ first_sg = i;
67675+ if (cmd->sg[i].offset == 0) {
67676+ first_page_offs = offset % PAGE_SIZE;
67677+ first_page = (offset - sg_offs) >> PAGE_SHIFT;
67678+ } else {
67679+ TRACE_SG("i=%d, sg[i].offset=%d, "
67680+ "sg_offs=%d", i, cmd->sg[i].offset, sg_offs);
67681+ if ((cmd->sg[i].offset + sg_offs) > offset) {
67682+ first_page_offs = offset - sg_offs;
67683+ first_page = 0;
67684+ } else {
67685+ int sec_page_offs = sg_offs +
67686+ (PAGE_SIZE - cmd->sg[i].offset);
67687+ first_page_offs = sec_page_offs % PAGE_SIZE;
67688+ first_page = 1 +
67689+ ((offset - sec_page_offs) >>
67690+ PAGE_SHIFT);
67691+ }
67692+ }
67693+ cnt = cmd->sg_cnt - i + (first_page_offs != 0);
67694+ break;
67695+ }
67696+ }
67697+ if (first_sg == -1) {
67698+ PRINT_ERROR("qla2x00t(%ld): Wrong offset %d, buf length %d",
67699+ cmd->tgt->ha->instance, offset, cmd->bufflen);
67700+ res = -EINVAL;
67701+ goto out;
67702+ }
67703+
67704+ TRACE_SG("offset=%d, first_sg=%d, first_page=%d, "
67705+ "first_page_offs=%d, cmd->bufflen=%d, cmd->sg_cnt=%d", offset,
67706+ first_sg, first_page, first_page_offs, cmd->bufflen,
67707+ cmd->sg_cnt);
67708+
67709+ sg = kmalloc(cnt * sizeof(sg[0]), GFP_KERNEL);
67710+ if (sg == NULL) {
67711+ PRINT_ERROR("qla2x00t(%ld): Unable to allocate cut "
67712+ "SG (len %zd)", cmd->tgt->ha->instance,
67713+ cnt * sizeof(sg[0]));
67714+ res = -ENOMEM;
67715+ goto out;
67716+ }
67717+ sg_init_table(sg, cnt);
67718+
67719+ cur_dst = 0;
67720+ cur_src = first_sg;
67721+ if (first_page_offs != 0) {
67722+ int fpgs;
67723+ sg_set_page(&sg[cur_dst], &sg_page(&cmd->sg[cur_src])[first_page],
67724+ PAGE_SIZE - first_page_offs, first_page_offs);
67725+ bufflen += sg[cur_dst].length;
67726+ TRACE_SG("cur_dst=%d, cur_src=%d, sg[].page=%p, "
67727+ "sg[].offset=%d, sg[].length=%d, bufflen=%zu",
67728+ cur_dst, cur_src, sg_page(&sg[cur_dst]), sg[cur_dst].offset,
67729+ sg[cur_dst].length, bufflen);
67730+ cur_dst++;
67731+
67732+ fpgs = (cmd->sg[cur_src].length >> PAGE_SHIFT) +
67733+ ((cmd->sg[cur_src].length & ~PAGE_MASK) != 0);
67734+ first_page++;
67735+ if (fpgs > first_page) {
67736+ sg_set_page(&sg[cur_dst],
67737+ &sg_page(&cmd->sg[cur_src])[first_page],
67738+ cmd->sg[cur_src].length - PAGE_SIZE*first_page,
67739+ 0);
67740+ TRACE_SG("fpgs=%d, cur_dst=%d, cur_src=%d, "
67741+ "sg[].page=%p, sg[].length=%d, bufflen=%zu",
67742+ fpgs, cur_dst, cur_src, sg_page(&sg[cur_dst]),
67743+ sg[cur_dst].length, bufflen);
67744+ bufflen += sg[cur_dst].length;
67745+ cur_dst++;
67746+ }
67747+ cur_src++;
67748+ }
67749+
67750+ while (cur_src < cmd->sg_cnt) {
67751+ sg_set_page(&sg[cur_dst], sg_page(&cmd->sg[cur_src]),
67752+ cmd->sg[cur_src].length, cmd->sg[cur_src].offset);
67753+ TRACE_SG("cur_dst=%d, cur_src=%d, "
67754+ "sg[].page=%p, sg[].length=%d, sg[].offset=%d, "
67755+ "bufflen=%zu", cur_dst, cur_src, sg_page(&sg[cur_dst]),
67756+ sg[cur_dst].length, sg[cur_dst].offset, bufflen);
67757+ bufflen += sg[cur_dst].length;
67758+ cur_dst++;
67759+ cur_src++;
67760+ }
67761+
67762+ if (cmd->free_sg)
67763+ kfree(cmd->sg);
67764+
67765+ cmd->sg = sg;
67766+ cmd->free_sg = 1;
67767+ cmd->sg_cnt = cur_dst;
67768+ cmd->bufflen = bufflen;
67769+ cmd->offset += offset;
67770+
67771+out:
67772+ TRACE_EXIT_RES(res);
67773+ return res;
67774+}
67775+
67776+static inline int q2t_srr_adjust_data(struct q2t_cmd *cmd,
67777+ uint32_t srr_rel_offs, int *xmit_type)
67778+{
67779+ int res = 0;
67780+ int rel_offs;
67781+
67782+ rel_offs = srr_rel_offs - cmd->offset;
67783+ TRACE_MGMT_DBG("srr_rel_offs=%d, rel_offs=%d", srr_rel_offs, rel_offs);
67784+
67785+ *xmit_type = Q2T_XMIT_ALL;
67786+
67787+ if (rel_offs < 0) {
67788+ PRINT_ERROR("qla2x00t(%ld): SRR rel_offs (%d) "
67789+ "< 0", cmd->tgt->ha->instance, rel_offs);
67790+ res = -1;
67791+ } else if (rel_offs == cmd->bufflen)
67792+ *xmit_type = Q2T_XMIT_STATUS;
67793+ else if (rel_offs > 0)
67794+ res = q2t_cut_cmd_data_head(cmd, rel_offs);
67795+
67796+ return res;
67797+}
67798+
67799+/* No locks, thread context */
67800+static void q24_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
67801+ struct srr_imm *imm)
67802+{
67803+ notify24xx_entry_t *ntfy = &imm->imm.notify_entry24;
67804+ struct q2t_cmd *cmd = sctio->cmd;
67805+
67806+ TRACE_ENTRY();
67807+
67808+ TRACE_MGMT_DBG("SRR cmd %p, srr_ui %x", cmd, ntfy->srr_ui);
67809+
67810+ switch (ntfy->srr_ui) {
67811+ case SRR_IU_STATUS:
67812+ spin_lock_irq(&ha->hardware_lock);
67813+ q24_send_notify_ack(ha, ntfy,
67814+ NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
67815+ spin_unlock_irq(&ha->hardware_lock);
67816+ __q24_xmit_response(cmd, Q2T_XMIT_STATUS);
67817+ break;
67818+ case SRR_IU_DATA_IN:
67819+ cmd->bufflen = scst_cmd_get_adjusted_resp_data_len(cmd->scst_cmd);
67820+ if (q2t_has_data(cmd)) {
67821+ uint32_t offset;
67822+ int xmit_type;
67823+ offset = le32_to_cpu(imm->imm.notify_entry24.srr_rel_offs);
67824+ if (q2t_srr_adjust_data(cmd, offset, &xmit_type) != 0)
67825+ goto out_reject;
67826+ spin_lock_irq(&ha->hardware_lock);
67827+ q24_send_notify_ack(ha, ntfy,
67828+ NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
67829+ spin_unlock_irq(&ha->hardware_lock);
67830+ __q24_xmit_response(cmd, xmit_type);
67831+ } else {
67832+ PRINT_ERROR("qla2x00t(%ld): SRR for in data for cmd "
67833+ "without them (tag %d, SCSI status %d), "
67834+ "reject", ha->instance, cmd->tag,
67835+ scst_cmd_get_status(cmd->scst_cmd));
67836+ goto out_reject;
67837+ }
67838+ break;
67839+ case SRR_IU_DATA_OUT:
67840+ cmd->bufflen = scst_cmd_get_write_fields(cmd->scst_cmd,
67841+ &cmd->sg, &cmd->sg_cnt);
67842+ if (q2t_has_data(cmd)) {
67843+ uint32_t offset;
67844+ int xmit_type;
67845+ offset = le32_to_cpu(imm->imm.notify_entry24.srr_rel_offs);
67846+ if (q2t_srr_adjust_data(cmd, offset, &xmit_type) != 0)
67847+ goto out_reject;
67848+ spin_lock_irq(&ha->hardware_lock);
67849+ q24_send_notify_ack(ha, ntfy,
67850+ NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
67851+ spin_unlock_irq(&ha->hardware_lock);
67852+ if (xmit_type & Q2T_XMIT_DATA)
67853+ __q2t_rdy_to_xfer(cmd);
67854+ } else {
67855+ PRINT_ERROR("qla2x00t(%ld): SRR for out data for cmd "
67856+ "without them (tag %d, SCSI status %d), "
67857+ "reject", ha->instance, cmd->tag,
67858+ scst_cmd_get_status(cmd->scst_cmd));
67859+ goto out_reject;
67860+ }
67861+ break;
67862+ default:
67863+ PRINT_ERROR("qla2x00t(%ld): Unknown srr_ui value %x",
67864+ ha->instance, ntfy->srr_ui);
67865+ goto out_reject;
67866+ }
67867+
67868+out:
67869+ TRACE_EXIT();
67870+ return;
67871+
67872+out_reject:
67873+ spin_lock_irq(&ha->hardware_lock);
67874+ q24_send_notify_ack(ha, ntfy, NOTIFY_ACK_SRR_FLAGS_REJECT,
67875+ NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM,
67876+ NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
67877+ if (cmd->state == Q2T_STATE_NEED_DATA) {
67878+ cmd->state = Q2T_STATE_DATA_IN;
67879+ scst_rx_data(cmd->scst_cmd, SCST_RX_STATUS_ERROR,
67880+ SCST_CONTEXT_THREAD);
67881+ } else
67882+ q24_send_term_exchange(ha, cmd, &cmd->atio.atio7, 1);
67883+ spin_unlock_irq(&ha->hardware_lock);
67884+ goto out;
67885+}
67886+
67887+/* No locks, thread context */
67888+static void q2x_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
67889+ struct srr_imm *imm)
67890+{
67891+ notify_entry_t *ntfy = &imm->imm.notify_entry;
67892+ struct q2t_cmd *cmd = sctio->cmd;
67893+
67894+ TRACE_ENTRY();
67895+
67896+ TRACE_MGMT_DBG("SRR cmd %p, srr_ui %x", cmd, ntfy->srr_ui);
67897+
67898+ switch (ntfy->srr_ui) {
67899+ case SRR_IU_STATUS:
67900+ spin_lock_irq(&ha->hardware_lock);
67901+ q2x_send_notify_ack(ha, ntfy, 0, 0, 0,
67902+ NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
67903+ spin_unlock_irq(&ha->hardware_lock);
67904+ __q2x_xmit_response(cmd, Q2T_XMIT_STATUS);
67905+ break;
67906+ case SRR_IU_DATA_IN:
67907+ cmd->bufflen = scst_cmd_get_adjusted_resp_data_len(cmd->scst_cmd);
67908+ if (q2t_has_data(cmd)) {
67909+ uint32_t offset;
67910+ int xmit_type;
67911+ offset = le32_to_cpu(imm->imm.notify_entry.srr_rel_offs);
67912+ if (q2t_srr_adjust_data(cmd, offset, &xmit_type) != 0)
67913+ goto out_reject;
67914+ spin_lock_irq(&ha->hardware_lock);
67915+ q2x_send_notify_ack(ha, ntfy, 0, 0, 0,
67916+ NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
67917+ spin_unlock_irq(&ha->hardware_lock);
67918+ __q2x_xmit_response(cmd, xmit_type);
67919+ } else {
67920+ PRINT_ERROR("qla2x00t(%ld): SRR for in data for cmd "
67921+ "without them (tag %d, SCSI status %d), "
67922+ "reject", ha->instance, cmd->tag,
67923+ scst_cmd_get_status(cmd->scst_cmd));
67924+ goto out_reject;
67925+ }
67926+ break;
67927+ case SRR_IU_DATA_OUT:
67928+ cmd->bufflen = scst_cmd_get_write_fields(cmd->scst_cmd,
67929+ &cmd->sg, &cmd->sg_cnt);
67930+ if (q2t_has_data(cmd)) {
67931+ uint32_t offset;
67932+ int xmit_type;
67933+ offset = le32_to_cpu(imm->imm.notify_entry.srr_rel_offs);
67934+ if (q2t_srr_adjust_data(cmd, offset, &xmit_type) != 0)
67935+ goto out_reject;
67936+ spin_lock_irq(&ha->hardware_lock);
67937+ q2x_send_notify_ack(ha, ntfy, 0, 0, 0,
67938+ NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
67939+ spin_unlock_irq(&ha->hardware_lock);
67940+ if (xmit_type & Q2T_XMIT_DATA)
67941+ __q2t_rdy_to_xfer(cmd);
67942+ } else {
67943+ PRINT_ERROR("qla2x00t(%ld): SRR for out data for cmd "
67944+ "without them (tag %d, SCSI status %d), "
67945+ "reject", ha->instance, cmd->tag,
67946+ scst_cmd_get_status(cmd->scst_cmd));
67947+ goto out_reject;
67948+ }
67949+ break;
67950+ default:
67951+ PRINT_ERROR("qla2x00t(%ld): Unknown srr_ui value %x",
67952+ ha->instance, ntfy->srr_ui);
67953+ goto out_reject;
67954+ }
67955+
67956+out:
67957+ TRACE_EXIT();
67958+ return;
67959+
67960+out_reject:
67961+ spin_lock_irq(&ha->hardware_lock);
67962+ q2x_send_notify_ack(ha, ntfy, 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_REJECT,
67963+ NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM,
67964+ NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
67965+ if (cmd->state == Q2T_STATE_NEED_DATA) {
67966+ cmd->state = Q2T_STATE_DATA_IN;
67967+ scst_rx_data(cmd->scst_cmd, SCST_RX_STATUS_ERROR,
67968+ SCST_CONTEXT_THREAD);
67969+ } else
67970+ q2x_send_term_exchange(ha, cmd, &cmd->atio.atio2x, 1);
67971+ spin_unlock_irq(&ha->hardware_lock);
67972+ goto out;
67973+}
67974+
67975+static void q2t_reject_free_srr_imm(scsi_qla_host_t *ha, struct srr_imm *imm,
67976+ int ha_locked)
67977+{
67978+ if (!ha_locked)
67979+ spin_lock_irq(&ha->hardware_lock);
67980+
67981+ if (IS_FWI2_CAPABLE(ha)) {
67982+ q24_send_notify_ack(ha, &imm->imm.notify_entry24,
67983+ NOTIFY_ACK_SRR_FLAGS_REJECT,
67984+ NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM,
67985+ NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
67986+ } else {
67987+ q2x_send_notify_ack(ha, &imm->imm.notify_entry,
67988+ 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_REJECT,
67989+ NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM,
67990+ NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
67991+ }
67992+
67993+ if (!ha_locked)
67994+ spin_unlock_irq(&ha->hardware_lock);
67995+
67996+ kfree(imm);
67997+ return;
67998+}
67999+
68000+static void q2t_handle_srr_work(struct work_struct *work)
68001+{
68002+ struct q2t_tgt *tgt = container_of(work, struct q2t_tgt, srr_work);
68003+ scsi_qla_host_t *ha = tgt->ha;
68004+ struct srr_ctio *sctio;
68005+
68006+ TRACE_ENTRY();
68007+
68008+ TRACE_MGMT_DBG("SRR work (tgt %p)", tgt);
68009+
68010+restart:
68011+ spin_lock_irq(&tgt->srr_lock);
68012+ list_for_each_entry(sctio, &tgt->srr_ctio_list, srr_list_entry) {
68013+ struct srr_imm *imm;
68014+ struct q2t_cmd *cmd;
68015+ struct srr_imm *i, *ti;
68016+
68017+ imm = NULL;
68018+ list_for_each_entry_safe(i, ti, &tgt->srr_imm_list,
68019+ srr_list_entry) {
68020+ if (i->srr_id == sctio->srr_id) {
68021+ list_del(&i->srr_list_entry);
68022+ if (imm) {
68023+ PRINT_ERROR("qla2x00t(%ld): There must "
68024+ "be only one IMM SRR per CTIO SRR "
68025+ "(IMM SRR %p, id %d, CTIO %p",
68026+ ha->instance, i, i->srr_id, sctio);
68027+ q2t_reject_free_srr_imm(ha, i, 0);
68028+ } else
68029+ imm = i;
68030+ }
68031+ }
68032+
68033+ TRACE_MGMT_DBG("IMM SRR %p, CTIO SRR %p (id %d)", imm, sctio,
68034+ sctio->srr_id);
68035+
68036+ if (imm == NULL) {
68037+ TRACE_MGMT_DBG("Not found matching IMM for SRR CTIO "
68038+ "(id %d)", sctio->srr_id);
68039+ continue;
68040+ } else
68041+ list_del(&sctio->srr_list_entry);
68042+
68043+ spin_unlock_irq(&tgt->srr_lock);
68044+
68045+ cmd = sctio->cmd;
68046+
68047+ /* Restore the originals, except bufflen */
68048+ cmd->offset = scst_cmd_get_ppl_offset(cmd->scst_cmd);
68049+ if (cmd->free_sg) {
68050+ kfree(cmd->sg);
68051+ cmd->free_sg = 0;
68052+ }
68053+ cmd->sg = scst_cmd_get_sg(cmd->scst_cmd);
68054+ cmd->sg_cnt = scst_cmd_get_sg_cnt(cmd->scst_cmd);
68055+
68056+ TRACE_MGMT_DBG("SRR cmd %p (scst_cmd %p, tag %d, op %x), "
68057+ "sg_cnt=%d, offset=%d", cmd, cmd->scst_cmd,
68058+ cmd->tag, cmd->scst_cmd->cdb[0], cmd->sg_cnt,
68059+ cmd->offset);
68060+
68061+ if (IS_FWI2_CAPABLE(ha))
68062+ q24_handle_srr(ha, sctio, imm);
68063+ else
68064+ q2x_handle_srr(ha, sctio, imm);
68065+
68066+ kfree(imm);
68067+ kfree(sctio);
68068+ goto restart;
68069+ }
68070+ spin_unlock_irq(&tgt->srr_lock);
68071+
68072+ TRACE_EXIT();
68073+ return;
68074+}
68075+
68076+/* ha->hardware_lock supposed to be held on entry */
68077+static void q2t_prepare_srr_imm(scsi_qla_host_t *ha, void *iocb)
68078+{
68079+ struct srr_imm *imm;
68080+ struct q2t_tgt *tgt = ha->tgt;
68081+ notify_entry_t *iocb2x = (notify_entry_t *)iocb;
68082+ notify24xx_entry_t *iocb24 = (notify24xx_entry_t *)iocb;
68083+ struct srr_ctio *sctio;
68084+
68085+ tgt->imm_srr_id++;
68086+
68087+ TRACE(TRACE_MGMT, "qla2x00t(%ld): SRR received", ha->instance);
68088+
68089+ imm = kzalloc(sizeof(*imm), GFP_ATOMIC);
68090+ if (imm != NULL) {
68091+ memcpy(&imm->imm.notify_entry, iocb,
68092+ sizeof(imm->imm.notify_entry));
68093+
68094+ /* IRQ is already OFF */
68095+ spin_lock(&tgt->srr_lock);
68096+ imm->srr_id = tgt->imm_srr_id;
68097+ list_add_tail(&imm->srr_list_entry,
68098+ &tgt->srr_imm_list);
68099+ TRACE_MGMT_DBG("IMM NTFY SRR %p added (id %d, ui %x)", imm,
68100+ imm->srr_id, iocb24->srr_ui);
68101+ if (tgt->imm_srr_id == tgt->ctio_srr_id) {
68102+ int found = 0;
68103+ list_for_each_entry(sctio, &tgt->srr_ctio_list,
68104+ srr_list_entry) {
68105+ if (sctio->srr_id == imm->srr_id) {
68106+ found = 1;
68107+ break;
68108+ }
68109+ }
68110+ if (found) {
68111+ TRACE_MGMT_DBG("%s", "Scheduling srr work");
68112+ schedule_work(&tgt->srr_work);
68113+ } else {
68114+ TRACE(TRACE_MGMT, "qla2x00t(%ld): imm_srr_id "
68115+ "== ctio_srr_id (%d), but there is no "
68116+ "corresponding SRR CTIO, deleting IMM "
68117+ "SRR %p", ha->instance, tgt->ctio_srr_id,
68118+ imm);
68119+ list_del(&imm->srr_list_entry);
68120+
68121+ kfree(imm);
68122+
68123+ spin_unlock(&tgt->srr_lock);
68124+ goto out_reject;
68125+ }
68126+ }
68127+ spin_unlock(&tgt->srr_lock);
68128+ } else {
68129+ struct srr_ctio *ts;
68130+
68131+ PRINT_ERROR("qla2x00t(%ld): Unable to allocate SRR IMM "
68132+ "entry, SRR request will be rejected", ha->instance);
68133+
68134+ /* IRQ is already OFF */
68135+ spin_lock(&tgt->srr_lock);
68136+ list_for_each_entry_safe(sctio, ts, &tgt->srr_ctio_list,
68137+ srr_list_entry) {
68138+ if (sctio->srr_id == tgt->imm_srr_id) {
68139+ TRACE_MGMT_DBG("CTIO SRR %p deleted "
68140+ "(id %d)", sctio, sctio->srr_id);
68141+ list_del(&sctio->srr_list_entry);
68142+ if (IS_FWI2_CAPABLE(ha)) {
68143+ q24_send_term_exchange(ha, sctio->cmd,
68144+ &sctio->cmd->atio.atio7, 1);
68145+ } else {
68146+ q2x_send_term_exchange(ha, sctio->cmd,
68147+ &sctio->cmd->atio.atio2x, 1);
68148+ }
68149+ kfree(sctio);
68150+ }
68151+ }
68152+ spin_unlock(&tgt->srr_lock);
68153+ goto out_reject;
68154+ }
68155+
68156+out:
68157+ return;
68158+
68159+out_reject:
68160+ if (IS_FWI2_CAPABLE(ha)) {
68161+ q24_send_notify_ack(ha, iocb24,
68162+ NOTIFY_ACK_SRR_FLAGS_REJECT,
68163+ NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM,
68164+ NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
68165+ } else {
68166+ q2x_send_notify_ack(ha, iocb2x,
68167+ 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_REJECT,
68168+ NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM,
68169+ NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
68170+ }
68171+ goto out;
68172+}
68173+
68174+/*
68175+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
68176+ */
68177+static void q2t_handle_imm_notify(scsi_qla_host_t *ha, void *iocb)
68178+{
68179+ uint16_t status;
68180+ uint32_t add_flags = 0;
68181+ int send_notify_ack = 1;
68182+ notify_entry_t *iocb2x = (notify_entry_t *)iocb;
68183+ notify24xx_entry_t *iocb24 = (notify24xx_entry_t *)iocb;
68184+
68185+ TRACE_ENTRY();
68186+
68187+ status = le16_to_cpu(iocb2x->status);
68188+
68189+ TRACE_BUFF_FLAG(TRACE_BUFF, "IMMED Notify Coming Up",
68190+ iocb, sizeof(*iocb2x));
68191+
68192+ switch (status) {
68193+ case IMM_NTFY_LIP_RESET:
68194+ {
68195+ if (IS_FWI2_CAPABLE(ha)) {
68196+ TRACE(TRACE_MGMT, "qla2x00t(%ld): LIP reset (loop %#x), "
68197+ "subcode %x", ha->instance,
68198+ le16_to_cpu(iocb24->nport_handle),
68199+ iocb24->status_subcode);
68200+ } else {
68201+ TRACE(TRACE_MGMT, "qla2x00t(%ld): LIP reset (I %#x)",
68202+ ha->instance, GET_TARGET_ID(ha, iocb2x));
68203+ /* set the Clear LIP reset event flag */
68204+ add_flags |= NOTIFY_ACK_CLEAR_LIP_RESET;
68205+ }
68206+ if (q2t_reset(ha, iocb, Q2T_ABORT_ALL) == 0)
68207+ send_notify_ack = 0;
68208+ break;
68209+ }
68210+
68211+ case IMM_NTFY_LIP_LINK_REINIT:
68212+ {
68213+ struct q2t_tgt *tgt = ha->tgt;
68214+ TRACE(TRACE_MGMT, "qla2x00t(%ld): LINK REINIT (loop %#x, "
68215+ "subcode %x)", ha->instance,
68216+ le16_to_cpu(iocb24->nport_handle),
68217+ iocb24->status_subcode);
68218+ if (tgt->link_reinit_iocb_pending)
68219+ q24_send_notify_ack(ha, &tgt->link_reinit_iocb, 0, 0, 0);
68220+ memcpy(&tgt->link_reinit_iocb, iocb24, sizeof(*iocb24));
68221+ tgt->link_reinit_iocb_pending = 1;
68222+ /*
68223+ * QLogic requires to wait after LINK REINIT for possible
68224+ * PDISC or ADISC ELS commands
68225+ */
68226+ send_notify_ack = 0;
68227+ break;
68228+ }
68229+
68230+ case IMM_NTFY_PORT_LOGOUT:
68231+ if (IS_FWI2_CAPABLE(ha)) {
68232+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Port logout (loop "
68233+ "%#x, subcode %x)", ha->instance,
68234+ le16_to_cpu(iocb24->nport_handle),
68235+ iocb24->status_subcode);
68236+ } else {
68237+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Port logout (S "
68238+ "%08x -> L %#x)", ha->instance,
68239+ le16_to_cpu(iocb2x->seq_id),
68240+ le16_to_cpu(iocb2x->lun));
68241+ }
68242+ if (q2t_reset(ha, iocb, Q2T_NEXUS_LOSS_SESS) == 0)
68243+ send_notify_ack = 0;
68244+ /* The sessions will be cleared in the callback, if needed */
68245+ break;
68246+
68247+ case IMM_NTFY_GLBL_TPRLO:
68248+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Global TPRLO (%x)",
68249+ ha->instance, status);
68250+ if (q2t_reset(ha, iocb, Q2T_NEXUS_LOSS) == 0)
68251+ send_notify_ack = 0;
68252+ /* The sessions will be cleared in the callback, if needed */
68253+ break;
68254+
68255+ case IMM_NTFY_PORT_CONFIG:
68256+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Port config changed (%x)",
68257+ ha->instance, status);
68258+ if (q2t_reset(ha, iocb, Q2T_ABORT_ALL) == 0)
68259+ send_notify_ack = 0;
68260+ /* The sessions will be cleared in the callback, if needed */
68261+ break;
68262+
68263+ case IMM_NTFY_GLBL_LOGO:
68264+ PRINT_WARNING("qla2x00t(%ld): Link failure detected",
68265+ ha->instance);
68266+ /* I_T nexus loss */
68267+ if (q2t_reset(ha, iocb, Q2T_NEXUS_LOSS) == 0)
68268+ send_notify_ack = 0;
68269+ break;
68270+
68271+ case IMM_NTFY_IOCB_OVERFLOW:
68272+ PRINT_ERROR("qla2x00t(%ld): Cannot provide requested "
68273+ "capability (IOCB overflowed the immediate notify "
68274+ "resource count)", ha->instance);
68275+ break;
68276+
68277+ case IMM_NTFY_ABORT_TASK:
68278+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Abort Task (S %08x I %#x -> "
68279+ "L %#x)", ha->instance, le16_to_cpu(iocb2x->seq_id),
68280+ GET_TARGET_ID(ha, iocb2x), le16_to_cpu(iocb2x->lun));
68281+ if (q2t_abort_task(ha, iocb2x) == 0)
68282+ send_notify_ack = 0;
68283+ break;
68284+
68285+ case IMM_NTFY_RESOURCE:
68286+ PRINT_ERROR("qla2x00t(%ld): Out of resources, host %ld",
68287+ ha->instance, ha->host_no);
68288+ break;
68289+
68290+ case IMM_NTFY_MSG_RX:
68291+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Immediate notify task %x",
68292+ ha->instance, iocb2x->task_flags);
68293+ if (q2t_handle_task_mgmt(ha, iocb2x) == 0)
68294+ send_notify_ack = 0;
68295+ break;
68296+
68297+ case IMM_NTFY_ELS:
68298+ if (q24_handle_els(ha, iocb24) == 0)
68299+ send_notify_ack = 0;
68300+ break;
68301+
68302+ case IMM_NTFY_SRR:
68303+ q2t_prepare_srr_imm(ha, iocb);
68304+ send_notify_ack = 0;
68305+ break;
68306+
68307+ default:
68308+ PRINT_ERROR("qla2x00t(%ld): Received unknown immediate "
68309+ "notify status %x", ha->instance, status);
68310+ break;
68311+ }
68312+
68313+ if (send_notify_ack) {
68314+ if (IS_FWI2_CAPABLE(ha))
68315+ q24_send_notify_ack(ha, iocb24, 0, 0, 0);
68316+ else
68317+ q2x_send_notify_ack(ha, iocb2x, add_flags, 0, 0, 0,
68318+ 0, 0);
68319+ }
68320+
68321+ TRACE_EXIT();
68322+ return;
68323+}
68324+
68325+/*
68326+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
68327+ */
68328+static void q2x_send_busy(scsi_qla_host_t *ha, atio_entry_t *atio)
68329+{
68330+ ctio_ret_entry_t *ctio;
68331+
68332+ TRACE_ENTRY();
68333+
68334+ /* Sending marker isn't necessary, since we called from ISR */
68335+
68336+ ctio = (ctio_ret_entry_t *)qla2x00_req_pkt(ha);
68337+ if (ctio == NULL) {
68338+ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
68339+ "request packet", ha->instance, __func__);
68340+ goto out;
68341+ }
68342+
68343+ ctio->entry_type = CTIO_RET_TYPE;
68344+ ctio->entry_count = 1;
68345+ ctio->handle = Q2T_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
68346+ ctio->scsi_status = __constant_cpu_to_le16(SAM_STAT_BUSY);
68347+ ctio->residual = atio->data_length;
68348+ if (ctio->residual != 0)
68349+ ctio->scsi_status |= SS_RESIDUAL_UNDER;
68350+
68351+ /* Set IDs */
68352+ SET_TARGET_ID(ha, ctio->target, GET_TARGET_ID(ha, atio));
68353+ ctio->rx_id = atio->rx_id;
68354+
68355+ ctio->flags = __constant_cpu_to_le16(OF_SSTS | OF_FAST_POST |
68356+ OF_NO_DATA | OF_SS_MODE_1);
68357+ ctio->flags |= __constant_cpu_to_le16(OF_INC_RC);
68358+ /*
68359+ * CTIO from fw w/o scst_cmd doesn't provide enough info to retry it,
68360+ * if the explicit conformation is used.
68361+ */
68362+
68363+ TRACE_BUFFER("CTIO BUSY packet data", ctio, REQUEST_ENTRY_SIZE);
68364+
68365+ q2t_exec_queue(ha);
68366+
68367+out:
68368+ TRACE_EXIT();
68369+ return;
68370+}
68371+
68372+/*
68373+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
68374+ */
68375+static void q24_send_busy(scsi_qla_host_t *ha, atio7_entry_t *atio,
68376+ uint16_t status)
68377+{
68378+ ctio7_status1_entry_t *ctio;
68379+ struct q2t_sess *sess;
68380+
68381+ TRACE_ENTRY();
68382+
68383+ sess = q2t_find_sess_by_s_id(ha->tgt, atio->fcp_hdr.s_id);
68384+ if (sess == NULL) {
68385+ q24_send_term_exchange(ha, NULL, atio, 1);
68386+ goto out;
68387+ }
68388+
68389+ /* Sending marker isn't necessary, since we called from ISR */
68390+
68391+ ctio = (ctio7_status1_entry_t *)qla2x00_req_pkt(ha);
68392+ if (ctio == NULL) {
68393+ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
68394+ "request packet", ha->instance, __func__);
68395+ goto out;
68396+ }
68397+
68398+ ctio->common.entry_type = CTIO_TYPE7;
68399+ ctio->common.entry_count = 1;
68400+ ctio->common.handle = Q2T_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
68401+ ctio->common.nport_handle = sess->loop_id;
68402+ ctio->common.timeout = __constant_cpu_to_le16(Q2T_TIMEOUT);
68403+ ctio->common.initiator_id[0] = atio->fcp_hdr.s_id[2];
68404+ ctio->common.initiator_id[1] = atio->fcp_hdr.s_id[1];
68405+ ctio->common.initiator_id[2] = atio->fcp_hdr.s_id[0];
68406+ ctio->common.exchange_addr = atio->exchange_addr;
68407+ ctio->flags = (atio->attr << 9) | __constant_cpu_to_le16(
68408+ CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS |
68409+ CTIO7_FLAGS_DONT_RET_CTIO);
68410+ /*
68411+ * CTIO from fw w/o scst_cmd doesn't provide enough info to retry it,
68412+ * if the explicit conformation is used.
68413+ */
68414+ ctio->ox_id = swab16(atio->fcp_hdr.ox_id);
68415+ ctio->scsi_status = cpu_to_le16(status);
68416+ ctio->residual = atio->fcp_cmnd.data_length;
68417+ if (ctio->residual != 0)
68418+ ctio->scsi_status |= SS_RESIDUAL_UNDER;
68419+
68420+ TRACE_BUFFER("CTIO7 BUSY packet data", ctio, REQUEST_ENTRY_SIZE);
68421+
68422+ q2t_exec_queue(ha);
68423+
68424+out:
68425+ TRACE_EXIT();
68426+ return;
68427+}
68428+
68429+/* ha->hardware_lock supposed to be held on entry */
68430+/* called via callback from qla2xxx */
68431+static void q24_atio_pkt(scsi_qla_host_t *ha, atio7_entry_t *atio)
68432+{
68433+ int rc;
68434+ struct q2t_tgt *tgt = ha->tgt;
68435+
68436+ TRACE_ENTRY();
68437+
68438+ if (unlikely(tgt == NULL)) {
68439+ TRACE_MGMT_DBG("ATIO pkt, but no tgt (ha %p)", ha);
68440+ goto out;
68441+ }
68442+
68443+ TRACE(TRACE_SCSI, "qla2x00t(%ld): ATIO pkt %p: type %02x count %02x",
68444+ ha->instance, atio, atio->entry_type, atio->entry_count);
68445+
68446+ /*
68447+ * In tgt_stop mode we also should allow all requests to pass.
68448+ * Otherwise, some commands can stuck.
68449+ */
68450+
68451+ tgt->irq_cmd_count++;
68452+
68453+ switch (atio->entry_type) {
68454+ case ATIO_TYPE7:
68455+ if (unlikely(atio->entry_count > 1) ||
68456+ unlikely(atio->fcp_cmnd.add_cdb_len != 0)) {
68457+ PRINT_ERROR("qla2x00t(%ld): Multi entry ATIO7 IOCBs "
68458+ "(%d), ie with CDBs>16 bytes (%d), are not "
68459+ "supported", ha->instance, atio->entry_count,
68460+ atio->fcp_cmnd.add_cdb_len);
68461+ break;
68462+ }
68463+ TRACE_DBG("ATIO_TYPE7 instance %ld, lun %Lx, read/write %d/%d, "
68464+ "data_length %04x, s_id %x:%x:%x", ha->instance,
68465+ atio->fcp_cmnd.lun, atio->fcp_cmnd.rddata,
68466+ atio->fcp_cmnd.wrdata,
68467+ be32_to_cpu(atio->fcp_cmnd.data_length),
68468+ atio->fcp_hdr.s_id[0], atio->fcp_hdr.s_id[1],
68469+ atio->fcp_hdr.s_id[2]);
68470+ TRACE_BUFFER("Incoming ATIO7 packet data", atio,
68471+ REQUEST_ENTRY_SIZE);
68472+ PRINT_BUFF_FLAG(TRACE_SCSI, "FCP CDB", atio->fcp_cmnd.cdb,
68473+ sizeof(atio->fcp_cmnd.cdb));
68474+ if (unlikely(atio->exchange_addr ==
68475+ ATIO_EXCHANGE_ADDRESS_UNKNOWN)) {
68476+ TRACE(TRACE_OUT_OF_MEM, "qla2x00t(%ld): ATIO_TYPE7 "
68477+ "received with UNKNOWN exchange address, "
68478+ "sending QUEUE_FULL", ha->instance);
68479+ q24_send_busy(ha, atio, SAM_STAT_TASK_SET_FULL);
68480+ break;
68481+ }
68482+ if (likely(atio->fcp_cmnd.task_mgmt_flags == 0))
68483+ rc = q2t_send_cmd_to_scst(ha, (atio_t *)atio);
68484+ else
68485+ rc = q2t_handle_task_mgmt(ha, atio);
68486+ if (unlikely(rc != 0)) {
68487+ if (rc == -ESRCH) {
68488+#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
68489+ q24_send_busy(ha, atio, SAM_STAT_BUSY);
68490+#else
68491+ q24_send_term_exchange(ha, NULL, atio, 1);
68492+#endif
68493+ } else {
68494+ PRINT_INFO("qla2x00t(%ld): Unable to send "
68495+ "command to SCST, sending BUSY status",
68496+ ha->instance);
68497+ q24_send_busy(ha, atio, SAM_STAT_BUSY);
68498+ }
68499+ }
68500+ break;
68501+
68502+ case IMMED_NOTIFY_TYPE:
68503+ {
68504+ notify_entry_t *pkt = (notify_entry_t *)atio;
68505+ if (unlikely(pkt->entry_status != 0)) {
68506+ PRINT_ERROR("qla2x00t(%ld): Received ATIO packet %x "
68507+ "with error status %x", ha->instance,
68508+ pkt->entry_type, pkt->entry_status);
68509+ break;
68510+ }
68511+ TRACE_DBG("%s", "IMMED_NOTIFY ATIO");
68512+ q2t_handle_imm_notify(ha, pkt);
68513+ break;
68514+ }
68515+
68516+ default:
68517+ PRINT_ERROR("qla2x00t(%ld): Received unknown ATIO atio "
68518+ "type %x", ha->instance, atio->entry_type);
68519+ break;
68520+ }
68521+
68522+ tgt->irq_cmd_count--;
68523+
68524+out:
68525+ TRACE_EXIT();
68526+ return;
68527+}
68528+
68529+/* ha->hardware_lock supposed to be held on entry */
68530+/* called via callback from qla2xxx */
68531+static void q2t_response_pkt(scsi_qla_host_t *ha, response_t *pkt)
68532+{
68533+ struct q2t_tgt *tgt = ha->tgt;
68534+
68535+ TRACE_ENTRY();
68536+
68537+ if (unlikely(tgt == NULL)) {
68538+ PRINT_ERROR("qla2x00t(%ld): Response pkt %x received, but no "
68539+ "tgt (ha %p)", ha->instance, pkt->entry_type, ha);
68540+ goto out;
68541+ }
68542+
68543+ TRACE(TRACE_SCSI, "qla2x00t(%ld): pkt %p: T %02x C %02x S %02x "
68544+ "handle %#x", ha->instance, pkt, pkt->entry_type,
68545+ pkt->entry_count, pkt->entry_status, pkt->handle);
68546+
68547+ /*
68548+ * In tgt_stop mode we also should allow all requests to pass.
68549+ * Otherwise, some commands can stuck.
68550+ */
68551+
68552+ if (unlikely(pkt->entry_status != 0)) {
68553+ PRINT_ERROR("qla2x00t(%ld): Received response packet %x "
68554+ "with error status %x", ha->instance, pkt->entry_type,
68555+ pkt->entry_status);
68556+ switch (pkt->entry_type) {
68557+ case ACCEPT_TGT_IO_TYPE:
68558+ case IMMED_NOTIFY_TYPE:
68559+ case ABTS_RECV_24XX:
68560+ goto out;
68561+ default:
68562+ break;
68563+ }
68564+ }
68565+
68566+ tgt->irq_cmd_count++;
68567+
68568+ switch (pkt->entry_type) {
68569+ case CTIO_TYPE7:
68570+ {
68571+ ctio7_fw_entry_t *entry = (ctio7_fw_entry_t *)pkt;
68572+ TRACE_DBG("CTIO_TYPE7: instance %ld",
68573+ ha->instance);
68574+ TRACE_BUFFER("Incoming CTIO7 packet data", entry,
68575+ REQUEST_ENTRY_SIZE);
68576+ q2t_do_ctio_completion(ha, entry->handle,
68577+ le16_to_cpu(entry->status)|(pkt->entry_status << 16),
68578+ entry);
68579+ break;
68580+ }
68581+
68582+ case ACCEPT_TGT_IO_TYPE:
68583+ {
68584+ atio_entry_t *atio;
68585+ int rc;
68586+ atio = (atio_entry_t *)pkt;
68587+ TRACE_DBG("ACCEPT_TGT_IO instance %ld status %04x "
68588+ "lun %04x read/write %d data_length %04x "
68589+ "target_id %02x rx_id %04x ",
68590+ ha->instance, le16_to_cpu(atio->status),
68591+ le16_to_cpu(atio->lun),
68592+ atio->execution_codes,
68593+ le32_to_cpu(atio->data_length),
68594+ GET_TARGET_ID(ha, atio), atio->rx_id);
68595+ TRACE_BUFFER("Incoming ATIO packet data", atio,
68596+ REQUEST_ENTRY_SIZE);
68597+ if (atio->status != __constant_cpu_to_le16(ATIO_CDB_VALID)) {
68598+ PRINT_ERROR("qla2x00t(%ld): ATIO with error "
68599+ "status %x received", ha->instance,
68600+ le16_to_cpu(atio->status));
68601+ break;
68602+ }
68603+ TRACE_BUFFER("Incoming ATIO packet data", atio, REQUEST_ENTRY_SIZE);
68604+ PRINT_BUFF_FLAG(TRACE_SCSI, "FCP CDB", atio->cdb,
68605+ sizeof(atio->cdb));
68606+ rc = q2t_send_cmd_to_scst(ha, (atio_t *)atio);
68607+ if (unlikely(rc != 0)) {
68608+ if (rc == -ESRCH) {
68609+#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
68610+ q2x_send_busy(ha, atio);
68611+#else
68612+ q2x_send_term_exchange(ha, NULL, atio, 1);
68613+#endif
68614+ } else {
68615+ PRINT_INFO("qla2x00t(%ld): Unable to send "
68616+ "command to SCST, sending BUSY status",
68617+ ha->instance);
68618+ q2x_send_busy(ha, atio);
68619+ }
68620+ }
68621+ }
68622+ break;
68623+
68624+ case CONTINUE_TGT_IO_TYPE:
68625+ {
68626+ ctio_common_entry_t *entry = (ctio_common_entry_t *)pkt;
68627+ TRACE_DBG("CONTINUE_TGT_IO: instance %ld", ha->instance);
68628+ TRACE_BUFFER("Incoming CTIO packet data", entry,
68629+ REQUEST_ENTRY_SIZE);
68630+ q2t_do_ctio_completion(ha, entry->handle,
68631+ le16_to_cpu(entry->status)|(pkt->entry_status << 16),
68632+ entry);
68633+ break;
68634+ }
68635+
68636+ case CTIO_A64_TYPE:
68637+ {
68638+ ctio_common_entry_t *entry = (ctio_common_entry_t *)pkt;
68639+ TRACE_DBG("CTIO_A64: instance %ld", ha->instance);
68640+ TRACE_BUFFER("Incoming CTIO_A64 packet data", entry,
68641+ REQUEST_ENTRY_SIZE);
68642+ q2t_do_ctio_completion(ha, entry->handle,
68643+ le16_to_cpu(entry->status)|(pkt->entry_status << 16),
68644+ entry);
68645+ break;
68646+ }
68647+
68648+ case IMMED_NOTIFY_TYPE:
68649+ TRACE_DBG("%s", "IMMED_NOTIFY");
68650+ q2t_handle_imm_notify(ha, (notify_entry_t *)pkt);
68651+ break;
68652+
68653+ case NOTIFY_ACK_TYPE:
68654+ if (tgt->notify_ack_expected > 0) {
68655+ nack_entry_t *entry = (nack_entry_t *)pkt;
68656+ TRACE_DBG("NOTIFY_ACK seq %08x status %x",
68657+ le16_to_cpu(entry->seq_id),
68658+ le16_to_cpu(entry->status));
68659+ TRACE_BUFFER("Incoming NOTIFY_ACK packet data", pkt,
68660+ RESPONSE_ENTRY_SIZE);
68661+ tgt->notify_ack_expected--;
68662+ if (entry->status != __constant_cpu_to_le16(NOTIFY_ACK_SUCCESS)) {
68663+ PRINT_ERROR("qla2x00t(%ld): NOTIFY_ACK "
68664+ "failed %x", ha->instance,
68665+ le16_to_cpu(entry->status));
68666+ }
68667+ } else {
68668+ PRINT_ERROR("qla2x00t(%ld): Unexpected NOTIFY_ACK "
68669+ "received", ha->instance);
68670+ }
68671+ break;
68672+
68673+ case ABTS_RECV_24XX:
68674+ TRACE_DBG("ABTS_RECV_24XX: instance %ld", ha->instance);
68675+ TRACE_BUFF_FLAG(TRACE_BUFF, "Incoming ABTS_RECV "
68676+ "packet data", pkt, REQUEST_ENTRY_SIZE);
68677+ q24_handle_abts(ha, (abts24_recv_entry_t *)pkt);
68678+ break;
68679+
68680+ case ABTS_RESP_24XX:
68681+ if (tgt->abts_resp_expected > 0) {
68682+ abts24_resp_fw_entry_t *entry =
68683+ (abts24_resp_fw_entry_t *)pkt;
68684+ TRACE_DBG("ABTS_RESP_24XX: compl_status %x",
68685+ entry->compl_status);
68686+ TRACE_BUFF_FLAG(TRACE_BUFF, "Incoming ABTS_RESP "
68687+ "packet data", pkt, REQUEST_ENTRY_SIZE);
68688+ tgt->abts_resp_expected--;
68689+ if (le16_to_cpu(entry->compl_status) != ABTS_RESP_COMPL_SUCCESS) {
68690+ if ((entry->error_subcode1 == 0x1E) &&
68691+ (entry->error_subcode2 == 0)) {
68692+ /*
68693+ * We've got a race here: aborted exchange not
68694+ * terminated, i.e. response for the aborted
68695+ * command was sent between the abort request
68696+ * was received and processed. Unfortunately,
68697+ * the firmware has a silly requirement that
68698+ * all aborted exchanges must be explicitely
68699+ * terminated, otherwise it refuses to send
68700+ * responses for the abort requests. So, we
68701+ * have to (re)terminate the exchange and
68702+ * retry the abort response.
68703+ */
68704+ q24_retry_term_exchange(ha, entry);
68705+ } else
68706+ PRINT_ERROR("qla2x00t(%ld): ABTS_RESP_24XX "
68707+ "failed %x (subcode %x:%x)", ha->instance,
68708+ entry->compl_status, entry->error_subcode1,
68709+ entry->error_subcode2);
68710+ }
68711+ } else {
68712+ PRINT_ERROR("qla2x00t(%ld): Unexpected ABTS_RESP_24XX "
68713+ "received", ha->instance);
68714+ }
68715+ break;
68716+
68717+ case MODIFY_LUN_TYPE:
68718+ if (tgt->modify_lun_expected > 0) {
68719+ modify_lun_entry_t *entry = (modify_lun_entry_t *)pkt;
68720+ TRACE_DBG("MODIFY_LUN %x, imm %c%d, cmd %c%d",
68721+ entry->status,
68722+ (entry->operators & MODIFY_LUN_IMM_ADD) ? '+'
68723+ : (entry->operators & MODIFY_LUN_IMM_SUB) ? '-'
68724+ : ' ',
68725+ entry->immed_notify_count,
68726+ (entry->operators & MODIFY_LUN_CMD_ADD) ? '+'
68727+ : (entry->operators & MODIFY_LUN_CMD_SUB) ? '-'
68728+ : ' ',
68729+ entry->command_count);
68730+ tgt->modify_lun_expected--;
68731+ if (entry->status != MODIFY_LUN_SUCCESS) {
68732+ PRINT_ERROR("qla2x00t(%ld): MODIFY_LUN "
68733+ "failed %x", ha->instance,
68734+ entry->status);
68735+ }
68736+ } else {
68737+ PRINT_ERROR("qla2x00t(%ld): Unexpected MODIFY_LUN "
68738+ "received", (ha != NULL) ? (long)ha->instance : -1);
68739+ }
68740+ break;
68741+
68742+ case ENABLE_LUN_TYPE:
68743+ {
68744+ elun_entry_t *entry = (elun_entry_t *)pkt;
68745+ TRACE_DBG("ENABLE_LUN %x imm %u cmd %u ",
68746+ entry->status, entry->immed_notify_count,
68747+ entry->command_count);
68748+ if (entry->status == ENABLE_LUN_ALREADY_ENABLED) {
68749+ TRACE_DBG("LUN is already enabled: %#x",
68750+ entry->status);
68751+ entry->status = ENABLE_LUN_SUCCESS;
68752+ } else if (entry->status == ENABLE_LUN_RC_NONZERO) {
68753+ TRACE_DBG("ENABLE_LUN succeeded, but with "
68754+ "error: %#x", entry->status);
68755+ entry->status = ENABLE_LUN_SUCCESS;
68756+ } else if (entry->status != ENABLE_LUN_SUCCESS) {
68757+ PRINT_ERROR("qla2x00t(%ld): ENABLE_LUN "
68758+ "failed %x", ha->instance, entry->status);
68759+ qla_clear_tgt_mode(ha);
68760+ } /* else success */
68761+ break;
68762+ }
68763+
68764+ default:
68765+ PRINT_ERROR("qla2x00t(%ld): Received unknown response pkt "
68766+ "type %x", ha->instance, pkt->entry_type);
68767+ break;
68768+ }
68769+
68770+ tgt->irq_cmd_count--;
68771+
68772+out:
68773+ TRACE_EXIT();
68774+ return;
68775+}
68776+
68777+/*
68778+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
68779+ */
68780+static void q2t_async_event(uint16_t code, scsi_qla_host_t *ha,
68781+ uint16_t *mailbox)
68782+{
68783+ struct q2t_tgt *tgt = ha->tgt;
68784+
68785+ TRACE_ENTRY();
68786+
68787+ if (unlikely(tgt == NULL)) {
68788+ TRACE_DBG("ASYNC EVENT %#x, but no tgt (ha %p)", code, ha);
68789+ goto out;
68790+ }
68791+
68792+ /*
68793+ * In tgt_stop mode we also should allow all requests to pass.
68794+ * Otherwise, some commands can stuck.
68795+ */
68796+
68797+ tgt->irq_cmd_count++;
68798+
68799+ switch (code) {
68800+ case MBA_RESET: /* Reset */
68801+ case MBA_SYSTEM_ERR: /* System Error */
68802+ case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */
68803+ case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */
68804+ case MBA_ATIO_TRANSFER_ERR: /* ATIO Queue Transfer Error */
68805+ TRACE(TRACE_MGMT, "qla2x00t(%ld): System error async event %#x "
68806+ "occured", ha->instance, code);
68807+ break;
68808+
68809+ case MBA_LOOP_UP:
68810+ {
68811+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Async LOOP_UP occured "
68812+ "(m[1]=%x, m[2]=%x, m[3]=%x, m[4]=%x)", ha->instance,
68813+ le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]),
68814+ le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4]));
68815+ if (tgt->link_reinit_iocb_pending) {
68816+ q24_send_notify_ack(ha, &tgt->link_reinit_iocb, 0, 0, 0);
68817+ tgt->link_reinit_iocb_pending = 0;
68818+ }
68819+ break;
68820+ }
68821+
68822+ case MBA_LIP_OCCURRED:
68823+ case MBA_LOOP_DOWN:
68824+ case MBA_LIP_RESET:
68825+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Async event %#x occured "
68826+ "(m[1]=%x, m[2]=%x, m[3]=%x, m[4]=%x)", ha->instance,
68827+ code, le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]),
68828+ le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4]));
68829+ break;
68830+
68831+ case MBA_PORT_UPDATE:
68832+ case MBA_RSCN_UPDATE:
68833+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Port update async event %#x "
68834+ "occured: updating the ports database (m[1]=%x, m[2]=%x, "
68835+ "m[3]=%x, m[4]=%x)", ha->instance, code,
68836+ le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]),
68837+ le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4]));
68838+ /* .mark_all_devices_lost() is handled by the initiator driver */
68839+ break;
68840+
68841+ default:
68842+ TRACE(TRACE_MGMT, "qla2x00t(%ld): Async event %#x occured: "
68843+ "ignore (m[1]=%x, m[2]=%x, m[3]=%x, m[4]=%x)",
68844+ ha->instance, code,
68845+ le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]),
68846+ le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4]));
68847+ break;
68848+ }
68849+
68850+ tgt->irq_cmd_count--;
68851+
68852+out:
68853+ TRACE_EXIT();
68854+ return;
68855+}
68856+
68857+static int q2t_get_target_name(scsi_qla_host_t *ha, char **wwn)
68858+{
68859+ const int wwn_len = 3*WWN_SIZE+2;
68860+ int res = 0;
68861+ char *name;
68862+
68863+ name = kmalloc(wwn_len, GFP_KERNEL);
68864+ if (name == NULL) {
68865+ TRACE(TRACE_OUT_OF_MEM, "%s", "qla2x00t: Allocation of tgt "
68866+ "name failed");
68867+ res = -ENOMEM;
68868+ goto out;
68869+ }
68870+
68871+ sprintf(name, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
68872+ ha->port_name[0], ha->port_name[1],
68873+ ha->port_name[2], ha->port_name[3],
68874+ ha->port_name[4], ha->port_name[5],
68875+ ha->port_name[6], ha->port_name[7]);
68876+
68877+ *wwn = name;
68878+
68879+out:
68880+ return res;
68881+}
68882+
68883+static int q24_get_loop_id(scsi_qla_host_t *ha, atio7_entry_t *atio7,
68884+ uint16_t *loop_id)
68885+{
68886+ dma_addr_t gid_list_dma;
68887+ struct gid_list_info *gid_list;
68888+ char *id_iter;
68889+ int res, rc, i;
68890+ uint16_t entries;
68891+
68892+ TRACE_ENTRY();
68893+
68894+ gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE,
68895+ &gid_list_dma, GFP_KERNEL);
68896+ if (gid_list == NULL) {
68897+ PRINT_ERROR("qla2x00t(%ld): DMA Alloc failed of %zd",
68898+ ha->instance, GID_LIST_SIZE);
68899+ res = -ENOMEM;
68900+ goto out;
68901+ }
68902+
68903+ /* Get list of logged in devices */
68904+ rc = qla2x00_get_id_list(ha, gid_list, gid_list_dma, &entries);
68905+ if (rc != QLA_SUCCESS) {
68906+ PRINT_ERROR("qla2x00t(%ld): get_id_list() failed: %x",
68907+ ha->instance, rc);
68908+ res = -1;
68909+ goto out_free_id_list;
68910+ }
68911+
68912+ id_iter = (char *)gid_list;
68913+ res = -1;
68914+ for (i = 0; i < entries; i++) {
68915+ struct gid_list_info *gid = (struct gid_list_info *)id_iter;
68916+ if ((gid->al_pa == atio7->fcp_hdr.s_id[2]) &&
68917+ (gid->area == atio7->fcp_hdr.s_id[1]) &&
68918+ (gid->domain == atio7->fcp_hdr.s_id[0])) {
68919+ *loop_id = le16_to_cpu(gid->loop_id);
68920+ res = 0;
68921+ break;
68922+ }
68923+ id_iter += ha->gid_list_info_size;
68924+ }
68925+
68926+ if (res != 0) {
68927+ if ((atio7->fcp_hdr.s_id[0] == 0xFF) &&
68928+ (atio7->fcp_hdr.s_id[1] == 0xFC)) {
68929+ /*
68930+ * This is Domain Controller. It should be OK to drop
68931+ * SCSI commands from it.
68932+ */
68933+ TRACE_MGMT_DBG("Unable to find initiator with S_ID "
68934+ "%x:%x:%x", atio7->fcp_hdr.s_id[0],
68935+ atio7->fcp_hdr.s_id[1], atio7->fcp_hdr.s_id[2]);
68936+ } else
68937+ PRINT_ERROR("qla2x00t(%ld): Unable to find initiator with "
68938+ "S_ID %x:%x:%x", ha->instance,
68939+ atio7->fcp_hdr.s_id[0], atio7->fcp_hdr.s_id[1],
68940+ atio7->fcp_hdr.s_id[2]);
68941+ }
68942+
68943+out_free_id_list:
68944+ dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, gid_list, gid_list_dma);
68945+
68946+out:
68947+ TRACE_EXIT_RES(res);
68948+ return res;
68949+}
68950+
68951+/* Must be called under tgt_mutex */
68952+static struct q2t_sess *q2t_make_local_sess(scsi_qla_host_t *ha, atio_t *atio)
68953+{
68954+ struct q2t_sess *sess = NULL;
68955+ fc_port_t *fcport = NULL;
68956+ uint16_t loop_id = 0xFFFF; /* to remove warning */
68957+ int rc;
68958+
68959+ TRACE_ENTRY();
68960+
68961+ if (IS_FWI2_CAPABLE(ha)) {
68962+ rc = q24_get_loop_id(ha, (atio7_entry_t *)atio, &loop_id);
68963+ if (rc != 0)
68964+ goto out;
68965+ } else
68966+ loop_id = GET_TARGET_ID(ha, (atio_entry_t *)atio);
68967+
68968+ fcport = kzalloc(sizeof(*fcport), GFP_KERNEL);
68969+ if (fcport == NULL) {
68970+ PRINT_ERROR("qla2x00t(%ld): Allocation of tmp FC port failed",
68971+ ha->instance);
68972+ goto out;
68973+ }
68974+
68975+ TRACE_MGMT_DBG("loop_id %d", loop_id);
68976+
68977+ fcport->loop_id = loop_id;
68978+
68979+ rc = qla2x00_get_port_database(ha, fcport, 0);
68980+ if (rc != QLA_SUCCESS) {
68981+ PRINT_ERROR("qla2x00t(%ld): Failed to retrieve fcport "
68982+ "information -- get_port_database() returned %x "
68983+ "(loop_id=0x%04x)", ha->instance, rc, loop_id);
68984+ goto out_free_fcport;
68985+ }
68986+
68987+ sess = q2t_create_sess(ha, fcport, true);
68988+
68989+out_free_fcport:
68990+ kfree(fcport);
68991+
68992+out:
68993+ TRACE_EXIT_HRES((unsigned long)sess);
68994+ return sess;
68995+}
68996+
68997+static int q2t_exec_sess_work(struct q2t_tgt *tgt,
68998+ struct q2t_sess_work_param *prm)
68999+{
69000+ scsi_qla_host_t *ha = tgt->ha;
69001+ int res = 0;
69002+ struct q2t_sess *sess = NULL;
69003+ struct q2t_cmd *cmd = prm->cmd;
69004+ atio_t *atio = (atio_t *)&cmd->atio;
69005+
69006+ TRACE_ENTRY();
69007+
69008+ TRACE_MGMT_DBG("cmd %p", cmd);
69009+
69010+ mutex_lock(&ha->tgt_mutex);
69011+ spin_lock_irq(&ha->hardware_lock);
69012+
69013+ if (tgt->tgt_stop)
69014+ goto send;
69015+
69016+ if (IS_FWI2_CAPABLE(ha)) {
69017+ atio7_entry_t *a = (atio7_entry_t *)atio;
69018+ sess = q2t_find_sess_by_s_id(tgt, a->fcp_hdr.s_id);
69019+ } else
69020+ sess = q2t_find_sess_by_loop_id(tgt,
69021+ GET_TARGET_ID(ha, (atio_entry_t *)atio));
69022+
69023+ if (sess != NULL) {
69024+ TRACE_MGMT_DBG("sess %p found", sess);
69025+ q2t_sess_get(sess);
69026+ } else {
69027+ /*
69028+ * We are under tgt_mutex, so a new sess can't be added
69029+ * behind us.
69030+ */
69031+ spin_unlock_irq(&ha->hardware_lock);
69032+ sess = q2t_make_local_sess(ha, atio);
69033+ spin_lock_irq(&ha->hardware_lock);
69034+ /* sess has got an extra creation ref */
69035+ }
69036+
69037+send:
69038+ if (!tgt->tm_to_unknown && !tgt->tgt_stop && (sess != NULL)) {
69039+ TRACE_MGMT_DBG("Sending work cmd %p to SCST", cmd);
69040+ res = q2t_do_send_cmd_to_scst(ha, cmd, sess);
69041+ } else {
69042+ /*
69043+ * Cmd might be already aborted behind us, so be safe and
69044+ * abort it. It should be OK, initiator will retry it. It has
69045+ * not sent to SCST yet, so pass NULL as the second argument.
69046+ */
69047+ TRACE_MGMT_DBG("Terminating work cmd %p", cmd);
69048+ if (IS_FWI2_CAPABLE(ha))
69049+ q24_send_term_exchange(ha, NULL , &cmd->atio.atio7, 1);
69050+ else
69051+ q2x_send_term_exchange(ha, NULL, &cmd->atio.atio2x, 1);
69052+ q2t_free_cmd(cmd);
69053+ }
69054+
69055+ if (sess != NULL)
69056+ q2t_sess_put(sess);
69057+
69058+ spin_unlock_irq(&ha->hardware_lock);
69059+ mutex_unlock(&ha->tgt_mutex);
69060+
69061+ TRACE_EXIT_RES(res);
69062+ return res;
69063+}
69064+
69065+static void q2t_sess_work_fn(struct work_struct *work)
69066+{
69067+ struct q2t_tgt *tgt = container_of(work, struct q2t_tgt, sess_work);
69068+
69069+ TRACE_ENTRY();
69070+
69071+ TRACE_MGMT_DBG("Sess work (tgt %p)", tgt);
69072+
69073+ spin_lock_irq(&tgt->sess_work_lock);
69074+ while (!list_empty(&tgt->sess_works_list)) {
69075+ int rc;
69076+ struct q2t_sess_work_param *prm = list_entry(
69077+ tgt->sess_works_list.next, typeof(*prm),
69078+ sess_works_list_entry);
69079+
69080+ /*
69081+ * This work can be scheduled on several CPUs at time, so we
69082+ * must delete the entry to eliminate double processing
69083+ */
69084+ list_del(&prm->sess_works_list_entry);
69085+
69086+ spin_unlock_irq(&tgt->sess_work_lock);
69087+
69088+ rc = q2t_exec_sess_work(tgt, prm);
69089+
69090+ spin_lock_irq(&tgt->sess_work_lock);
69091+
69092+ if (rc != 0) {
69093+ TRACE_MGMT_DBG("Unable to complete sess work (tgt %p), "
69094+ "freeing cmd %p", tgt, prm->cmd);
69095+ q2t_free_cmd(prm->cmd);
69096+ }
69097+
69098+ kfree(prm);
69099+ }
69100+ spin_unlock_irq(&tgt->sess_work_lock);
69101+
69102+ spin_lock_irq(&tgt->ha->hardware_lock);
69103+ spin_lock(&tgt->sess_work_lock);
69104+ if (list_empty(&tgt->sess_works_list)) {
69105+ tgt->sess_works_pending = 0;
69106+ tgt->tm_to_unknown = 0;
69107+ }
69108+ spin_unlock(&tgt->sess_work_lock);
69109+ spin_unlock_irq(&tgt->ha->hardware_lock);
69110+
69111+ TRACE_EXIT();
69112+ return;
69113+}
69114+
69115+/* ha->hardware_lock supposed to be held and IRQs off */
69116+static void q2t_cleanup_hw_pending_cmd(scsi_qla_host_t *ha, struct q2t_cmd *cmd)
69117+{
69118+ uint32_t h;
69119+
69120+ for (h = 0; h < MAX_OUTSTANDING_COMMANDS; h++) {
69121+ if (ha->cmds[h] == cmd) {
69122+ TRACE_DBG("Clearing handle %d for cmd %p", h, cmd);
69123+ ha->cmds[h] = NULL;
69124+ break;
69125+ }
69126+ }
69127+ return;
69128+}
69129+
69130+static void q2t_on_hw_pending_cmd_timeout(struct scst_cmd *scst_cmd)
69131+{
69132+ struct q2t_cmd *cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
69133+ struct q2t_tgt *tgt = cmd->tgt;
69134+ scsi_qla_host_t *ha = tgt->ha;
69135+ unsigned long flags;
69136+
69137+ TRACE_ENTRY();
69138+
69139+ TRACE_MGMT_DBG("Cmd %p HW pending for too long (state %x)", cmd,
69140+ cmd->state);
69141+
69142+ spin_lock_irqsave(&ha->hardware_lock, flags);
69143+
69144+ if (cmd->sg_mapped)
69145+ q2t_unmap_sg(ha, cmd);
69146+
69147+ if (cmd->state == Q2T_STATE_PROCESSED) {
69148+ TRACE_MGMT_DBG("Force finishing cmd %p", cmd);
69149+ } else if (cmd->state == Q2T_STATE_NEED_DATA) {
69150+ TRACE_MGMT_DBG("Force rx_data cmd %p", cmd);
69151+
69152+ q2t_cleanup_hw_pending_cmd(ha, cmd);
69153+
69154+ scst_rx_data(scst_cmd, SCST_RX_STATUS_ERROR_FATAL,
69155+ SCST_CONTEXT_THREAD);
69156+ goto out_unlock;
69157+ } else if (cmd->state == Q2T_STATE_ABORTED) {
69158+ TRACE_MGMT_DBG("Force finishing aborted cmd %p (tag %d)",
69159+ cmd, cmd->tag);
69160+ } else {
69161+ PRINT_ERROR("qla2x00t(%ld): A command in state (%d) should "
69162+ "not be HW pending", ha->instance, cmd->state);
69163+ goto out_unlock;
69164+ }
69165+
69166+ q2t_cleanup_hw_pending_cmd(ha, cmd);
69167+
69168+ scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_FAILED);
69169+ scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_THREAD);
69170+
69171+out_unlock:
69172+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
69173+ TRACE_EXIT();
69174+ return;
69175+}
69176+
69177+/* Must be called under tgt_host_action_mutex */
69178+static int q2t_add_target(scsi_qla_host_t *ha)
69179+{
69180+ int res, rc;
69181+ char *wwn;
69182+ int sg_tablesize;
69183+ struct q2t_tgt *tgt;
69184+
69185+ TRACE_ENTRY();
69186+
69187+ TRACE_DBG("Registering target for host %ld(%p)", ha->host_no, ha);
69188+
69189+ BUG_ON((ha->q2t_tgt != NULL) || (ha->tgt != NULL));
69190+
69191+ tgt = kzalloc(sizeof(*tgt), GFP_KERNEL);
69192+ if (tgt == NULL) {
69193+ TRACE(TRACE_OUT_OF_MEM, "qla2x00t: %s", "Allocation of tgt "
69194+ "failed");
69195+ res = -ENOMEM;
69196+ goto out;
69197+ }
69198+
69199+ tgt->ha = ha;
69200+ init_waitqueue_head(&tgt->waitQ);
69201+ INIT_LIST_HEAD(&tgt->sess_list);
69202+ INIT_LIST_HEAD(&tgt->del_sess_list);
69203+ init_timer(&tgt->sess_del_timer);
69204+ tgt->sess_del_timer.data = (unsigned long)tgt;
69205+ tgt->sess_del_timer.function = q2t_del_sess_timer_fn;
69206+ spin_lock_init(&tgt->sess_work_lock);
69207+ INIT_WORK(&tgt->sess_work, q2t_sess_work_fn);
69208+ INIT_LIST_HEAD(&tgt->sess_works_list);
69209+ spin_lock_init(&tgt->srr_lock);
69210+ INIT_LIST_HEAD(&tgt->srr_ctio_list);
69211+ INIT_LIST_HEAD(&tgt->srr_imm_list);
69212+ INIT_WORK(&tgt->srr_work, q2t_handle_srr_work);
69213+
69214+ ha->q2t_tgt = tgt;
69215+
69216+ if (q2t_get_target_name(ha, &wwn) != 0)
69217+ goto out_free;
69218+
69219+ tgt->scst_tgt = scst_register_target(&tgt2x_template, wwn);
69220+
69221+ kfree(wwn);
69222+
69223+ if (!tgt->scst_tgt) {
69224+ PRINT_ERROR("qla2x00t(%ld): scst_register_target() "
69225+ "failed for host %ld(%p)", ha->instance,
69226+ ha->host_no, ha);
69227+ res = -ENOMEM;
69228+ goto out_free;
69229+ }
69230+
69231+ if (IS_FWI2_CAPABLE(ha)) {
69232+ PRINT_INFO("qla2x00t(%ld): using 64 Bit PCI "
69233+ "addressing", ha->instance);
69234+ tgt->tgt_enable_64bit_addr = 1;
69235+ /* 3 is reserved */
69236+ sg_tablesize =
69237+ QLA_MAX_SG_24XX(ha->request_q_length - 3);
69238+ tgt->datasegs_per_cmd = DATASEGS_PER_COMMAND_24XX;
69239+ tgt->datasegs_per_cont = DATASEGS_PER_CONT_24XX;
69240+ } else {
69241+ if (ha->flags.enable_64bit_addressing) {
69242+ PRINT_INFO("qla2x00t(%ld): 64 Bit PCI "
69243+ "addressing enabled", ha->instance);
69244+ tgt->tgt_enable_64bit_addr = 1;
69245+ /* 3 is reserved */
69246+ sg_tablesize =
69247+ QLA_MAX_SG64(ha->request_q_length - 3);
69248+ tgt->datasegs_per_cmd = DATASEGS_PER_COMMAND64;
69249+ tgt->datasegs_per_cont = DATASEGS_PER_CONT64;
69250+ } else {
69251+ PRINT_INFO("qla2x00t(%ld): Using 32 Bit "
69252+ "PCI addressing", ha->instance);
69253+ sg_tablesize =
69254+ QLA_MAX_SG32(ha->request_q_length - 3);
69255+ tgt->datasegs_per_cmd = DATASEGS_PER_COMMAND32;
69256+ tgt->datasegs_per_cont = DATASEGS_PER_CONT32;
69257+ }
69258+ }
69259+
69260+ rc = sysfs_create_link(scst_sysfs_get_tgt_kobj(tgt->scst_tgt),
69261+ &ha->host->shost_dev.kobj, "host");
69262+ if (rc != 0)
69263+ PRINT_ERROR("qla2x00t(%ld): Unable to create \"host\" link for "
69264+ "target %s", ha->instance,
69265+ scst_get_tgt_name(tgt->scst_tgt));
69266+
69267+ scst_tgt_set_sg_tablesize(tgt->scst_tgt, sg_tablesize);
69268+ scst_tgt_set_tgt_priv(tgt->scst_tgt, tgt);
69269+
69270+out:
69271+ TRACE_EXIT_RES(res);
69272+ return res;
69273+
69274+out_free:
69275+ ha->q2t_tgt = NULL;
69276+ kfree(tgt);
69277+ goto out;
69278+}
69279+
69280+/* Must be called under tgt_host_action_mutex */
69281+static int q2t_remove_target(scsi_qla_host_t *ha)
69282+{
69283+ TRACE_ENTRY();
69284+
69285+ if ((ha->q2t_tgt == NULL) || (ha->tgt != NULL)) {
69286+ PRINT_ERROR("qla2x00t(%ld): Can't remove "
69287+ "existing target", ha->instance);
69288+ }
69289+
69290+ TRACE_DBG("Unregistering target for host %ld(%p)", ha->host_no, ha);
69291+ scst_unregister_target(ha->tgt->scst_tgt);
69292+ /*
69293+ * Free of tgt happens via callback q2t_target_release
69294+ * called from scst_unregister_target, so we shouldn't touch
69295+ * it again.
69296+ */
69297+
69298+ TRACE_EXIT();
69299+ return 0;
69300+}
69301+
69302+static int q2t_host_action(scsi_qla_host_t *ha,
69303+ qla2x_tgt_host_action_t action)
69304+{
69305+ int res = 0;
69306+
69307+ TRACE_ENTRY();
69308+
69309+ BUG_ON(ha == NULL);
69310+
69311+ /* To sync with q2t_exit() */
69312+ if (down_read_trylock(&q2t_unreg_rwsem) == 0)
69313+ goto out;
69314+
69315+ mutex_lock(&ha->tgt_host_action_mutex);
69316+
69317+ switch (action) {
69318+ case ADD_TARGET:
69319+ res = q2t_add_target(ha);
69320+ break;
69321+ case REMOVE_TARGET:
69322+ res = q2t_remove_target(ha);
69323+ break;
69324+ case ENABLE_TARGET_MODE:
69325+ {
69326+ fc_port_t *fcport;
69327+
69328+ if (qla_tgt_mode_enabled(ha)) {
69329+ PRINT_INFO("qla2x00t(%ld): Target mode already "
69330+ "enabled", ha->instance);
69331+ break;
69332+ }
69333+
69334+ if ((ha->q2t_tgt == NULL) || (ha->tgt != NULL)) {
69335+ PRINT_ERROR("qla2x00t(%ld): Can't enable target mode "
69336+ "for not existing target", ha->instance);
69337+ break;
69338+ }
69339+
69340+ PRINT_INFO("qla2x00t(%ld): Enabling target mode",
69341+ ha->instance);
69342+
69343+ spin_lock_irq(&ha->hardware_lock);
69344+ ha->tgt = ha->q2t_tgt;
69345+ ha->tgt->tgt_stop = 0;
69346+ spin_unlock_irq(&ha->hardware_lock);
69347+ list_for_each_entry_rcu(fcport, &ha->fcports, list) {
69348+ q2t_fc_port_added(ha, fcport);
69349+ }
69350+ TRACE_DBG("Enable tgt mode for host %ld(%ld,%p)",
69351+ ha->host_no, ha->instance, ha);
69352+ qla2x00_enable_tgt_mode(ha);
69353+ break;
69354+ }
69355+
69356+ case DISABLE_TARGET_MODE:
69357+ if (!qla_tgt_mode_enabled(ha)) {
69358+ PRINT_INFO("qla2x00t(%ld): Target mode already "
69359+ "disabled", ha->instance);
69360+ break;
69361+ }
69362+
69363+ PRINT_INFO("qla2x00t(%ld): Disabling target mode",
69364+ ha->instance);
69365+
69366+ BUG_ON(ha->tgt == NULL);
69367+
69368+ q2t_target_stop(ha->tgt->scst_tgt);
69369+ break;
69370+
69371+ default:
69372+ PRINT_ERROR("qla2x00t(%ld): %s: unsupported action %d",
69373+ ha->instance, __func__, action);
69374+ res = -EINVAL;
69375+ break;
69376+ }
69377+
69378+ mutex_unlock(&ha->tgt_host_action_mutex);
69379+
69380+ up_read(&q2t_unreg_rwsem);
69381+out:
69382+ TRACE_EXIT_RES(res);
69383+ return res;
69384+}
69385+
69386+static int q2t_enable_tgt(struct scst_tgt *scst_tgt, bool enable)
69387+{
69388+ struct q2t_tgt *tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
69389+ scsi_qla_host_t *ha = tgt->ha;
69390+ int res;
69391+
69392+ if (enable)
69393+ res = q2t_host_action(ha, ENABLE_TARGET_MODE);
69394+ else
69395+ res = q2t_host_action(ha, DISABLE_TARGET_MODE);
69396+
69397+ return res;
69398+}
69399+
69400+static bool q2t_is_tgt_enabled(struct scst_tgt *scst_tgt)
69401+{
69402+ struct q2t_tgt *tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
69403+ scsi_qla_host_t *ha = tgt->ha;
69404+
69405+ return qla_tgt_mode_enabled(ha);
69406+}
69407+
69408+static int q2t_get_initiator_port_transport_id(struct scst_session *scst_sess,
69409+ uint8_t **transport_id)
69410+{
69411+ struct q2t_sess *sess;
69412+ int res = 0;
69413+ int tr_id_size;
69414+ uint8_t *tr_id;
69415+
69416+ TRACE_ENTRY();
69417+
69418+ if (scst_sess == NULL) {
69419+ res = SCSI_TRANSPORTID_PROTOCOLID_FCP2;
69420+ goto out;
69421+ }
69422+
69423+ sess = (struct q2t_sess *)scst_sess_get_tgt_priv(scst_sess);
69424+
69425+ tr_id_size = 24;
69426+
69427+ tr_id = kzalloc(tr_id_size, GFP_KERNEL);
69428+ if (tr_id == NULL) {
69429+ PRINT_ERROR("qla2x00t: Allocation of TransportID (size %d) "
69430+ "failed", tr_id_size);
69431+ res = -ENOMEM;
69432+ goto out;
69433+ }
69434+
69435+ tr_id[0] = SCSI_TRANSPORTID_PROTOCOLID_FCP2;
69436+
69437+ BUILD_BUG_ON(sizeof(sess->port_name) != 8);
69438+ memcpy(&tr_id[8], sess->port_name, 8);
69439+
69440+ *transport_id = tr_id;
69441+
69442+ TRACE_BUFF_FLAG(TRACE_DEBUG, "Created tid", tr_id, tr_id_size);
69443+
69444+out:
69445+ TRACE_EXIT_RES(res);
69446+ return res;
69447+}
69448+
69449+static ssize_t q2t_show_expl_conf_enabled(struct kobject *kobj,
69450+ struct kobj_attribute *attr, char *buffer)
69451+{
69452+ struct scst_tgt *scst_tgt;
69453+ struct q2t_tgt *tgt;
69454+ scsi_qla_host_t *ha;
69455+ ssize_t size;
69456+
69457+ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
69458+ tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
69459+ ha = tgt->ha;
69460+
69461+ size = scnprintf(buffer, PAGE_SIZE, "%d\n%s", ha->enable_explicit_conf,
69462+ ha->enable_explicit_conf ? SCST_SYSFS_KEY_MARK "\n" : "");
69463+
69464+ return size;
69465+}
69466+
69467+static ssize_t q2t_store_expl_conf_enabled(struct kobject *kobj,
69468+ struct kobj_attribute *attr, const char *buffer, size_t size)
69469+{
69470+ struct scst_tgt *scst_tgt;
69471+ struct q2t_tgt *tgt;
69472+ scsi_qla_host_t *ha;
69473+ unsigned long flags;
69474+
69475+ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
69476+ tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
69477+ ha = tgt->ha;
69478+
69479+ spin_lock_irqsave(&ha->hardware_lock, flags);
69480+
69481+ switch (buffer[0]) {
69482+ case '0':
69483+ ha->enable_explicit_conf = 0;
69484+ PRINT_INFO("qla2x00t(%ld): explicit conformations disabled",
69485+ ha->instance);
69486+ break;
69487+ case '1':
69488+ ha->enable_explicit_conf = 1;
69489+ PRINT_INFO("qla2x00t(%ld): explicit conformations enabled",
69490+ ha->instance);
69491+ break;
69492+ default:
69493+ PRINT_ERROR("%s: qla2x00t(%ld): Requested action not "
69494+ "understood: %s", __func__, ha->instance, buffer);
69495+ break;
69496+ }
69497+
69498+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
69499+
69500+ return size;
69501+}
69502+
69503+static ssize_t q2t_abort_isp_store(struct kobject *kobj,
69504+ struct kobj_attribute *attr, const char *buffer, size_t size)
69505+{
69506+ struct scst_tgt *scst_tgt;
69507+ struct q2t_tgt *tgt;
69508+ scsi_qla_host_t *ha;
69509+
69510+ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
69511+ tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
69512+ ha = tgt->ha;
69513+
69514+ PRINT_INFO("qla2x00t(%ld): Aborting ISP", ha->instance);
69515+
69516+ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
69517+ qla2x00_wait_for_hba_online(ha);
69518+
69519+ return size;
69520+}
69521+
69522+static ssize_t q2t_version_show(struct kobject *kobj,
69523+ struct kobj_attribute *attr, char *buf)
69524+{
69525+ sprintf(buf, "%s\n", Q2T_VERSION_STRING);
69526+
69527+#ifdef CONFIG_SCST_EXTRACHECKS
69528+ strcat(buf, "EXTRACHECKS\n");
69529+#endif
69530+
69531+#ifdef CONFIG_SCST_TRACING
69532+ strcat(buf, "TRACING\n");
69533+#endif
69534+
69535+#ifdef CONFIG_SCST_DEBUG
69536+ strcat(buf, "DEBUG\n");
69537+#endif
69538+
69539+#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
69540+ strcat(buf, "QLA_TGT_DEBUG_WORK_IN_THREAD\n");
69541+#endif
69542+
69543+ TRACE_EXIT();
69544+ return strlen(buf);
69545+}
69546+
69547+static uint16_t q2t_get_scsi_transport_version(struct scst_tgt *scst_tgt)
69548+{
69549+ /* FCP-2 */
69550+ return 0x0900;
69551+}
69552+
69553+static uint16_t q2t_get_phys_transport_version(struct scst_tgt *scst_tgt)
69554+{
69555+ return 0x0DA0; /* FC-FS */
69556+}
69557+
69558+static int __init q2t_init(void)
69559+{
69560+ int res = 0;
69561+
69562+ TRACE_ENTRY();
69563+
69564+ BUILD_BUG_ON(sizeof(atio7_entry_t) != sizeof(atio_entry_t));
69565+
69566+ PRINT_INFO("qla2x00t: Initializing QLogic Fibre Channel HBA Driver "
69567+ "target mode addon version %s", Q2T_VERSION_STRING);
69568+
69569+ q2t_cmd_cachep = KMEM_CACHE(q2t_cmd, SCST_SLAB_FLAGS);
69570+ if (q2t_cmd_cachep == NULL) {
69571+ res = -ENOMEM;
69572+ goto out;
69573+ }
69574+
69575+ q2t_mgmt_cmd_cachep = KMEM_CACHE(q2t_mgmt_cmd, SCST_SLAB_FLAGS);
69576+ if (q2t_mgmt_cmd_cachep == NULL) {
69577+ res = -ENOMEM;
69578+ goto out_cmd_free;
69579+ }
69580+
69581+ q2t_mgmt_cmd_mempool = mempool_create(25, mempool_alloc_slab,
69582+ mempool_free_slab, q2t_mgmt_cmd_cachep);
69583+ if (q2t_mgmt_cmd_mempool == NULL) {
69584+ res = -ENOMEM;
69585+ goto out_kmem_free;
69586+ }
69587+
69588+ res = scst_register_target_template(&tgt2x_template);
69589+ if (res < 0)
69590+ goto out_mempool_free;
69591+
69592+ /*
69593+ * qla2xxx_tgt_register_driver() happens in q2t_target_detect
69594+ * called via scst_register_target_template()
69595+ */
69596+
69597+out:
69598+ TRACE_EXIT_RES(res);
69599+ return res;
69600+
69601+ scst_unregister_target_template(&tgt2x_template);
69602+ qla2xxx_tgt_unregister_driver();
69603+
69604+out_mempool_free:
69605+ mempool_destroy(q2t_mgmt_cmd_mempool);
69606+
69607+out_kmem_free:
69608+ kmem_cache_destroy(q2t_mgmt_cmd_cachep);
69609+
69610+out_cmd_free:
69611+ kmem_cache_destroy(q2t_cmd_cachep);
69612+ goto out;
69613+}
69614+
69615+static void __exit q2t_exit(void)
69616+{
69617+ TRACE_ENTRY();
69618+
69619+ PRINT_INFO("qla2x00t: %s", "Unloading QLogic Fibre Channel HBA Driver "
69620+ "target mode addon driver");
69621+
69622+ /* To sync with q2t_host_action() */
69623+ down_write(&q2t_unreg_rwsem);
69624+
69625+ scst_unregister_target_template(&tgt2x_template);
69626+
69627+ /*
69628+ * Now we have everywhere target mode disabled and no possibilities
69629+ * to call us through sysfs, so we can safely remove all the references
69630+ * to our functions.
69631+ */
69632+ qla2xxx_tgt_unregister_driver();
69633+
69634+ mempool_destroy(q2t_mgmt_cmd_mempool);
69635+ kmem_cache_destroy(q2t_mgmt_cmd_cachep);
69636+ kmem_cache_destroy(q2t_cmd_cachep);
69637+
69638+ /* Let's make lockdep happy */
69639+ up_write(&q2t_unreg_rwsem);
69640+
69641+ TRACE_EXIT();
69642+ return;
69643+}
69644+
69645+module_init(q2t_init);
69646+module_exit(q2t_exit);
69647+
69648+MODULE_AUTHOR("Vladislav Bolkhovitin and others");
69649+MODULE_DESCRIPTION("Target mode addon for qla2[2,3,4,5+]xx");
69650+MODULE_LICENSE("GPL");
69651+MODULE_VERSION(Q2T_VERSION_STRING);
69652diff -uprN orig/linux-2.6.35/drivers/scst/qla2xxx-target/qla2x00t.h linux-2.6.35/drivers/scst/qla2xxx-target/qla2x00t.h
69653--- orig/linux-2.6.35/drivers/scst/qla2xxx-target/qla2x00t.h
69654+++ linux-2.6.35/drivers/scst/qla2xxx-target/qla2x00t.h
69655@@ -0,0 +1,273 @@
69656+/*
69657+ * qla2x00t.h
69658+ *
69659+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
69660+ * Copyright (C) 2004 - 2005 Leonid Stoljar
69661+ * Copyright (C) 2006 Nathaniel Clark <nate@misrule.us>
69662+ * Copyright (C) 2006 - 2010 ID7 Ltd.
69663+ *
69664+ * QLogic 22xx/23xx/24xx/25xx FC target driver.
69665+ *
69666+ * This program is free software; you can redistribute it and/or
69667+ * modify it under the terms of the GNU General Public License
69668+ * as published by the Free Software Foundation, version 2
69669+ * of the License.
69670+ *
69671+ * This program is distributed in the hope that it will be useful,
69672+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
69673+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69674+ * GNU General Public License for more details.
69675+ */
69676+
69677+#ifndef __QLA2X00T_H
69678+#define __QLA2X00T_H
69679+
69680+#include <qla_def.h>
69681+#include <qla2x_tgt.h>
69682+#include <qla2x_tgt_def.h>
69683+
69684+#include <scst_debug.h>
69685+
69686+/* Version numbers, the same as for the kernel */
69687+#define Q2T_VERSION(a, b, c, d) (((a) << 030) + ((b) << 020) + (c) << 010 + (d))
69688+#define Q2T_VERSION_CODE Q2T_VERSION(1, 0, 2, 0)
69689+#define Q2T_VERSION_STRING "2.0.0-rc3"
69690+#define Q2T_PROC_VERSION_NAME "version"
69691+
69692+#define Q2T_MAX_CDB_LEN 16
69693+#define Q2T_TIMEOUT 10 /* in seconds */
69694+
69695+#define Q2T_MAX_HW_PENDING_TIME 60 /* in seconds */
69696+
69697+/* Immediate notify status constants */
69698+#define IMM_NTFY_LIP_RESET 0x000E
69699+#define IMM_NTFY_LIP_LINK_REINIT 0x000F
69700+#define IMM_NTFY_IOCB_OVERFLOW 0x0016
69701+#define IMM_NTFY_ABORT_TASK 0x0020
69702+#define IMM_NTFY_PORT_LOGOUT 0x0029
69703+#define IMM_NTFY_PORT_CONFIG 0x002A
69704+#define IMM_NTFY_GLBL_TPRLO 0x002D
69705+#define IMM_NTFY_GLBL_LOGO 0x002E
69706+#define IMM_NTFY_RESOURCE 0x0034
69707+#define IMM_NTFY_MSG_RX 0x0036
69708+#define IMM_NTFY_SRR 0x0045
69709+#define IMM_NTFY_ELS 0x0046
69710+
69711+/* Immediate notify task flags */
69712+#define IMM_NTFY_TASK_MGMT_SHIFT 8
69713+
69714+#define Q2T_CLEAR_ACA 0x40
69715+#define Q2T_TARGET_RESET 0x20
69716+#define Q2T_LUN_RESET 0x10
69717+#define Q2T_CLEAR_TS 0x04
69718+#define Q2T_ABORT_TS 0x02
69719+#define Q2T_ABORT_ALL_SESS 0xFFFF
69720+#define Q2T_ABORT_ALL 0xFFFE
69721+#define Q2T_NEXUS_LOSS_SESS 0xFFFD
69722+#define Q2T_NEXUS_LOSS 0xFFFC
69723+
69724+/* Notify Acknowledge flags */
69725+#define NOTIFY_ACK_RES_COUNT BIT_8
69726+#define NOTIFY_ACK_CLEAR_LIP_RESET BIT_5
69727+#define NOTIFY_ACK_TM_RESP_CODE_VALID BIT_4
69728+
69729+/* Command's states */
69730+#define Q2T_STATE_NEW 0 /* New command and SCST processing it */
69731+#define Q2T_STATE_NEED_DATA 1 /* SCST needs data to continue */
69732+#define Q2T_STATE_DATA_IN 2 /* Data arrived and SCST processing it */
69733+#define Q2T_STATE_PROCESSED 3 /* SCST done processing */
69734+#define Q2T_STATE_ABORTED 4 /* Command aborted */
69735+
69736+/* Special handles */
69737+#define Q2T_NULL_HANDLE 0
69738+#define Q2T_SKIP_HANDLE (0xFFFFFFFF & ~CTIO_COMPLETION_HANDLE_MARK)
69739+
69740+/* ATIO task_codes field */
69741+#define ATIO_SIMPLE_QUEUE 0
69742+#define ATIO_HEAD_OF_QUEUE 1
69743+#define ATIO_ORDERED_QUEUE 2
69744+#define ATIO_ACA_QUEUE 4
69745+#define ATIO_UNTAGGED 5
69746+
69747+/* TM failed response codes, see FCP (9.4.11 FCP_RSP_INFO) */
69748+#define FC_TM_SUCCESS 0
69749+#define FC_TM_BAD_FCP_DATA 1
69750+#define FC_TM_BAD_CMD 2
69751+#define FC_TM_FCP_DATA_MISMATCH 3
69752+#define FC_TM_REJECT 4
69753+#define FC_TM_FAILED 5
69754+
69755+/*
69756+ * Error code of q2t_pre_xmit_response() meaning that cmd's exchange was
69757+ * terminated, so no more actions is needed and success should be returned
69758+ * to SCST. Must be different from any SCST_TGT_RES_* codes.
69759+ */
69760+#define Q2T_PRE_XMIT_RESP_CMD_ABORTED 0x1717
69761+
69762+#if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
69763+#define pci_dma_lo32(a) (a & 0xffffffff)
69764+#define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff)
69765+#else
69766+#define pci_dma_lo32(a) (a & 0xffffffff)
69767+#define pci_dma_hi32(a) 0
69768+#endif
69769+
69770+struct q2t_tgt {
69771+ struct scst_tgt *scst_tgt;
69772+ scsi_qla_host_t *ha;
69773+
69774+ /*
69775+ * To sync between IRQ handlers and q2t_target_release(). Needed,
69776+ * because req_pkt() can drop/reaquire HW lock inside. Protected by
69777+ * HW lock.
69778+ */
69779+ int irq_cmd_count;
69780+
69781+ int datasegs_per_cmd, datasegs_per_cont;
69782+
69783+ /* Target's flags, serialized by ha->hardware_lock */
69784+ unsigned int tgt_enable_64bit_addr:1; /* 64-bits PCI addressing enabled */
69785+ unsigned int link_reinit_iocb_pending:1;
69786+ unsigned int tm_to_unknown:1; /* TM to unknown session was sent */
69787+ unsigned int sess_works_pending:1; /* there are sess_work entries */
69788+
69789+ /*
69790+ * Protected by tgt_mutex AND hardware_lock for writing and tgt_mutex
69791+ * OR hardware_lock for reading.
69792+ */
69793+ unsigned long tgt_stop; /* the driver is being stopped */
69794+
69795+ /* Count of sessions refering q2t_tgt. Protected by hardware_lock. */
69796+ int sess_count;
69797+
69798+ /* Protected by hardware_lock. Addition also protected by tgt_mutex. */
69799+ struct list_head sess_list;
69800+
69801+ /* Protected by hardware_lock */
69802+ struct list_head del_sess_list;
69803+ struct timer_list sess_del_timer;
69804+
69805+ spinlock_t sess_work_lock;
69806+ struct list_head sess_works_list;
69807+ struct work_struct sess_work;
69808+
69809+ notify24xx_entry_t link_reinit_iocb;
69810+ wait_queue_head_t waitQ;
69811+ int notify_ack_expected;
69812+ int abts_resp_expected;
69813+ int modify_lun_expected;
69814+
69815+ int ctio_srr_id;
69816+ int imm_srr_id;
69817+ spinlock_t srr_lock;
69818+ struct list_head srr_ctio_list;
69819+ struct list_head srr_imm_list;
69820+ struct work_struct srr_work;
69821+
69822+ struct list_head tgt_list_entry;
69823+};
69824+
69825+/*
69826+ * Equivilant to IT Nexus (Initiator-Target)
69827+ */
69828+struct q2t_sess {
69829+ uint16_t loop_id;
69830+ port_id_t s_id;
69831+
69832+ unsigned int conf_compl_supported:1;
69833+ unsigned int deleted:1;
69834+ unsigned int local:1;
69835+
69836+ struct scst_session *scst_sess;
69837+ struct q2t_tgt *tgt;
69838+
69839+ int sess_ref; /* protected by hardware_lock */
69840+
69841+ struct list_head sess_list_entry;
69842+ unsigned long expires;
69843+ struct list_head del_list_entry;
69844+
69845+ uint8_t port_name[WWN_SIZE];
69846+};
69847+
69848+struct q2t_cmd {
69849+ struct q2t_sess *sess;
69850+ int state;
69851+ struct scst_cmd *scst_cmd;
69852+
69853+ unsigned int conf_compl_supported:1;/* to save extra sess dereferences */
69854+ unsigned int sg_mapped:1;
69855+ unsigned int free_sg:1;
69856+ unsigned int aborted:1; /* Needed in case of SRR */
69857+ unsigned int write_data_transferred:1;
69858+
69859+ struct scatterlist *sg; /* cmd data buffer SG vector */
69860+ int sg_cnt; /* SG segments count */
69861+ int bufflen; /* cmd buffer length */
69862+ int offset;
69863+ scst_data_direction data_direction;
69864+ uint32_t tag;
69865+ dma_addr_t dma_handle;
69866+ enum dma_data_direction dma_data_direction;
69867+
69868+ uint16_t loop_id; /* to save extra sess dereferences */
69869+ struct q2t_tgt *tgt; /* to save extra sess dereferences */
69870+
69871+ union {
69872+ atio7_entry_t atio7;
69873+ atio_entry_t atio2x;
69874+ } __attribute__((packed)) atio;
69875+};
69876+
69877+struct q2t_sess_work_param {
69878+ struct list_head sess_works_list_entry;
69879+ struct q2t_cmd *cmd;
69880+};
69881+
69882+struct q2t_mgmt_cmd {
69883+ struct q2t_sess *sess;
69884+ unsigned int flags;
69885+#define Q24_MGMT_SEND_NACK 1
69886+ union {
69887+ atio7_entry_t atio7;
69888+ notify_entry_t notify_entry;
69889+ notify24xx_entry_t notify_entry24;
69890+ abts24_recv_entry_t abts;
69891+ } __attribute__((packed)) orig_iocb;
69892+};
69893+
69894+struct q2t_prm {
69895+ struct q2t_cmd *cmd;
69896+ struct q2t_tgt *tgt;
69897+ void *pkt;
69898+ struct scatterlist *sg; /* cmd data buffer SG vector */
69899+ int seg_cnt;
69900+ int req_cnt;
69901+ uint16_t rq_result;
69902+ uint16_t scsi_status;
69903+ unsigned char *sense_buffer;
69904+ int sense_buffer_len;
69905+ int residual;
69906+ int add_status_pkt;
69907+};
69908+
69909+struct srr_imm {
69910+ struct list_head srr_list_entry;
69911+ int srr_id;
69912+ union {
69913+ notify_entry_t notify_entry;
69914+ notify24xx_entry_t notify_entry24;
69915+ } __attribute__((packed)) imm;
69916+};
69917+
69918+struct srr_ctio {
69919+ struct list_head srr_list_entry;
69920+ int srr_id;
69921+ struct q2t_cmd *cmd;
69922+};
69923+
69924+#define Q2T_XMIT_DATA 1
69925+#define Q2T_XMIT_STATUS 2
69926+#define Q2T_XMIT_ALL (Q2T_XMIT_STATUS|Q2T_XMIT_DATA)
69927+
69928+#endif /* __QLA2X00T_H */
69929diff -uprN orig/linux-2.6.35/Documentation/scst/README.qla2x00t linux-2.6.35/Documentation/scst/README.qla2x00t
69930--- orig/linux-2.6.35/Documentation/scst/README.qla2x00t
69931+++ linux-2.6.35/Documentation/scst/README.qla2x00t
69932@@ -0,0 +1,526 @@
69933+Target driver for Qlogic 22xx/23xx/24xx/25xx Fibre Channel cards
69934+================================================================
69935+
69936+Version 2.0.0, XX XXXXX 2010
69937+----------------------------
69938+
69939+This driver consists from two parts: the target mode driver itself and
69940+the changed initiator driver from Linux kernel, which is, particularly,
69941+intended to perform all the initialization and shutdown tasks. The
69942+initiator driver was changed to provide the target mode support and all
69943+necessary callbacks, but it's still capable to work as initiator only.
69944+Mode, when a host acts as the initiator and the target simultaneously,
69945+is supported as well.
69946+
69947+This version is compatible with SCST core version 2.0.0 and higher and
69948+Linux kernel 2.6.26 and higher. Sorry, kernels below 2.6.26 are not
69949+supported, because it's too hard to backport used initiator driver to
69950+older kernels.
69951+
69952+NPIV is partially supported by this driver. You can create virtual
69953+targets using standard Linux interface by echoing wwpn:wwnn into
69954+/sys/class/fc_host/hostX/vport_create and work with them, but SCST core
69955+will not see those virtual targets and, hence, provide the
69956+target-oriented access control for them. However, the initiator-oriented
69957+access control will still work very well. Note, you need NPIV-supporting
69958+firmware as well as NPIV-supporting switches to use NPIV.
69959+
69960+The original initiator driver was taken from the kernel 2.6.26. Also the
69961+following 2.6.26.x commits have been applied to it (upstream ID):
69962+048feec5548c0582ee96148c61b87cccbcb5f9be,
69963+031e134e5f95233d80fb1b62fdaf5e1be587597c,
69964+5f3a9a207f1fccde476dd31b4c63ead2967d934f,
69965+85821c906cf3563a00a3d98fa380a2581a7a5ff1,
69966+3c01b4f9fbb43fc911acd33ea7a14ea7a4f9866b,
69967+8eca3f39c4b11320787f7b216f63214aee8415a9.
69968+
69969+See also "ToDo" file for list of known issues and unimplemented
69970+features.
69971+
69972+Installation
69973+------------
69974+
69975+Only vanilla kernels from kernel.org and RHEL/CentOS 5.2 kernels are
69976+supported, but SCST should work on other (vendors') kernels, if you
69977+manage to successfully compile it on them. The main problem with
69978+vendors' kernels is that they often contain patches, which will appear
69979+only in the next version of the vanilla kernel, therefore it's quite
69980+hard to track such changes. Thus, if during compilation for some vendor
69981+kernel your compiler complains about redefinition of some symbol, you
69982+should either switch to vanilla kernel, or add or change as necessary
69983+the corresponding to that symbol "#if LINUX_VERSION_CODE" statement.
69984+
69985+Before installation make sure that the link
69986+"/lib/modules/`you_kernel_version`/build" points to the source code for
69987+your currently running kernel.
69988+
69989+Then you should replace (or link) by the initiator driver from this
69990+package "qla2xxx" subdirectory in kernel_source/drivers/scsi/ of the
69991+currently running kernel and using your favorite kernel configuration
69992+tool enable in the QLogic QLA2XXX Fibre Channel driver target mode
69993+support (CONFIG_SCSI_QLA2XXX_TARGET). Then rebuild the kernel and its
69994+modules. During this step you will compile the initiator driver. To
69995+install it, install the built kernel and its modules.
69996+
69997+Then edit qla2x00-target/Makefile and set SCST_INC_DIR variable to point
69998+to the directory, where SCST's public include files are located. If you
69999+install QLA2x00 target driver's source code in the SCST's directory,
70000+then SCST_INC_DIR will be set correctly for you.
70001+
70002+Also you can set SCST_DIR variable to the directory, where SCST was
70003+built, but this is optional. If you don't set it or set incorrectly,
70004+during the compilation you will get a bunch of harmless warnings like
70005+"WARNING: "scst_rx_data" [/XXX/qla2x00tgt.ko] undefined!"
70006+
70007+To compile the target driver, type 'make' in qla2x00-target/
70008+subdirectory. It will build qla2x00tgt.ko module.
70009+
70010+To install the target driver, type 'make install' in qla2x00-target/
70011+subdirectory. The target driver will be installed in
70012+/lib/modules/`you_kernel_version`/extra. To uninstall it, type 'make
70013+uninstall'.
70014+
70015+Usage
70016+-----
70017+
70018+After the drivers are loaded and adapters successfully initialized by
70019+the initiator driver, including firmware image load, you should
70020+configure exported devices using the corresponding interface of SCST
70021+core. It is highly recommended to use scstadmin utility for that
70022+purpose.
70023+
70024+Then target mode should be enabled via a sysfs interface on a per card
70025+basis, like:
70026+
70027+echo "1" >/sys/kernel/scst_tgt/targets/qla2x00t/target/enabled
70028+
70029+See below for full description of the driver's sysfs interface.
70030+
70031+With the obsolete proc interface you should instead use
70032+target_mode_enabled under the appropriate scsi_host entry, like:
70033+
70034+echo "1" >/sys/class/scsi_host/host0/target_mode_enabled
70035+
70036+You can find some installation and configuration HOWTOs in
70037+http://scst.sourceforge.net/qla2x00t-howto.html and
70038+https://forums.openfiler.com/viewtopic.php?id=3422.
70039+
70040+IMPORTANT USAGE NOTES
70041+---------------------
70042+
70043+1. It is strongly recommended to use firmware version 5.x or higher
70044+for 24xx/25xx adapters. See
70045+http://sourceforge.net/mailarchive/forum.php?thread_name=4B4CD39F.6020401%40vlnb.net&forum_name=scst-devel
70046+for more details why.
70047+
70048+2. If you reload qla2x00tgt module, you should also reload qla2xxx
70049+module, otherwise your initiators could not see the target, when it is
70050+enabled after qla2x00tgt module load.
70051+
70052+3. If you delete and then add back with the same WWN an NPIV initiator
70053+on the initiator side, make sure it has the same port_id as well. In
70054+Fibre Channel initiators identified by port_id (s_id in FC terms), so if
70055+the recreated NPIV initiator has another port_id, which was already used
70056+by another (NPIV) initiator, those initiators could be confused by the
70057+target and assigned to incorrect security groups, hence they could see
70058+incorrect LUNs.
70059+
70060+If you can't ensure the same port_id's for recreated initiators, it is
70061+safer to restart qla2x00tgt and qla2xxx modules on the target to make
70062+sure the target doesn't have any initiator port_id cached.
70063+
70064+Initiator and target modes
70065+--------------------------
70066+
70067+When qla2xxx compiled with CONFIG_SCSI_QLA2XXX_TARGET enabled, it has
70068+parameter "qlini_mode", which determines when initiator mode will be
70069+enabled. Possible values:
70070+
70071+ - "exclusive" (default ) - initiator mode will be enabled on load,
70072+disabled on enabling target mode and then on disabling target mode
70073+enabled back.
70074+
70075+ - "disabled" - initiator mode will never be enabled.
70076+
70077+ - "enabled" - initiator mode will always stay enabled.
70078+
70079+Usage of mode "disabled" is recommended, if you have incorrectly
70080+functioning your target's initiators, which if once seen a port in
70081+initiator mode, later refuse to see it as a target. Although this mode
70082+does make a noticeable difference, it isn't absolutely strong, since the
70083+firmware once initialized requires a HBA to be in either initiator, or
70084+target mode, so until you enable target mode on a port, your initiators
70085+will report this port as working in initiator mode. If you need
70086+absolutely strong assurance that initiator mode never enabled, you can
70087+consider using patch
70088+unsupported-patches/qla_delayed_hw_init_tgt_mode_from_the_beginning.diff.
70089+See description of it inside the patch.
70090+
70091+Use mode "enabled" if you need your QLA adapters to work in both
70092+initiator and target modes at the same time.
70093+
70094+You can always see which modes are currently active in active_mode sysfs
70095+attribute.
70096+
70097+In all the modes you can at any time use sysfs attribute
70098+ini_mode_force_reverse to force enable or disable initiator mode on any
70099+particular port. Setting this attribute to 1 will reverse current status
70100+of the initiator mode from enabled to disabled and vice versa.
70101+
70102+Explicit conformation
70103+---------------------
70104+
70105+This option should (actually, almost always must) be enabled by echoing
70106+"1" in /sys/kernel/scst_tgt/targets/qla2x00t/target/host/explicit_conform_enabled,
70107+if a target card exports at least one stateful SCSI device, like tape,
70108+and class 2 isn't used, otherwise link-level errors could lead to loss
70109+of the target/initiator state synchronization. Also check if initiator
70110+supports this feature, it is reported in the kernel logs ("confirmed
70111+completion supported" or not). No major performance degradation was
70112+noticed, if it is enabled. Supported only for 23xx+. Disabled by
70113+default.
70114+
70115+Class 2
70116+-------
70117+
70118+Class 2 is the close equivalent of the TCP in the IP world. If you
70119+enable it, all the Fibre Channel packets will be acknowledged. By
70120+default, class 3 is used, which is UDP-like. Enable it by echoing "1" in
70121+/sys/kernel/scst_tgt/targets/qla2x00t/target/host/class2_enabled. This
70122+option needs a special firmware with class 2 support. Disabled by
70123+default.
70124+
70125+Compilation options
70126+-------------------
70127+
70128+There are the following compilation options, that could be commented
70129+in/out in Makefile:
70130+
70131+ - CONFIG_SCST_DEBUG - turns on some debugging code, including some logging.
70132+ Makes the driver considerably bigger and slower, producing large amount of
70133+ log data.
70134+
70135+ - CONFIG_SCST_TRACING - turns on ability to log events. Makes the driver
70136+ considerably bigger and leads to some performance loss.
70137+
70138+ - CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD - makes SCST process incoming
70139+ commands from the qla2x00t target driver and call the driver's
70140+ callbacks in internal SCST threads context instead of SIRQ context,
70141+ where those commands were received. Useful for debugging and lead to
70142+ some performance loss.
70143+
70144+ - CONFIG_QLA_TGT_DEBUG_SRR - turns on retransmitting packets (SRR)
70145+ debugging. In this mode some CTIOs will be "broken" to force the
70146+ initiator to issue a retransmit request.
70147+
70148+Sysfs interface
70149+---------------
70150+
70151+Starting from 2.0.0 this driver has sysfs interface. The procfs
70152+interface from version 2.0.0 is obsolete and will be removed in one of
70153+the next versions.
70154+
70155+Root of SCST sysfs interface is /sys/kernel/scst_tgt. Root of this
70156+driver is /sys/kernel/scst_tgt/targets/qla2x00t. It has the following
70157+entries:
70158+
70159+ - None, one or more subdirectories for targets with name equal to port
70160+ names of the corresponding targets.
70161+
70162+ - trace_level - allows to enable and disable various tracing
70163+ facilities. See content of this file for help how to use it.
70164+
70165+ - version - read-only attribute, which allows to see version of
70166+ this driver and enabled optional features.
70167+
70168+Each target subdirectory contains the following entries:
70169+
70170+ - host - link pointing on the corresponding scsi_host of the initiator
70171+ driver
70172+
70173+ - ini_groups - subdirectory defining initiator groups for this target,
70174+ used to define per-initiator access control. See SCST core README for
70175+ more details.
70176+
70177+ - luns - subdirectory defining LUNs of this target. See SCST core
70178+ README for more details.
70179+
70180+ - sessions - subdirectory containing connected to this target sessions.
70181+
70182+ - enabled - using this attribute you can enable or disable target mode
70183+ of this FC port. It allows to finish configuring it before it starts
70184+ accepting new connections. 0 by default.
70185+
70186+ - explicit_confirmation - allows to enable explicit conformations, see
70187+ above.
70188+
70189+ - rel_tgt_id - allows to read or write SCSI Relative Target Port
70190+ Identifier attribute. This identifier is used to identify SCSI Target
70191+ Ports by some SCSI commands, mainly by Persistent Reservations
70192+ commands. This identifier must be unique among all SCST targets, but
70193+ for convenience SCST allows disabled targets to have not unique
70194+ rel_tgt_id. In this case SCST will not allow to enable this target
70195+ until rel_tgt_id becomes unique. This attribute initialized unique by
70196+ SCST by default.
70197+
70198+Subdirectory "sessions" contains one subdirectory for each connected
70199+session with name equal to port name of the connected initiator.
70200+
70201+Each session subdirectory contains the following entries:
70202+
70203+ - initiator_name - contains initiator's port name
70204+
70205+ - active_commands - contains number of active, i.e. not yet or being
70206+ executed, SCSI commands in this session.
70207+
70208+ - commands - contains overall number of SCSI commands in this session.
70209+
70210+Below is a sample script, which configures 1 virtual disk "disk1" using
70211+/disk1 image for usage with 25:00:00:f0:98:87:92:f3 target. All
70212+initiators connected to this target will see this device.
70213+
70214+#!/bin/bash
70215+
70216+modprobe scst
70217+modprobe scst_vdisk
70218+
70219+echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
70220+
70221+modprobe qla2x00tgt
70222+
70223+echo "add disk1 0" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
70224+echo 1 >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/enabled
70225+
70226+Below is another sample script, which configures 1 real local SCSI disk
70227+0:0:1:0 for usage with 25:00:00:f0:98:87:92:f3 target:
70228+
70229+#!/bin/bash
70230+
70231+modprobe scst
70232+modprobe scst_disk
70233+
70234+echo "add_device 0:0:1:0" >/sys/kernel/scst_tgt/handlers/dev_disk/mgmt
70235+
70236+modprobe qla2x00tgt
70237+
70238+echo "add 0:0:1:0 0" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
70239+echo 1 >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/enabled
70240+
70241+Below is an advanced sample script, which configures more virtual
70242+devices of various types, including virtual CDROM. In this script
70243+initiator 25:00:00:f0:99:87:94:a3 will see disk1 and disk2 devices, all
70244+other initiators will see read only blockio, nullio and cdrom devices.
70245+
70246+#!/bin/bash
70247+
70248+modprobe scst
70249+modprobe scst_vdisk
70250+
70251+echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
70252+echo "add_device disk2 filename=/disk2; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
70253+echo "add_device blockio filename=/dev/sda5" >/sys/kernel/scst_tgt/handlers/vdisk_blockio/mgmt
70254+echo "add_device nullio" >/sys/kernel/scst_tgt/handlers/vdisk_nullio/mgmt
70255+echo "add_device cdrom" >/sys/kernel/scst_tgt/handlers/vcdrom/mgmt
70256+
70257+modprobe qla2x00tgt
70258+
70259+echo "add blockio 0 read_only=1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
70260+echo "add nullio 1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
70261+echo "add cdrom 2" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
70262+
70263+echo "create 25:00:00:f0:99:87:94:a3" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/mgmt
70264+echo "add disk1 0" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/luns/mgmt
70265+echo "add disk2 1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/luns/mgmt
70266+echo "add 25:00:00:f0:99:87:94:a3" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/initiators/mgmt
70267+
70268+echo 1 >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/enabled
70269+
70270+The resulting overall SCST sysfs hierarchy with initiator
70271+25:00:00:f0:99:87:94:a3 connected will look like:
70272+
70273+/sys/kernel/scst_tgt
70274+|-- devices
70275+| |-- blockio
70276+| | |-- blocksize
70277+| | |-- exported
70278+| | | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/0
70279+| | |-- filename
70280+| | |-- handler -> ../../handlers/vdisk_blockio
70281+| | |-- nv_cache
70282+| | |-- read_only
70283+| | |-- removable
70284+| | |-- resync_size
70285+| | |-- size_mb
70286+| | |-- t10_dev_id
70287+| | |-- threads_num
70288+| | |-- threads_pool_type
70289+| | |-- type
70290+| | `-- usn
70291+| |-- cdrom
70292+| | |-- exported
70293+| | | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/2
70294+| | |-- filename
70295+| | |-- handler -> ../../handlers/vcdrom
70296+| | |-- size_mb
70297+| | |-- t10_dev_id
70298+| | |-- threads_num
70299+| | |-- threads_pool_type
70300+| | |-- type
70301+| | `-- usn
70302+| |-- disk1
70303+| | |-- blocksize
70304+| | |-- exported
70305+| | | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/luns/0
70306+| | |-- filename
70307+| | |-- handler -> ../../handlers/vdisk_fileio
70308+| | |-- nv_cache
70309+| | |-- o_direct
70310+| | |-- read_only
70311+| | |-- removable
70312+| | |-- resync_size
70313+| | |-- size_mb
70314+| | |-- t10_dev_id
70315+| | |-- threads_num
70316+| | |-- threads_pool_type
70317+| | |-- type
70318+| | |-- usn
70319+| | `-- write_through
70320+| |-- disk2
70321+| | |-- blocksize
70322+| | |-- exported
70323+| | | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/luns/1
70324+| | |-- filename
70325+| | |-- handler -> ../../handlers/vdisk_fileio
70326+| | |-- nv_cache
70327+| | |-- o_direct
70328+| | |-- read_only
70329+| | |-- removable
70330+| | |-- resync_size
70331+| | |-- size_mb
70332+| | |-- t10_dev_id
70333+| | |-- threads_num
70334+| | |-- threads_pool_type
70335+| | |-- type
70336+| | |-- usn
70337+| | `-- write_through
70338+| `-- nullio
70339+| |-- blocksize
70340+| |-- exported
70341+| | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/1
70342+| |-- handler -> ../../handlers/vdisk_nullio
70343+| |-- read_only
70344+| |-- removable
70345+| |-- size_mb
70346+| |-- t10_dev_id
70347+| |-- threads_num
70348+| |-- threads_pool_type
70349+| |-- type
70350+| `-- usn
70351+|-- handlers
70352+| |-- vcdrom
70353+| | |-- cdrom -> ../../devices/cdrom
70354+| | |-- mgmt
70355+| | |-- trace_level
70356+| | `-- type
70357+| |-- vdisk_blockio
70358+| | |-- blockio -> ../../devices/blockio
70359+| | |-- mgmt
70360+| | |-- trace_level
70361+| | `-- type
70362+| |-- vdisk_fileio
70363+| | |-- disk1 -> ../../devices/disk1
70364+| | |-- disk2 -> ../../devices/disk2
70365+| | |-- mgmt
70366+| | |-- trace_level
70367+| | `-- type
70368+| `-- vdisk_nullio
70369+| |-- mgmt
70370+| |-- nullio -> ../../devices/nullio
70371+| |-- trace_level
70372+| `-- type
70373+|-- sgv
70374+| |-- global_stats
70375+| |-- sgv
70376+| | `-- stats
70377+| |-- sgv-clust
70378+| | `-- stats
70379+| `-- sgv-dma
70380+| `-- stats
70381+|-- targets
70382+| `-- qla2x00t
70383+| |-- 25:00:00:f0:98:87:92:f3
70384+| | |-- enabled
70385+| | |-- explicit_confirmation
70386+| | |-- host -> ../../../../../class/scsi_host/host4
70387+| | |-- ini_groups
70388+| | | |-- 25:00:00:f0:99:87:94:a3
70389+| | | | |-- initiators
70390+| | | | | |-- 25:00:00:f0:99:87:94:a3
70391+| | | | | `-- mgmt
70392+| | | | `-- luns
70393+| | | | |-- 0
70394+| | | | | |-- device -> ../../../../../../../devices/disk1
70395+| | | | | `-- read_only
70396+| | | | |-- 1
70397+| | | | | |-- device -> ../../../../../../../devices/disk2
70398+| | | | | `-- read_only
70399+| | | | `-- mgmt
70400+| | | `-- mgmt
70401+| | |-- luns
70402+| | | |-- 0
70403+| | | | |-- device -> ../../../../../devices/blockio
70404+| | | | `-- read_only
70405+| | | |-- 1
70406+| | | | |-- device -> ../../../../../devices/nullio
70407+| | | | `-- read_only
70408+| | | |-- 2
70409+| | | | |-- device -> ../../../../../devices/cdrom
70410+| | | | `-- read_only
70411+| | | `-- mgmt
70412+| | |-- rel_tgt_id
70413+| | `-- sessions
70414+| | `-- 25:00:00:f0:99:87:94:a3
70415+| | |-- active_commands
70416+| | |-- commands
70417+| | |-- initiator_name
70418+| | `-- luns -> ../../ini_groups/25:00:00:f0:99:87:94:a3/luns
70419+| |-- trace_level
70420+| `-- version
70421+|-- threads
70422+|-- trace_level
70423+`-- version
70424+
70425+Performance advices
70426+-------------------
70427+
70428+1. If you are going to use your target in an VM environment, for
70429+instance as a shared storage with VMware, make sure all your VMs
70430+connected to the target via *separate* sessions. You can check it using
70431+SCST proc or sysfs interface. You should use available facilities, like
70432+NPIV, to make separate sessions for each VM. If you miss it, you can
70433+greatly loose performance of parallel access to your target from
70434+different VMs. This isn't related to the case if your VMs are using the
70435+same shared storage, like with VMFS, for instance. In this case all your
70436+VM hosts will be connected to the target via separate sessions, which is
70437+enough.
70438+
70439+2. See SCST core's README for more advices. Especially pay attention to
70440+have io_grouping_type option set correctly.
70441+
70442+Credits
70443+-------
70444+
70445+Thanks to:
70446+
70447+ * QLogic support for their invaluable help.
70448+
70449+ * Nathaniel Clark <nate@misrule.us> for porting to new 2.6 kernel
70450+initiator driver.
70451+
70452+ * Mark Buechler <mark.buechler@gmail.com> for the original
70453+WWN-based authentification, a lot of useful suggestions, bug reports and
70454+help in debugging.
70455+
70456+ * Ming Zhang <mingz@ele.uri.edu> for fixes.
70457+
70458+Vladislav Bolkhovitin <vst@vlnb.net>, http://scst.sourceforge.net
70459diff -uprN orig/linux-2.6.35/drivers/scst/srpt/Kconfig linux-2.6.35/drivers/scst/srpt/Kconfig
70460--- orig/linux-2.6.35/drivers/scst/srpt/Kconfig
70461+++ linux-2.6.35/drivers/scst/srpt/Kconfig
70462@@ -0,0 +1,12 @@
70463+config SCST_SRPT
70464+ tristate "InfiniBand SCSI RDMA Protocol target support"
70465+ depends on INFINIBAND && SCST
70466+ ---help---
70467+
70468+ Support for the SCSI RDMA Protocol (SRP) Target driver. The
70469+ SRP protocol is a protocol that allows an initiator to access
70470+ a block storage device on another host (target) over a network
70471+ that supports the RDMA protocol. Currently the RDMA protocol is
70472+ supported by InfiniBand and by iWarp network hardware. More
70473+ information about the SRP protocol can be found on the website
70474+ of the INCITS T10 technical committee (http://www.t10.org/).
70475diff -uprN orig/linux-2.6.35/drivers/scst/srpt/Makefile linux-2.6.35/drivers/scst/srpt/Makefile
70476--- orig/linux-2.6.35/drivers/scst/srpt/Makefile
70477+++ linux-2.6.35/drivers/scst/srpt/Makefile
70478@@ -0,0 +1,1 @@
70479+obj-$(CONFIG_SCST_SRPT) += ib_srpt.o
70480diff -uprN orig/linux-2.6.35/drivers/scst/srpt/ib_dm_mad.h linux-2.6.35/drivers/scst/srpt/ib_dm_mad.h
70481--- orig/linux-2.6.35/drivers/scst/srpt/ib_dm_mad.h
70482+++ linux-2.6.35/drivers/scst/srpt/ib_dm_mad.h
70483@@ -0,0 +1,139 @@
70484+/*
70485+ * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.
70486+ *
70487+ * This software is available to you under a choice of one of two
70488+ * licenses. You may choose to be licensed under the terms of the GNU
70489+ * General Public License (GPL) Version 2, available from the file
70490+ * COPYING in the main directory of this source tree, or the
70491+ * OpenIB.org BSD license below:
70492+ *
70493+ * Redistribution and use in source and binary forms, with or
70494+ * without modification, are permitted provided that the following
70495+ * conditions are met:
70496+ *
70497+ * - Redistributions of source code must retain the above
70498+ * copyright notice, this list of conditions and the following
70499+ * disclaimer.
70500+ *
70501+ * - Redistributions in binary form must reproduce the above
70502+ * copyright notice, this list of conditions and the following
70503+ * disclaimer in the documentation and/or other materials
70504+ * provided with the distribution.
70505+ *
70506+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
70507+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
70508+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
70509+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
70510+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
70511+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
70512+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
70513+ * SOFTWARE.
70514+ *
70515+ */
70516+
70517+#ifndef IB_DM_MAD_H
70518+#define IB_DM_MAD_H
70519+
70520+#include <linux/types.h>
70521+
70522+#include <rdma/ib_mad.h>
70523+
70524+enum {
70525+ /*
70526+ * See also section 13.4.7 Status Field, table 115 MAD Common Status
70527+ * Field Bit Values and also section 16.3.1.1 Status Field in the
70528+ * InfiniBand Architecture Specification.
70529+ */
70530+ DM_MAD_STATUS_UNSUP_METHOD = 0x0008,
70531+ DM_MAD_STATUS_UNSUP_METHOD_ATTR = 0x000c,
70532+ DM_MAD_STATUS_INVALID_FIELD = 0x001c,
70533+ DM_MAD_STATUS_NO_IOC = 0x0100,
70534+
70535+ /*
70536+ * See also the Device Management chapter, section 16.3.3 Attributes,
70537+ * table 279 Device Management Attributes in the InfiniBand
70538+ * Architecture Specification.
70539+ */
70540+ DM_ATTR_CLASS_PORT_INFO = 0x01,
70541+ DM_ATTR_IOU_INFO = 0x10,
70542+ DM_ATTR_IOC_PROFILE = 0x11,
70543+ DM_ATTR_SVC_ENTRIES = 0x12
70544+};
70545+
70546+struct ib_dm_hdr {
70547+ u8 reserved[28];
70548+};
70549+
70550+/*
70551+ * Structure of management datagram sent by the SRP target implementation.
70552+ * Contains a management datagram header, reliable multi-packet transaction
70553+ * protocol (RMPP) header and ib_dm_hdr. Notes:
70554+ * - The SRP target implementation does not use RMPP or ib_dm_hdr when sending
70555+ * management datagrams.
70556+ * - The header size must be exactly 64 bytes (IB_MGMT_DEVICE_HDR), since this
70557+ * is the header size that is passed to ib_create_send_mad() in ib_srpt.c.
70558+ * - The maximum supported size for a management datagram when not using RMPP
70559+ * is 256 bytes -- 64 bytes header and 192 (IB_MGMT_DEVICE_DATA) bytes data.
70560+ */
70561+struct ib_dm_mad {
70562+ struct ib_mad_hdr mad_hdr;
70563+ struct ib_rmpp_hdr rmpp_hdr;
70564+ struct ib_dm_hdr dm_hdr;
70565+ u8 data[IB_MGMT_DEVICE_DATA];
70566+};
70567+
70568+/*
70569+ * IOUnitInfo as defined in section 16.3.3.3 IOUnitInfo of the InfiniBand
70570+ * Architecture Specification.
70571+ */
70572+struct ib_dm_iou_info {
70573+ __be16 change_id;
70574+ u8 max_controllers;
70575+ u8 op_rom;
70576+ u8 controller_list[128];
70577+};
70578+
70579+/*
70580+ * IOControllerprofile as defined in section 16.3.3.4 IOControllerProfile of
70581+ * the InfiniBand Architecture Specification.
70582+ */
70583+struct ib_dm_ioc_profile {
70584+ __be64 guid;
70585+ __be32 vendor_id;
70586+ __be32 device_id;
70587+ __be16 device_version;
70588+ __be16 reserved1;
70589+ __be32 subsys_vendor_id;
70590+ __be32 subsys_device_id;
70591+ __be16 io_class;
70592+ __be16 io_subclass;
70593+ __be16 protocol;
70594+ __be16 protocol_version;
70595+ __be16 service_conn;
70596+ __be16 initiators_supported;
70597+ __be16 send_queue_depth;
70598+ u8 reserved2;
70599+ u8 rdma_read_depth;
70600+ __be32 send_size;
70601+ __be32 rdma_size;
70602+ u8 op_cap_mask;
70603+ u8 svc_cap_mask;
70604+ u8 num_svc_entries;
70605+ u8 reserved3[9];
70606+ u8 id_string[64];
70607+};
70608+
70609+struct ib_dm_svc_entry {
70610+ u8 name[40];
70611+ __be64 id;
70612+};
70613+
70614+/*
70615+ * See also section 16.3.3.5 ServiceEntries in the InfiniBand Architecture
70616+ * Specification. See also section B.7, table B.8 in the T10 SRP r16a document.
70617+ */
70618+struct ib_dm_svc_entries {
70619+ struct ib_dm_svc_entry service_entries[4];
70620+};
70621+
70622+#endif
70623diff -uprN orig/linux-2.6.35/drivers/scst/srpt/ib_srpt.c linux-2.6.35/drivers/scst/srpt/ib_srpt.c
70624--- orig/linux-2.6.35/drivers/scst/srpt/ib_srpt.c
70625+++ linux-2.6.35/drivers/scst/srpt/ib_srpt.c
70626@@ -0,0 +1,3698 @@
70627+/*
70628+ * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.
70629+ * Copyright (C) 2008 Vladislav Bolkhovitin <vst@vlnb.net>
70630+ * Copyright (C) 2008 - 2010 Bart Van Assche <bart.vanassche@gmail.com>
70631+ *
70632+ * This software is available to you under a choice of one of two
70633+ * licenses. You may choose to be licensed under the terms of the GNU
70634+ * General Public License (GPL) Version 2, available from the file
70635+ * COPYING in the main directory of this source tree, or the
70636+ * OpenIB.org BSD license below:
70637+ *
70638+ * Redistribution and use in source and binary forms, with or
70639+ * without modification, are permitted provided that the following
70640+ * conditions are met:
70641+ *
70642+ * - Redistributions of source code must retain the above
70643+ * copyright notice, this list of conditions and the following
70644+ * disclaimer.
70645+ *
70646+ * - Redistributions in binary form must reproduce the above
70647+ * copyright notice, this list of conditions and the following
70648+ * disclaimer in the documentation and/or other materials
70649+ * provided with the distribution.
70650+ *
70651+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
70652+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
70653+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
70654+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
70655+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
70656+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
70657+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
70658+ * SOFTWARE.
70659+ *
70660+ */
70661+
70662+#include <linux/module.h>
70663+#include <linux/init.h>
70664+#include <linux/slab.h>
70665+#include <linux/err.h>
70666+#include <linux/ctype.h>
70667+#include <linux/kthread.h>
70668+#include <linux/string.h>
70669+#include <linux/delay.h>
70670+#include <asm/atomic.h>
70671+#include "ib_srpt.h"
70672+#define LOG_PREFIX "ib_srpt" /* Prefix for SCST tracing macros. */
70673+#include <scst/scst_debug.h>
70674+
70675+/* Name of this kernel module. */
70676+#define DRV_NAME "ib_srpt"
70677+#define DRV_VERSION "2.0.0"
70678+#define DRV_RELDATE "October 25, 2010"
70679+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
70680+/* Flags to be used in SCST debug tracing statements. */
70681+#define DEFAULT_SRPT_TRACE_FLAGS (TRACE_OUT_OF_MEM | TRACE_MINOR \
70682+ | TRACE_MGMT | TRACE_SPECIAL)
70683+/* Name of the entry that will be created under /proc/scsi_tgt/ib_srpt. */
70684+#define SRPT_PROC_TRACE_LEVEL_NAME "trace_level"
70685+#endif
70686+
70687+#define MELLANOX_SRPT_ID_STRING "SCST SRP target"
70688+
70689+MODULE_AUTHOR("Vu Pham");
70690+MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol target "
70691+ "v" DRV_VERSION " (" DRV_RELDATE ")");
70692+MODULE_LICENSE("Dual BSD/GPL");
70693+
70694+/*
70695+ * Local data types.
70696+ */
70697+
70698+enum threading_mode {
70699+ MODE_ALL_IN_SIRQ = 0,
70700+ MODE_IB_COMPLETION_IN_THREAD = 1,
70701+ MODE_IB_COMPLETION_IN_SIRQ = 2,
70702+};
70703+
70704+/*
70705+ * Global Variables
70706+ */
70707+
70708+static u64 srpt_service_guid;
70709+/* List of srpt_device structures. */
70710+static atomic_t srpt_device_count;
70711+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
70712+static unsigned long trace_flag = DEFAULT_SRPT_TRACE_FLAGS;
70713+module_param(trace_flag, long, 0644);
70714+MODULE_PARM_DESC(trace_flag, "SCST trace flags.");
70715+#endif
70716+
70717+static int thread = 1;
70718+module_param(thread, int, 0444);
70719+MODULE_PARM_DESC(thread,
70720+ "IB completion and SCSI command processing context. Defaults"
70721+ " to one, i.e. process IB completions and SCSI commands in"
70722+ " kernel thread context. 0 means soft IRQ whenever possible"
70723+ " and 2 means process IB completions in soft IRQ context and"
70724+ " SCSI commands in kernel thread context.");
70725+
70726+static unsigned srp_max_rdma_size = DEFAULT_MAX_RDMA_SIZE;
70727+module_param(srp_max_rdma_size, int, 0744);
70728+MODULE_PARM_DESC(srp_max_rdma_size,
70729+ "Maximum size of SRP RDMA transfers for new connections.");
70730+
70731+static unsigned srp_max_req_size = DEFAULT_MAX_REQ_SIZE;
70732+module_param(srp_max_req_size, int, 0444);
70733+MODULE_PARM_DESC(srp_max_req_size,
70734+ "Maximum size of SRP request messages in bytes.");
70735+
70736+static unsigned int srp_max_rsp_size = DEFAULT_MAX_RSP_SIZE;
70737+module_param(srp_max_rsp_size, int, 0444);
70738+MODULE_PARM_DESC(thread,
70739+ "Maximum size of SRP response messages in bytes.");
70740+
70741+static int srpt_srq_size = DEFAULT_SRPT_SRQ_SIZE;
70742+module_param(srpt_srq_size, int, 0444);
70743+MODULE_PARM_DESC(srpt_srq_size,
70744+ "Shared receive queue (SRQ) size.");
70745+
70746+static int srpt_sq_size = DEF_SRPT_SQ_SIZE;
70747+module_param(srpt_sq_size, int, 0444);
70748+MODULE_PARM_DESC(srpt_sq_size,
70749+ "Per-channel send queue (SQ) size.");
70750+
70751+static bool use_port_guid_in_session_name;
70752+module_param(use_port_guid_in_session_name, bool, 0444);
70753+MODULE_PARM_DESC(use_port_guid_in_session_name,
70754+ "Use target port ID in the SCST session name such that"
70755+ " redundant paths between multiport systems can be masked.");
70756+
70757+static int srpt_get_u64_x(char *buffer, struct kernel_param *kp)
70758+{
70759+ return sprintf(buffer, "0x%016llx", *(u64 *)kp->arg);
70760+}
70761+module_param_call(srpt_service_guid, NULL, srpt_get_u64_x, &srpt_service_guid,
70762+ 0444);
70763+MODULE_PARM_DESC(srpt_service_guid,
70764+ "Using this value for ioc_guid, id_ext, and cm_listen_id"
70765+ " instead of using the node_guid of the first HCA.");
70766+
70767+static void srpt_add_one(struct ib_device *device);
70768+static void srpt_remove_one(struct ib_device *device);
70769+static void srpt_unregister_mad_agent(struct srpt_device *sdev);
70770+static void srpt_unmap_sg_to_ib_sge(struct srpt_rdma_ch *ch,
70771+ struct srpt_send_ioctx *ioctx);
70772+static void srpt_release_channel(struct scst_session *scst_sess);
70773+
70774+static struct ib_client srpt_client = {
70775+ .name = DRV_NAME,
70776+ .add = srpt_add_one,
70777+ .remove = srpt_remove_one
70778+};
70779+
70780+/**
70781+ * srpt_test_and_set_channel_state() - Test and set the channel state.
70782+ *
70783+ * @ch: RDMA channel.
70784+ * @old: channel state to compare with.
70785+ * @new: state to change the channel state to if the current state matches the
70786+ * argument 'old'.
70787+ *
70788+ * Returns the previous channel state.
70789+ */
70790+static enum rdma_ch_state
70791+srpt_test_and_set_channel_state(struct srpt_rdma_ch *ch,
70792+ enum rdma_ch_state old,
70793+ enum rdma_ch_state new)
70794+{
70795+ return atomic_cmpxchg(&ch->state, old, new);
70796+}
70797+
70798+/**
70799+ * srpt_event_handler() - Asynchronous IB event callback function.
70800+ *
70801+ * Callback function called by the InfiniBand core when an asynchronous IB
70802+ * event occurs. This callback may occur in interrupt context. See also
70803+ * section 11.5.2, Set Asynchronous Event Handler in the InfiniBand
70804+ * Architecture Specification.
70805+ */
70806+static void srpt_event_handler(struct ib_event_handler *handler,
70807+ struct ib_event *event)
70808+{
70809+ struct srpt_device *sdev;
70810+ struct srpt_port *sport;
70811+
70812+ TRACE_ENTRY();
70813+
70814+ sdev = ib_get_client_data(event->device, &srpt_client);
70815+ if (!sdev || sdev->device != event->device)
70816+ return;
70817+
70818+ TRACE_DBG("ASYNC event= %d on device= %s",
70819+ event->event, sdev->device->name);
70820+
70821+ switch (event->event) {
70822+ case IB_EVENT_PORT_ERR:
70823+ if (event->element.port_num <= sdev->device->phys_port_cnt) {
70824+ sport = &sdev->port[event->element.port_num - 1];
70825+ sport->lid = 0;
70826+ sport->sm_lid = 0;
70827+ }
70828+ break;
70829+ case IB_EVENT_PORT_ACTIVE:
70830+ case IB_EVENT_LID_CHANGE:
70831+ case IB_EVENT_PKEY_CHANGE:
70832+ case IB_EVENT_SM_CHANGE:
70833+ case IB_EVENT_CLIENT_REREGISTER:
70834+ /*
70835+ * Refresh port data asynchronously. Note: it is safe to call
70836+ * schedule_work() even if &sport->work is already on the
70837+ * global workqueue because schedule_work() tests for the
70838+ * work_pending() condition before adding &sport->work to the
70839+ * global work queue.
70840+ */
70841+ if (event->element.port_num <= sdev->device->phys_port_cnt) {
70842+ sport = &sdev->port[event->element.port_num - 1];
70843+ if (!sport->lid && !sport->sm_lid)
70844+ schedule_work(&sport->work);
70845+ }
70846+ break;
70847+ default:
70848+ PRINT_ERROR("received unrecognized IB event %d", event->event);
70849+ break;
70850+ }
70851+
70852+ TRACE_EXIT();
70853+}
70854+
70855+/**
70856+ * srpt_srq_event() - SRQ event callback function.
70857+ */
70858+static void srpt_srq_event(struct ib_event *event, void *ctx)
70859+{
70860+ PRINT_INFO("SRQ event %d", event->event);
70861+}
70862+
70863+/**
70864+ * srpt_qp_event() - QP event callback function.
70865+ */
70866+static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch)
70867+{
70868+ TRACE_DBG("QP event %d on cm_id=%p sess_name=%s state=%d",
70869+ event->event, ch->cm_id, ch->sess_name,
70870+ atomic_read(&ch->state));
70871+
70872+ switch (event->event) {
70873+ case IB_EVENT_COMM_EST:
70874+ ib_cm_notify(ch->cm_id, event->event);
70875+ break;
70876+ case IB_EVENT_QP_LAST_WQE_REACHED:
70877+ if (srpt_test_and_set_channel_state(ch, RDMA_CHANNEL_LIVE,
70878+ RDMA_CHANNEL_DISCONNECTING) == RDMA_CHANNEL_LIVE) {
70879+ PRINT_INFO("disconnected session %s.", ch->sess_name);
70880+ ib_send_cm_dreq(ch->cm_id, NULL, 0);
70881+ }
70882+ break;
70883+ default:
70884+ PRINT_ERROR("received unrecognized IB QP event %d",
70885+ event->event);
70886+ break;
70887+ }
70888+}
70889+
70890+/**
70891+ * srpt_set_ioc() - Helper function for initializing an IOUnitInfo structure.
70892+ *
70893+ * @slot: one-based slot number.
70894+ * @value: four-bit value.
70895+ *
70896+ * Copies the lowest four bits of value in element slot of the array of four
70897+ * bit elements called c_list (controller list). The index slot is one-based.
70898+ */
70899+static void srpt_set_ioc(u8 *c_list, u32 slot, u8 value)
70900+{
70901+ u16 id;
70902+ u8 tmp;
70903+
70904+ id = (slot - 1) / 2;
70905+ if (slot & 0x1) {
70906+ tmp = c_list[id] & 0xf;
70907+ c_list[id] = (value << 4) | tmp;
70908+ } else {
70909+ tmp = c_list[id] & 0xf0;
70910+ c_list[id] = (value & 0xf) | tmp;
70911+ }
70912+}
70913+
70914+/**
70915+ * srpt_get_class_port_info() - Copy ClassPortInfo to a management datagram.
70916+ *
70917+ * See also section 16.3.3.1 ClassPortInfo in the InfiniBand Architecture
70918+ * Specification.
70919+ */
70920+static void srpt_get_class_port_info(struct ib_dm_mad *mad)
70921+{
70922+ struct ib_class_port_info *cif;
70923+
70924+ cif = (struct ib_class_port_info *)mad->data;
70925+ memset(cif, 0, sizeof *cif);
70926+ cif->base_version = 1;
70927+ cif->class_version = 1;
70928+ cif->resp_time_value = 20;
70929+
70930+ mad->mad_hdr.status = 0;
70931+}
70932+
70933+/**
70934+ * srpt_get_iou() - Write IOUnitInfo to a management datagram.
70935+ *
70936+ * See also section 16.3.3.3 IOUnitInfo in the InfiniBand Architecture
70937+ * Specification. See also section B.7, table B.6 in the SRP r16a document.
70938+ */
70939+static void srpt_get_iou(struct ib_dm_mad *mad)
70940+{
70941+ struct ib_dm_iou_info *ioui;
70942+ u8 slot;
70943+ int i;
70944+
70945+ ioui = (struct ib_dm_iou_info *)mad->data;
70946+ ioui->change_id = __constant_cpu_to_be16(1);
70947+ ioui->max_controllers = 16;
70948+
70949+ /* set present for slot 1 and empty for the rest */
70950+ srpt_set_ioc(ioui->controller_list, 1, 1);
70951+ for (i = 1, slot = 2; i < 16; i++, slot++)
70952+ srpt_set_ioc(ioui->controller_list, slot, 0);
70953+
70954+ mad->mad_hdr.status = 0;
70955+}
70956+
70957+/**
70958+ * srpt_get_ioc() - Write IOControllerprofile to a management datagram.
70959+ *
70960+ * See also section 16.3.3.4 IOControllerProfile in the InfiniBand
70961+ * Architecture Specification. See also section B.7, table B.7 in the SRP
70962+ * r16a document.
70963+ */
70964+static void srpt_get_ioc(struct srpt_device *sdev, u32 slot,
70965+ struct ib_dm_mad *mad)
70966+{
70967+ struct ib_dm_ioc_profile *iocp;
70968+
70969+ iocp = (struct ib_dm_ioc_profile *)mad->data;
70970+
70971+ if (!slot || slot > 16) {
70972+ mad->mad_hdr.status
70973+ = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);
70974+ return;
70975+ }
70976+
70977+ if (slot > 2) {
70978+ mad->mad_hdr.status
70979+ = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC);
70980+ return;
70981+ }
70982+
70983+ memset(iocp, 0, sizeof *iocp);
70984+ strcpy(iocp->id_string, MELLANOX_SRPT_ID_STRING);
70985+ iocp->guid = cpu_to_be64(srpt_service_guid);
70986+ iocp->vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id);
70987+ iocp->device_id = cpu_to_be32(sdev->dev_attr.vendor_part_id);
70988+ iocp->device_version = cpu_to_be16(sdev->dev_attr.hw_ver);
70989+ iocp->subsys_vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id);
70990+ iocp->subsys_device_id = 0x0;
70991+ iocp->io_class = __constant_cpu_to_be16(SRP_REV16A_IB_IO_CLASS);
70992+ iocp->io_subclass = __constant_cpu_to_be16(SRP_IO_SUBCLASS);
70993+ iocp->protocol = __constant_cpu_to_be16(SRP_PROTOCOL);
70994+ iocp->protocol_version = __constant_cpu_to_be16(SRP_PROTOCOL_VERSION);
70995+ iocp->send_queue_depth = cpu_to_be16(sdev->srq_size);
70996+ iocp->rdma_read_depth = 4;
70997+ iocp->send_size = cpu_to_be32(srp_max_req_size);
70998+ iocp->rdma_size = cpu_to_be32(min(max(srp_max_rdma_size, 256U),
70999+ 1U << 24));
71000+ iocp->num_svc_entries = 1;
71001+ iocp->op_cap_mask = SRP_SEND_TO_IOC | SRP_SEND_FROM_IOC |
71002+ SRP_RDMA_READ_FROM_IOC | SRP_RDMA_WRITE_FROM_IOC;
71003+
71004+ mad->mad_hdr.status = 0;
71005+}
71006+
71007+/**
71008+ * srpt_get_svc_entries() - Write ServiceEntries to a management datagram.
71009+ *
71010+ * See also section 16.3.3.5 ServiceEntries in the InfiniBand Architecture
71011+ * Specification. See also section B.7, table B.8 in the SRP r16a document.
71012+ */
71013+static void srpt_get_svc_entries(u64 ioc_guid,
71014+ u16 slot, u8 hi, u8 lo, struct ib_dm_mad *mad)
71015+{
71016+ struct ib_dm_svc_entries *svc_entries;
71017+
71018+ WARN_ON(!ioc_guid);
71019+
71020+ if (!slot || slot > 16) {
71021+ mad->mad_hdr.status
71022+ = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);
71023+ return;
71024+ }
71025+
71026+ if (slot > 2 || lo > hi || hi > 1) {
71027+ mad->mad_hdr.status
71028+ = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC);
71029+ return;
71030+ }
71031+
71032+ svc_entries = (struct ib_dm_svc_entries *)mad->data;
71033+ memset(svc_entries, 0, sizeof *svc_entries);
71034+ svc_entries->service_entries[0].id = cpu_to_be64(ioc_guid);
71035+ snprintf(svc_entries->service_entries[0].name,
71036+ sizeof(svc_entries->service_entries[0].name),
71037+ "%s%016llx",
71038+ SRP_SERVICE_NAME_PREFIX,
71039+ ioc_guid);
71040+
71041+ mad->mad_hdr.status = 0;
71042+}
71043+
71044+/**
71045+ * srpt_mgmt_method_get() - Process a received management datagram.
71046+ * @sp: source port through which the MAD has been received.
71047+ * @rq_mad: received MAD.
71048+ * @rsp_mad: response MAD.
71049+ */
71050+static void srpt_mgmt_method_get(struct srpt_port *sp, struct ib_mad *rq_mad,
71051+ struct ib_dm_mad *rsp_mad)
71052+{
71053+ u16 attr_id;
71054+ u32 slot;
71055+ u8 hi, lo;
71056+
71057+ attr_id = be16_to_cpu(rq_mad->mad_hdr.attr_id);
71058+ switch (attr_id) {
71059+ case DM_ATTR_CLASS_PORT_INFO:
71060+ srpt_get_class_port_info(rsp_mad);
71061+ break;
71062+ case DM_ATTR_IOU_INFO:
71063+ srpt_get_iou(rsp_mad);
71064+ break;
71065+ case DM_ATTR_IOC_PROFILE:
71066+ slot = be32_to_cpu(rq_mad->mad_hdr.attr_mod);
71067+ srpt_get_ioc(sp->sdev, slot, rsp_mad);
71068+ break;
71069+ case DM_ATTR_SVC_ENTRIES:
71070+ slot = be32_to_cpu(rq_mad->mad_hdr.attr_mod);
71071+ hi = (u8) ((slot >> 8) & 0xff);
71072+ lo = (u8) (slot & 0xff);
71073+ slot = (u16) ((slot >> 16) & 0xffff);
71074+ srpt_get_svc_entries(srpt_service_guid,
71075+ slot, hi, lo, rsp_mad);
71076+ break;
71077+ default:
71078+ rsp_mad->mad_hdr.status =
71079+ __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);
71080+ break;
71081+ }
71082+}
71083+
71084+/**
71085+ * srpt_mad_send_handler() - Post MAD-send callback function.
71086+ */
71087+static void srpt_mad_send_handler(struct ib_mad_agent *mad_agent,
71088+ struct ib_mad_send_wc *mad_wc)
71089+{
71090+ ib_destroy_ah(mad_wc->send_buf->ah);
71091+ ib_free_send_mad(mad_wc->send_buf);
71092+}
71093+
71094+/**
71095+ * srpt_mad_recv_handler() - MAD reception callback function.
71096+ */
71097+static void srpt_mad_recv_handler(struct ib_mad_agent *mad_agent,
71098+ struct ib_mad_recv_wc *mad_wc)
71099+{
71100+ struct srpt_port *sport = (struct srpt_port *)mad_agent->context;
71101+ struct ib_ah *ah;
71102+ struct ib_mad_send_buf *rsp;
71103+ struct ib_dm_mad *dm_mad;
71104+
71105+ if (!mad_wc || !mad_wc->recv_buf.mad)
71106+ return;
71107+
71108+ ah = ib_create_ah_from_wc(mad_agent->qp->pd, mad_wc->wc,
71109+ mad_wc->recv_buf.grh, mad_agent->port_num);
71110+ if (IS_ERR(ah))
71111+ goto err;
71112+
71113+ BUILD_BUG_ON(offsetof(struct ib_dm_mad, data) != IB_MGMT_DEVICE_HDR);
71114+
71115+ rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp,
71116+ mad_wc->wc->pkey_index, 0,
71117+ IB_MGMT_DEVICE_HDR, IB_MGMT_DEVICE_DATA,
71118+ GFP_KERNEL);
71119+ if (IS_ERR(rsp))
71120+ goto err_rsp;
71121+
71122+ rsp->ah = ah;
71123+
71124+ dm_mad = rsp->mad;
71125+ memcpy(dm_mad, mad_wc->recv_buf.mad, sizeof *dm_mad);
71126+ dm_mad->mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
71127+ dm_mad->mad_hdr.status = 0;
71128+
71129+ switch (mad_wc->recv_buf.mad->mad_hdr.method) {
71130+ case IB_MGMT_METHOD_GET:
71131+ srpt_mgmt_method_get(sport, mad_wc->recv_buf.mad, dm_mad);
71132+ break;
71133+ case IB_MGMT_METHOD_SET:
71134+ dm_mad->mad_hdr.status =
71135+ __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);
71136+ break;
71137+ default:
71138+ dm_mad->mad_hdr.status =
71139+ __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD);
71140+ break;
71141+ }
71142+
71143+ if (!ib_post_send_mad(rsp, NULL)) {
71144+ ib_free_recv_mad(mad_wc);
71145+ /* will destroy_ah & free_send_mad in send completion */
71146+ return;
71147+ }
71148+
71149+ ib_free_send_mad(rsp);
71150+
71151+err_rsp:
71152+ ib_destroy_ah(ah);
71153+err:
71154+ ib_free_recv_mad(mad_wc);
71155+}
71156+
71157+/**
71158+ * srpt_refresh_port() - Configure a HCA port.
71159+ *
71160+ * Enable InfiniBand management datagram processing, update the cached sm_lid,
71161+ * lid and gid values, and register a callback function for processing MADs
71162+ * on the specified port.
71163+ *
71164+ * Note: It is safe to call this function more than once for the same port.
71165+ */
71166+static int srpt_refresh_port(struct srpt_port *sport)
71167+{
71168+ struct ib_mad_reg_req reg_req;
71169+ struct ib_port_modify port_modify;
71170+ struct ib_port_attr port_attr;
71171+ int ret;
71172+
71173+ TRACE_ENTRY();
71174+
71175+ memset(&port_modify, 0, sizeof port_modify);
71176+ port_modify.set_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP;
71177+ port_modify.clr_port_cap_mask = 0;
71178+
71179+ ret = ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify);
71180+ if (ret)
71181+ goto err_mod_port;
71182+
71183+ ret = ib_query_port(sport->sdev->device, sport->port, &port_attr);
71184+ if (ret)
71185+ goto err_query_port;
71186+
71187+ sport->sm_lid = port_attr.sm_lid;
71188+ sport->lid = port_attr.lid;
71189+
71190+ ret = ib_query_gid(sport->sdev->device, sport->port, 0, &sport->gid);
71191+ if (ret)
71192+ goto err_query_port;
71193+
71194+ if (!sport->mad_agent) {
71195+ memset(&reg_req, 0, sizeof reg_req);
71196+ reg_req.mgmt_class = IB_MGMT_CLASS_DEVICE_MGMT;
71197+ reg_req.mgmt_class_version = IB_MGMT_BASE_VERSION;
71198+ set_bit(IB_MGMT_METHOD_GET, reg_req.method_mask);
71199+ set_bit(IB_MGMT_METHOD_SET, reg_req.method_mask);
71200+
71201+ sport->mad_agent = ib_register_mad_agent(sport->sdev->device,
71202+ sport->port,
71203+ IB_QPT_GSI,
71204+ &reg_req, 0,
71205+ srpt_mad_send_handler,
71206+ srpt_mad_recv_handler,
71207+ sport);
71208+ if (IS_ERR(sport->mad_agent)) {
71209+ ret = PTR_ERR(sport->mad_agent);
71210+ sport->mad_agent = NULL;
71211+ goto err_query_port;
71212+ }
71213+ }
71214+
71215+ TRACE_EXIT_RES(0);
71216+
71217+ return 0;
71218+
71219+err_query_port:
71220+
71221+ port_modify.set_port_cap_mask = 0;
71222+ port_modify.clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP;
71223+ ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify);
71224+
71225+err_mod_port:
71226+
71227+ TRACE_EXIT_RES(ret);
71228+
71229+ return ret;
71230+}
71231+
71232+/**
71233+ * srpt_unregister_mad_agent() - Unregister MAD callback functions.
71234+ *
71235+ * Note: It is safe to call this function more than once for the same device.
71236+ */
71237+static void srpt_unregister_mad_agent(struct srpt_device *sdev)
71238+{
71239+ struct ib_port_modify port_modify = {
71240+ .clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP,
71241+ };
71242+ struct srpt_port *sport;
71243+ int i;
71244+
71245+ for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
71246+ sport = &sdev->port[i - 1];
71247+ WARN_ON(sport->port != i);
71248+ if (ib_modify_port(sdev->device, i, 0, &port_modify) < 0)
71249+ PRINT_ERROR("%s", "disabling MAD processing failed.");
71250+ if (sport->mad_agent) {
71251+ ib_unregister_mad_agent(sport->mad_agent);
71252+ sport->mad_agent = NULL;
71253+ }
71254+ }
71255+}
71256+
71257+/**
71258+ * srpt_alloc_ioctx() - Allocate an SRPT I/O context structure.
71259+ */
71260+static struct srpt_ioctx *srpt_alloc_ioctx(struct srpt_device *sdev,
71261+ int ioctx_size, int dma_size,
71262+ enum dma_data_direction dir)
71263+{
71264+ struct srpt_ioctx *ioctx;
71265+
71266+ ioctx = kmalloc(ioctx_size, GFP_KERNEL);
71267+ if (!ioctx)
71268+ goto err;
71269+
71270+ ioctx->buf = kmalloc(dma_size, GFP_KERNEL);
71271+ if (!ioctx->buf)
71272+ goto err_free_ioctx;
71273+
71274+ ioctx->dma = ib_dma_map_single(sdev->device, ioctx->buf, dma_size, dir);
71275+ if (ib_dma_mapping_error(sdev->device, ioctx->dma))
71276+ goto err_free_buf;
71277+
71278+ return ioctx;
71279+
71280+err_free_buf:
71281+ kfree(ioctx->buf);
71282+err_free_ioctx:
71283+ kfree(ioctx);
71284+err:
71285+ return NULL;
71286+}
71287+
71288+/**
71289+ * srpt_free_ioctx() - Free an SRPT I/O context structure.
71290+ */
71291+static void srpt_free_ioctx(struct srpt_device *sdev, struct srpt_ioctx *ioctx,
71292+ int dma_size, enum dma_data_direction dir)
71293+{
71294+ if (!ioctx)
71295+ return;
71296+
71297+ ib_dma_unmap_single(sdev->device, ioctx->dma, dma_size, dir);
71298+ kfree(ioctx->buf);
71299+ kfree(ioctx);
71300+}
71301+
71302+/**
71303+ * srpt_alloc_ioctx_ring() - Allocate a ring of SRPT I/O context structures.
71304+ * @sdev: Device to allocate the I/O context ring for.
71305+ * @ring_size: Number of elements in the I/O context ring.
71306+ * @ioctx_size: I/O context size.
71307+ * @dma_size: DMA buffer size.
71308+ * @dir: DMA data direction.
71309+ */
71310+static struct srpt_ioctx **srpt_alloc_ioctx_ring(struct srpt_device *sdev,
71311+ int ring_size, int ioctx_size,
71312+ int dma_size, enum dma_data_direction dir)
71313+{
71314+ struct srpt_ioctx **ring;
71315+ int i;
71316+
71317+ TRACE_ENTRY();
71318+
71319+ WARN_ON(ioctx_size != sizeof(struct srpt_recv_ioctx)
71320+ && ioctx_size != sizeof(struct srpt_send_ioctx));
71321+ WARN_ON(dma_size != srp_max_req_size && dma_size != srp_max_rsp_size);
71322+
71323+ ring = kmalloc(ring_size * sizeof(ring[0]), GFP_KERNEL);
71324+ if (!ring)
71325+ goto out;
71326+ for (i = 0; i < ring_size; ++i) {
71327+ ring[i] = srpt_alloc_ioctx(sdev, ioctx_size, dma_size, dir);
71328+ if (!ring[i])
71329+ goto err;
71330+ ring[i]->index = i;
71331+ }
71332+ goto out;
71333+
71334+err:
71335+ while (--i >= 0)
71336+ srpt_free_ioctx(sdev, ring[i], dma_size, dir);
71337+ kfree(ring);
71338+out:
71339+ TRACE_EXIT_RES(ring);
71340+ return ring;
71341+}
71342+
71343+/**
71344+ * srpt_free_ioctx_ring() - Free the ring of SRPT I/O context structures.
71345+ */
71346+static void srpt_free_ioctx_ring(struct srpt_ioctx **ioctx_ring,
71347+ struct srpt_device *sdev, int ring_size,
71348+ int dma_size, enum dma_data_direction dir)
71349+{
71350+ int i;
71351+
71352+ WARN_ON(dma_size != srp_max_req_size && dma_size != srp_max_rsp_size);
71353+
71354+ for (i = 0; i < ring_size; ++i)
71355+ srpt_free_ioctx(sdev, ioctx_ring[i], dma_size, dir);
71356+ kfree(ioctx_ring);
71357+}
71358+
71359+/**
71360+ * srpt_get_cmd_state() - Get the state of a SCSI command.
71361+ */
71362+static enum srpt_command_state srpt_get_cmd_state(struct srpt_send_ioctx *ioctx)
71363+{
71364+ BUG_ON(!ioctx);
71365+
71366+ return atomic_read(&ioctx->state);
71367+}
71368+
71369+/**
71370+ * srpt_set_cmd_state() - Set the state of a SCSI command.
71371+ * @new: New state to be set.
71372+ *
71373+ * Does not modify the state of aborted commands. Returns the previous command
71374+ * state.
71375+ */
71376+static enum srpt_command_state srpt_set_cmd_state(struct srpt_send_ioctx *ioctx,
71377+ enum srpt_command_state new)
71378+{
71379+ enum srpt_command_state previous;
71380+
71381+ BUG_ON(!ioctx);
71382+
71383+ do {
71384+ previous = atomic_read(&ioctx->state);
71385+ } while (previous != SRPT_STATE_DONE
71386+ && atomic_cmpxchg(&ioctx->state, previous, new) != previous);
71387+
71388+ return previous;
71389+}
71390+
71391+/**
71392+ * srpt_test_and_set_cmd_state() - Test and set the state of a command.
71393+ * @old: State to compare against.
71394+ * @new: New state to be set if the current state matches 'old'.
71395+ *
71396+ * Returns the previous command state.
71397+ */
71398+static enum srpt_command_state
71399+srpt_test_and_set_cmd_state(struct srpt_send_ioctx *ioctx,
71400+ enum srpt_command_state old,
71401+ enum srpt_command_state new)
71402+{
71403+ WARN_ON(!ioctx);
71404+ WARN_ON(old == SRPT_STATE_DONE);
71405+ WARN_ON(new == SRPT_STATE_NEW);
71406+
71407+ return atomic_cmpxchg(&ioctx->state, old, new);
71408+}
71409+
71410+/**
71411+ * srpt_post_recv() - Post an IB receive request.
71412+ */
71413+static int srpt_post_recv(struct srpt_device *sdev,
71414+ struct srpt_recv_ioctx *ioctx)
71415+{
71416+ struct ib_sge list;
71417+ struct ib_recv_wr wr, *bad_wr;
71418+
71419+ BUG_ON(!sdev);
71420+ wr.wr_id = encode_wr_id(IB_WC_RECV, ioctx->ioctx.index);
71421+
71422+ list.addr = ioctx->ioctx.dma;
71423+ list.length = srp_max_req_size;
71424+ list.lkey = sdev->mr->lkey;
71425+
71426+ wr.next = NULL;
71427+ wr.sg_list = &list;
71428+ wr.num_sge = 1;
71429+
71430+ return ib_post_srq_recv(sdev->srq, &wr, &bad_wr);
71431+}
71432+
71433+/**
71434+ * srpt_post_send() - Post an IB send request.
71435+ * @ch: RDMA channel to post the send request on.
71436+ * @ioctx: I/O context of the send request.
71437+ * @len: length of the request to be sent in bytes.
71438+ *
71439+ * Returns zero upon success and a non-zero value upon failure.
71440+ */
71441+static int srpt_post_send(struct srpt_rdma_ch *ch,
71442+ struct srpt_send_ioctx *ioctx, int len)
71443+{
71444+ struct ib_sge list;
71445+ struct ib_send_wr wr, *bad_wr;
71446+ struct srpt_device *sdev = ch->sport->sdev;
71447+ int ret;
71448+
71449+ ret = -ENOMEM;
71450+ if (atomic_dec_return(&ch->sq_wr_avail) < 0) {
71451+ PRINT_WARNING("%s", "IB send queue full (needed 1)");
71452+ goto out;
71453+ }
71454+
71455+ ib_dma_sync_single_for_device(sdev->device, ioctx->ioctx.dma, len,
71456+ DMA_TO_DEVICE);
71457+
71458+ list.addr = ioctx->ioctx.dma;
71459+ list.length = len;
71460+ list.lkey = sdev->mr->lkey;
71461+
71462+ wr.next = NULL;
71463+ wr.wr_id = encode_wr_id(IB_WC_SEND, ioctx->ioctx.index);
71464+ wr.sg_list = &list;
71465+ wr.num_sge = 1;
71466+ wr.opcode = IB_WR_SEND;
71467+ wr.send_flags = IB_SEND_SIGNALED;
71468+
71469+ ret = ib_post_send(ch->qp, &wr, &bad_wr);
71470+
71471+out:
71472+ if (ret < 0)
71473+ atomic_inc(&ch->sq_wr_avail);
71474+ return ret;
71475+}
71476+
71477+/**
71478+ * srpt_get_desc_tbl() - Parse the data descriptors of an SRP_CMD request.
71479+ * @ioctx: Pointer to the I/O context associated with the request.
71480+ * @srp_cmd: Pointer to the SRP_CMD request data.
71481+ * @dir: Pointer to the variable to which the transfer direction will be
71482+ * written.
71483+ * @data_len: Pointer to the variable to which the total data length of all
71484+ * descriptors in the SRP_CMD request will be written.
71485+ *
71486+ * This function initializes ioctx->nrbuf and ioctx->r_bufs.
71487+ *
71488+ * Returns -EINVAL when the SRP_CMD request contains inconsistent descriptors;
71489+ * -ENOMEM when memory allocation fails and zero upon success.
71490+ */
71491+static int srpt_get_desc_tbl(struct srpt_send_ioctx *ioctx,
71492+ struct srp_cmd *srp_cmd,
71493+ scst_data_direction *dir, u64 *data_len)
71494+{
71495+ struct srp_indirect_buf *idb;
71496+ struct srp_direct_buf *db;
71497+ unsigned add_cdb_offset;
71498+ int ret;
71499+
71500+ /*
71501+ * The pointer computations below will only be compiled correctly
71502+ * if srp_cmd::add_data is declared as s8*, u8*, s8[] or u8[], so check
71503+ * whether srp_cmd::add_data has been declared as a byte pointer.
71504+ */
71505+ BUILD_BUG_ON(!__same_type(srp_cmd->add_data[0], (s8)0)
71506+ && !__same_type(srp_cmd->add_data[0], (u8)0));
71507+
71508+ BUG_ON(!dir);
71509+ BUG_ON(!data_len);
71510+
71511+ ret = 0;
71512+ *data_len = 0;
71513+
71514+ /*
71515+ * The lower four bits of the buffer format field contain the DATA-IN
71516+ * buffer descriptor format, and the highest four bits contain the
71517+ * DATA-OUT buffer descriptor format.
71518+ */
71519+ *dir = SCST_DATA_NONE;
71520+ if (srp_cmd->buf_fmt & 0xf)
71521+ /* DATA-IN: transfer data from target to initiator. */
71522+ *dir = SCST_DATA_READ;
71523+ else if (srp_cmd->buf_fmt >> 4)
71524+ /* DATA-OUT: transfer data from initiator to target. */
71525+ *dir = SCST_DATA_WRITE;
71526+
71527+ /*
71528+ * According to the SRP spec, the lower two bits of the 'ADDITIONAL
71529+ * CDB LENGTH' field are reserved and the size in bytes of this field
71530+ * is four times the value specified in bits 3..7. Hence the "& ~3".
71531+ */
71532+ add_cdb_offset = srp_cmd->add_cdb_len & ~3;
71533+ if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_DIRECT) ||
71534+ ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_DIRECT)) {
71535+ ioctx->n_rbuf = 1;
71536+ ioctx->rbufs = &ioctx->single_rbuf;
71537+
71538+ db = (struct srp_direct_buf *)(srp_cmd->add_data
71539+ + add_cdb_offset);
71540+ memcpy(ioctx->rbufs, db, sizeof *db);
71541+ *data_len = be32_to_cpu(db->len);
71542+ } else if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_INDIRECT) ||
71543+ ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_INDIRECT)) {
71544+ idb = (struct srp_indirect_buf *)(srp_cmd->add_data
71545+ + add_cdb_offset);
71546+
71547+ ioctx->n_rbuf = be32_to_cpu(idb->table_desc.len) / sizeof *db;
71548+
71549+ if (ioctx->n_rbuf >
71550+ (srp_cmd->data_out_desc_cnt + srp_cmd->data_in_desc_cnt)) {
71551+ PRINT_ERROR("received unsupported SRP_CMD request type"
71552+ " (%u out + %u in != %u / %zu)",
71553+ srp_cmd->data_out_desc_cnt,
71554+ srp_cmd->data_in_desc_cnt,
71555+ be32_to_cpu(idb->table_desc.len),
71556+ sizeof(*db));
71557+ ioctx->n_rbuf = 0;
71558+ ret = -EINVAL;
71559+ goto out;
71560+ }
71561+
71562+ if (ioctx->n_rbuf == 1)
71563+ ioctx->rbufs = &ioctx->single_rbuf;
71564+ else {
71565+ ioctx->rbufs =
71566+ kmalloc(ioctx->n_rbuf * sizeof *db, GFP_ATOMIC);
71567+ if (!ioctx->rbufs) {
71568+ ioctx->n_rbuf = 0;
71569+ ret = -ENOMEM;
71570+ goto out;
71571+ }
71572+ }
71573+
71574+ db = idb->desc_list;
71575+ memcpy(ioctx->rbufs, db, ioctx->n_rbuf * sizeof *db);
71576+ *data_len = be32_to_cpu(idb->len);
71577+ }
71578+out:
71579+ return ret;
71580+}
71581+
71582+/**
71583+ * srpt_init_ch_qp() - Initialize queue pair attributes.
71584+ *
71585+ * Initialized the attributes of queue pair 'qp' by allowing local write,
71586+ * remote read and remote write. Also transitions 'qp' to state IB_QPS_INIT.
71587+ */
71588+static int srpt_init_ch_qp(struct srpt_rdma_ch *ch, struct ib_qp *qp)
71589+{
71590+ struct ib_qp_attr *attr;
71591+ int ret;
71592+
71593+ attr = kzalloc(sizeof *attr, GFP_KERNEL);
71594+ if (!attr)
71595+ return -ENOMEM;
71596+
71597+ attr->qp_state = IB_QPS_INIT;
71598+ attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_READ |
71599+ IB_ACCESS_REMOTE_WRITE;
71600+ attr->port_num = ch->sport->port;
71601+ attr->pkey_index = 0;
71602+
71603+ ret = ib_modify_qp(qp, attr,
71604+ IB_QP_STATE | IB_QP_ACCESS_FLAGS | IB_QP_PORT |
71605+ IB_QP_PKEY_INDEX);
71606+
71607+ kfree(attr);
71608+ return ret;
71609+}
71610+
71611+/**
71612+ * srpt_ch_qp_rtr() - Change the state of a channel to 'ready to receive' (RTR).
71613+ * @ch: channel of the queue pair.
71614+ * @qp: queue pair to change the state of.
71615+ *
71616+ * Returns zero upon success and a negative value upon failure.
71617+ *
71618+ * Note: currently a struct ib_qp_attr takes 136 bytes on a 64-bit system.
71619+ * If this structure ever becomes larger, it might be necessary to allocate
71620+ * it dynamically instead of on the stack.
71621+ */
71622+static int srpt_ch_qp_rtr(struct srpt_rdma_ch *ch, struct ib_qp *qp)
71623+{
71624+ struct ib_qp_attr qp_attr;
71625+ int attr_mask;
71626+ int ret;
71627+
71628+ qp_attr.qp_state = IB_QPS_RTR;
71629+ ret = ib_cm_init_qp_attr(ch->cm_id, &qp_attr, &attr_mask);
71630+ if (ret)
71631+ goto out;
71632+
71633+ qp_attr.max_dest_rd_atomic = 4;
71634+
71635+ ret = ib_modify_qp(qp, &qp_attr, attr_mask);
71636+
71637+out:
71638+ return ret;
71639+}
71640+
71641+/**
71642+ * srpt_ch_qp_rts() - Change the state of a channel to 'ready to send' (RTS).
71643+ * @ch: channel of the queue pair.
71644+ * @qp: queue pair to change the state of.
71645+ *
71646+ * Returns zero upon success and a negative value upon failure.
71647+ *
71648+ * Note: currently a struct ib_qp_attr takes 136 bytes on a 64-bit system.
71649+ * If this structure ever becomes larger, it might be necessary to allocate
71650+ * it dynamically instead of on the stack.
71651+ */
71652+static int srpt_ch_qp_rts(struct srpt_rdma_ch *ch, struct ib_qp *qp)
71653+{
71654+ struct ib_qp_attr qp_attr;
71655+ int attr_mask;
71656+ int ret;
71657+
71658+ qp_attr.qp_state = IB_QPS_RTS;
71659+ ret = ib_cm_init_qp_attr(ch->cm_id, &qp_attr, &attr_mask);
71660+ if (ret)
71661+ goto out;
71662+
71663+ qp_attr.max_rd_atomic = 4;
71664+
71665+ ret = ib_modify_qp(qp, &qp_attr, attr_mask);
71666+
71667+out:
71668+ return ret;
71669+}
71670+
71671+/**
71672+ * srpt_get_send_ioctx() - Obtain an I/O context for sending to the initiator.
71673+ */
71674+static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch)
71675+{
71676+ struct srpt_send_ioctx *ioctx;
71677+ unsigned long flags;
71678+
71679+ BUG_ON(!ch);
71680+
71681+ ioctx = NULL;
71682+ spin_lock_irqsave(&ch->spinlock, flags);
71683+ if (!list_empty(&ch->free_list)) {
71684+ ioctx = list_first_entry(&ch->free_list,
71685+ struct srpt_send_ioctx, free_list);
71686+ list_del(&ioctx->free_list);
71687+ }
71688+ spin_unlock_irqrestore(&ch->spinlock, flags);
71689+
71690+ if (!ioctx)
71691+ return ioctx;
71692+
71693+ BUG_ON(ioctx->ch != ch);
71694+ atomic_set(&ioctx->state, SRPT_STATE_NEW);
71695+ ioctx->n_rbuf = 0;
71696+ ioctx->rbufs = NULL;
71697+ ioctx->n_rdma = 0;
71698+ ioctx->n_rdma_ius = 0;
71699+ ioctx->rdma_ius = NULL;
71700+ ioctx->mapped_sg_count = 0;
71701+ ioctx->scmnd = NULL;
71702+
71703+ return ioctx;
71704+}
71705+
71706+/**
71707+ * srpt_put_send_ioctx() - Free up resources.
71708+ */
71709+static void srpt_put_send_ioctx(struct srpt_send_ioctx *ioctx)
71710+{
71711+ struct srpt_rdma_ch *ch;
71712+ unsigned long flags;
71713+
71714+ BUG_ON(!ioctx);
71715+ ch = ioctx->ch;
71716+ BUG_ON(!ch);
71717+
71718+ WARN_ON(srpt_get_cmd_state(ioctx) != SRPT_STATE_DONE);
71719+
71720+ ioctx->scmnd = NULL;
71721+
71722+ /*
71723+ * If the WARN_ON() below gets triggered this means that
71724+ * srpt_unmap_sg_to_ib_sge() has not been called before
71725+ * scst_tgt_cmd_done().
71726+ */
71727+ WARN_ON(ioctx->mapped_sg_count);
71728+
71729+ if (ioctx->n_rbuf > 1) {
71730+ kfree(ioctx->rbufs);
71731+ ioctx->rbufs = NULL;
71732+ ioctx->n_rbuf = 0;
71733+ }
71734+
71735+ spin_lock_irqsave(&ch->spinlock, flags);
71736+ list_add(&ioctx->free_list, &ch->free_list);
71737+ spin_unlock_irqrestore(&ch->spinlock, flags);
71738+}
71739+
71740+/**
71741+ * srpt_abort_scst_cmd() - Abort a SCSI command.
71742+ * @ioctx: I/O context associated with the SCSI command.
71743+ * @context: Preferred execution context.
71744+ */
71745+static void srpt_abort_scst_cmd(struct srpt_send_ioctx *ioctx,
71746+ enum scst_exec_context context)
71747+{
71748+ struct scst_cmd *scmnd;
71749+ enum srpt_command_state state;
71750+
71751+ TRACE_ENTRY();
71752+
71753+ BUG_ON(!ioctx);
71754+
71755+ /*
71756+ * If the command is in a state where the SCST core is waiting for the
71757+ * ib_srpt driver, change the state to the next state. Changing the
71758+ * state of the command from SRPT_STATE_NEED_DATA to SRPT_STATE_DATA_IN
71759+ * ensures that srpt_xmit_response() will call this function a second
71760+ * time.
71761+ */
71762+ state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA,
71763+ SRPT_STATE_DATA_IN);
71764+ if (state != SRPT_STATE_NEED_DATA) {
71765+ state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_DATA_IN,
71766+ SRPT_STATE_DONE);
71767+ if (state != SRPT_STATE_DATA_IN) {
71768+ state = srpt_test_and_set_cmd_state(ioctx,
71769+ SRPT_STATE_CMD_RSP_SENT, SRPT_STATE_DONE);
71770+ }
71771+ }
71772+ if (state == SRPT_STATE_DONE)
71773+ goto out;
71774+
71775+ scmnd = ioctx->scmnd;
71776+ WARN_ON(!scmnd);
71777+ if (!scmnd)
71778+ goto out;
71779+
71780+ WARN_ON(ioctx != scst_cmd_get_tgt_priv(scmnd));
71781+
71782+ TRACE_DBG("Aborting cmd with state %d and tag %lld",
71783+ state, scst_cmd_get_tag(scmnd));
71784+
71785+ switch (state) {
71786+ case SRPT_STATE_NEW:
71787+ case SRPT_STATE_DATA_IN:
71788+ /*
71789+ * Do nothing - defer abort processing until
71790+ * srpt_xmit_response() is invoked.
71791+ */
71792+ WARN_ON(!scst_cmd_aborted(scmnd));
71793+ break;
71794+ case SRPT_STATE_NEED_DATA:
71795+ /* SCST_DATA_WRITE - RDMA read error or RDMA read timeout. */
71796+ scst_rx_data(ioctx->scmnd, SCST_RX_STATUS_ERROR, context);
71797+ break;
71798+ case SRPT_STATE_CMD_RSP_SENT:
71799+ /*
71800+ * SRP_RSP sending failed or the SRP_RSP send completion has
71801+ * not been received in time.
71802+ */
71803+ srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx);
71804+ srpt_put_send_ioctx(ioctx);
71805+ scst_set_delivery_status(scmnd, SCST_CMD_DELIVERY_ABORTED);
71806+ scst_tgt_cmd_done(scmnd, context);
71807+ break;
71808+ case SRPT_STATE_MGMT_RSP_SENT:
71809+ /*
71810+ * Management command response sending failed. This state is
71811+ * never reached since there is no scmnd associated with
71812+ * management commands. Note: the SCST core frees these
71813+ * commands immediately after srpt_tsk_mgmt_done() returned.
71814+ */
71815+ WARN_ON("ERROR: unexpected command state");
71816+ break;
71817+ default:
71818+ WARN_ON("ERROR: unexpected command state");
71819+ break;
71820+ }
71821+
71822+out:
71823+ ;
71824+
71825+ TRACE_EXIT();
71826+}
71827+
71828+/**
71829+ * srpt_handle_send_err_comp() - Process an IB_WC_SEND error completion.
71830+ */
71831+static void srpt_handle_send_err_comp(struct srpt_rdma_ch *ch, u64 wr_id,
71832+ enum scst_exec_context context)
71833+{
71834+ struct srpt_send_ioctx *ioctx;
71835+ enum srpt_command_state state;
71836+ struct scst_cmd *scmnd;
71837+ u32 index;
71838+
71839+ atomic_inc(&ch->sq_wr_avail);
71840+
71841+ index = idx_from_wr_id(wr_id);
71842+ ioctx = ch->ioctx_ring[index];
71843+ state = srpt_get_cmd_state(ioctx);
71844+ scmnd = ioctx->scmnd;
71845+
71846+ EXTRACHECKS_WARN_ON(state != SRPT_STATE_CMD_RSP_SENT
71847+ && state != SRPT_STATE_MGMT_RSP_SENT
71848+ && state != SRPT_STATE_NEED_DATA
71849+ && state != SRPT_STATE_DONE);
71850+
71851+ /* If SRP_RSP sending failed, undo the ch->req_lim change. */
71852+ if (state == SRPT_STATE_CMD_RSP_SENT
71853+ || state == SRPT_STATE_MGMT_RSP_SENT)
71854+ atomic_dec(&ch->req_lim);
71855+ if (state != SRPT_STATE_DONE) {
71856+ if (scmnd)
71857+ srpt_abort_scst_cmd(ioctx, context);
71858+ else {
71859+ srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
71860+ srpt_put_send_ioctx(ioctx);
71861+ }
71862+ } else
71863+ PRINT_ERROR("Received more than one IB error completion"
71864+ " for wr_id = %u.", (unsigned)index);
71865+}
71866+
71867+/**
71868+ * srpt_handle_send_comp() - Process an IB send completion notification.
71869+ */
71870+static void srpt_handle_send_comp(struct srpt_rdma_ch *ch,
71871+ struct srpt_send_ioctx *ioctx,
71872+ enum scst_exec_context context)
71873+{
71874+ enum srpt_command_state state;
71875+
71876+ atomic_inc(&ch->sq_wr_avail);
71877+
71878+ state = srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
71879+
71880+ EXTRACHECKS_WARN_ON(state != SRPT_STATE_CMD_RSP_SENT
71881+ && state != SRPT_STATE_MGMT_RSP_SENT
71882+ && state != SRPT_STATE_DONE);
71883+
71884+ if (state != SRPT_STATE_DONE) {
71885+ struct scst_cmd *scmnd;
71886+
71887+ scmnd = ioctx->scmnd;
71888+ EXTRACHECKS_WARN_ON((state == SRPT_STATE_MGMT_RSP_SENT)
71889+ != (scmnd == NULL));
71890+ if (scmnd) {
71891+ srpt_unmap_sg_to_ib_sge(ch, ioctx);
71892+ srpt_put_send_ioctx(ioctx);
71893+ scst_tgt_cmd_done(scmnd, context);
71894+ } else
71895+ srpt_put_send_ioctx(ioctx);
71896+ } else {
71897+ PRINT_ERROR("IB completion has been received too late for"
71898+ " wr_id = %u.", ioctx->ioctx.index);
71899+ }
71900+}
71901+
71902+/**
71903+ * srpt_handle_rdma_comp() - Process an IB RDMA completion notification.
71904+ */
71905+static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
71906+ struct srpt_send_ioctx *ioctx,
71907+ enum scst_exec_context context)
71908+{
71909+ enum srpt_command_state state;
71910+ struct scst_cmd *scmnd;
71911+
71912+ EXTRACHECKS_WARN_ON(ioctx->n_rdma <= 0);
71913+ atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);
71914+
71915+ scmnd = ioctx->scmnd;
71916+ if (scmnd) {
71917+ state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA,
71918+ SRPT_STATE_DATA_IN);
71919+ if (state == SRPT_STATE_NEED_DATA)
71920+ scst_rx_data(ioctx->scmnd, SCST_RX_STATUS_SUCCESS,
71921+ context);
71922+ else
71923+ PRINT_ERROR("%s[%d]: wrong state = %d", __func__,
71924+ __LINE__, state);
71925+ } else
71926+ PRINT_ERROR("%s[%d]: scmnd == NULL", __func__, __LINE__);
71927+}
71928+
71929+/**
71930+ * srpt_handle_rdma_err_comp() - Process an IB RDMA error completion.
71931+ */
71932+static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch,
71933+ struct srpt_send_ioctx *ioctx,
71934+ u8 opcode,
71935+ enum scst_exec_context context)
71936+{
71937+ struct scst_cmd *scmnd;
71938+ enum srpt_command_state state;
71939+
71940+ scmnd = ioctx->scmnd;
71941+ state = srpt_get_cmd_state(ioctx);
71942+ if (scmnd) {
71943+ switch (opcode) {
71944+ case IB_WC_RDMA_READ:
71945+ if (ioctx->n_rdma <= 0) {
71946+ PRINT_ERROR("Received invalid RDMA read error"
71947+ " completion with idx %d",
71948+ ioctx->ioctx.index);
71949+ break;
71950+ }
71951+ atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);
71952+ if (state == SRPT_STATE_NEED_DATA)
71953+ srpt_abort_scst_cmd(ioctx, context);
71954+ else
71955+ PRINT_ERROR("%s[%d]: wrong state = %d",
71956+ __func__, __LINE__, state);
71957+ break;
71958+ case IB_WC_RDMA_WRITE:
71959+ scst_set_delivery_status(scmnd,
71960+ SCST_CMD_DELIVERY_ABORTED);
71961+ break;
71962+ default:
71963+ PRINT_ERROR("%s[%d]: opcode = %u", __func__, __LINE__,
71964+ opcode);
71965+ break;
71966+ }
71967+ } else
71968+ PRINT_ERROR("%s[%d]: scmnd == NULL", __func__, __LINE__);
71969+}
71970+
71971+/**
71972+ * srpt_build_cmd_rsp() - Build an SRP_RSP response.
71973+ * @ch: RDMA channel through which the request has been received.
71974+ * @ioctx: I/O context associated with the SRP_CMD request. The response will
71975+ * be built in the buffer ioctx->buf points at and hence this function will
71976+ * overwrite the request data.
71977+ * @tag: tag of the request for which this response is being generated.
71978+ * @status: value for the STATUS field of the SRP_RSP information unit.
71979+ * @sense_data: pointer to sense data to be included in the response.
71980+ * @sense_data_len: length in bytes of the sense data.
71981+ *
71982+ * Returns the size in bytes of the SRP_RSP response.
71983+ *
71984+ * An SRP_RSP response contains a SCSI status or service response. See also
71985+ * section 6.9 in the SRP r16a document for the format of an SRP_RSP
71986+ * response. See also SPC-2 for more information about sense data.
71987+ */
71988+static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
71989+ struct srpt_send_ioctx *ioctx, u64 tag,
71990+ int status, const u8 *sense_data,
71991+ int sense_data_len)
71992+{
71993+ struct srp_rsp *srp_rsp;
71994+ int max_sense_len;
71995+
71996+ /*
71997+ * The lowest bit of all SAM-3 status codes is zero (see also
71998+ * paragraph 5.3 in SAM-3).
71999+ */
72000+ EXTRACHECKS_WARN_ON(status & 1);
72001+
72002+ srp_rsp = ioctx->ioctx.buf;
72003+ BUG_ON(!srp_rsp);
72004+ memset(srp_rsp, 0, sizeof *srp_rsp);
72005+
72006+ srp_rsp->opcode = SRP_RSP;
72007+ srp_rsp->req_lim_delta = __constant_cpu_to_be32(1
72008+ + atomic_xchg(&ch->req_lim_delta, 0));
72009+ srp_rsp->tag = tag;
72010+ srp_rsp->status = status;
72011+
72012+ if (!SCST_SENSE_VALID(sense_data))
72013+ sense_data_len = 0;
72014+ else {
72015+ BUILD_BUG_ON(MIN_MAX_RSP_SIZE <= sizeof(*srp_rsp));
72016+ max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp);
72017+ if (sense_data_len > max_sense_len) {
72018+ PRINT_WARNING("truncated sense data from %d to %d"
72019+ " bytes", sense_data_len, max_sense_len);
72020+ sense_data_len = max_sense_len;
72021+ }
72022+
72023+ srp_rsp->flags |= SRP_RSP_FLAG_SNSVALID;
72024+ srp_rsp->sense_data_len = cpu_to_be32(sense_data_len);
72025+ memcpy(srp_rsp + 1, sense_data, sense_data_len);
72026+ }
72027+
72028+ return sizeof(*srp_rsp) + sense_data_len;
72029+}
72030+
72031+/**
72032+ * srpt_build_tskmgmt_rsp() - Build a task management response.
72033+ * @ch: RDMA channel through which the request has been received.
72034+ * @ioctx: I/O context in which the SRP_RSP response will be built.
72035+ * @rsp_code: RSP_CODE that will be stored in the response.
72036+ * @tag: Tag of the request for which this response is being generated.
72037+ *
72038+ * Returns the size in bytes of the SRP_RSP response.
72039+ *
72040+ * An SRP_RSP response contains a SCSI status or service response. See also
72041+ * section 6.9 in the SRP r16a document for the format of an SRP_RSP
72042+ * response.
72043+ */
72044+static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
72045+ struct srpt_send_ioctx *ioctx,
72046+ u8 rsp_code, u64 tag)
72047+{
72048+ struct srp_rsp *srp_rsp;
72049+ int resp_data_len;
72050+ int resp_len;
72051+
72052+ resp_data_len = (rsp_code == SRP_TSK_MGMT_SUCCESS) ? 0 : 4;
72053+ resp_len = sizeof(*srp_rsp) + resp_data_len;
72054+
72055+ srp_rsp = ioctx->ioctx.buf;
72056+ BUG_ON(!srp_rsp);
72057+ memset(srp_rsp, 0, sizeof *srp_rsp);
72058+
72059+ srp_rsp->opcode = SRP_RSP;
72060+ srp_rsp->req_lim_delta = __constant_cpu_to_be32(1
72061+ + atomic_xchg(&ch->req_lim_delta, 0));
72062+ srp_rsp->tag = tag;
72063+
72064+ if (rsp_code != SRP_TSK_MGMT_SUCCESS) {
72065+ srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
72066+ srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);
72067+ srp_rsp->data[3] = rsp_code;
72068+ }
72069+
72070+ return resp_len;
72071+}
72072+
72073+/**
72074+ * srpt_handle_cmd() - Process SRP_CMD.
72075+ */
72076+static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
72077+ struct srpt_recv_ioctx *recv_ioctx,
72078+ struct srpt_send_ioctx *send_ioctx,
72079+ enum scst_exec_context context)
72080+{
72081+ struct scst_cmd *scmnd;
72082+ struct srp_cmd *srp_cmd;
72083+ scst_data_direction dir;
72084+ u64 data_len;
72085+ int ret;
72086+ int atomic;
72087+
72088+ BUG_ON(!send_ioctx);
72089+
72090+ srp_cmd = recv_ioctx->ioctx.buf;
72091+
72092+ atomic = context == SCST_CONTEXT_TASKLET ? SCST_ATOMIC
72093+ : SCST_NON_ATOMIC;
72094+ scmnd = scst_rx_cmd(ch->scst_sess, (u8 *) &srp_cmd->lun,
72095+ sizeof srp_cmd->lun, srp_cmd->cdb,
72096+ sizeof srp_cmd->cdb, atomic);
72097+ if (!scmnd) {
72098+ PRINT_ERROR("0x%llx: allocation of an SCST command failed",
72099+ srp_cmd->tag);
72100+ goto err;
72101+ }
72102+
72103+ send_ioctx->scmnd = scmnd;
72104+
72105+ ret = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len);
72106+ if (ret) {
72107+ PRINT_ERROR("0x%llx: parsing SRP descriptor table failed.",
72108+ srp_cmd->tag);
72109+ scst_set_cmd_error(scmnd,
72110+ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
72111+ }
72112+
72113+ switch (srp_cmd->task_attr) {
72114+ case SRP_CMD_HEAD_OF_Q:
72115+ scst_cmd_set_queue_type(scmnd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
72116+ break;
72117+ case SRP_CMD_ORDERED_Q:
72118+ scst_cmd_set_queue_type(scmnd, SCST_CMD_QUEUE_ORDERED);
72119+ break;
72120+ case SRP_CMD_SIMPLE_Q:
72121+ scst_cmd_set_queue_type(scmnd, SCST_CMD_QUEUE_SIMPLE);
72122+ break;
72123+ case SRP_CMD_ACA:
72124+ scst_cmd_set_queue_type(scmnd, SCST_CMD_QUEUE_ACA);
72125+ break;
72126+ default:
72127+ scst_cmd_set_queue_type(scmnd, SCST_CMD_QUEUE_ORDERED);
72128+ break;
72129+ }
72130+
72131+ scst_cmd_set_tag(scmnd, srp_cmd->tag);
72132+ scst_cmd_set_tgt_priv(scmnd, send_ioctx);
72133+ scst_cmd_set_expected(scmnd, dir, data_len);
72134+ scst_cmd_init_done(scmnd, context);
72135+
72136+ return 0;
72137+
72138+err:
72139+ srpt_put_send_ioctx(send_ioctx);
72140+ return -1;
72141+}
72142+
72143+/**
72144+ * srpt_handle_tsk_mgmt() - Process an SRP_TSK_MGMT information unit.
72145+ *
72146+ * Returns SCST_MGMT_STATUS_SUCCESS upon success.
72147+ *
72148+ * Each task management function is performed by calling one of the
72149+ * scst_rx_mgmt_fn*() functions. These functions will either report failure
72150+ * or process the task management function asynchronously. The function
72151+ * srpt_tsk_mgmt_done() will be called by the SCST core upon completion of the
72152+ * task management function. When srpt_handle_tsk_mgmt() reports failure
72153+ * (i.e. returns -1) a response will have been built in ioctx->buf. This
72154+ * information unit has to be sent back by the caller.
72155+ *
72156+ * For more information about SRP_TSK_MGMT information units, see also section
72157+ * 6.7 in the SRP r16a document.
72158+ */
72159+static u8 srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
72160+ struct srpt_recv_ioctx *recv_ioctx,
72161+ struct srpt_send_ioctx *send_ioctx)
72162+{
72163+ struct srp_tsk_mgmt *srp_tsk;
72164+ struct srpt_mgmt_ioctx *mgmt_ioctx;
72165+ int ret;
72166+
72167+ ret = SCST_MGMT_STATUS_FAILED;
72168+
72169+ BUG_ON(!send_ioctx);
72170+
72171+ srp_tsk = recv_ioctx->ioctx.buf;
72172+
72173+ TRACE_DBG("recv_tsk_mgmt= %d for task_tag= %lld"
72174+ " using tag= %lld cm_id= %p sess= %p",
72175+ srp_tsk->tsk_mgmt_func, srp_tsk->task_tag, srp_tsk->tag,
72176+ ch->cm_id, ch->scst_sess);
72177+
72178+ mgmt_ioctx = kmalloc(sizeof *mgmt_ioctx, GFP_ATOMIC);
72179+ if (!mgmt_ioctx) {
72180+ PRINT_ERROR("tag 0x%llx: memory allocation for task management"
72181+ " function failed. Ignoring task management request"
72182+ " (func %d).", srp_tsk->task_tag,
72183+ srp_tsk->tsk_mgmt_func);
72184+ goto err;
72185+ }
72186+
72187+ mgmt_ioctx->ioctx = send_ioctx;
72188+ BUG_ON(mgmt_ioctx->ioctx->ch != ch);
72189+ mgmt_ioctx->tag = srp_tsk->tag;
72190+
72191+ switch (srp_tsk->tsk_mgmt_func) {
72192+ case SRP_TSK_ABORT_TASK:
72193+ TRACE_DBG("%s", "Processing SRP_TSK_ABORT_TASK");
72194+ ret = scst_rx_mgmt_fn_tag(ch->scst_sess,
72195+ SCST_ABORT_TASK,
72196+ srp_tsk->task_tag,
72197+ SCST_ATOMIC, mgmt_ioctx);
72198+ break;
72199+ case SRP_TSK_ABORT_TASK_SET:
72200+ TRACE_DBG("%s", "Processing SRP_TSK_ABORT_TASK_SET");
72201+ ret = scst_rx_mgmt_fn_lun(ch->scst_sess,
72202+ SCST_ABORT_TASK_SET,
72203+ (u8 *) &srp_tsk->lun,
72204+ sizeof srp_tsk->lun,
72205+ SCST_ATOMIC, mgmt_ioctx);
72206+ break;
72207+ case SRP_TSK_CLEAR_TASK_SET:
72208+ TRACE_DBG("%s", "Processing SRP_TSK_CLEAR_TASK_SET");
72209+ ret = scst_rx_mgmt_fn_lun(ch->scst_sess,
72210+ SCST_CLEAR_TASK_SET,
72211+ (u8 *) &srp_tsk->lun,
72212+ sizeof srp_tsk->lun,
72213+ SCST_ATOMIC, mgmt_ioctx);
72214+ break;
72215+ case SRP_TSK_LUN_RESET:
72216+ TRACE_DBG("%s", "Processing SRP_TSK_LUN_RESET");
72217+ ret = scst_rx_mgmt_fn_lun(ch->scst_sess,
72218+ SCST_LUN_RESET,
72219+ (u8 *) &srp_tsk->lun,
72220+ sizeof srp_tsk->lun,
72221+ SCST_ATOMIC, mgmt_ioctx);
72222+ break;
72223+ case SRP_TSK_CLEAR_ACA:
72224+ TRACE_DBG("%s", "Processing SRP_TSK_CLEAR_ACA");
72225+ ret = scst_rx_mgmt_fn_lun(ch->scst_sess,
72226+ SCST_CLEAR_ACA,
72227+ (u8 *) &srp_tsk->lun,
72228+ sizeof srp_tsk->lun,
72229+ SCST_ATOMIC, mgmt_ioctx);
72230+ break;
72231+ default:
72232+ TRACE_DBG("%s", "Unsupported task management function.");
72233+ ret = SCST_MGMT_STATUS_FN_NOT_SUPPORTED;
72234+ }
72235+
72236+ if (ret != SCST_MGMT_STATUS_SUCCESS)
72237+ goto err;
72238+ return ret;
72239+
72240+err:
72241+ kfree(mgmt_ioctx);
72242+ return ret;
72243+}
72244+
72245+static u8 scst_to_srp_tsk_mgmt_status(const int scst_mgmt_status)
72246+{
72247+ switch (scst_mgmt_status) {
72248+ case SCST_MGMT_STATUS_SUCCESS:
72249+ return SRP_TSK_MGMT_SUCCESS;
72250+ case SCST_MGMT_STATUS_FN_NOT_SUPPORTED:
72251+ return SRP_TSK_MGMT_FUNC_NOT_SUPP;
72252+ case SCST_MGMT_STATUS_TASK_NOT_EXIST:
72253+ case SCST_MGMT_STATUS_LUN_NOT_EXIST:
72254+ case SCST_MGMT_STATUS_REJECTED:
72255+ case SCST_MGMT_STATUS_FAILED:
72256+ default:
72257+ break;
72258+ }
72259+ return SRP_TSK_MGMT_FAILED;
72260+}
72261+
72262+/**
72263+ * srpt_handle_new_iu() - Process a newly received information unit.
72264+ * @ch: RDMA channel through which the information unit has been received.
72265+ * @ioctx: SRPT I/O context associated with the information unit.
72266+ */
72267+static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
72268+ struct srpt_recv_ioctx *recv_ioctx,
72269+ struct srpt_send_ioctx *send_ioctx,
72270+ enum scst_exec_context context)
72271+{
72272+ struct srp_cmd *srp_cmd;
72273+ enum rdma_ch_state ch_state;
72274+
72275+ BUG_ON(!ch);
72276+ BUG_ON(!recv_ioctx);
72277+
72278+ ib_dma_sync_single_for_cpu(ch->sport->sdev->device,
72279+ recv_ioctx->ioctx.dma, srp_max_req_size,
72280+ DMA_FROM_DEVICE);
72281+
72282+ ch_state = atomic_read(&ch->state);
72283+ srp_cmd = recv_ioctx->ioctx.buf;
72284+ if (unlikely(ch_state == RDMA_CHANNEL_CONNECTING)) {
72285+ list_add_tail(&recv_ioctx->wait_list, &ch->cmd_wait_list);
72286+ goto out;
72287+ }
72288+
72289+ if (unlikely(ch_state == RDMA_CHANNEL_DISCONNECTING))
72290+ goto post_recv;
72291+
72292+ if (srp_cmd->opcode == SRP_CMD || srp_cmd->opcode == SRP_TSK_MGMT) {
72293+ if (!send_ioctx)
72294+ send_ioctx = srpt_get_send_ioctx(ch);
72295+ if (unlikely(!send_ioctx)) {
72296+ list_add_tail(&recv_ioctx->wait_list,
72297+ &ch->cmd_wait_list);
72298+ goto out;
72299+ }
72300+ }
72301+
72302+ WARN_ON(ch_state != RDMA_CHANNEL_LIVE);
72303+
72304+ switch (srp_cmd->opcode) {
72305+ case SRP_CMD:
72306+ srpt_handle_cmd(ch, recv_ioctx, send_ioctx, context);
72307+ break;
72308+ case SRP_TSK_MGMT:
72309+ srpt_handle_tsk_mgmt(ch, recv_ioctx, send_ioctx);
72310+ break;
72311+ case SRP_I_LOGOUT:
72312+ PRINT_ERROR("%s", "Not yet implemented: SRP_I_LOGOUT");
72313+ break;
72314+ case SRP_CRED_RSP:
72315+ TRACE_DBG("%s", "received SRP_CRED_RSP");
72316+ break;
72317+ case SRP_AER_RSP:
72318+ TRACE_DBG("%s", "received SRP_AER_RSP");
72319+ break;
72320+ case SRP_RSP:
72321+ PRINT_ERROR("%s", "Received SRP_RSP");
72322+ break;
72323+ default:
72324+ PRINT_ERROR("received IU with unknown opcode 0x%x",
72325+ srp_cmd->opcode);
72326+ break;
72327+ }
72328+
72329+post_recv:
72330+ srpt_post_recv(ch->sport->sdev, recv_ioctx);
72331+out:
72332+ return;
72333+}
72334+
72335+static void srpt_process_rcv_completion(struct ib_cq *cq,
72336+ struct srpt_rdma_ch *ch,
72337+ enum scst_exec_context context,
72338+ struct ib_wc *wc)
72339+{
72340+ struct srpt_device *sdev = ch->sport->sdev;
72341+ struct srpt_recv_ioctx *ioctx;
72342+ u32 index;
72343+
72344+ index = idx_from_wr_id(wc->wr_id);
72345+ if (wc->status == IB_WC_SUCCESS) {
72346+ int req_lim;
72347+
72348+ req_lim = atomic_dec_return(&ch->req_lim);
72349+ if (unlikely(req_lim < 0))
72350+ PRINT_ERROR("req_lim = %d < 0", req_lim);
72351+ ioctx = sdev->ioctx_ring[index];
72352+ srpt_handle_new_iu(ch, ioctx, NULL, context);
72353+ } else {
72354+ PRINT_INFO("receiving failed for idx %u with status %d",
72355+ index, wc->status);
72356+ }
72357+}
72358+
72359+/**
72360+ * srpt_process_send_completion() - Process an IB send completion.
72361+ *
72362+ * Note: Although this has not yet been observed during tests, at least in
72363+ * theory it is possible that the srpt_get_send_ioctx() call invoked by
72364+ * srpt_handle_new_iu() fails. This is possible because the req_lim_delta
72365+ * value in each response is set to one, and it is possible that this response
72366+ * makes the initiator send a new request before the send completion for that
72367+ * response has been processed. This could e.g. happen if the call to
72368+ * srpt_put_send_iotcx() is delayed because of a higher priority interrupt or
72369+ * if IB retransmission causes generation of the send completion to be
72370+ * delayed. Incoming information units for which srpt_get_send_ioctx() fails
72371+ * are queued on cmd_wait_list. The code below processes these delayed
72372+ * requests one at a time.
72373+ */
72374+static void srpt_process_send_completion(struct ib_cq *cq,
72375+ struct srpt_rdma_ch *ch,
72376+ enum scst_exec_context context,
72377+ struct ib_wc *wc)
72378+{
72379+ struct srpt_send_ioctx *send_ioctx;
72380+ uint32_t index;
72381+ u8 opcode;
72382+
72383+ index = idx_from_wr_id(wc->wr_id);
72384+ opcode = opcode_from_wr_id(wc->wr_id);
72385+ send_ioctx = ch->ioctx_ring[index];
72386+ if (wc->status == IB_WC_SUCCESS) {
72387+ if (opcode == IB_WC_SEND)
72388+ srpt_handle_send_comp(ch, send_ioctx, context);
72389+ else {
72390+ EXTRACHECKS_WARN_ON(wc->opcode != IB_WC_RDMA_READ);
72391+ srpt_handle_rdma_comp(ch, send_ioctx, context);
72392+ }
72393+ } else {
72394+ if (opcode == IB_WC_SEND) {
72395+ PRINT_INFO("sending response for idx %u failed with"
72396+ " status %d", index, wc->status);
72397+ srpt_handle_send_err_comp(ch, wc->wr_id, context);
72398+ } else {
72399+ PRINT_INFO("RDMA %s for idx %u failed with status %d",
72400+ opcode == IB_WC_RDMA_READ ? "read"
72401+ : opcode == IB_WC_RDMA_WRITE ? "write"
72402+ : "???", index, wc->status);
72403+ srpt_handle_rdma_err_comp(ch, send_ioctx, opcode,
72404+ context);
72405+ }
72406+ }
72407+
72408+ while (unlikely(opcode == IB_WC_SEND
72409+ && !list_empty(&ch->cmd_wait_list)
72410+ && atomic_read(&ch->state) == RDMA_CHANNEL_LIVE
72411+ && (send_ioctx = srpt_get_send_ioctx(ch)) != NULL)) {
72412+ struct srpt_recv_ioctx *recv_ioctx;
72413+
72414+ recv_ioctx = list_first_entry(&ch->cmd_wait_list,
72415+ struct srpt_recv_ioctx,
72416+ wait_list);
72417+ list_del(&recv_ioctx->wait_list);
72418+ srpt_handle_new_iu(ch, recv_ioctx, send_ioctx, context);
72419+ }
72420+}
72421+
72422+static void srpt_process_completion(struct ib_cq *cq,
72423+ struct srpt_rdma_ch *ch,
72424+ enum scst_exec_context context)
72425+{
72426+ struct ib_wc *const wc = ch->wc;
72427+ int i, n;
72428+
72429+ EXTRACHECKS_WARN_ON(cq != ch->cq);
72430+
72431+ ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
72432+ while ((n = ib_poll_cq(cq, ARRAY_SIZE(ch->wc), wc)) > 0) {
72433+ for (i = 0; i < n; i++) {
72434+ if (opcode_from_wr_id(wc[i].wr_id) & IB_WC_RECV)
72435+ srpt_process_rcv_completion(cq, ch, context,
72436+ &wc[i]);
72437+ else
72438+ srpt_process_send_completion(cq, ch, context,
72439+ &wc[i]);
72440+ }
72441+ }
72442+}
72443+
72444+/**
72445+ * srpt_completion() - IB completion queue callback function.
72446+ *
72447+ * Notes:
72448+ * - It is guaranteed that a completion handler will never be invoked
72449+ * concurrently on two different CPUs for the same completion queue. See also
72450+ * Documentation/infiniband/core_locking.txt and the implementation of
72451+ * handle_edge_irq() in kernel/irq/chip.c.
72452+ * - When threaded IRQs are enabled, completion handlers are invoked in thread
72453+ * context instead of interrupt context.
72454+ */
72455+static void srpt_completion(struct ib_cq *cq, void *ctx)
72456+{
72457+ struct srpt_rdma_ch *ch = ctx;
72458+
72459+ BUG_ON(!ch);
72460+ atomic_inc(&ch->processing_compl);
72461+ switch (thread) {
72462+ case MODE_IB_COMPLETION_IN_THREAD:
72463+ wake_up_interruptible(&ch->wait_queue);
72464+ break;
72465+ case MODE_IB_COMPLETION_IN_SIRQ:
72466+ srpt_process_completion(cq, ch, SCST_CONTEXT_THREAD);
72467+ break;
72468+ case MODE_ALL_IN_SIRQ:
72469+ srpt_process_completion(cq, ch, SCST_CONTEXT_TASKLET);
72470+ break;
72471+ }
72472+ atomic_dec(&ch->processing_compl);
72473+}
72474+
72475+static int srpt_compl_thread(void *arg)
72476+{
72477+ struct srpt_rdma_ch *ch;
72478+
72479+ /* Hibernation / freezing of the SRPT kernel thread is not supported. */
72480+ current->flags |= PF_NOFREEZE;
72481+
72482+ ch = arg;
72483+ BUG_ON(!ch);
72484+ PRINT_INFO("Session %s: kernel thread %s (PID %d) started",
72485+ ch->sess_name, ch->thread->comm, current->pid);
72486+ while (!kthread_should_stop()) {
72487+ wait_event_interruptible(ch->wait_queue,
72488+ (srpt_process_completion(ch->cq, ch,
72489+ SCST_CONTEXT_THREAD),
72490+ kthread_should_stop()));
72491+ }
72492+ PRINT_INFO("Session %s: kernel thread %s (PID %d) stopped",
72493+ ch->sess_name, ch->thread->comm, current->pid);
72494+ return 0;
72495+}
72496+
72497+/**
72498+ * srpt_create_ch_ib() - Create receive and send completion queues.
72499+ */
72500+static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
72501+{
72502+ struct ib_qp_init_attr *qp_init;
72503+ struct srpt_device *sdev = ch->sport->sdev;
72504+ int ret;
72505+
72506+ EXTRACHECKS_WARN_ON(ch->rq_size < 1);
72507+
72508+ ret = -ENOMEM;
72509+ qp_init = kzalloc(sizeof *qp_init, GFP_KERNEL);
72510+ if (!qp_init)
72511+ goto out;
72512+
72513+ ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch,
72514+ ch->rq_size + srpt_sq_size, 0);
72515+ if (IS_ERR(ch->cq)) {
72516+ ret = PTR_ERR(ch->cq);
72517+ PRINT_ERROR("failed to create CQ cqe= %d ret= %d",
72518+ ch->rq_size + srpt_sq_size, ret);
72519+ goto out;
72520+ }
72521+
72522+ qp_init->qp_context = (void *)ch;
72523+ qp_init->event_handler
72524+ = (void(*)(struct ib_event *, void*))srpt_qp_event;
72525+ qp_init->send_cq = ch->cq;
72526+ qp_init->recv_cq = ch->cq;
72527+ qp_init->srq = sdev->srq;
72528+ qp_init->sq_sig_type = IB_SIGNAL_REQ_WR;
72529+ qp_init->qp_type = IB_QPT_RC;
72530+ qp_init->cap.max_send_wr = srpt_sq_size;
72531+ qp_init->cap.max_send_sge = SRPT_DEF_SG_PER_WQE;
72532+
72533+ ch->qp = ib_create_qp(sdev->pd, qp_init);
72534+ if (IS_ERR(ch->qp)) {
72535+ ret = PTR_ERR(ch->qp);
72536+ PRINT_ERROR("failed to create_qp ret= %d", ret);
72537+ goto err_destroy_cq;
72538+ }
72539+
72540+ atomic_set(&ch->sq_wr_avail, qp_init->cap.max_send_wr);
72541+
72542+ TRACE_DBG("%s: max_cqe= %d max_sge= %d sq_size = %d"
72543+ " cm_id= %p", __func__, ch->cq->cqe,
72544+ qp_init->cap.max_send_sge, qp_init->cap.max_send_wr,
72545+ ch->cm_id);
72546+
72547+ ret = srpt_init_ch_qp(ch, ch->qp);
72548+ if (ret)
72549+ goto err_destroy_qp;
72550+
72551+ if (thread == MODE_IB_COMPLETION_IN_THREAD) {
72552+ init_waitqueue_head(&ch->wait_queue);
72553+
72554+ TRACE_DBG("creating IB completion thread for session %s",
72555+ ch->sess_name);
72556+
72557+ ch->thread = kthread_run(srpt_compl_thread, ch,
72558+ "ib_srpt_compl");
72559+ if (IS_ERR(ch->thread)) {
72560+ PRINT_ERROR("failed to create kernel thread %ld",
72561+ PTR_ERR(ch->thread));
72562+ ch->thread = NULL;
72563+ goto err_destroy_qp;
72564+ }
72565+ } else
72566+ ib_req_notify_cq(ch->cq, IB_CQ_NEXT_COMP);
72567+
72568+out:
72569+ kfree(qp_init);
72570+ return ret;
72571+
72572+err_destroy_qp:
72573+ ib_destroy_qp(ch->qp);
72574+err_destroy_cq:
72575+ ib_destroy_cq(ch->cq);
72576+ goto out;
72577+}
72578+
72579+static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch)
72580+{
72581+ if (ch->thread)
72582+ kthread_stop(ch->thread);
72583+
72584+ ib_destroy_qp(ch->qp);
72585+ ib_destroy_cq(ch->cq);
72586+}
72587+
72588+/**
72589+ * srpt_unregister_channel() - Start RDMA channel disconnection.
72590+ *
72591+ * Note: The caller must hold ch->sdev->spinlock.
72592+ */
72593+static void srpt_unregister_channel(struct srpt_rdma_ch *ch)
72594+ __acquires(&ch->sport->sdev->spinlock)
72595+ __releases(&ch->sport->sdev->spinlock)
72596+{
72597+ struct srpt_device *sdev;
72598+ struct ib_qp_attr qp_attr;
72599+ int ret;
72600+
72601+ sdev = ch->sport->sdev;
72602+ list_del(&ch->list);
72603+ atomic_set(&ch->state, RDMA_CHANNEL_DISCONNECTING);
72604+ spin_unlock_irq(&sdev->spinlock);
72605+
72606+ qp_attr.qp_state = IB_QPS_ERR;
72607+ ret = ib_modify_qp(ch->qp, &qp_attr, IB_QP_STATE);
72608+ if (ret < 0)
72609+ PRINT_ERROR("Setting queue pair in error state failed: %d",
72610+ ret);
72611+
72612+ while (atomic_read(&ch->processing_compl))
72613+ ;
72614+
72615+ /*
72616+ * At this point it is guaranteed that no new commands will be sent to
72617+ * the SCST core for channel ch, which is a requirement for
72618+ * scst_unregister_session().
72619+ */
72620+
72621+ TRACE_DBG("unregistering session %p", ch->scst_sess);
72622+ scst_unregister_session(ch->scst_sess, 0, srpt_release_channel);
72623+ spin_lock_irq(&sdev->spinlock);
72624+}
72625+
72626+/**
72627+ * srpt_release_channel_by_cmid() - Release a channel.
72628+ * @cm_id: Pointer to the CM ID of the channel to be released.
72629+ *
72630+ * Note: Must be called from inside srpt_cm_handler to avoid a race between
72631+ * accessing sdev->spinlock and the call to kfree(sdev) in srpt_remove_one()
72632+ * (the caller of srpt_cm_handler holds the cm_id spinlock; srpt_remove_one()
72633+ * waits until all SCST sessions for the associated IB device have been
72634+ * unregistered and SCST session registration involves a call to
72635+ * ib_destroy_cm_id(), which locks the cm_id spinlock and hence waits until
72636+ * this function has finished).
72637+ */
72638+static void srpt_release_channel_by_cmid(struct ib_cm_id *cm_id)
72639+{
72640+ struct srpt_device *sdev;
72641+ struct srpt_rdma_ch *ch;
72642+
72643+ TRACE_ENTRY();
72644+
72645+ EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
72646+
72647+ sdev = cm_id->context;
72648+ BUG_ON(!sdev);
72649+ spin_lock_irq(&sdev->spinlock);
72650+ list_for_each_entry(ch, &sdev->rch_list, list) {
72651+ if (ch->cm_id == cm_id) {
72652+ srpt_unregister_channel(ch);
72653+ break;
72654+ }
72655+ }
72656+ spin_unlock_irq(&sdev->spinlock);
72657+
72658+ TRACE_EXIT();
72659+}
72660+
72661+/**
72662+ * srpt_find_channel() - Look up an RDMA channel.
72663+ * @cm_id: Pointer to the CM ID of the channel to be looked up.
72664+ *
72665+ * Return NULL if no matching RDMA channel has been found.
72666+ */
72667+static struct srpt_rdma_ch *srpt_find_channel(struct srpt_device *sdev,
72668+ struct ib_cm_id *cm_id)
72669+{
72670+ struct srpt_rdma_ch *ch;
72671+ bool found;
72672+
72673+ EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
72674+ BUG_ON(!sdev);
72675+
72676+ found = false;
72677+ spin_lock_irq(&sdev->spinlock);
72678+ list_for_each_entry(ch, &sdev->rch_list, list) {
72679+ if (ch->cm_id == cm_id) {
72680+ found = true;
72681+ break;
72682+ }
72683+ }
72684+ spin_unlock_irq(&sdev->spinlock);
72685+
72686+ return found ? ch : NULL;
72687+}
72688+
72689+/**
72690+ * srpt_release_channel() - Release all resources associated with an RDMA channel.
72691+ *
72692+ * Notes:
72693+ * - The caller must have removed the channel from the channel list before
72694+ * calling this function.
72695+ * - Must be called as a callback function via scst_unregister_session(). Never
72696+ * call this function directly because doing so would trigger several race
72697+ * conditions.
72698+ * - Do not access ch->sport or ch->sport->sdev in this function because the
72699+ * memory that was allocated for the sport and/or sdev data structures may
72700+ * already have been freed at the time this function is called.
72701+ */
72702+static void srpt_release_channel(struct scst_session *scst_sess)
72703+{
72704+ struct srpt_rdma_ch *ch;
72705+
72706+ TRACE_ENTRY();
72707+
72708+ ch = scst_sess_get_tgt_priv(scst_sess);
72709+ BUG_ON(!ch);
72710+ WARN_ON(atomic_read(&ch->state) != RDMA_CHANNEL_DISCONNECTING);
72711+
72712+ TRACE_DBG("destroying cm_id %p", ch->cm_id);
72713+ BUG_ON(!ch->cm_id);
72714+ ib_destroy_cm_id(ch->cm_id);
72715+
72716+ srpt_destroy_ch_ib(ch);
72717+
72718+ srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
72719+ ch->sport->sdev, ch->rq_size,
72720+ srp_max_rsp_size, DMA_TO_DEVICE);
72721+
72722+ kfree(ch);
72723+
72724+ TRACE_EXIT();
72725+}
72726+
72727+/**
72728+ * srpt_enable_target() - Allows to enable a target via sysfs.
72729+ */
72730+static int srpt_enable_target(struct scst_tgt *scst_tgt, bool enable)
72731+{
72732+ struct srpt_device *sdev = scst_tgt_get_tgt_priv(scst_tgt);
72733+
72734+ EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
72735+
72736+ if (!sdev)
72737+ return -ENOENT;
72738+
72739+ TRACE_DBG("%s target %s", enable ? "Enabling" : "Disabling",
72740+ sdev->device->name);
72741+
72742+ spin_lock_irq(&sdev->spinlock);
72743+ sdev->enabled = enable;
72744+ spin_unlock_irq(&sdev->spinlock);
72745+
72746+ return 0;
72747+}
72748+
72749+/**
72750+ * srpt_is_target_enabled() - Allows to query a targets status via sysfs.
72751+ */
72752+static bool srpt_is_target_enabled(struct scst_tgt *scst_tgt)
72753+{
72754+ struct srpt_device *sdev = scst_tgt_get_tgt_priv(scst_tgt);
72755+ bool res;
72756+
72757+ EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
72758+
72759+ if (!sdev)
72760+ return false;
72761+
72762+ spin_lock_irq(&sdev->spinlock);
72763+ res = sdev->enabled;
72764+ spin_unlock_irq(&sdev->spinlock);
72765+ return res;
72766+}
72767+
72768+/**
72769+ * srpt_cm_req_recv() - Process the event IB_CM_REQ_RECEIVED.
72770+ *
72771+ * Ownership of the cm_id is transferred to the SCST session if this functions
72772+ * returns zero. Otherwise the caller remains the owner of cm_id.
72773+ */
72774+static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
72775+ struct ib_cm_req_event_param *param,
72776+ void *private_data)
72777+{
72778+ struct srpt_device *sdev = cm_id->context;
72779+ struct srp_login_req *req;
72780+ struct srp_login_rsp *rsp;
72781+ struct srp_login_rej *rej;
72782+ struct ib_cm_rep_param *rep_param;
72783+ struct srpt_rdma_ch *ch, *tmp_ch;
72784+ u32 it_iu_len;
72785+ int i;
72786+ int ret = 0;
72787+
72788+ EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
72789+
72790+ if (WARN_ON(!sdev || !private_data))
72791+ return -EINVAL;
72792+
72793+ req = (struct srp_login_req *)private_data;
72794+
72795+ it_iu_len = be32_to_cpu(req->req_it_iu_len);
72796+
72797+ PRINT_INFO("Received SRP_LOGIN_REQ with"
72798+ " i_port_id 0x%llx:0x%llx, t_port_id 0x%llx:0x%llx and it_iu_len %d"
72799+ " on port %d (guid=0x%llx:0x%llx)",
72800+ be64_to_cpu(*(__be64 *)&req->initiator_port_id[0]),
72801+ be64_to_cpu(*(__be64 *)&req->initiator_port_id[8]),
72802+ be64_to_cpu(*(__be64 *)&req->target_port_id[0]),
72803+ be64_to_cpu(*(__be64 *)&req->target_port_id[8]),
72804+ it_iu_len,
72805+ param->port,
72806+ be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[0]),
72807+ be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[8]));
72808+
72809+ rsp = kzalloc(sizeof *rsp, GFP_KERNEL);
72810+ rej = kzalloc(sizeof *rej, GFP_KERNEL);
72811+ rep_param = kzalloc(sizeof *rep_param, GFP_KERNEL);
72812+
72813+ if (!rsp || !rej || !rep_param) {
72814+ ret = -ENOMEM;
72815+ goto out;
72816+ }
72817+
72818+ if (it_iu_len > srp_max_req_size || it_iu_len < 64) {
72819+ rej->reason = __constant_cpu_to_be32(
72820+ SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE);
72821+ ret = -EINVAL;
72822+ PRINT_ERROR("rejected SRP_LOGIN_REQ because its"
72823+ " length (%d bytes) is out of range (%d .. %d)",
72824+ it_iu_len, 64, srp_max_req_size);
72825+ goto reject;
72826+ }
72827+
72828+ if (!srpt_is_target_enabled(sdev->scst_tgt)) {
72829+ rej->reason = __constant_cpu_to_be32(
72830+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
72831+ ret = -EINVAL;
72832+ PRINT_ERROR("rejected SRP_LOGIN_REQ because the target %s"
72833+ " has not yet been enabled", sdev->device->name);
72834+ goto reject;
72835+ }
72836+
72837+ if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) {
72838+ rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN;
72839+
72840+ spin_lock_irq(&sdev->spinlock);
72841+
72842+ list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) {
72843+ if (!memcmp(ch->i_port_id, req->initiator_port_id, 16)
72844+ && !memcmp(ch->t_port_id, req->target_port_id, 16)
72845+ && param->port == ch->sport->port
72846+ && param->listen_id == ch->sport->sdev->cm_id
72847+ && ch->cm_id) {
72848+ enum rdma_ch_state prev_state;
72849+
72850+ /* found an existing channel */
72851+ TRACE_DBG("Found existing channel name= %s"
72852+ " cm_id= %p state= %d",
72853+ ch->sess_name, ch->cm_id,
72854+ atomic_read(&ch->state));
72855+
72856+ prev_state = atomic_xchg(&ch->state,
72857+ RDMA_CHANNEL_DISCONNECTING);
72858+ if (prev_state == RDMA_CHANNEL_CONNECTING)
72859+ srpt_unregister_channel(ch);
72860+
72861+ spin_unlock_irq(&sdev->spinlock);
72862+
72863+ rsp->rsp_flags =
72864+ SRP_LOGIN_RSP_MULTICHAN_TERMINATED;
72865+
72866+ if (prev_state == RDMA_CHANNEL_LIVE) {
72867+ ib_send_cm_dreq(ch->cm_id, NULL, 0);
72868+ PRINT_INFO("disconnected"
72869+ " session %s because a new"
72870+ " SRP_LOGIN_REQ has been received.",
72871+ ch->sess_name);
72872+ } else if (prev_state ==
72873+ RDMA_CHANNEL_CONNECTING) {
72874+ PRINT_ERROR("%s", "rejected"
72875+ " SRP_LOGIN_REQ because another login"
72876+ " request is being processed.");
72877+ ib_send_cm_rej(ch->cm_id,
72878+ IB_CM_REJ_NO_RESOURCES,
72879+ NULL, 0, NULL, 0);
72880+ }
72881+
72882+ spin_lock_irq(&sdev->spinlock);
72883+ }
72884+ }
72885+
72886+ spin_unlock_irq(&sdev->spinlock);
72887+
72888+ } else
72889+ rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED;
72890+
72891+ if (*(__be64 *)req->target_port_id != cpu_to_be64(srpt_service_guid)
72892+ || *(__be64 *)(req->target_port_id + 8) !=
72893+ cpu_to_be64(srpt_service_guid)) {
72894+ rej->reason = __constant_cpu_to_be32(
72895+ SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL);
72896+ ret = -ENOMEM;
72897+ PRINT_ERROR("%s", "rejected SRP_LOGIN_REQ because it"
72898+ " has an invalid target port identifier.");
72899+ goto reject;
72900+ }
72901+
72902+ ch = kzalloc(sizeof *ch, GFP_KERNEL);
72903+ if (!ch) {
72904+ rej->reason = __constant_cpu_to_be32(
72905+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
72906+ PRINT_ERROR("%s",
72907+ "rejected SRP_LOGIN_REQ because out of memory.");
72908+ ret = -ENOMEM;
72909+ goto reject;
72910+ }
72911+
72912+ memcpy(ch->i_port_id, req->initiator_port_id, 16);
72913+ memcpy(ch->t_port_id, req->target_port_id, 16);
72914+ ch->sport = &sdev->port[param->port - 1];
72915+ ch->cm_id = cm_id;
72916+ /*
72917+ * Avoid QUEUE_FULL conditions by limiting the number of buffers used
72918+ * for the SRP protocol to the SCST SCSI command queue size.
72919+ */
72920+ ch->rq_size = min(SRPT_RQ_SIZE, scst_get_max_lun_commands(NULL, 0));
72921+ atomic_set(&ch->processing_compl, 0);
72922+ atomic_set(&ch->state, RDMA_CHANNEL_CONNECTING);
72923+ INIT_LIST_HEAD(&ch->cmd_wait_list);
72924+
72925+ spin_lock_init(&ch->spinlock);
72926+ ch->ioctx_ring = (struct srpt_send_ioctx **)
72927+ srpt_alloc_ioctx_ring(ch->sport->sdev, ch->rq_size,
72928+ sizeof(*ch->ioctx_ring[0]),
72929+ srp_max_rsp_size, DMA_TO_DEVICE);
72930+ if (!ch->ioctx_ring)
72931+ goto free_ch;
72932+
72933+ INIT_LIST_HEAD(&ch->free_list);
72934+ for (i = 0; i < ch->rq_size; i++) {
72935+ ch->ioctx_ring[i]->ch = ch;
72936+ list_add_tail(&ch->ioctx_ring[i]->free_list, &ch->free_list);
72937+ }
72938+
72939+ ret = srpt_create_ch_ib(ch);
72940+ if (ret) {
72941+ rej->reason = __constant_cpu_to_be32(
72942+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
72943+ PRINT_ERROR("%s", "rejected SRP_LOGIN_REQ because creating"
72944+ " a new RDMA channel failed.");
72945+ goto free_ring;
72946+ }
72947+
72948+ ret = srpt_ch_qp_rtr(ch, ch->qp);
72949+ if (ret) {
72950+ rej->reason = __constant_cpu_to_be32(
72951+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
72952+ PRINT_ERROR("rejected SRP_LOGIN_REQ because enabling"
72953+ " RTR failed (error code = %d)", ret);
72954+ goto destroy_ib;
72955+ }
72956+
72957+ if (use_port_guid_in_session_name) {
72958+ /*
72959+ * If the kernel module parameter use_port_guid_in_session_name
72960+ * has been specified, use a combination of the target port
72961+ * GUID and the initiator port ID as the session name. This
72962+ * was the original behavior of the SRP target implementation
72963+ * (i.e. before the SRPT was included in OFED 1.3).
72964+ */
72965+ snprintf(ch->sess_name, sizeof(ch->sess_name),
72966+ "0x%016llx%016llx",
72967+ be64_to_cpu(*(__be64 *)
72968+ &sdev->port[param->port - 1].gid.raw[8]),
72969+ be64_to_cpu(*(__be64 *)(ch->i_port_id + 8)));
72970+ } else {
72971+ /*
72972+ * Default behavior: use the initator port identifier as the
72973+ * session name.
72974+ */
72975+ snprintf(ch->sess_name, sizeof(ch->sess_name),
72976+ "0x%016llx%016llx",
72977+ be64_to_cpu(*(__be64 *)ch->i_port_id),
72978+ be64_to_cpu(*(__be64 *)(ch->i_port_id + 8)));
72979+ }
72980+
72981+ TRACE_DBG("registering session %s", ch->sess_name);
72982+
72983+ BUG_ON(!sdev->scst_tgt);
72984+ ch->scst_sess = scst_register_session(sdev->scst_tgt, 0, ch->sess_name,
72985+ ch, NULL, NULL);
72986+ if (!ch->scst_sess) {
72987+ rej->reason = __constant_cpu_to_be32(
72988+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
72989+ TRACE_DBG("%s", "Failed to create SCST session");
72990+ goto release_channel;
72991+ }
72992+
72993+ TRACE_DBG("Establish connection sess=%p name=%s cm_id=%p",
72994+ ch->scst_sess, ch->sess_name, ch->cm_id);
72995+
72996+ /* create srp_login_response */
72997+ rsp->opcode = SRP_LOGIN_RSP;
72998+ rsp->tag = req->tag;
72999+ rsp->max_it_iu_len = req->req_it_iu_len;
73000+ rsp->max_ti_iu_len = req->req_it_iu_len;
73001+ ch->max_ti_iu_len = it_iu_len;
73002+ rsp->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT
73003+ | SRP_BUF_FORMAT_INDIRECT);
73004+ rsp->req_lim_delta = cpu_to_be32(ch->rq_size);
73005+ atomic_set(&ch->req_lim, ch->rq_size);
73006+ atomic_set(&ch->req_lim_delta, 0);
73007+
73008+ /* create cm reply */
73009+ rep_param->qp_num = ch->qp->qp_num;
73010+ rep_param->private_data = (void *)rsp;
73011+ rep_param->private_data_len = sizeof *rsp;
73012+ rep_param->rnr_retry_count = 7;
73013+ rep_param->flow_control = 1;
73014+ rep_param->failover_accepted = 0;
73015+ rep_param->srq = 1;
73016+ rep_param->responder_resources = 4;
73017+ rep_param->initiator_depth = 4;
73018+
73019+ ret = ib_send_cm_rep(cm_id, rep_param);
73020+ if (ret) {
73021+ PRINT_ERROR("sending SRP_LOGIN_REQ response failed"
73022+ " (error code = %d)", ret);
73023+ goto release_channel;
73024+ }
73025+
73026+ spin_lock_irq(&sdev->spinlock);
73027+ list_add_tail(&ch->list, &sdev->rch_list);
73028+ spin_unlock_irq(&sdev->spinlock);
73029+
73030+ goto out;
73031+
73032+release_channel:
73033+ atomic_set(&ch->state, RDMA_CHANNEL_DISCONNECTING);
73034+ scst_unregister_session(ch->scst_sess, 0, NULL);
73035+ ch->scst_sess = NULL;
73036+
73037+destroy_ib:
73038+ srpt_destroy_ch_ib(ch);
73039+
73040+free_ring:
73041+ srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
73042+ ch->sport->sdev, ch->rq_size,
73043+ srp_max_rsp_size, DMA_TO_DEVICE);
73044+
73045+free_ch:
73046+ kfree(ch);
73047+
73048+reject:
73049+ rej->opcode = SRP_LOGIN_REJ;
73050+ rej->tag = req->tag;
73051+ rej->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT
73052+ | SRP_BUF_FORMAT_INDIRECT);
73053+
73054+ ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
73055+ (void *)rej, sizeof *rej);
73056+
73057+out:
73058+ kfree(rep_param);
73059+ kfree(rsp);
73060+ kfree(rej);
73061+
73062+ return ret;
73063+}
73064+
73065+static void srpt_cm_rej_recv(struct ib_cm_id *cm_id)
73066+{
73067+ PRINT_INFO("Received InfiniBand REJ packet for cm_id %p.", cm_id);
73068+ srpt_release_channel_by_cmid(cm_id);
73069+}
73070+
73071+/**
73072+ * srpt_cm_rtu_recv() - Process an IB_CM_RTU_RECEIVED or IB_CM_USER_ESTABLISHED event.
73073+ *
73074+ * An IB_CM_RTU_RECEIVED message indicates that the connection is established
73075+ * and that the recipient may begin transmitting (RTU = ready to use).
73076+ */
73077+static void srpt_cm_rtu_recv(struct ib_cm_id *cm_id)
73078+{
73079+ struct srpt_rdma_ch *ch;
73080+ int ret;
73081+
73082+ ch = srpt_find_channel(cm_id->context, cm_id);
73083+ WARN_ON(!ch);
73084+ if (!ch)
73085+ goto out;
73086+
73087+ if (srpt_test_and_set_channel_state(ch, RDMA_CHANNEL_CONNECTING,
73088+ RDMA_CHANNEL_LIVE) == RDMA_CHANNEL_CONNECTING) {
73089+ struct srpt_recv_ioctx *ioctx, *ioctx_tmp;
73090+
73091+ ret = srpt_ch_qp_rts(ch, ch->qp);
73092+
73093+ list_for_each_entry_safe(ioctx, ioctx_tmp, &ch->cmd_wait_list,
73094+ wait_list) {
73095+ list_del(&ioctx->wait_list);
73096+ srpt_handle_new_iu(ch, ioctx, NULL,
73097+ SCST_CONTEXT_THREAD);
73098+ }
73099+ if (ret && srpt_test_and_set_channel_state(ch,
73100+ RDMA_CHANNEL_LIVE,
73101+ RDMA_CHANNEL_DISCONNECTING) == RDMA_CHANNEL_LIVE) {
73102+ TRACE_DBG("cm_id=%p sess_name=%s state=%d",
73103+ cm_id, ch->sess_name,
73104+ atomic_read(&ch->state));
73105+ ib_send_cm_dreq(ch->cm_id, NULL, 0);
73106+ }
73107+ }
73108+
73109+out:
73110+ ;
73111+}
73112+
73113+static void srpt_cm_timewait_exit(struct ib_cm_id *cm_id)
73114+{
73115+ PRINT_INFO("Received InfiniBand TimeWait exit for cm_id %p.", cm_id);
73116+ srpt_release_channel_by_cmid(cm_id);
73117+}
73118+
73119+static void srpt_cm_rep_error(struct ib_cm_id *cm_id)
73120+{
73121+ PRINT_INFO("Received InfiniBand REP error for cm_id %p.", cm_id);
73122+ srpt_release_channel_by_cmid(cm_id);
73123+}
73124+
73125+/**
73126+ * srpt_cm_dreq_recv() - Process reception of a DREQ message.
73127+ */
73128+static void srpt_cm_dreq_recv(struct ib_cm_id *cm_id)
73129+{
73130+ struct srpt_rdma_ch *ch;
73131+
73132+ ch = srpt_find_channel(cm_id->context, cm_id);
73133+ if (!ch) {
73134+ TRACE_DBG("Received DREQ for channel %p which is already"
73135+ " being unregistered.", cm_id);
73136+ goto out;
73137+ }
73138+
73139+ TRACE_DBG("cm_id= %p ch->state= %d", cm_id, atomic_read(&ch->state));
73140+
73141+ switch (atomic_read(&ch->state)) {
73142+ case RDMA_CHANNEL_LIVE:
73143+ case RDMA_CHANNEL_CONNECTING:
73144+ ib_send_cm_drep(ch->cm_id, NULL, 0);
73145+ PRINT_INFO("Received DREQ and sent DREP for session %s.",
73146+ ch->sess_name);
73147+ break;
73148+ case RDMA_CHANNEL_DISCONNECTING:
73149+ default:
73150+ break;
73151+ }
73152+
73153+out:
73154+ ;
73155+}
73156+
73157+/**
73158+ * srpt_cm_drep_recv() - Process reception of a DREP message.
73159+ */
73160+static void srpt_cm_drep_recv(struct ib_cm_id *cm_id)
73161+{
73162+ PRINT_INFO("Received InfiniBand DREP message for cm_id %p.", cm_id);
73163+ srpt_release_channel_by_cmid(cm_id);
73164+}
73165+
73166+/**
73167+ * srpt_cm_handler() - IB connection manager callback function.
73168+ *
73169+ * A non-zero return value will cause the caller destroy the CM ID.
73170+ *
73171+ * Note: srpt_cm_handler() must only return a non-zero value when transferring
73172+ * ownership of the cm_id to a channel by srpt_cm_req_recv() failed. Returning
73173+ * a non-zero value in any other case will trigger a race with the
73174+ * ib_destroy_cm_id() call in srpt_release_channel().
73175+ */
73176+static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
73177+{
73178+ int ret;
73179+
73180+ ret = 0;
73181+ switch (event->event) {
73182+ case IB_CM_REQ_RECEIVED:
73183+ ret = srpt_cm_req_recv(cm_id, &event->param.req_rcvd,
73184+ event->private_data);
73185+ break;
73186+ case IB_CM_REJ_RECEIVED:
73187+ srpt_cm_rej_recv(cm_id);
73188+ break;
73189+ case IB_CM_RTU_RECEIVED:
73190+ case IB_CM_USER_ESTABLISHED:
73191+ srpt_cm_rtu_recv(cm_id);
73192+ break;
73193+ case IB_CM_DREQ_RECEIVED:
73194+ srpt_cm_dreq_recv(cm_id);
73195+ break;
73196+ case IB_CM_DREP_RECEIVED:
73197+ srpt_cm_drep_recv(cm_id);
73198+ break;
73199+ case IB_CM_TIMEWAIT_EXIT:
73200+ srpt_cm_timewait_exit(cm_id);
73201+ break;
73202+ case IB_CM_REP_ERROR:
73203+ srpt_cm_rep_error(cm_id);
73204+ break;
73205+ case IB_CM_DREQ_ERROR:
73206+ PRINT_INFO("%s", "Received IB DREQ ERROR event.");
73207+ break;
73208+ case IB_CM_MRA_RECEIVED:
73209+ PRINT_INFO("%s", "Received IB MRA event");
73210+ break;
73211+ default:
73212+ PRINT_ERROR("received unrecognized IB CM event %d",
73213+ event->event);
73214+ break;
73215+ }
73216+
73217+ return ret;
73218+}
73219+
73220+/**
73221+ * srpt_map_sg_to_ib_sge() - Map an SG list to an IB SGE list.
73222+ */
73223+static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch,
73224+ struct srpt_send_ioctx *ioctx,
73225+ struct scst_cmd *scmnd)
73226+{
73227+ struct scatterlist *sg;
73228+ int sg_cnt;
73229+ scst_data_direction dir;
73230+ struct rdma_iu *riu;
73231+ struct srp_direct_buf *db;
73232+ dma_addr_t dma_addr;
73233+ struct ib_sge *sge;
73234+ u64 raddr;
73235+ u32 rsize;
73236+ u32 tsize;
73237+ u32 dma_len;
73238+ int count, nrdma;
73239+ int i, j, k;
73240+
73241+ BUG_ON(!ch);
73242+ BUG_ON(!ioctx);
73243+ BUG_ON(!scmnd);
73244+ dir = scst_cmd_get_data_direction(scmnd);
73245+ BUG_ON(dir == SCST_DATA_NONE);
73246+ /*
73247+ * Cache 'dir' because it is needed in srpt_unmap_sg_to_ib_sge()
73248+ * and because scst_set_cmd_error_status() resets scmnd->data_direction.
73249+ */
73250+ ioctx->dir = dir;
73251+ if (dir == SCST_DATA_WRITE) {
73252+ scst_cmd_get_write_fields(scmnd, &sg, &sg_cnt);
73253+ WARN_ON(!sg);
73254+ } else {
73255+ sg = scst_cmd_get_sg(scmnd);
73256+ sg_cnt = scst_cmd_get_sg_cnt(scmnd);
73257+ WARN_ON(!sg);
73258+ }
73259+ ioctx->sg = sg;
73260+ ioctx->sg_cnt = sg_cnt;
73261+ count = ib_dma_map_sg(ch->sport->sdev->device, sg, sg_cnt,
73262+ scst_to_tgt_dma_dir(dir));
73263+ if (unlikely(!count))
73264+ return -EBUSY;
73265+
73266+ ioctx->mapped_sg_count = count;
73267+
73268+ if (ioctx->rdma_ius && ioctx->n_rdma_ius)
73269+ nrdma = ioctx->n_rdma_ius;
73270+ else {
73271+ nrdma = count / SRPT_DEF_SG_PER_WQE + ioctx->n_rbuf;
73272+
73273+ ioctx->rdma_ius = kzalloc(nrdma * sizeof *riu,
73274+ scst_cmd_atomic(scmnd)
73275+ ? GFP_ATOMIC : GFP_KERNEL);
73276+ if (!ioctx->rdma_ius)
73277+ goto free_mem;
73278+
73279+ ioctx->n_rdma_ius = nrdma;
73280+ }
73281+
73282+ db = ioctx->rbufs;
73283+ tsize = (dir == SCST_DATA_READ)
73284+ ? scst_cmd_get_adjusted_resp_data_len(scmnd)
73285+ : scst_cmd_get_bufflen(scmnd);
73286+ dma_len = sg_dma_len(&sg[0]);
73287+ riu = ioctx->rdma_ius;
73288+
73289+ /*
73290+ * For each remote desc - calculate the #ib_sge.
73291+ * If #ib_sge < SRPT_DEF_SG_PER_WQE per rdma operation then
73292+ * each remote desc rdma_iu is required a rdma wr;
73293+ * else
73294+ * we need to allocate extra rdma_iu to carry extra #ib_sge in
73295+ * another rdma wr
73296+ */
73297+ for (i = 0, j = 0;
73298+ j < count && i < ioctx->n_rbuf && tsize > 0; ++i, ++riu, ++db) {
73299+ rsize = be32_to_cpu(db->len);
73300+ raddr = be64_to_cpu(db->va);
73301+ riu->raddr = raddr;
73302+ riu->rkey = be32_to_cpu(db->key);
73303+ riu->sge_cnt = 0;
73304+
73305+ /* calculate how many sge required for this remote_buf */
73306+ while (rsize > 0 && tsize > 0) {
73307+
73308+ if (rsize >= dma_len) {
73309+ tsize -= dma_len;
73310+ rsize -= dma_len;
73311+ raddr += dma_len;
73312+
73313+ if (tsize > 0) {
73314+ ++j;
73315+ if (j < count)
73316+ dma_len = sg_dma_len(&sg[j]);
73317+ }
73318+ } else {
73319+ tsize -= rsize;
73320+ dma_len -= rsize;
73321+ rsize = 0;
73322+ }
73323+
73324+ ++riu->sge_cnt;
73325+
73326+ if (rsize > 0 && riu->sge_cnt == SRPT_DEF_SG_PER_WQE) {
73327+ ++ioctx->n_rdma;
73328+ riu->sge =
73329+ kmalloc(riu->sge_cnt * sizeof *riu->sge,
73330+ scst_cmd_atomic(scmnd)
73331+ ? GFP_ATOMIC : GFP_KERNEL);
73332+ if (!riu->sge)
73333+ goto free_mem;
73334+
73335+ ++riu;
73336+ riu->sge_cnt = 0;
73337+ riu->raddr = raddr;
73338+ riu->rkey = be32_to_cpu(db->key);
73339+ }
73340+ }
73341+
73342+ ++ioctx->n_rdma;
73343+ riu->sge = kmalloc(riu->sge_cnt * sizeof *riu->sge,
73344+ scst_cmd_atomic(scmnd)
73345+ ? GFP_ATOMIC : GFP_KERNEL);
73346+ if (!riu->sge)
73347+ goto free_mem;
73348+ }
73349+
73350+ db = ioctx->rbufs;
73351+ tsize = (dir == SCST_DATA_READ)
73352+ ? scst_cmd_get_adjusted_resp_data_len(scmnd)
73353+ : scst_cmd_get_bufflen(scmnd);
73354+ riu = ioctx->rdma_ius;
73355+ dma_len = sg_dma_len(&sg[0]);
73356+ dma_addr = sg_dma_address(&sg[0]);
73357+
73358+ /* this second loop is really mapped sg_addres to rdma_iu->ib_sge */
73359+ for (i = 0, j = 0;
73360+ j < count && i < ioctx->n_rbuf && tsize > 0; ++i, ++riu, ++db) {
73361+ rsize = be32_to_cpu(db->len);
73362+ sge = riu->sge;
73363+ k = 0;
73364+
73365+ while (rsize > 0 && tsize > 0) {
73366+ sge->addr = dma_addr;
73367+ sge->lkey = ch->sport->sdev->mr->lkey;
73368+
73369+ if (rsize >= dma_len) {
73370+ sge->length =
73371+ (tsize < dma_len) ? tsize : dma_len;
73372+ tsize -= dma_len;
73373+ rsize -= dma_len;
73374+
73375+ if (tsize > 0) {
73376+ ++j;
73377+ if (j < count) {
73378+ dma_len = sg_dma_len(&sg[j]);
73379+ dma_addr =
73380+ sg_dma_address(&sg[j]);
73381+ }
73382+ }
73383+ } else {
73384+ sge->length = (tsize < rsize) ? tsize : rsize;
73385+ tsize -= rsize;
73386+ dma_len -= rsize;
73387+ dma_addr += rsize;
73388+ rsize = 0;
73389+ }
73390+
73391+ ++k;
73392+ if (k == riu->sge_cnt && rsize > 0) {
73393+ ++riu;
73394+ sge = riu->sge;
73395+ k = 0;
73396+ } else if (rsize > 0)
73397+ ++sge;
73398+ }
73399+ }
73400+
73401+ return 0;
73402+
73403+free_mem:
73404+ srpt_unmap_sg_to_ib_sge(ch, ioctx);
73405+
73406+ return -ENOMEM;
73407+}
73408+
73409+/**
73410+ * srpt_unmap_sg_to_ib_sge() - Unmap an IB SGE list.
73411+ */
73412+static void srpt_unmap_sg_to_ib_sge(struct srpt_rdma_ch *ch,
73413+ struct srpt_send_ioctx *ioctx)
73414+{
73415+ struct scst_cmd *scmnd;
73416+ struct scatterlist *sg;
73417+ scst_data_direction dir;
73418+
73419+ EXTRACHECKS_BUG_ON(!ch);
73420+ EXTRACHECKS_BUG_ON(!ioctx);
73421+ EXTRACHECKS_BUG_ON(ioctx->n_rdma && !ioctx->rdma_ius);
73422+
73423+ while (ioctx->n_rdma)
73424+ kfree(ioctx->rdma_ius[--ioctx->n_rdma].sge);
73425+
73426+ kfree(ioctx->rdma_ius);
73427+ ioctx->rdma_ius = NULL;
73428+
73429+ if (ioctx->mapped_sg_count) {
73430+ scmnd = ioctx->scmnd;
73431+ EXTRACHECKS_BUG_ON(!scmnd);
73432+ EXTRACHECKS_WARN_ON(ioctx->scmnd != scmnd);
73433+ EXTRACHECKS_WARN_ON(ioctx != scst_cmd_get_tgt_priv(scmnd));
73434+ sg = ioctx->sg;
73435+ EXTRACHECKS_WARN_ON(!sg);
73436+ dir = ioctx->dir;
73437+ EXTRACHECKS_BUG_ON(dir == SCST_DATA_NONE);
73438+ ib_dma_unmap_sg(ch->sport->sdev->device, sg, ioctx->sg_cnt,
73439+ scst_to_tgt_dma_dir(dir));
73440+ ioctx->mapped_sg_count = 0;
73441+ }
73442+}
73443+
73444+/**
73445+ * srpt_perform_rdmas() - Perform IB RDMA.
73446+ *
73447+ * Returns zero upon success or a negative number upon failure.
73448+ */
73449+static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
73450+ struct srpt_send_ioctx *ioctx,
73451+ scst_data_direction dir)
73452+{
73453+ struct ib_send_wr wr;
73454+ struct ib_send_wr *bad_wr;
73455+ struct rdma_iu *riu;
73456+ int i;
73457+ int ret;
73458+ int sq_wr_avail;
73459+
73460+ if (dir == SCST_DATA_WRITE) {
73461+ ret = -ENOMEM;
73462+ sq_wr_avail = atomic_sub_return(ioctx->n_rdma,
73463+ &ch->sq_wr_avail);
73464+ if (sq_wr_avail < 0) {
73465+ PRINT_WARNING("IB send queue full (needed %d)",
73466+ ioctx->n_rdma);
73467+ goto out;
73468+ }
73469+ }
73470+
73471+ ret = 0;
73472+ riu = ioctx->rdma_ius;
73473+ memset(&wr, 0, sizeof wr);
73474+
73475+ for (i = 0; i < ioctx->n_rdma; ++i, ++riu) {
73476+ if (dir == SCST_DATA_READ) {
73477+ wr.opcode = IB_WR_RDMA_WRITE;
73478+ wr.wr_id = encode_wr_id(IB_WC_RDMA_WRITE,
73479+ ioctx->ioctx.index);
73480+ } else {
73481+ wr.opcode = IB_WR_RDMA_READ;
73482+ wr.wr_id = encode_wr_id(IB_WC_RDMA_READ,
73483+ ioctx->ioctx.index);
73484+ }
73485+ wr.next = NULL;
73486+ wr.wr.rdma.remote_addr = riu->raddr;
73487+ wr.wr.rdma.rkey = riu->rkey;
73488+ wr.num_sge = riu->sge_cnt;
73489+ wr.sg_list = riu->sge;
73490+
73491+ /* only get completion event for the last rdma wr */
73492+ if (i == (ioctx->n_rdma - 1) && dir == SCST_DATA_WRITE)
73493+ wr.send_flags = IB_SEND_SIGNALED;
73494+
73495+ ret = ib_post_send(ch->qp, &wr, &bad_wr);
73496+ if (ret)
73497+ goto out;
73498+ }
73499+
73500+out:
73501+ if (unlikely(dir == SCST_DATA_WRITE && ret < 0))
73502+ atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);
73503+ return ret;
73504+}
73505+
73506+/**
73507+ * srpt_xfer_data() - Start data transfer from initiator to target.
73508+ *
73509+ * Returns an SCST_TGT_RES_... status code.
73510+ *
73511+ * Note: Must not block.
73512+ */
73513+static int srpt_xfer_data(struct srpt_rdma_ch *ch,
73514+ struct srpt_send_ioctx *ioctx,
73515+ struct scst_cmd *scmnd)
73516+{
73517+ int ret;
73518+
73519+ ret = srpt_map_sg_to_ib_sge(ch, ioctx, scmnd);
73520+ if (ret) {
73521+ PRINT_ERROR("%s[%d] ret=%d", __func__, __LINE__, ret);
73522+ ret = SCST_TGT_RES_QUEUE_FULL;
73523+ goto out;
73524+ }
73525+
73526+ ret = srpt_perform_rdmas(ch, ioctx, scst_cmd_get_data_direction(scmnd));
73527+ if (ret) {
73528+ if (ret == -EAGAIN || ret == -ENOMEM) {
73529+ PRINT_INFO("%s[%d] queue full -- ret=%d",
73530+ __func__, __LINE__, ret);
73531+ ret = SCST_TGT_RES_QUEUE_FULL;
73532+ } else {
73533+ PRINT_ERROR("%s[%d] fatal error -- ret=%d",
73534+ __func__, __LINE__, ret);
73535+ ret = SCST_TGT_RES_FATAL_ERROR;
73536+ }
73537+ goto out_unmap;
73538+ }
73539+
73540+ ret = SCST_TGT_RES_SUCCESS;
73541+
73542+out:
73543+ return ret;
73544+out_unmap:
73545+ srpt_unmap_sg_to_ib_sge(ch, ioctx);
73546+ goto out;
73547+}
73548+
73549+/**
73550+ * srpt_pending_cmd_timeout() - SCST command HCA processing timeout callback.
73551+ *
73552+ * Called by the SCST core if no IB completion notification has been received
73553+ * within max_hw_pending_time seconds.
73554+ */
73555+static void srpt_pending_cmd_timeout(struct scst_cmd *scmnd)
73556+{
73557+ struct srpt_send_ioctx *ioctx;
73558+ enum srpt_command_state state;
73559+
73560+ ioctx = scst_cmd_get_tgt_priv(scmnd);
73561+ BUG_ON(!ioctx);
73562+
73563+ state = srpt_get_cmd_state(ioctx);
73564+ switch (state) {
73565+ case SRPT_STATE_NEW:
73566+ case SRPT_STATE_DATA_IN:
73567+ case SRPT_STATE_DONE:
73568+ /*
73569+ * srpt_pending_cmd_timeout() should never be invoked for
73570+ * commands in this state.
73571+ */
73572+ PRINT_ERROR("Processing SCST command %p (SRPT state %d) took"
73573+ " too long -- aborting", scmnd, state);
73574+ break;
73575+ case SRPT_STATE_NEED_DATA:
73576+ case SRPT_STATE_CMD_RSP_SENT:
73577+ case SRPT_STATE_MGMT_RSP_SENT:
73578+ default:
73579+ PRINT_ERROR("Command %p: IB completion for idx %u has not"
73580+ " been received in time (SRPT command state %d)",
73581+ scmnd, ioctx->ioctx.index, state);
73582+ break;
73583+ }
73584+
73585+ srpt_abort_scst_cmd(ioctx, SCST_CONTEXT_SAME);
73586+}
73587+
73588+/**
73589+ * srpt_rdy_to_xfer() - Transfers data from initiator to target.
73590+ *
73591+ * Called by the SCST core to transfer data from the initiator to the target
73592+ * (SCST_DATA_WRITE). Must not block.
73593+ */
73594+static int srpt_rdy_to_xfer(struct scst_cmd *scmnd)
73595+{
73596+ struct srpt_rdma_ch *ch;
73597+ struct srpt_send_ioctx *ioctx;
73598+ enum srpt_command_state new_state;
73599+ enum rdma_ch_state ch_state;
73600+ int ret;
73601+
73602+ ioctx = scst_cmd_get_tgt_priv(scmnd);
73603+ BUG_ON(!ioctx);
73604+
73605+ new_state = srpt_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA);
73606+ WARN_ON(new_state == SRPT_STATE_DONE);
73607+
73608+ ch = ioctx->ch;
73609+ WARN_ON(ch != scst_sess_get_tgt_priv(scst_cmd_get_session(scmnd)));
73610+ BUG_ON(!ch);
73611+
73612+ ch_state = atomic_read(&ch->state);
73613+ if (ch_state == RDMA_CHANNEL_DISCONNECTING) {
73614+ TRACE_DBG("cmd with tag %lld: channel disconnecting",
73615+ scst_cmd_get_tag(scmnd));
73616+ srpt_set_cmd_state(ioctx, SRPT_STATE_DATA_IN);
73617+ ret = SCST_TGT_RES_FATAL_ERROR;
73618+ goto out;
73619+ } else if (ch_state == RDMA_CHANNEL_CONNECTING) {
73620+ ret = SCST_TGT_RES_QUEUE_FULL;
73621+ goto out;
73622+ }
73623+ ret = srpt_xfer_data(ch, ioctx, scmnd);
73624+
73625+out:
73626+ return ret;
73627+}
73628+
73629+/**
73630+ * srpt_xmit_response() - Transmits the response to a SCSI command.
73631+ *
73632+ * Callback function called by the SCST core. Must not block. Must ensure that
73633+ * scst_tgt_cmd_done() will get invoked when returning SCST_TGT_RES_SUCCESS.
73634+ */
73635+static int srpt_xmit_response(struct scst_cmd *scmnd)
73636+{
73637+ struct srpt_rdma_ch *ch;
73638+ struct srpt_send_ioctx *ioctx;
73639+ enum srpt_command_state state;
73640+ int ret;
73641+ scst_data_direction dir;
73642+ int resp_len;
73643+
73644+ ret = SCST_TGT_RES_SUCCESS;
73645+
73646+ ioctx = scst_cmd_get_tgt_priv(scmnd);
73647+ BUG_ON(!ioctx);
73648+
73649+ ch = scst_sess_get_tgt_priv(scst_cmd_get_session(scmnd));
73650+ BUG_ON(!ch);
73651+
73652+ state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEW,
73653+ SRPT_STATE_CMD_RSP_SENT);
73654+ if (state != SRPT_STATE_NEW) {
73655+ state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_DATA_IN,
73656+ SRPT_STATE_CMD_RSP_SENT);
73657+ if (state != SRPT_STATE_DATA_IN)
73658+ PRINT_ERROR("Unexpected command state %d",
73659+ srpt_get_cmd_state(ioctx));
73660+ }
73661+
73662+ if (unlikely(scst_cmd_aborted(scmnd))) {
73663+ atomic_inc(&ch->req_lim_delta);
73664+ srpt_abort_scst_cmd(ioctx, SCST_CONTEXT_SAME);
73665+ goto out;
73666+ }
73667+
73668+ EXTRACHECKS_BUG_ON(scst_cmd_atomic(scmnd));
73669+
73670+ dir = scst_cmd_get_data_direction(scmnd);
73671+
73672+ /* For read commands, transfer the data to the initiator. */
73673+ if (dir == SCST_DATA_READ
73674+ && scst_cmd_get_adjusted_resp_data_len(scmnd)) {
73675+ ret = srpt_xfer_data(ch, ioctx, scmnd);
73676+ if (ret == SCST_TGT_RES_QUEUE_FULL) {
73677+ srpt_set_cmd_state(ioctx, state);
73678+ PRINT_WARNING("xfer_data failed for tag %llu"
73679+ " - retrying", scst_cmd_get_tag(scmnd));
73680+ goto out;
73681+ } else if (ret != SCST_TGT_RES_SUCCESS) {
73682+ PRINT_ERROR("xfer_data failed for tag %llu",
73683+ scst_cmd_get_tag(scmnd));
73684+ goto out;
73685+ }
73686+ }
73687+
73688+ atomic_inc(&ch->req_lim);
73689+
73690+ resp_len = srpt_build_cmd_rsp(ch, ioctx,
73691+ scst_cmd_get_tag(scmnd),
73692+ scst_cmd_get_status(scmnd),
73693+ scst_cmd_get_sense_buffer(scmnd),
73694+ scst_cmd_get_sense_buffer_len(scmnd));
73695+
73696+ if (srpt_post_send(ch, ioctx, resp_len)) {
73697+ srpt_unmap_sg_to_ib_sge(ch, ioctx);
73698+ srpt_set_cmd_state(ioctx, state);
73699+ atomic_dec(&ch->req_lim);
73700+ PRINT_WARNING("sending response failed for tag %llu - retrying",
73701+ scst_cmd_get_tag(scmnd));
73702+ ret = SCST_TGT_RES_QUEUE_FULL;
73703+ }
73704+
73705+out:
73706+ return ret;
73707+}
73708+
73709+/**
73710+ * srpt_tsk_mgmt_done() - SCST callback function that sends back the response
73711+ * for a task management request.
73712+ *
73713+ * Must not block.
73714+ */
73715+static void srpt_tsk_mgmt_done(struct scst_mgmt_cmd *mcmnd)
73716+{
73717+ struct srpt_rdma_ch *ch;
73718+ struct srpt_mgmt_ioctx *mgmt_ioctx;
73719+ struct srpt_send_ioctx *ioctx;
73720+ enum srpt_command_state new_state;
73721+ int rsp_len;
73722+
73723+ mgmt_ioctx = scst_mgmt_cmd_get_tgt_priv(mcmnd);
73724+ BUG_ON(!mgmt_ioctx);
73725+
73726+ ioctx = mgmt_ioctx->ioctx;
73727+ BUG_ON(!ioctx);
73728+
73729+ ch = ioctx->ch;
73730+ BUG_ON(!ch);
73731+
73732+ TRACE_DBG("%s: tsk_mgmt_done for tag= %lld status=%d",
73733+ __func__, mgmt_ioctx->tag, scst_mgmt_cmd_get_status(mcmnd));
73734+
73735+ WARN_ON(in_irq());
73736+
73737+ new_state = srpt_set_cmd_state(ioctx, SRPT_STATE_MGMT_RSP_SENT);
73738+ WARN_ON(new_state == SRPT_STATE_DONE);
73739+
73740+ atomic_inc(&ch->req_lim);
73741+
73742+ rsp_len = srpt_build_tskmgmt_rsp(ch, ioctx,
73743+ scst_to_srp_tsk_mgmt_status(
73744+ scst_mgmt_cmd_get_status(mcmnd)),
73745+ mgmt_ioctx->tag);
73746+ /*
73747+ * Note: the srpt_post_send() call below sends the task management
73748+ * response asynchronously. It is possible that the SCST core has
73749+ * already freed the struct scst_mgmt_cmd structure before the
73750+ * response is sent. This is fine however.
73751+ */
73752+ if (srpt_post_send(ch, ioctx, rsp_len)) {
73753+ PRINT_ERROR("%s", "Sending SRP_RSP response failed.");
73754+ srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
73755+ srpt_put_send_ioctx(ioctx);
73756+ atomic_dec(&ch->req_lim);
73757+ }
73758+
73759+ scst_mgmt_cmd_set_tgt_priv(mcmnd, NULL);
73760+
73761+ kfree(mgmt_ioctx);
73762+}
73763+
73764+/**
73765+ * srpt_get_initiator_port_transport_id() - SCST TransportID callback function.
73766+ *
73767+ * See also SPC-3, section 7.5.4.5, TransportID for initiator ports using SRP.
73768+ */
73769+static int srpt_get_initiator_port_transport_id(struct scst_session *scst_sess,
73770+ uint8_t **transport_id)
73771+{
73772+ struct srpt_rdma_ch *ch;
73773+ struct spc_rdma_transport_id {
73774+ uint8_t protocol_identifier;
73775+ uint8_t reserved[7];
73776+ uint8_t i_port_id[16];
73777+ };
73778+ struct spc_rdma_transport_id *tr_id;
73779+ int res;
73780+
73781+ TRACE_ENTRY();
73782+
73783+ if (!scst_sess) {
73784+ res = SCSI_TRANSPORTID_PROTOCOLID_SRP;
73785+ goto out;
73786+ }
73787+
73788+ ch = scst_sess_get_tgt_priv(scst_sess);
73789+ BUG_ON(!ch);
73790+
73791+ BUILD_BUG_ON(sizeof(*tr_id) != 24);
73792+
73793+ tr_id = kzalloc(sizeof(struct spc_rdma_transport_id), GFP_KERNEL);
73794+ if (!tr_id) {
73795+ PRINT_ERROR("%s", "Allocation of TransportID failed");
73796+ res = -ENOMEM;
73797+ goto out;
73798+ }
73799+
73800+ res = 0;
73801+ tr_id->protocol_identifier = SCSI_TRANSPORTID_PROTOCOLID_SRP;
73802+ memcpy(tr_id->i_port_id, ch->i_port_id, sizeof(ch->i_port_id));
73803+
73804+ *transport_id = (uint8_t *)tr_id;
73805+
73806+out:
73807+ TRACE_EXIT_RES(res);
73808+ return res;
73809+}
73810+
73811+/**
73812+ * srpt_on_free_cmd() - Free command-private data.
73813+ *
73814+ * Called by the SCST core. May be called in IRQ context.
73815+ */
73816+static void srpt_on_free_cmd(struct scst_cmd *scmnd)
73817+{
73818+}
73819+
73820+static void srpt_refresh_port_work(struct work_struct *work)
73821+{
73822+ struct srpt_port *sport = container_of(work, struct srpt_port, work);
73823+
73824+ srpt_refresh_port(sport);
73825+}
73826+
73827+/**
73828+ * srpt_detect() - Returns the number of target adapters.
73829+ *
73830+ * Callback function called by the SCST core.
73831+ */
73832+static int srpt_detect(struct scst_tgt_template *tp)
73833+{
73834+ int device_count;
73835+
73836+ TRACE_ENTRY();
73837+
73838+ device_count = atomic_read(&srpt_device_count);
73839+
73840+ TRACE_EXIT_RES(device_count);
73841+
73842+ return device_count;
73843+}
73844+
73845+/**
73846+ * srpt_release() - Free the resources associated with an SCST target.
73847+ *
73848+ * Callback function called by the SCST core from scst_unregister_target().
73849+ */
73850+static int srpt_release(struct scst_tgt *scst_tgt)
73851+{
73852+ struct srpt_device *sdev = scst_tgt_get_tgt_priv(scst_tgt);
73853+ struct srpt_rdma_ch *ch;
73854+
73855+ TRACE_ENTRY();
73856+
73857+ EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
73858+
73859+ BUG_ON(!scst_tgt);
73860+ if (WARN_ON(!sdev))
73861+ return -ENODEV;
73862+
73863+ spin_lock_irq(&sdev->spinlock);
73864+ while (!list_empty(&sdev->rch_list)) {
73865+ ch = list_first_entry(&sdev->rch_list, typeof(*ch), list);
73866+ srpt_unregister_channel(ch);
73867+ }
73868+ spin_unlock_irq(&sdev->spinlock);
73869+
73870+ scst_tgt_set_tgt_priv(scst_tgt, NULL);
73871+
73872+ TRACE_EXIT();
73873+
73874+ return 0;
73875+}
73876+
73877+/**
73878+ * srpt_get_scsi_transport_version() - Returns the SCSI transport version.
73879+ * This function is called from scst_pres.c, the code that implements
73880+ * persistent reservation support.
73881+ */
73882+static uint16_t srpt_get_scsi_transport_version(struct scst_tgt *scst_tgt)
73883+{
73884+ return 0x0940; /* SRP */
73885+}
73886+
73887+static ssize_t show_req_lim(struct kobject *kobj,
73888+ struct kobj_attribute *attr, char *buf)
73889+{
73890+ struct scst_session *scst_sess;
73891+ struct srpt_rdma_ch *ch;
73892+
73893+ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
73894+ ch = scst_sess_get_tgt_priv(scst_sess);
73895+ if (!ch)
73896+ return -ENOENT;
73897+ return sprintf(buf, "%d\n", atomic_read(&ch->req_lim));
73898+}
73899+
73900+static ssize_t show_req_lim_delta(struct kobject *kobj,
73901+ struct kobj_attribute *attr, char *buf)
73902+{
73903+ struct scst_session *scst_sess;
73904+ struct srpt_rdma_ch *ch;
73905+
73906+ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
73907+ ch = scst_sess_get_tgt_priv(scst_sess);
73908+ if (!ch)
73909+ return -ENOENT;
73910+ return sprintf(buf, "%d\n", atomic_read(&ch->req_lim_delta));
73911+}
73912+
73913+static const struct kobj_attribute srpt_req_lim_attr =
73914+ __ATTR(req_lim, S_IRUGO, show_req_lim, NULL);
73915+static const struct kobj_attribute srpt_req_lim_delta_attr =
73916+ __ATTR(req_lim_delta, S_IRUGO, show_req_lim_delta, NULL);
73917+
73918+static const struct attribute *srpt_sess_attrs[] = {
73919+ &srpt_req_lim_attr.attr,
73920+ &srpt_req_lim_delta_attr.attr,
73921+ NULL
73922+};
73923+
73924+/* SCST target template for the SRP target implementation. */
73925+static struct scst_tgt_template srpt_template = {
73926+ .name = DRV_NAME,
73927+ .sg_tablesize = SRPT_DEF_SG_TABLESIZE,
73928+ .max_hw_pending_time = 60/*seconds*/,
73929+ .enable_target = srpt_enable_target,
73930+ .is_target_enabled = srpt_is_target_enabled,
73931+ .sess_attrs = srpt_sess_attrs,
73932+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
73933+ .default_trace_flags = DEFAULT_SRPT_TRACE_FLAGS,
73934+ .trace_flags = &trace_flag,
73935+#endif
73936+ .detect = srpt_detect,
73937+ .release = srpt_release,
73938+ .xmit_response = srpt_xmit_response,
73939+ .rdy_to_xfer = srpt_rdy_to_xfer,
73940+ .on_hw_pending_cmd_timeout = srpt_pending_cmd_timeout,
73941+ .on_free_cmd = srpt_on_free_cmd,
73942+ .task_mgmt_fn_done = srpt_tsk_mgmt_done,
73943+ .get_initiator_port_transport_id = srpt_get_initiator_port_transport_id,
73944+ .get_scsi_transport_version = srpt_get_scsi_transport_version,
73945+};
73946+
73947+/**
73948+ * srpt_dev_release() - Device release callback function.
73949+ *
73950+ * The callback function srpt_dev_release() is called whenever a
73951+ * device is removed from the /sys/class/infiniband_srpt device class.
73952+ * Although this function has been left empty, a release function has been
73953+ * defined such that upon module removal no complaint is logged about a
73954+ * missing release function.
73955+ */
73956+static void srpt_dev_release(struct device *dev)
73957+{
73958+}
73959+
73960+static ssize_t show_login_info(struct device *dev,
73961+ struct device_attribute *attr, char *buf)
73962+{
73963+ struct srpt_device *sdev;
73964+ struct srpt_port *sport;
73965+ int i;
73966+ int len;
73967+
73968+ sdev = container_of(dev, struct srpt_device, dev);
73969+ len = 0;
73970+ for (i = 0; i < sdev->device->phys_port_cnt; i++) {
73971+ sport = &sdev->port[i];
73972+
73973+ len += sprintf(buf + len,
73974+ "tid_ext=%016llx,ioc_guid=%016llx,pkey=ffff,"
73975+ "dgid=%04x%04x%04x%04x%04x%04x%04x%04x,"
73976+ "service_id=%016llx\n",
73977+ srpt_service_guid,
73978+ srpt_service_guid,
73979+ be16_to_cpu(((__be16 *) sport->gid.raw)[0]),
73980+ be16_to_cpu(((__be16 *) sport->gid.raw)[1]),
73981+ be16_to_cpu(((__be16 *) sport->gid.raw)[2]),
73982+ be16_to_cpu(((__be16 *) sport->gid.raw)[3]),
73983+ be16_to_cpu(((__be16 *) sport->gid.raw)[4]),
73984+ be16_to_cpu(((__be16 *) sport->gid.raw)[5]),
73985+ be16_to_cpu(((__be16 *) sport->gid.raw)[6]),
73986+ be16_to_cpu(((__be16 *) sport->gid.raw)[7]),
73987+ srpt_service_guid);
73988+ }
73989+
73990+ return len;
73991+}
73992+
73993+static struct class_attribute srpt_class_attrs[] = {
73994+ __ATTR_NULL,
73995+};
73996+
73997+static struct device_attribute srpt_dev_attrs[] = {
73998+ __ATTR(login_info, S_IRUGO, show_login_info, NULL),
73999+ __ATTR_NULL,
74000+};
74001+
74002+static struct class srpt_class = {
74003+ .name = "infiniband_srpt",
74004+ .dev_release = srpt_dev_release,
74005+ .class_attrs = srpt_class_attrs,
74006+ .dev_attrs = srpt_dev_attrs,
74007+};
74008+
74009+/**
74010+ * srpt_add_one() - Infiniband device addition callback function.
74011+ */
74012+static void srpt_add_one(struct ib_device *device)
74013+{
74014+ struct srpt_device *sdev;
74015+ struct srpt_port *sport;
74016+ struct ib_srq_init_attr srq_attr;
74017+ int i;
74018+
74019+ TRACE_ENTRY();
74020+
74021+ TRACE_DBG("device = %p, device->dma_ops = %p", device, device->dma_ops);
74022+
74023+ sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
74024+ if (!sdev)
74025+ goto err;
74026+
74027+ sdev->device = device;
74028+ INIT_LIST_HEAD(&sdev->rch_list);
74029+ spin_lock_init(&sdev->spinlock);
74030+
74031+ sdev->scst_tgt = scst_register_target(&srpt_template, NULL);
74032+ if (!sdev->scst_tgt) {
74033+ PRINT_ERROR("SCST registration failed for %s.",
74034+ sdev->device->name);
74035+ goto free_dev;
74036+ }
74037+
74038+ scst_tgt_set_tgt_priv(sdev->scst_tgt, sdev);
74039+
74040+ sdev->dev.class = &srpt_class;
74041+ sdev->dev.parent = device->dma_device;
74042+ dev_set_name(&sdev->dev, "srpt-%s", device->name);
74043+
74044+ if (device_register(&sdev->dev))
74045+ goto unregister_tgt;
74046+
74047+ if (ib_query_device(device, &sdev->dev_attr))
74048+ goto err_dev;
74049+
74050+ sdev->pd = ib_alloc_pd(device);
74051+ if (IS_ERR(sdev->pd))
74052+ goto err_dev;
74053+
74054+ sdev->mr = ib_get_dma_mr(sdev->pd, IB_ACCESS_LOCAL_WRITE);
74055+ if (IS_ERR(sdev->mr))
74056+ goto err_pd;
74057+
74058+ sdev->srq_size = min(srpt_srq_size, sdev->dev_attr.max_srq_wr);
74059+
74060+ srq_attr.event_handler = srpt_srq_event;
74061+ srq_attr.srq_context = (void *)sdev;
74062+ srq_attr.attr.max_wr = sdev->srq_size;
74063+ srq_attr.attr.max_sge = 1;
74064+ srq_attr.attr.srq_limit = 0;
74065+
74066+ sdev->srq = ib_create_srq(sdev->pd, &srq_attr);
74067+ if (IS_ERR(sdev->srq))
74068+ goto err_mr;
74069+
74070+ TRACE_DBG("%s: create SRQ #wr= %d max_allow=%d dev= %s", __func__,
74071+ sdev->srq_size, sdev->dev_attr.max_srq_wr, device->name);
74072+
74073+ if (!srpt_service_guid)
74074+ srpt_service_guid = be64_to_cpu(device->node_guid);
74075+
74076+ sdev->cm_id = ib_create_cm_id(device, srpt_cm_handler, sdev);
74077+ if (IS_ERR(sdev->cm_id))
74078+ goto err_srq;
74079+
74080+ /* print out target login information */
74081+ TRACE_DBG("Target login info: id_ext=%016llx,"
74082+ "ioc_guid=%016llx,pkey=ffff,service_id=%016llx",
74083+ srpt_service_guid, srpt_service_guid, srpt_service_guid);
74084+
74085+ /*
74086+ * We do not have a consistent service_id (ie. also id_ext of target_id)
74087+ * to identify this target. We currently use the guid of the first HCA
74088+ * in the system as service_id; therefore, the target_id will change
74089+ * if this HCA is gone bad and replaced by different HCA
74090+ */
74091+ if (ib_cm_listen(sdev->cm_id, cpu_to_be64(srpt_service_guid), 0, NULL))
74092+ goto err_cm;
74093+
74094+ INIT_IB_EVENT_HANDLER(&sdev->event_handler, sdev->device,
74095+ srpt_event_handler);
74096+ if (ib_register_event_handler(&sdev->event_handler))
74097+ goto err_cm;
74098+
74099+ sdev->ioctx_ring = (struct srpt_recv_ioctx **)
74100+ srpt_alloc_ioctx_ring(sdev, sdev->srq_size,
74101+ sizeof(*sdev->ioctx_ring[0]),
74102+ srp_max_req_size, DMA_FROM_DEVICE);
74103+ if (!sdev->ioctx_ring)
74104+ goto err_event;
74105+
74106+ for (i = 0; i < sdev->srq_size; ++i)
74107+ srpt_post_recv(sdev, sdev->ioctx_ring[i]);
74108+
74109+ WARN_ON(sdev->device->phys_port_cnt
74110+ > sizeof(sdev->port)/sizeof(sdev->port[0]));
74111+
74112+ for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
74113+ sport = &sdev->port[i - 1];
74114+ sport->sdev = sdev;
74115+ sport->port = i;
74116+ INIT_WORK(&sport->work, srpt_refresh_port_work);
74117+ if (srpt_refresh_port(sport)) {
74118+ PRINT_ERROR("MAD registration failed for %s-%d.",
74119+ sdev->device->name, i);
74120+ goto err_ring;
74121+ }
74122+ }
74123+
74124+ atomic_inc(&srpt_device_count);
74125+out:
74126+ ib_set_client_data(device, &srpt_client, sdev);
74127+
74128+ TRACE_EXIT();
74129+ return;
74130+
74131+err_ring:
74132+ srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev,
74133+ sdev->srq_size, srp_max_req_size,
74134+ DMA_FROM_DEVICE);
74135+err_event:
74136+ ib_unregister_event_handler(&sdev->event_handler);
74137+err_cm:
74138+ ib_destroy_cm_id(sdev->cm_id);
74139+err_srq:
74140+ ib_destroy_srq(sdev->srq);
74141+err_mr:
74142+ ib_dereg_mr(sdev->mr);
74143+err_pd:
74144+ ib_dealloc_pd(sdev->pd);
74145+err_dev:
74146+ device_unregister(&sdev->dev);
74147+unregister_tgt:
74148+ scst_unregister_target(sdev->scst_tgt);
74149+free_dev:
74150+ kfree(sdev);
74151+err:
74152+ sdev = NULL;
74153+ PRINT_INFO("%s(%s) failed.", __func__, device->name);
74154+ goto out;
74155+}
74156+
74157+/**
74158+ * srpt_remove_one() - InfiniBand device removal callback function.
74159+ */
74160+static void srpt_remove_one(struct ib_device *device)
74161+{
74162+ int i;
74163+ struct srpt_device *sdev;
74164+
74165+ TRACE_ENTRY();
74166+
74167+ sdev = ib_get_client_data(device, &srpt_client);
74168+ if (!sdev) {
74169+ PRINT_INFO("%s(%s): nothing to do.", __func__, device->name);
74170+ return;
74171+ }
74172+
74173+ srpt_unregister_mad_agent(sdev);
74174+
74175+ ib_unregister_event_handler(&sdev->event_handler);
74176+
74177+ /* Cancel any work queued by the just unregistered IB event handler. */
74178+ for (i = 0; i < sdev->device->phys_port_cnt; i++)
74179+ cancel_work_sync(&sdev->port[i].work);
74180+
74181+ ib_destroy_cm_id(sdev->cm_id);
74182+ ib_destroy_srq(sdev->srq);
74183+ ib_dereg_mr(sdev->mr);
74184+ ib_dealloc_pd(sdev->pd);
74185+
74186+ device_unregister(&sdev->dev);
74187+
74188+ /*
74189+ * Unregistering an SCST target must happen after destroying sdev->cm_id
74190+ * such that no new SRP_LOGIN_REQ information units can arrive while
74191+ * destroying the SCST target.
74192+ */
74193+ scst_unregister_target(sdev->scst_tgt);
74194+ sdev->scst_tgt = NULL;
74195+
74196+ srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev,
74197+ sdev->srq_size, srp_max_req_size, DMA_FROM_DEVICE);
74198+ sdev->ioctx_ring = NULL;
74199+ kfree(sdev);
74200+
74201+ TRACE_EXIT();
74202+}
74203+
74204+/**
74205+ * srpt_init_module() - Kernel module initialization.
74206+ *
74207+ * Note: Since ib_register_client() registers callback functions, and since at
74208+ * least one of these callback functions (srpt_add_one()) calls SCST functions,
74209+ * the SCST target template must be registered before ib_register_client() is
74210+ * called.
74211+ */
74212+static int __init srpt_init_module(void)
74213+{
74214+ int ret;
74215+
74216+ ret = -EINVAL;
74217+ if (srp_max_req_size < MIN_MAX_REQ_SIZE) {
74218+ PRINT_ERROR("invalid value %d for kernel module parameter"
74219+ " srp_max_req_size -- must be at least %d.",
74220+ srp_max_req_size,
74221+ MIN_MAX_REQ_SIZE);
74222+ goto out;
74223+ }
74224+
74225+ if (srp_max_rsp_size < MIN_MAX_RSP_SIZE) {
74226+ PRINT_ERROR("invalid value %d for kernel module parameter"
74227+ " srp_max_rsp_size -- must be at least %d.",
74228+ srp_max_rsp_size,
74229+ MIN_MAX_RSP_SIZE);
74230+ goto out;
74231+ }
74232+
74233+ if (srpt_srq_size < MIN_SRPT_SRQ_SIZE
74234+ || srpt_srq_size > MAX_SRPT_SRQ_SIZE) {
74235+ PRINT_ERROR("invalid value %d for kernel module parameter"
74236+ " srpt_srq_size -- must be in the range [%d..%d].",
74237+ srpt_srq_size, MIN_SRPT_SRQ_SIZE,
74238+ MAX_SRPT_SRQ_SIZE);
74239+ goto out;
74240+ }
74241+
74242+ if (srpt_sq_size < MIN_SRPT_SQ_SIZE) {
74243+ PRINT_ERROR("invalid value %d for kernel module parameter"
74244+ " srpt_sq_size -- must be at least %d.",
74245+ srpt_srq_size, MIN_SRPT_SQ_SIZE);
74246+ goto out;
74247+ }
74248+
74249+ ret = class_register(&srpt_class);
74250+ if (ret) {
74251+ PRINT_ERROR("%s", "couldn't register class ib_srpt");
74252+ goto out;
74253+ }
74254+
74255+ switch (thread) {
74256+ case MODE_ALL_IN_SIRQ:
74257+ /*
74258+ * Process both IB completions and SCST commands in SIRQ
74259+ * context. May lead to soft lockups and other scary behavior
74260+ * under sufficient load.
74261+ */
74262+ srpt_template.rdy_to_xfer_atomic = true;
74263+ break;
74264+ case MODE_IB_COMPLETION_IN_THREAD:
74265+ /*
74266+ * Process IB completions in the kernel thread associated with
74267+ * the RDMA channel, and process SCST commands in the kernel
74268+ * threads created by the SCST core.
74269+ */
74270+ srpt_template.rdy_to_xfer_atomic = false;
74271+ break;
74272+ case MODE_IB_COMPLETION_IN_SIRQ:
74273+ default:
74274+ /*
74275+ * Process IB completions in SIRQ context and SCST commands in
74276+ * the kernel threads created by the SCST core.
74277+ */
74278+ srpt_template.rdy_to_xfer_atomic = false;
74279+ break;
74280+ }
74281+
74282+ ret = scst_register_target_template(&srpt_template);
74283+ if (ret < 0) {
74284+ PRINT_ERROR("%s", "couldn't register with scst");
74285+ ret = -ENODEV;
74286+ goto out_unregister_class;
74287+ }
74288+
74289+ ret = ib_register_client(&srpt_client);
74290+ if (ret) {
74291+ PRINT_ERROR("%s", "couldn't register IB client");
74292+ goto out_unregister_procfs;
74293+ }
74294+
74295+ return 0;
74296+
74297+out_unregister_procfs:
74298+ scst_unregister_target_template(&srpt_template);
74299+out_unregister_class:
74300+ class_unregister(&srpt_class);
74301+out:
74302+ return ret;
74303+}
74304+
74305+static void __exit srpt_cleanup_module(void)
74306+{
74307+ TRACE_ENTRY();
74308+
74309+ ib_unregister_client(&srpt_client);
74310+ scst_unregister_target_template(&srpt_template);
74311+ class_unregister(&srpt_class);
74312+
74313+ TRACE_EXIT();
74314+}
74315+
74316+module_init(srpt_init_module);
74317+module_exit(srpt_cleanup_module);
74318+
74319+/*
74320+ * Local variables:
74321+ * c-basic-offset: 8
74322+ * indent-tabs-mode: t
74323+ * End:
74324+ */
74325diff -uprN orig/linux-2.6.35/drivers/scst/srpt/ib_srpt.h linux-2.6.35/drivers/scst/srpt/ib_srpt.h
74326--- orig/linux-2.6.35/drivers/scst/srpt/ib_srpt.h
74327+++ linux-2.6.35/drivers/scst/srpt/ib_srpt.h
74328@@ -0,0 +1,353 @@
74329+/*
74330+ * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.
74331+ * Copyright (C) 2009 - 2010 Bart Van Assche <bart.vanassche@gmail.com>
74332+ *
74333+ * This software is available to you under a choice of one of two
74334+ * licenses. You may choose to be licensed under the terms of the GNU
74335+ * General Public License (GPL) Version 2, available from the file
74336+ * COPYING in the main directory of this source tree, or the
74337+ * OpenIB.org BSD license below:
74338+ *
74339+ * Redistribution and use in source and binary forms, with or
74340+ * without modification, are permitted provided that the following
74341+ * conditions are met:
74342+ *
74343+ * - Redistributions of source code must retain the above
74344+ * copyright notice, this list of conditions and the following
74345+ * disclaimer.
74346+ *
74347+ * - Redistributions in binary form must reproduce the above
74348+ * copyright notice, this list of conditions and the following
74349+ * disclaimer in the documentation and/or other materials
74350+ * provided with the distribution.
74351+ *
74352+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
74353+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
74354+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
74355+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
74356+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
74357+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
74358+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
74359+ * SOFTWARE.
74360+ *
74361+ */
74362+
74363+#ifndef IB_SRPT_H
74364+#define IB_SRPT_H
74365+
74366+#include <linux/version.h>
74367+#include <linux/types.h>
74368+#include <linux/list.h>
74369+
74370+#include <rdma/ib_verbs.h>
74371+#include <rdma/ib_sa.h>
74372+#include <rdma/ib_cm.h>
74373+
74374+#include <scsi/srp.h>
74375+
74376+#include <scst/scst.h>
74377+
74378+#include "ib_dm_mad.h"
74379+
74380+/*
74381+ * The prefix the ServiceName field must start with in the device management
74382+ * ServiceEntries attribute pair. See also the SRP r16a document.
74383+ */
74384+#define SRP_SERVICE_NAME_PREFIX "SRP.T10:"
74385+
74386+enum {
74387+ /*
74388+ * SRP IOControllerProfile attributes for SRP target ports that have
74389+ * not been defined in <scsi/srp.h>. Source: section B.7, table B.7
74390+ * in the SRP r16a document.
74391+ */
74392+ SRP_PROTOCOL = 0x0108,
74393+ SRP_PROTOCOL_VERSION = 0x0001,
74394+ SRP_IO_SUBCLASS = 0x609e,
74395+ SRP_SEND_TO_IOC = 0x01,
74396+ SRP_SEND_FROM_IOC = 0x02,
74397+ SRP_RDMA_READ_FROM_IOC = 0x08,
74398+ SRP_RDMA_WRITE_FROM_IOC = 0x20,
74399+
74400+ /*
74401+ * srp_login_cmd.req_flags bitmasks. See also table 9 in the SRP r16a
74402+ * document.
74403+ */
74404+ SRP_MTCH_ACTION = 0x03, /* MULTI-CHANNEL ACTION */
74405+ SRP_LOSOLNT = 0x10, /* logout solicited notification */
74406+ SRP_CRSOLNT = 0x20, /* credit request solicited notification */
74407+ SRP_AESOLNT = 0x40, /* asynchronous event solicited notification */
74408+
74409+ /*
74410+ * srp_cmd.sol_nt / srp_tsk_mgmt.sol_not bitmasks. See also tables
74411+ * 18 and 20 in the T10 r16a document.
74412+ */
74413+ SRP_SCSOLNT = 0x02, /* SCSOLNT = successful solicited notification */
74414+ SRP_UCSOLNT = 0x04, /* UCSOLNT = unsuccessful solicited notification */
74415+
74416+ /*
74417+ * srp_rsp.sol_not / srp_t_logout.sol_not bitmasks. See also tables
74418+ * 16 and 22 in the T10 r16a document.
74419+ */
74420+ SRP_SOLNT = 0x01, /* SOLNT = solicited notification */
74421+
74422+ /* See also table 24 in the T10 r16a document. */
74423+ SRP_TSK_MGMT_SUCCESS = 0x00,
74424+ SRP_TSK_MGMT_FUNC_NOT_SUPP = 0x04,
74425+ SRP_TSK_MGMT_FAILED = 0x05,
74426+
74427+ /* See also table 21 in the T10 r16a document. */
74428+ SRP_CMD_SIMPLE_Q = 0x0,
74429+ SRP_CMD_HEAD_OF_Q = 0x1,
74430+ SRP_CMD_ORDERED_Q = 0x2,
74431+ SRP_CMD_ACA = 0x4,
74432+
74433+ SRP_LOGIN_RSP_MULTICHAN_NO_CHAN = 0x0,
74434+ SRP_LOGIN_RSP_MULTICHAN_TERMINATED = 0x1,
74435+ SRP_LOGIN_RSP_MULTICHAN_MAINTAINED = 0x2,
74436+
74437+ SRPT_DEF_SG_TABLESIZE = 128,
74438+ SRPT_DEF_SG_PER_WQE = 16,
74439+
74440+ MIN_SRPT_SQ_SIZE = 16,
74441+ DEF_SRPT_SQ_SIZE = 4096,
74442+ SRPT_RQ_SIZE = 128,
74443+ MIN_SRPT_SRQ_SIZE = 4,
74444+ DEFAULT_SRPT_SRQ_SIZE = 4095,
74445+ MAX_SRPT_SRQ_SIZE = 65535,
74446+
74447+ MIN_MAX_REQ_SIZE = 996,
74448+ DEFAULT_MAX_REQ_SIZE
74449+ = sizeof(struct srp_cmd)/*48*/
74450+ + sizeof(struct srp_indirect_buf)/*20*/
74451+ + 128 * sizeof(struct srp_direct_buf)/*16*/,
74452+
74453+ MIN_MAX_RSP_SIZE = sizeof(struct srp_rsp)/*36*/ + 4,
74454+ DEFAULT_MAX_RSP_SIZE = 256, /* leaves 220 bytes for sense data */
74455+
74456+ DEFAULT_MAX_RDMA_SIZE = 65536,
74457+};
74458+
74459+static inline u64 encode_wr_id(u8 opcode, u32 idx)
74460+{ return ((u64)opcode << 32) | idx; }
74461+static inline u8 opcode_from_wr_id(u64 wr_id)
74462+{ return wr_id >> 32; }
74463+static inline u32 idx_from_wr_id(u64 wr_id)
74464+{ return (u32)wr_id; }
74465+
74466+struct rdma_iu {
74467+ u64 raddr;
74468+ u32 rkey;
74469+ struct ib_sge *sge;
74470+ u32 sge_cnt;
74471+ int mem_id;
74472+};
74473+
74474+/**
74475+ * enum srpt_command_state - SCSI command state managed by SRPT.
74476+ * @SRPT_STATE_NEW: New command arrived and is being processed.
74477+ * @SRPT_STATE_NEED_DATA: Processing a write or bidir command and waiting
74478+ * for data arrival.
74479+ * @SRPT_STATE_DATA_IN: Data for the write or bidir command arrived and is
74480+ * being processed.
74481+ * @SRPT_STATE_CMD_RSP_SENT: SRP_RSP for SRP_CMD has been sent.
74482+ * @SRPT_STATE_MGMT_RSP_SENT: SRP_RSP for SRP_TSK_MGMT has been sent.
74483+ * @SRPT_STATE_DONE: Command processing finished successfully, command
74484+ * processing has been aborted or command processing
74485+ * failed.
74486+ */
74487+enum srpt_command_state {
74488+ SRPT_STATE_NEW = 0,
74489+ SRPT_STATE_NEED_DATA = 1,
74490+ SRPT_STATE_DATA_IN = 2,
74491+ SRPT_STATE_CMD_RSP_SENT = 3,
74492+ SRPT_STATE_MGMT_RSP_SENT = 4,
74493+ SRPT_STATE_DONE = 5,
74494+};
74495+
74496+/**
74497+ * struct srpt_ioctx - Shared SRPT I/O context information.
74498+ * @buf: Pointer to the buffer.
74499+ * @dma: DMA address of the buffer.
74500+ * @index: Index of the I/O context in its ioctx_ring array.
74501+ */
74502+struct srpt_ioctx {
74503+ void *buf;
74504+ dma_addr_t dma;
74505+ uint32_t index;
74506+};
74507+
74508+/**
74509+ * struct srpt_recv_ioctx - SRPT receive I/O context.
74510+ * @ioctx: See above.
74511+ * @wait_list: Node for insertion in srpt_rdma_ch.cmd_wait_list.
74512+ */
74513+struct srpt_recv_ioctx {
74514+ struct srpt_ioctx ioctx;
74515+ struct list_head wait_list;
74516+};
74517+
74518+/**
74519+ * struct srpt_send_ioctx - SRPT send I/O context.
74520+ * @ioctx: See above.
74521+ * @free_list: Allows to make this struct an entry in srpt_rdma_ch.free_list.
74522+ * @state: I/O context state. See also enum srpt_command_state.
74523+ */
74524+struct srpt_send_ioctx {
74525+ struct srpt_ioctx ioctx;
74526+ struct srpt_rdma_ch *ch;
74527+ struct rdma_iu *rdma_ius;
74528+ struct srp_direct_buf *rbufs;
74529+ struct srp_direct_buf single_rbuf;
74530+ struct scatterlist *sg;
74531+ struct list_head free_list;
74532+ int sg_cnt;
74533+ int mapped_sg_count;
74534+ u16 n_rdma_ius;
74535+ u8 n_rdma;
74536+ u8 n_rbuf;
74537+
74538+ struct scst_cmd *scmnd;
74539+ scst_data_direction dir;
74540+ atomic_t state;
74541+};
74542+
74543+/**
74544+ * struct srpt_mgmt_ioctx - SCST management command context information.
74545+ * @ioctx: SRPT I/O context associated with the management command.
74546+ * @tag: SCSI tag of the management command.
74547+ */
74548+struct srpt_mgmt_ioctx {
74549+ struct srpt_send_ioctx *ioctx;
74550+ u64 tag;
74551+};
74552+
74553+/**
74554+ * enum rdma_ch_state - SRP channel state.
74555+ */
74556+enum rdma_ch_state {
74557+ RDMA_CHANNEL_CONNECTING,
74558+ RDMA_CHANNEL_LIVE,
74559+ RDMA_CHANNEL_DISCONNECTING
74560+};
74561+
74562+/**
74563+ * struct srpt_rdma_ch - RDMA channel.
74564+ * @wait_queue: Allows the kernel thread to wait for more work.
74565+ * @thread: Kernel thread that processes the IB queues associated with
74566+ * the channel.
74567+ * @cm_id: IB CM ID associated with the channel.
74568+ * @rq_size: IB receive queue size.
74569+ * @processing_compl: whether or not an IB completion is being processed.
74570+ * @qp: IB queue pair used for communicating over this channel.
74571+ * @sq_wr_avail: number of work requests available in the send queue.
74572+ * @cq: IB completion queue for this channel.
74573+ * @sport: pointer to the information of the HCA port used by this
74574+ * channel.
74575+ * @i_port_id: 128-bit initiator port identifier copied from SRP_LOGIN_REQ.
74576+ * @t_port_id: 128-bit target port identifier copied from SRP_LOGIN_REQ.
74577+ * @max_ti_iu_len: maximum target-to-initiator information unit length.
74578+ * @supports_cred_req: whether or not the initiator supports SRP_CRED_REQ.
74579+ * @req_lim: request limit: maximum number of requests that may be sent
74580+ * by the initiator without having received a response.
74581+ * @state: channel state. See also enum rdma_ch_state.
74582+ * @list: node for insertion in the srpt_device.rch_list list.
74583+ * @cmd_wait_list: list of SCST commands that arrived before the RTU event. This
74584+ * list contains struct srpt_ioctx elements and is protected
74585+ * against concurrent modification by the cm_id spinlock.
74586+ * @spinlock: Protects free_list.
74587+ * @free_list: Head of list with free send I/O contexts.
74588+ * @scst_sess: SCST session information associated with this SRP channel.
74589+ * @sess_name: SCST session name.
74590+ */
74591+struct srpt_rdma_ch {
74592+ wait_queue_head_t wait_queue;
74593+ struct task_struct *thread;
74594+ struct ib_cm_id *cm_id;
74595+ struct ib_qp *qp;
74596+ int rq_size;
74597+ atomic_t processing_compl;
74598+ struct ib_cq *cq;
74599+ atomic_t sq_wr_avail;
74600+ struct srpt_port *sport;
74601+ u8 i_port_id[16];
74602+ u8 t_port_id[16];
74603+ int max_ti_iu_len;
74604+ atomic_t req_lim;
74605+ atomic_t req_lim_delta;
74606+ spinlock_t spinlock;
74607+ struct list_head free_list;
74608+ struct srpt_send_ioctx **ioctx_ring;
74609+ struct ib_wc wc[16];
74610+ atomic_t state;
74611+ struct list_head list;
74612+ struct list_head cmd_wait_list;
74613+
74614+ struct scst_session *scst_sess;
74615+ u8 sess_name[36];
74616+};
74617+
74618+/**
74619+ * struct srpt_port - Information associated by SRPT with a single IB port.
74620+ * @sdev: backpointer to the HCA information.
74621+ * @mad_agent: per-port management datagram processing information.
74622+ * @port: one-based port number.
74623+ * @sm_lid: cached value of the port's sm_lid.
74624+ * @lid: cached value of the port's lid.
74625+ * @gid: cached value of the port's gid.
74626+ * @work: work structure for refreshing the aforementioned cached values.
74627+ */
74628+struct srpt_port {
74629+ struct srpt_device *sdev;
74630+ struct ib_mad_agent *mad_agent;
74631+ u8 port;
74632+ u16 sm_lid;
74633+ u16 lid;
74634+ union ib_gid gid;
74635+ struct work_struct work;
74636+};
74637+
74638+/**
74639+ * struct srpt_device - Information associated by SRPT with a single HCA.
74640+ * @device: backpointer to the struct ib_device managed by the IB core.
74641+ * @pd: IB protection domain.
74642+ * @mr: L_Key (local key) with write access to all local memory.
74643+ * @srq: Per-HCA SRQ (shared receive queue).
74644+ * @cm_id: connection identifier.
74645+ * @dev_attr: attributes of the InfiniBand device as obtained during the
74646+ * ib_client.add() callback.
74647+ * @ioctx_ring: Per-HCA I/O context ring.
74648+ * @rch_list: per-device channel list -- see also srpt_rdma_ch.list.
74649+ * @spinlock: protects rch_list.
74650+ * @srpt_port: information about the ports owned by this HCA.
74651+ * @event_handler: per-HCA asynchronous IB event handler.
74652+ * @dev: per-port srpt-<portname> device instance.
74653+ * @scst_tgt: SCST target information associated with this HCA.
74654+ * @enabled: Whether or not this SCST target is enabled.
74655+ */
74656+struct srpt_device {
74657+ struct ib_device *device;
74658+ struct ib_pd *pd;
74659+ struct ib_mr *mr;
74660+ struct ib_srq *srq;
74661+ struct ib_cm_id *cm_id;
74662+ struct ib_device_attr dev_attr;
74663+ int srq_size;
74664+ struct srpt_recv_ioctx **ioctx_ring;
74665+ struct list_head rch_list;
74666+ spinlock_t spinlock;
74667+ struct srpt_port port[2];
74668+ struct ib_event_handler event_handler;
74669+ struct device dev;
74670+ struct scst_tgt *scst_tgt;
74671+ bool enabled;
74672+};
74673+
74674+#endif /* IB_SRPT_H */
74675+
74676+/*
74677+ * Local variables:
74678+ * c-basic-offset: 8
74679+ * indent-tabs-mode: t
74680+ * End:
74681+ */
74682diff -uprN orig/linux-2.6.35/Documentation/scst/README.srpt linux-2.6.35/Documentation/scst/README.srpt
74683--- orig/linux-2.6.35/Documentation/scst/README.srpt
74684+++ linux-2.6.35/Documentation/scst/README.srpt
74685@@ -0,0 +1,109 @@
74686+SCSI RDMA Protocol (SRP) Target driver for Linux
74687+=================================================
74688+
74689+The SRP Target driver is designed to work directly on top of the
74690+OpenFabrics OFED-1.x software stack (http://www.openfabrics.org) or
74691+the Infiniband drivers in the Linux kernel tree
74692+(http://www.kernel.org). The SRP target driver also interfaces with
74693+the generic SCSI target mid-level driver called SCST
74694+(http://scst.sourceforge.net).
74695+
74696+How-to run
74697+-----------
74698+
74699+A. On srp target machine
74700+1. Please refer to SCST's README for loading scst driver and its
74701+dev_handlers drivers (scst_disk, scst_vdisk block or file IO mode, nullio, ...)
74702+
74703+Example 1: working with real back-end scsi disks
74704+a. modprobe scst
74705+b. modprobe scst_disk
74706+c. cat /proc/scsi_tgt/scsi_tgt
74707+
74708+ibstor00:~ # cat /proc/scsi_tgt/scsi_tgt
74709+Device (host:ch:id:lun or name) Device handler
74710+0:0:0:0 dev_disk
74711+4:0:0:0 dev_disk
74712+5:0:0:0 dev_disk
74713+6:0:0:0 dev_disk
74714+7:0:0:0 dev_disk
74715+
74716+Now you want to exclude the first scsi disk and expose the last 4 scsi disks as
74717+IB/SRP luns for I/O
74718+echo "add 4:0:0:0 0" >/proc/scsi_tgt/groups/Default/devices
74719+echo "add 5:0:0:0 1" >/proc/scsi_tgt/groups/Default/devices
74720+echo "add 6:0:0:0 2" >/proc/scsi_tgt/groups/Default/devices
74721+echo "add 7:0:0:0 3" >/proc/scsi_tgt/groups/Default/devices
74722+
74723+Example 2: working with VDISK FILEIO mode (using md0 device and file 10G-file)
74724+a. modprobe scst
74725+b. modprobe scst_vdisk
74726+c. echo "open vdisk0 /dev/md0" > /proc/scsi_tgt/vdisk/vdisk
74727+d. echo "open vdisk1 /10G-file" > /proc/scsi_tgt/vdisk/vdisk
74728+e. echo "add vdisk0 0" >/proc/scsi_tgt/groups/Default/devices
74729+f. echo "add vdisk1 1" >/proc/scsi_tgt/groups/Default/devices
74730+
74731+Example 3: working with VDISK BLOCKIO mode (using md0 device, sda, and cciss/c1d0)
74732+a. modprobe scst
74733+b. modprobe scst_vdisk
74734+c. echo "open vdisk0 /dev/md0 BLOCKIO" > /proc/scsi_tgt/vdisk/vdisk
74735+d. echo "open vdisk1 /dev/sda BLOCKIO" > /proc/scsi_tgt/vdisk/vdisk
74736+e. echo "open vdisk2 /dev/cciss/c1d0 BLOCKIO" > /proc/scsi_tgt/vdisk/vdisk
74737+f. echo "add vdisk0 0" >/proc/scsi_tgt/groups/Default/devices
74738+g. echo "add vdisk1 1" >/proc/scsi_tgt/groups/Default/devices
74739+h. echo "add vdisk2 2" >/proc/scsi_tgt/groups/Default/devices
74740+
74741+2. modprobe ib_srpt
74742+
74743+B. On initiator machines you can manualy do the following steps:
74744+1. modprobe ib_srp
74745+2. ibsrpdm -c (to discover new SRP target)
74746+3. echo <new target info> > /sys/class/infiniband_srp/srp-mthca0-1/add_target
74747+4. fdisk -l (will show new discovered scsi disks)
74748+
74749+Example:
74750+Assume that you use port 1 of first HCA in the system ie. mthca0
74751+
74752+[root@lab104 ~]# ibsrpdm -c -d /dev/infiniband/umad0
74753+id_ext=0002c90200226cf4,ioc_guid=0002c90200226cf4,
74754+dgid=fe800000000000000002c90200226cf5,pkey=ffff,service_id=0002c90200226cf4
74755+[root@lab104 ~]# echo id_ext=0002c90200226cf4,ioc_guid=0002c90200226cf4,
74756+dgid=fe800000000000000002c90200226cf5,pkey=ffff,service_id=0002c90200226cf4 >
74757+/sys/class/infiniband_srp/srp-mthca0-1/add_target
74758+
74759+OR
74760+
74761++ You can edit /etc/infiniband/openib.conf to load srp driver and srp HA daemon
74762+automatically ie. set SRP_LOAD=yes, and SRPHA_ENABLE=yes
74763++ To set up and use high availability feature you need dm-multipath driver
74764+and multipath tool
74765++ Please refer to OFED-1.x SRP's user manual for more in-details instructions
74766+on how-to enable/use HA feature
74767+
74768+To minimize QUEUE_FULL conditions, you can apply scst_increase_max_tgt_cmds
74769+patch from SRPT package from http://sourceforge.net/project/showfiles.php?group_id=110471
74770+
74771+Performance notes
74772+-----------------
74773+
74774+In some cases, for instance working with SSD devices, which consume 100%
74775+of a single CPU load for data transfers in their internal threads, to
74776+maximize IOPS it can be needed to assign for those threads dedicated
74777+CPUs using Linux CPU affinity facilities. No IRQ processing should be
74778+done on those CPUs. Check that using /proc/interrupts. See taskset
74779+command and Documentation/IRQ-affinity.txt in your kernel's source tree
74780+for how to assign CPU affinity to tasks and IRQs.
74781+
74782+The reason for that is that processing of coming commands in SIRQ context
74783+can be done on the same CPUs as SSD devices' threads doing data
74784+transfers. As the result, those threads won't receive all the CPU power
74785+and perform worse.
74786+
74787+Alternatively to CPU affinity assignment, you can try to enable SRP
74788+target's internal thread. It will allows Linux CPU scheduler to better
74789+distribute load among available CPUs. To enable SRP target driver's
74790+internal thread you should load ib_srpt module with parameter
74791+"thread=1".
74792+
74793+Send questions about this driver to scst-devel@lists.sourceforge.net, CC:
74794+Vu Pham <vuhuong@mellanox.com> and Bart Van Assche <bart.vanassche@gmail.com>.
74795diff -uprN orig/linux-2.6.35/drivers/scst/scst_local/Kconfig linux-2.6.35/drivers/scst/scst_local/Kconfig
74796--- orig/linux-2.6.35/drivers/scst/scst_local/Kconfig
74797+++ linux-2.6.35/drivers/scst/scst_local/Kconfig
74798@@ -0,0 +1,22 @@
74799+config SCST_LOCAL
74800+ tristate "SCST Local driver"
74801+ depends on SCST && !HIGHMEM4G && !HIGHMEM64G
74802+ ---help---
74803+ This module provides a LLD SCSI driver that connects to
74804+ the SCST target mode subsystem in a loop-back manner.
74805+ It allows you to test target-mode device-handlers locally.
74806+ You will need the SCST subsystem as well.
74807+
74808+ If unsure whether you really want or need this, say N.
74809+
74810+config SCST_LOCAL_FORCE_DIRECT_PROCESSING
74811+ bool "Force local processing"
74812+ depends on SCST_LOCAL
74813+ help
74814+ This experimental option forces scst_local to make SCST process
74815+ SCSI commands in the same context, in which they was submitted.
74816+ Otherwise, they will be processed in SCST threads. Setting this
74817+ option to "Y" will give some performance increase, but might be
74818+ unsafe.
74819+
74820+ If unsure, say "N".
74821diff -uprN orig/linux-2.6.35/drivers/scst/scst_local/Makefile linux-2.6.35/drivers/scst/scst_local/Makefile
74822--- orig/linux-2.6.35/drivers/scst/scst_local/Makefile
74823+++ linux-2.6.35/drivers/scst/scst_local/Makefile
74824@@ -0,0 +1,2 @@
74825+obj-$(CONFIG_SCST_LOCAL) += scst_local.o
74826+
74827diff -uprN orig/linux-2.6.35/drivers/scst/scst_local/scst_local.c linux-2.6.35/drivers/scst/scst_local/scst_local.c
74828--- orig/linux-2.6.35/drivers/scst/scst_local/scst_local.c
74829+++ linux-2.6.35/drivers/scst/scst_local/scst_local.c
74830@@ -0,0 +1,1563 @@
74831+/*
74832+ * Copyright (C) 2008 - 2010 Richard Sharpe
74833+ * Copyright (C) 1992 Eric Youngdale
74834+ * Copyright (C) 2008 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
74835+ *
74836+ * Simulate a host adapter and an SCST target adapter back to back
74837+ *
74838+ * Based on the scsi_debug.c driver originally by Eric Youngdale and
74839+ * others, including D Gilbert et al
74840+ *
74841+ */
74842+
74843+#include <linux/module.h>
74844+
74845+#include <linux/kernel.h>
74846+#include <linux/errno.h>
74847+#include <linux/types.h>
74848+#include <linux/init.h>
74849+#include <linux/moduleparam.h>
74850+#include <linux/scatterlist.h>
74851+#include <linux/slab.h>
74852+#include <linux/completion.h>
74853+#include <linux/spinlock.h>
74854+
74855+#include <scsi/scsi.h>
74856+#include <scsi/scsi_cmnd.h>
74857+#include <scsi/scsi_host.h>
74858+#include <scsi/scsi_tcq.h>
74859+
74860+#define LOG_PREFIX "scst_local"
74861+
74862+/* SCST includes ... */
74863+#include <scst/scst_const.h>
74864+#include <scst/scst.h>
74865+#include <scst/scst_debug.h>
74866+
74867+#ifdef CONFIG_SCST_DEBUG
74868+#define SCST_LOCAL_DEFAULT_LOG_FLAGS (TRACE_FUNCTION | TRACE_PID | \
74869+ TRACE_LINE | TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MGMT_DEBUG | \
74870+ TRACE_MINOR | TRACE_SPECIAL)
74871+#else
74872+# ifdef CONFIG_SCST_TRACING
74873+#define SCST_LOCAL_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
74874+ TRACE_SPECIAL)
74875+# endif
74876+#endif
74877+
74878+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
74879+#define trace_flag scst_local_trace_flag
74880+static unsigned long scst_local_trace_flag = SCST_LOCAL_DEFAULT_LOG_FLAGS;
74881+#endif
74882+
74883+#define TRUE 1
74884+#define FALSE 0
74885+
74886+#define SCST_LOCAL_VERSION "1.0.0"
74887+static const char *scst_local_version_date = "20100910";
74888+
74889+/* Some statistics */
74890+static atomic_t num_aborts = ATOMIC_INIT(0);
74891+static atomic_t num_dev_resets = ATOMIC_INIT(0);
74892+static atomic_t num_target_resets = ATOMIC_INIT(0);
74893+
74894+static bool scst_local_add_default_tgt = true;
74895+module_param_named(add_default_tgt, scst_local_add_default_tgt, bool, S_IRUGO);
74896+MODULE_PARM_DESC(add_default_tgt, "add (default) or not on start default "
74897+ "target scst_local_tgt with default session scst_local_host");
74898+
74899+struct scst_aen_work_item {
74900+ struct list_head work_list_entry;
74901+ struct scst_aen *aen;
74902+};
74903+
74904+struct scst_local_tgt {
74905+ struct scst_tgt *scst_tgt;
74906+ struct list_head sessions_list; /* protected by scst_local_mutex */
74907+ struct list_head tgts_list_entry;
74908+
74909+ /* SCSI version descriptors */
74910+ uint16_t scsi_transport_version;
74911+ uint16_t phys_transport_version;
74912+};
74913+
74914+struct scst_local_sess {
74915+ struct scst_session *scst_sess;
74916+
74917+ unsigned int unregistering:1;
74918+
74919+ struct device dev;
74920+ struct Scsi_Host *shost;
74921+ struct scst_local_tgt *tgt;
74922+
74923+ int number;
74924+
74925+ struct mutex tr_id_mutex;
74926+ uint8_t *transport_id;
74927+ int transport_id_len;
74928+
74929+ struct work_struct aen_work;
74930+ spinlock_t aen_lock;
74931+ struct list_head aen_work_list; /* protected by aen_lock */
74932+
74933+ struct list_head sessions_list_entry;
74934+};
74935+
74936+#define to_scst_lcl_sess(d) \
74937+ container_of(d, struct scst_local_sess, dev)
74938+
74939+static int __scst_local_add_adapter(struct scst_local_tgt *tgt,
74940+ const char *initiator_name, struct scst_local_sess **out_sess,
74941+ bool locked);
74942+static int scst_local_add_adapter(struct scst_local_tgt *tgt,
74943+ const char *initiator_name, struct scst_local_sess **out_sess);
74944+static void scst_local_remove_adapter(struct scst_local_sess *sess);
74945+static int scst_local_add_target(const char *target_name,
74946+ struct scst_local_tgt **out_tgt);
74947+static void __scst_local_remove_target(struct scst_local_tgt *tgt);
74948+static void scst_local_remove_target(struct scst_local_tgt *tgt);
74949+
74950+static atomic_t scst_local_sess_num = ATOMIC_INIT(0);
74951+
74952+static LIST_HEAD(scst_local_tgts_list);
74953+static DEFINE_MUTEX(scst_local_mutex);
74954+
74955+static DECLARE_RWSEM(scst_local_exit_rwsem);
74956+
74957+MODULE_AUTHOR("Richard Sharpe, Vladislav Bolkhovitin + ideas from SCSI_DEBUG");
74958+MODULE_DESCRIPTION("SCSI+SCST local adapter driver");
74959+MODULE_LICENSE("GPL");
74960+MODULE_VERSION(SCST_LOCAL_VERSION);
74961+
74962+static int scst_local_get_sas_transport_id(struct scst_local_sess *sess,
74963+ uint8_t **transport_id, int *len)
74964+{
74965+ int res = 0;
74966+ int tr_id_size = 0;
74967+ uint8_t *tr_id = NULL;
74968+
74969+ TRACE_ENTRY();
74970+
74971+ tr_id_size = 24; /* A SAS TransportID */
74972+
74973+ tr_id = kzalloc(tr_id_size, GFP_KERNEL);
74974+ if (tr_id == NULL) {
74975+ PRINT_ERROR("Allocation of TransportID (size %d) failed",
74976+ tr_id_size);
74977+ res = -ENOMEM;
74978+ goto out;
74979+ }
74980+
74981+ tr_id[0] = 0x00 | SCSI_TRANSPORTID_PROTOCOLID_SAS;
74982+
74983+ /*
74984+ * Assemble a valid SAS address = 0x5OOUUIIR12345678 ... Does SCST
74985+ * have one?
74986+ */
74987+
74988+ tr_id[4] = 0x5F;
74989+ tr_id[5] = 0xEE;
74990+ tr_id[6] = 0xDE;
74991+ tr_id[7] = 0x40 | ((sess->number >> 4) & 0x0F);
74992+ tr_id[8] = 0x0F | (sess->number & 0xF0);
74993+ tr_id[9] = 0xAD;
74994+ tr_id[10] = 0xE0;
74995+ tr_id[11] = 0x50;
74996+
74997+ *transport_id = tr_id;
74998+ *len = tr_id_size;
74999+
75000+ TRACE_DBG("Created tid '%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'",
75001+ tr_id[4], tr_id[5], tr_id[6], tr_id[7],
75002+ tr_id[8], tr_id[9], tr_id[10], tr_id[11]);
75003+
75004+out:
75005+ TRACE_EXIT_RES(res);
75006+ return res;
75007+}
75008+
75009+static int scst_local_get_initiator_port_transport_id(
75010+ struct scst_session *scst_sess, uint8_t **transport_id)
75011+{
75012+ int res = 0;
75013+ int tr_id_size = 0;
75014+ uint8_t *tr_id = NULL;
75015+ struct scst_local_sess *sess;
75016+
75017+ TRACE_ENTRY();
75018+
75019+ if (scst_sess == NULL) {
75020+ res = SCSI_TRANSPORTID_PROTOCOLID_SAS;
75021+ goto out;
75022+ }
75023+
75024+ sess = (struct scst_local_sess *)scst_sess_get_tgt_priv(scst_sess);
75025+
75026+ mutex_lock(&sess->tr_id_mutex);
75027+
75028+ if (sess->transport_id == NULL) {
75029+ res = scst_local_get_sas_transport_id(sess,
75030+ transport_id, &tr_id_size);
75031+ goto out_unlock;
75032+ }
75033+
75034+ tr_id_size = sess->transport_id_len;
75035+ BUG_ON(tr_id_size == 0);
75036+
75037+ tr_id = kzalloc(tr_id_size, GFP_KERNEL);
75038+ if (tr_id == NULL) {
75039+ PRINT_ERROR("Allocation of TransportID (size %d) failed",
75040+ tr_id_size);
75041+ res = -ENOMEM;
75042+ goto out;
75043+ }
75044+
75045+ memcpy(tr_id, sess->transport_id, sess->transport_id_len);
75046+
75047+out_unlock:
75048+ mutex_unlock(&sess->tr_id_mutex);
75049+
75050+out:
75051+ TRACE_EXIT_RES(res);
75052+ return res;
75053+}
75054+
75055+/**
75056+ ** Tgtt attributes
75057+ **/
75058+
75059+static ssize_t scst_local_version_show(struct kobject *kobj,
75060+ struct kobj_attribute *attr, char *buf)
75061+{
75062+ sprintf(buf, "%s/%s\n", SCST_LOCAL_VERSION, scst_local_version_date);
75063+
75064+#ifdef CONFIG_SCST_EXTRACHECKS
75065+ strcat(buf, "EXTRACHECKS\n");
75066+#endif
75067+
75068+#ifdef CONFIG_SCST_TRACING
75069+ strcat(buf, "TRACING\n");
75070+#endif
75071+
75072+#ifdef CONFIG_SCST_DEBUG
75073+ strcat(buf, "DEBUG\n");
75074+#endif
75075+
75076+ TRACE_EXIT();
75077+ return strlen(buf);
75078+}
75079+
75080+static struct kobj_attribute scst_local_version_attr =
75081+ __ATTR(version, S_IRUGO, scst_local_version_show, NULL);
75082+
75083+static ssize_t scst_local_stats_show(struct kobject *kobj,
75084+ struct kobj_attribute *attr, char *buf)
75085+
75086+{
75087+ return sprintf(buf, "Aborts: %d, Device Resets: %d, Target Resets: %d",
75088+ atomic_read(&num_aborts), atomic_read(&num_dev_resets),
75089+ atomic_read(&num_target_resets));
75090+}
75091+
75092+static struct kobj_attribute scst_local_stats_attr =
75093+ __ATTR(stats, S_IRUGO, scst_local_stats_show, NULL);
75094+
75095+static const struct attribute *scst_local_tgtt_attrs[] = {
75096+ &scst_local_version_attr.attr,
75097+ &scst_local_stats_attr.attr,
75098+ NULL,
75099+};
75100+
75101+/**
75102+ ** Tgt attributes
75103+ **/
75104+
75105+static ssize_t scst_local_scsi_transport_version_show(struct kobject *kobj,
75106+ struct kobj_attribute *attr, char *buf)
75107+{
75108+ struct scst_tgt *scst_tgt;
75109+ struct scst_local_tgt *tgt;
75110+ ssize_t res;
75111+
75112+ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
75113+ return -ENOENT;
75114+
75115+ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
75116+ tgt = (struct scst_local_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
75117+
75118+ if (tgt->scsi_transport_version != 0)
75119+ res = sprintf(buf, "0x%x\n%s", tgt->scsi_transport_version,
75120+ SCST_SYSFS_KEY_MARK "\n");
75121+ else
75122+ res = sprintf(buf, "0x%x\n", 0x0BE0); /* SAS */
75123+
75124+ up_read(&scst_local_exit_rwsem);
75125+ return res;
75126+}
75127+
75128+static ssize_t scst_local_scsi_transport_version_store(struct kobject *kobj,
75129+ struct kobj_attribute *attr, const char *buffer, size_t size)
75130+{
75131+ ssize_t res;
75132+ struct scst_tgt *scst_tgt;
75133+ struct scst_local_tgt *tgt;
75134+ unsigned long val;
75135+
75136+ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
75137+ return -ENOENT;
75138+
75139+ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
75140+ tgt = (struct scst_local_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
75141+
75142+ res = strict_strtoul(buffer, 0, &val);
75143+ if (res != 0) {
75144+ PRINT_ERROR("strict_strtoul() for %s failed: %zd", buffer, res);
75145+ goto out_up;
75146+ }
75147+
75148+ tgt->scsi_transport_version = val;
75149+
75150+ res = size;
75151+
75152+out_up:
75153+ up_read(&scst_local_exit_rwsem);
75154+ return res;
75155+}
75156+
75157+static struct kobj_attribute scst_local_scsi_transport_version_attr =
75158+ __ATTR(scsi_transport_version, S_IRUGO | S_IWUSR,
75159+ scst_local_scsi_transport_version_show,
75160+ scst_local_scsi_transport_version_store);
75161+
75162+static ssize_t scst_local_phys_transport_version_show(struct kobject *kobj,
75163+ struct kobj_attribute *attr, char *buf)
75164+{
75165+ struct scst_tgt *scst_tgt;
75166+ struct scst_local_tgt *tgt;
75167+ ssize_t res;
75168+
75169+ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
75170+ return -ENOENT;
75171+
75172+ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
75173+ tgt = (struct scst_local_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
75174+
75175+ res = sprintf(buf, "0x%x\n%s", tgt->phys_transport_version,
75176+ (tgt->phys_transport_version != 0) ?
75177+ SCST_SYSFS_KEY_MARK "\n" : "");
75178+
75179+ up_read(&scst_local_exit_rwsem);
75180+ return res;
75181+}
75182+
75183+static ssize_t scst_local_phys_transport_version_store(struct kobject *kobj,
75184+ struct kobj_attribute *attr, const char *buffer, size_t size)
75185+{
75186+ ssize_t res;
75187+ struct scst_tgt *scst_tgt;
75188+ struct scst_local_tgt *tgt;
75189+ unsigned long val;
75190+
75191+ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
75192+ return -ENOENT;
75193+
75194+ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
75195+ tgt = (struct scst_local_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
75196+
75197+ res = strict_strtoul(buffer, 0, &val);
75198+ if (res != 0) {
75199+ PRINT_ERROR("strict_strtoul() for %s failed: %zd", buffer, res);
75200+ goto out_up;
75201+ }
75202+
75203+ tgt->phys_transport_version = val;
75204+
75205+ res = size;
75206+
75207+out_up:
75208+ up_read(&scst_local_exit_rwsem);
75209+ return res;
75210+}
75211+
75212+static struct kobj_attribute scst_local_phys_transport_version_attr =
75213+ __ATTR(phys_transport_version, S_IRUGO | S_IWUSR,
75214+ scst_local_phys_transport_version_show,
75215+ scst_local_phys_transport_version_store);
75216+
75217+static const struct attribute *scst_local_tgt_attrs[] = {
75218+ &scst_local_scsi_transport_version_attr.attr,
75219+ &scst_local_phys_transport_version_attr.attr,
75220+ NULL,
75221+};
75222+
75223+/**
75224+ ** Session attributes
75225+ **/
75226+
75227+static ssize_t scst_local_transport_id_show(struct kobject *kobj,
75228+ struct kobj_attribute *attr, char *buf)
75229+{
75230+ ssize_t res;
75231+ struct scst_session *scst_sess;
75232+ struct scst_local_sess *sess;
75233+ uint8_t *tr_id;
75234+ int tr_id_len, i;
75235+
75236+ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
75237+ return -ENOENT;
75238+
75239+ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
75240+ sess = (struct scst_local_sess *)scst_sess_get_tgt_priv(scst_sess);
75241+
75242+ mutex_lock(&sess->tr_id_mutex);
75243+
75244+ if (sess->transport_id != NULL) {
75245+ tr_id = sess->transport_id;
75246+ tr_id_len = sess->transport_id_len;
75247+ } else {
75248+ res = scst_local_get_sas_transport_id(sess, &tr_id, &tr_id_len);
75249+ if (res != 0)
75250+ goto out_unlock;
75251+ }
75252+
75253+ res = 0;
75254+ for (i = 0; i < tr_id_len; i++)
75255+ res += sprintf(&buf[res], "%c", tr_id[i]);
75256+
75257+ if (sess->transport_id == NULL)
75258+ kfree(tr_id);
75259+
75260+out_unlock:
75261+ mutex_unlock(&sess->tr_id_mutex);
75262+ up_read(&scst_local_exit_rwsem);
75263+ return res;
75264+}
75265+
75266+static ssize_t scst_local_transport_id_store(struct kobject *kobj,
75267+ struct kobj_attribute *attr, const char *buffer, size_t size)
75268+{
75269+ ssize_t res;
75270+ struct scst_session *scst_sess;
75271+ struct scst_local_sess *sess;
75272+
75273+ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
75274+ return -ENOENT;
75275+
75276+ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
75277+ sess = (struct scst_local_sess *)scst_sess_get_tgt_priv(scst_sess);
75278+
75279+ mutex_lock(&sess->tr_id_mutex);
75280+
75281+ if (sess->transport_id != NULL) {
75282+ kfree(sess->transport_id);
75283+ sess->transport_id = NULL;
75284+ sess->transport_id_len = 0;
75285+ }
75286+
75287+ if (size == 0)
75288+ goto out_res;
75289+
75290+ sess->transport_id = kzalloc(size, GFP_KERNEL);
75291+ if (sess->transport_id == NULL) {
75292+ PRINT_ERROR("Allocation of transport_id (size %zd) failed",
75293+ size);
75294+ res = -ENOMEM;
75295+ goto out_unlock;
75296+ }
75297+
75298+ sess->transport_id_len = size;
75299+
75300+ memcpy(sess->transport_id, buffer, sess->transport_id_len);
75301+
75302+out_res:
75303+ res = size;
75304+
75305+out_unlock:
75306+ mutex_unlock(&sess->tr_id_mutex);
75307+ up_read(&scst_local_exit_rwsem);
75308+ return res;
75309+}
75310+
75311+static struct kobj_attribute scst_local_transport_id_attr =
75312+ __ATTR(transport_id, S_IRUGO | S_IWUSR,
75313+ scst_local_transport_id_show,
75314+ scst_local_transport_id_store);
75315+
75316+static const struct attribute *scst_local_sess_attrs[] = {
75317+ &scst_local_transport_id_attr.attr,
75318+ NULL,
75319+};
75320+
75321+static ssize_t scst_local_sysfs_add_target(const char *target_name, char *params)
75322+{
75323+ int res;
75324+ struct scst_local_tgt *tgt;
75325+ char *param, *p;
75326+
75327+ TRACE_ENTRY();
75328+
75329+ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
75330+ return -ENOENT;
75331+
75332+ res = scst_local_add_target(target_name, &tgt);
75333+ if (res != 0)
75334+ goto out_up;
75335+
75336+ while (1) {
75337+ param = scst_get_next_token_str(&params);
75338+ if (param == NULL)
75339+ break;
75340+
75341+ p = scst_get_next_lexem(&param);
75342+ if (*p == '\0')
75343+ break;
75344+
75345+ if (strcasecmp("session_name", p) != 0) {
75346+ PRINT_ERROR("Unknown parameter %s", p);
75347+ res = -EINVAL;
75348+ goto out_remove;
75349+ }
75350+
75351+ p = scst_get_next_lexem(&param);
75352+ if (*p == '\0') {
75353+ PRINT_ERROR("Wrong session name %s", p);
75354+ res = -EINVAL;
75355+ goto out_remove;
75356+ }
75357+
75358+ res = scst_local_add_adapter(tgt, p, NULL);
75359+ if (res != 0)
75360+ goto out_remove;
75361+ }
75362+
75363+out_up:
75364+ up_read(&scst_local_exit_rwsem);
75365+
75366+ TRACE_EXIT_RES(res);
75367+ return res;
75368+
75369+out_remove:
75370+ scst_local_remove_target(tgt);
75371+ goto out_up;
75372+}
75373+
75374+static ssize_t scst_local_sysfs_del_target(const char *target_name)
75375+{
75376+ int res;
75377+ struct scst_local_tgt *tgt;
75378+ bool deleted = false;
75379+
75380+ TRACE_ENTRY();
75381+
75382+ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
75383+ return -ENOENT;
75384+
75385+ mutex_lock(&scst_local_mutex);
75386+ list_for_each_entry(tgt, &scst_local_tgts_list, tgts_list_entry) {
75387+ if (strcmp(target_name, tgt->scst_tgt->tgt_name) == 0) {
75388+ __scst_local_remove_target(tgt);
75389+ deleted = true;
75390+ break;
75391+ }
75392+ }
75393+ mutex_unlock(&scst_local_mutex);
75394+
75395+ if (!deleted) {
75396+ PRINT_ERROR("Target %s not found", target_name);
75397+ res = -ENOENT;
75398+ goto out_up;
75399+ }
75400+
75401+ res = 0;
75402+
75403+out_up:
75404+ up_read(&scst_local_exit_rwsem);
75405+
75406+ TRACE_EXIT_RES(res);
75407+ return res;
75408+}
75409+
75410+static ssize_t scst_local_sysfs_mgmt_cmd(char *buf)
75411+{
75412+ ssize_t res;
75413+ char *command, *target_name, *session_name;
75414+ struct scst_local_tgt *t, *tgt;
75415+
75416+ TRACE_ENTRY();
75417+
75418+ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
75419+ return -ENOENT;
75420+
75421+ command = scst_get_next_lexem(&buf);
75422+
75423+ target_name = scst_get_next_lexem(&buf);
75424+ if (*target_name == '\0') {
75425+ PRINT_ERROR("%s", "Target name required");
75426+ res = -EINVAL;
75427+ goto out_up;
75428+ }
75429+
75430+ mutex_lock(&scst_local_mutex);
75431+
75432+ tgt = NULL;
75433+ list_for_each_entry(t, &scst_local_tgts_list, tgts_list_entry) {
75434+ if (strcmp(t->scst_tgt->tgt_name, target_name) == 0) {
75435+ tgt = t;
75436+ break;
75437+ }
75438+ }
75439+ if (tgt == NULL) {
75440+ PRINT_ERROR("Target %s not found", target_name);
75441+ res = -EINVAL;
75442+ goto out_unlock;
75443+ }
75444+
75445+ session_name = scst_get_next_lexem(&buf);
75446+ if (*session_name == '\0') {
75447+ PRINT_ERROR("%s", "Session name required");
75448+ res = -EINVAL;
75449+ goto out_unlock;
75450+ }
75451+
75452+ if (strcasecmp("add_session", command) == 0) {
75453+ res = __scst_local_add_adapter(tgt, session_name, NULL, true);
75454+ } else if (strcasecmp("del_session", command) == 0) {
75455+ struct scst_local_sess *s, *sess = NULL;
75456+ list_for_each_entry(s, &tgt->sessions_list,
75457+ sessions_list_entry) {
75458+ if (strcmp(s->scst_sess->initiator_name, session_name) == 0) {
75459+ sess = s;
75460+ break;
75461+ }
75462+ }
75463+ if (sess == NULL) {
75464+ PRINT_ERROR("Session %s not found (target %s)",
75465+ session_name, target_name);
75466+ res = -EINVAL;
75467+ goto out_unlock;
75468+ }
75469+ scst_local_remove_adapter(sess);
75470+ }
75471+
75472+ res = 0;
75473+
75474+out_unlock:
75475+ mutex_unlock(&scst_local_mutex);
75476+
75477+out_up:
75478+ up_read(&scst_local_exit_rwsem);
75479+
75480+ TRACE_EXIT_RES(res);
75481+ return res;
75482+}
75483+
75484+static int scst_local_abort(struct scsi_cmnd *SCpnt)
75485+{
75486+ struct scst_local_sess *sess;
75487+ int ret;
75488+ DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
75489+
75490+ TRACE_ENTRY();
75491+
75492+ sess = to_scst_lcl_sess(scsi_get_device(SCpnt->device->host));
75493+
75494+ ret = scst_rx_mgmt_fn_tag(sess->scst_sess, SCST_ABORT_TASK, SCpnt->tag,
75495+ FALSE, &dev_reset_completion);
75496+
75497+ /* Now wait for the completion ... */
75498+ wait_for_completion_interruptible(&dev_reset_completion);
75499+
75500+ atomic_inc(&num_aborts);
75501+
75502+ if (ret == 0)
75503+ ret = SUCCESS;
75504+
75505+ TRACE_EXIT_RES(ret);
75506+ return ret;
75507+}
75508+
75509+static int scst_local_device_reset(struct scsi_cmnd *SCpnt)
75510+{
75511+ struct scst_local_sess *sess;
75512+ uint16_t lun;
75513+ int ret;
75514+ DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
75515+
75516+ TRACE_ENTRY();
75517+
75518+ sess = to_scst_lcl_sess(scsi_get_device(SCpnt->device->host));
75519+
75520+ lun = SCpnt->device->lun;
75521+ lun = cpu_to_be16(lun);
75522+
75523+ ret = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_LUN_RESET,
75524+ (const uint8_t *)&lun, sizeof(lun), FALSE,
75525+ &dev_reset_completion);
75526+
75527+ /* Now wait for the completion ... */
75528+ wait_for_completion_interruptible(&dev_reset_completion);
75529+
75530+ atomic_inc(&num_dev_resets);
75531+
75532+ if (ret == 0)
75533+ ret = SUCCESS;
75534+
75535+ TRACE_EXIT_RES(ret);
75536+ return ret;
75537+}
75538+
75539+static int scst_local_target_reset(struct scsi_cmnd *SCpnt)
75540+{
75541+ struct scst_local_sess *sess;
75542+ uint16_t lun;
75543+ int ret;
75544+ DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
75545+
75546+ TRACE_ENTRY();
75547+
75548+ sess = to_scst_lcl_sess(scsi_get_device(SCpnt->device->host));
75549+
75550+ lun = SCpnt->device->lun;
75551+ lun = cpu_to_be16(lun);
75552+
75553+ ret = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_TARGET_RESET,
75554+ (const uint8_t *)&lun, sizeof(lun), FALSE,
75555+ &dev_reset_completion);
75556+
75557+ /* Now wait for the completion ... */
75558+ wait_for_completion_interruptible(&dev_reset_completion);
75559+
75560+ atomic_inc(&num_target_resets);
75561+
75562+ if (ret == 0)
75563+ ret = SUCCESS;
75564+
75565+ TRACE_EXIT_RES(ret);
75566+ return ret;
75567+}
75568+
75569+static void copy_sense(struct scsi_cmnd *cmnd, struct scst_cmd *scst_cmnd)
75570+{
75571+ int scst_cmnd_sense_len = scst_cmd_get_sense_buffer_len(scst_cmnd);
75572+
75573+ TRACE_ENTRY();
75574+
75575+ scst_cmnd_sense_len = (SCSI_SENSE_BUFFERSIZE < scst_cmnd_sense_len ?
75576+ SCSI_SENSE_BUFFERSIZE : scst_cmnd_sense_len);
75577+ memcpy(cmnd->sense_buffer, scst_cmd_get_sense_buffer(scst_cmnd),
75578+ scst_cmnd_sense_len);
75579+
75580+ TRACE_BUFFER("Sense set", cmnd->sense_buffer, scst_cmnd_sense_len);
75581+
75582+ TRACE_EXIT();
75583+ return;
75584+}
75585+
75586+/*
75587+ * Utility function to handle processing of done and allow
75588+ * easy insertion of error injection if desired
75589+ */
75590+static int scst_local_send_resp(struct scsi_cmnd *cmnd,
75591+ struct scst_cmd *scst_cmnd,
75592+ void (*done)(struct scsi_cmnd *),
75593+ int scsi_result)
75594+{
75595+ int ret = 0;
75596+
75597+ TRACE_ENTRY();
75598+
75599+ if (scst_cmnd) {
75600+ /* The buffer isn't ours, so let's be safe and restore it */
75601+ scst_check_restore_sg_buff(scst_cmnd);
75602+
75603+ /* Simulate autosense by this driver */
75604+ if (unlikely(SCST_SENSE_VALID(scst_cmnd->sense)))
75605+ copy_sense(cmnd, scst_cmnd);
75606+ }
75607+
75608+ cmnd->result = scsi_result;
75609+
75610+ done(cmnd);
75611+
75612+ TRACE_EXIT_RES(ret);
75613+ return ret;
75614+}
75615+
75616+/*
75617+ * This does the heavy lifting ... we pass all the commands on to the
75618+ * target driver and have it do its magic ...
75619+ */
75620+static int scst_local_queuecommand(struct scsi_cmnd *SCpnt,
75621+ void (*done)(struct scsi_cmnd *))
75622+ __acquires(&h->host_lock)
75623+ __releases(&h->host_lock)
75624+{
75625+ struct scst_local_sess *sess;
75626+ struct scatterlist *sgl = NULL;
75627+ int sgl_count = 0;
75628+ uint16_t lun;
75629+ struct scst_cmd *scst_cmd = NULL;
75630+ scst_data_direction dir;
75631+
75632+ TRACE_ENTRY();
75633+
75634+ TRACE_DBG("lun %d, cmd: 0x%02X", SCpnt->device->lun, SCpnt->cmnd[0]);
75635+
75636+ sess = to_scst_lcl_sess(scsi_get_device(SCpnt->device->host));
75637+
75638+ scsi_set_resid(SCpnt, 0);
75639+
75640+ /*
75641+ * We save a pointer to the done routine in SCpnt->scsi_done and
75642+ * we save that as tgt specific stuff below.
75643+ */
75644+ SCpnt->scsi_done = done;
75645+
75646+ /*
75647+ * Tell the target that we have a command ... but first we need
75648+ * to get the LUN into a format that SCST understand
75649+ */
75650+ lun = SCpnt->device->lun;
75651+ lun = cpu_to_be16(lun);
75652+ scst_cmd = scst_rx_cmd(sess->scst_sess, (const uint8_t *)&lun,
75653+ sizeof(lun), SCpnt->cmnd, SCpnt->cmd_len, TRUE);
75654+ if (!scst_cmd) {
75655+ PRINT_ERROR("%s", "scst_rx_cmd() failed");
75656+ return -ENOMEM;
75657+ }
75658+
75659+ scst_cmd_set_tag(scst_cmd, SCpnt->tag);
75660+ switch (scsi_get_tag_type(SCpnt->device)) {
75661+ case MSG_SIMPLE_TAG:
75662+ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_SIMPLE);
75663+ break;
75664+ case MSG_HEAD_TAG:
75665+ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
75666+ break;
75667+ case MSG_ORDERED_TAG:
75668+ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_ORDERED);
75669+ break;
75670+ case SCSI_NO_TAG:
75671+ default:
75672+ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_UNTAGGED);
75673+ break;
75674+ }
75675+
75676+ sgl = scsi_sglist(SCpnt);
75677+ sgl_count = scsi_sg_count(SCpnt);
75678+
75679+ dir = SCST_DATA_NONE;
75680+ switch (SCpnt->sc_data_direction) {
75681+ case DMA_TO_DEVICE:
75682+ dir = SCST_DATA_WRITE;
75683+ scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt));
75684+ scst_cmd_set_tgt_sg(scst_cmd, sgl, sgl_count);
75685+ break;
75686+ case DMA_FROM_DEVICE:
75687+ dir = SCST_DATA_READ;
75688+ scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt));
75689+ scst_cmd_set_tgt_sg(scst_cmd, sgl, sgl_count);
75690+ break;
75691+ case DMA_BIDIRECTIONAL:
75692+ /* Some of these symbols are only defined after 2.6.24 */
75693+ dir = SCST_DATA_BIDI;
75694+ scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt));
75695+ scst_cmd_set_expected_out_transfer_len(scst_cmd,
75696+ scsi_in(SCpnt)->length);
75697+ scst_cmd_set_tgt_sg(scst_cmd, scsi_in(SCpnt)->table.sgl,
75698+ scsi_in(SCpnt)->table.nents);
75699+ scst_cmd_set_tgt_out_sg(scst_cmd, sgl, sgl_count);
75700+ break;
75701+ case DMA_NONE:
75702+ default:
75703+ dir = SCST_DATA_NONE;
75704+ scst_cmd_set_expected(scst_cmd, dir, 0);
75705+ break;
75706+ }
75707+
75708+ /* Save the correct thing below depending on version */
75709+ scst_cmd_set_tgt_priv(scst_cmd, SCpnt);
75710+
75711+#ifdef CONFIG_SCST_LOCAL_FORCE_DIRECT_PROCESSING
75712+ {
75713+ struct Scsi_Host *h = SCpnt->device->host;
75714+ spin_unlock_irq(h->host_lock);
75715+ scst_cmd_init_done(scst_cmd, scst_estimate_context_direct());
75716+ spin_lock_irq(h->host_lock);
75717+ }
75718+#else
75719+ /*
75720+ * Unfortunately, we called with IRQs disabled, so have no choice,
75721+ * except to pass to the thread context.
75722+ */
75723+ scst_cmd_init_done(scst_cmd, SCST_CONTEXT_THREAD);
75724+#endif
75725+
75726+ TRACE_EXIT();
75727+ return 0;
75728+}
75729+
75730+static int scst_local_targ_pre_exec(struct scst_cmd *scst_cmd)
75731+{
75732+ int res = SCST_PREPROCESS_STATUS_SUCCESS;
75733+
75734+ TRACE_ENTRY();
75735+
75736+ if (scst_cmd_get_dh_data_buff_alloced(scst_cmd) &&
75737+ (scst_cmd_get_data_direction(scst_cmd) & SCST_DATA_WRITE))
75738+ scst_copy_sg(scst_cmd, SCST_SG_COPY_FROM_TARGET);
75739+
75740+ TRACE_EXIT_RES(res);
75741+ return res;
75742+}
75743+
75744+/* Must be called under sess->aen_lock. Drops then reacquires it inside. */
75745+static void scst_process_aens(struct scst_local_sess *sess,
75746+ bool cleanup_only)
75747+{
75748+ struct scst_aen_work_item *work_item = NULL;
75749+
75750+ TRACE_ENTRY();
75751+
75752+ TRACE_DBG("Target work sess %p", sess);
75753+
75754+ while (!list_empty(&sess->aen_work_list)) {
75755+ work_item = list_entry(sess->aen_work_list.next,
75756+ struct scst_aen_work_item, work_list_entry);
75757+ list_del(&work_item->work_list_entry);
75758+
75759+ spin_unlock(&sess->aen_lock);
75760+
75761+ if (cleanup_only)
75762+ goto done;
75763+
75764+ BUG_ON(work_item->aen->event_fn != SCST_AEN_SCSI);
75765+
75766+ /* Let's always rescan */
75767+ scsi_scan_target(&sess->shost->shost_gendev, 0, 0,
75768+ SCAN_WILD_CARD, 1);
75769+
75770+done:
75771+ scst_aen_done(work_item->aen);
75772+ kfree(work_item);
75773+
75774+ spin_lock(&sess->aen_lock);
75775+ }
75776+
75777+ TRACE_EXIT();
75778+ return;
75779+}
75780+
75781+static void scst_aen_work_fn(struct work_struct *work)
75782+{
75783+ struct scst_local_sess *sess =
75784+ container_of(work, struct scst_local_sess, aen_work);
75785+
75786+ TRACE_ENTRY();
75787+
75788+ TRACE_MGMT_DBG("Target work %p)", sess);
75789+
75790+ spin_lock(&sess->aen_lock);
75791+ scst_process_aens(sess, false);
75792+ spin_unlock(&sess->aen_lock);
75793+
75794+ TRACE_EXIT();
75795+ return;
75796+}
75797+
75798+static int scst_local_report_aen(struct scst_aen *aen)
75799+{
75800+ int res = 0;
75801+ int event_fn = scst_aen_get_event_fn(aen);
75802+ struct scst_local_sess *sess;
75803+ struct scst_aen_work_item *work_item = NULL;
75804+
75805+ TRACE_ENTRY();
75806+
75807+ sess = (struct scst_local_sess *)scst_sess_get_tgt_priv(
75808+ scst_aen_get_sess(aen));
75809+ switch (event_fn) {
75810+ case SCST_AEN_SCSI:
75811+ /*
75812+ * Allocate a work item and place it on the queue
75813+ */
75814+ work_item = kzalloc(sizeof(*work_item), GFP_KERNEL);
75815+ if (!work_item) {
75816+ PRINT_ERROR("%s", "Unable to allocate work item "
75817+ "to handle AEN!");
75818+ return -ENOMEM;
75819+ }
75820+
75821+ spin_lock(&sess->aen_lock);
75822+
75823+ if (unlikely(sess->unregistering)) {
75824+ spin_unlock(&sess->aen_lock);
75825+ kfree(work_item);
75826+ res = SCST_AEN_RES_NOT_SUPPORTED;
75827+ goto out;
75828+ }
75829+
75830+ list_add_tail(&work_item->work_list_entry, &sess->aen_work_list);
75831+ work_item->aen = aen;
75832+
75833+ spin_unlock(&sess->aen_lock);
75834+
75835+ schedule_work(&sess->aen_work);
75836+ break;
75837+
75838+ default:
75839+ TRACE_MGMT_DBG("Unsupported AEN %d", event_fn);
75840+ res = SCST_AEN_RES_NOT_SUPPORTED;
75841+ break;
75842+ }
75843+
75844+out:
75845+ TRACE_EXIT_RES(res);
75846+ return res;
75847+}
75848+
75849+static int scst_local_targ_detect(struct scst_tgt_template *tgt_template)
75850+{
75851+ TRACE_ENTRY();
75852+
75853+ TRACE_EXIT();
75854+ return 0;
75855+};
75856+
75857+static int scst_local_targ_release(struct scst_tgt *tgt)
75858+{
75859+ TRACE_ENTRY();
75860+
75861+ TRACE_EXIT();
75862+ return 0;
75863+}
75864+
75865+static int scst_local_targ_xmit_response(struct scst_cmd *scst_cmd)
75866+{
75867+ struct scsi_cmnd *SCpnt = NULL;
75868+ void (*done)(struct scsi_cmnd *);
75869+
75870+ TRACE_ENTRY();
75871+
75872+ if (unlikely(scst_cmd_aborted(scst_cmd))) {
75873+ scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_ABORTED);
75874+ scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME);
75875+ return SCST_TGT_RES_SUCCESS;
75876+ }
75877+
75878+ if (scst_cmd_get_dh_data_buff_alloced(scst_cmd) &&
75879+ (scst_cmd_get_data_direction(scst_cmd) & SCST_DATA_READ))
75880+ scst_copy_sg(scst_cmd, SCST_SG_COPY_TO_TARGET);
75881+
75882+ SCpnt = scst_cmd_get_tgt_priv(scst_cmd);
75883+ done = SCpnt->scsi_done;
75884+
75885+ /*
75886+ * This might have to change to use the two status flags
75887+ */
75888+ if (scst_cmd_get_is_send_status(scst_cmd)) {
75889+ int resid = 0, out_resid = 0;
75890+
75891+ /* Calculate the residual ... */
75892+ if (likely(!scst_get_resid(scst_cmd, &resid, &out_resid))) {
75893+ TRACE_DBG("No residuals for request %p", SCpnt);
75894+ } else {
75895+ if (out_resid != 0)
75896+ PRINT_ERROR("Unable to return OUT residual %d "
75897+ "(op %02x)", out_resid, SCpnt->cmnd[0]);
75898+ }
75899+
75900+ scsi_set_resid(SCpnt, resid);
75901+
75902+ /*
75903+ * It seems like there is no way to set out_resid ...
75904+ */
75905+
75906+ (void)scst_local_send_resp(SCpnt, scst_cmd, done,
75907+ scst_cmd_get_status(scst_cmd));
75908+ }
75909+
75910+ /* Now tell SCST that the command is done ... */
75911+ scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME);
75912+
75913+ TRACE_EXIT();
75914+ return SCST_TGT_RES_SUCCESS;
75915+}
75916+
75917+static void scst_local_targ_task_mgmt_done(struct scst_mgmt_cmd *mgmt_cmd)
75918+{
75919+ struct completion *compl;
75920+
75921+ TRACE_ENTRY();
75922+
75923+ compl = (struct completion *)scst_mgmt_cmd_get_tgt_priv(mgmt_cmd);
75924+ if (compl)
75925+ complete(compl);
75926+
75927+ TRACE_EXIT();
75928+ return;
75929+}
75930+
75931+static uint16_t scst_local_get_scsi_transport_version(struct scst_tgt *scst_tgt)
75932+{
75933+ struct scst_local_tgt *tgt;
75934+
75935+ tgt = (struct scst_local_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
75936+
75937+ if (tgt->scsi_transport_version == 0)
75938+ return 0x0BE0; /* SAS */
75939+ else
75940+ return tgt->scsi_transport_version;
75941+}
75942+
75943+static uint16_t scst_local_get_phys_transport_version(struct scst_tgt *scst_tgt)
75944+{
75945+ struct scst_local_tgt *tgt;
75946+
75947+ tgt = (struct scst_local_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
75948+
75949+ return tgt->phys_transport_version;
75950+}
75951+
75952+static struct scst_tgt_template scst_local_targ_tmpl = {
75953+ .name = "scst_local",
75954+ .sg_tablesize = 0xffff,
75955+ .xmit_response_atomic = 1,
75956+ .enabled_attr_not_needed = 1,
75957+ .tgtt_attrs = scst_local_tgtt_attrs,
75958+ .tgt_attrs = scst_local_tgt_attrs,
75959+ .sess_attrs = scst_local_sess_attrs,
75960+ .add_target = scst_local_sysfs_add_target,
75961+ .del_target = scst_local_sysfs_del_target,
75962+ .mgmt_cmd = scst_local_sysfs_mgmt_cmd,
75963+ .add_target_parameters = "session_name",
75964+ .mgmt_cmd_help = " echo \"add_session target_name session_name\" >mgmt\n"
75965+ " echo \"del_session target_name session_name\" >mgmt\n",
75966+ .detect = scst_local_targ_detect,
75967+ .release = scst_local_targ_release,
75968+ .pre_exec = scst_local_targ_pre_exec,
75969+ .xmit_response = scst_local_targ_xmit_response,
75970+ .task_mgmt_fn_done = scst_local_targ_task_mgmt_done,
75971+ .report_aen = scst_local_report_aen,
75972+ .get_initiator_port_transport_id = scst_local_get_initiator_port_transport_id,
75973+ .get_scsi_transport_version = scst_local_get_scsi_transport_version,
75974+ .get_phys_transport_version = scst_local_get_phys_transport_version,
75975+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
75976+ .default_trace_flags = SCST_LOCAL_DEFAULT_LOG_FLAGS,
75977+ .trace_flags = &trace_flag,
75978+#endif
75979+};
75980+
75981+static struct scsi_host_template scst_lcl_ini_driver_template = {
75982+ .name = SCST_LOCAL_NAME,
75983+ .queuecommand = scst_local_queuecommand,
75984+ .eh_abort_handler = scst_local_abort,
75985+ .eh_device_reset_handler = scst_local_device_reset,
75986+ .eh_target_reset_handler = scst_local_target_reset,
75987+ .can_queue = 256,
75988+ .this_id = -1,
75989+ /* SCST doesn't support sg chaining */
75990+ .sg_tablesize = SG_MAX_SINGLE_ALLOC,
75991+ .cmd_per_lun = 32,
75992+ .max_sectors = 0xffff,
75993+ /* SCST doesn't support sg chaining */
75994+ .use_clustering = ENABLE_CLUSTERING,
75995+ .skip_settle_delay = 1,
75996+ .module = THIS_MODULE,
75997+};
75998+
75999+/*
76000+ * LLD Bus and functions
76001+ */
76002+
76003+static int scst_local_driver_probe(struct device *dev)
76004+{
76005+ int ret;
76006+ struct scst_local_sess *sess;
76007+ struct Scsi_Host *hpnt;
76008+
76009+ TRACE_ENTRY();
76010+
76011+ sess = to_scst_lcl_sess(dev);
76012+
76013+ TRACE_DBG("sess %p", sess);
76014+
76015+ hpnt = scsi_host_alloc(&scst_lcl_ini_driver_template, sizeof(*sess));
76016+ if (NULL == hpnt) {
76017+ PRINT_ERROR("%s", "scsi_register() failed");
76018+ ret = -ENODEV;
76019+ goto out;
76020+ }
76021+
76022+ sess->shost = hpnt;
76023+
76024+ hpnt->max_id = 0; /* Don't want more than one id */
76025+ hpnt->max_lun = 0xFFFF;
76026+
76027+ /*
76028+ * Because of a change in the size of this field at 2.6.26
76029+ * we use this check ... it allows us to work on earlier
76030+ * kernels. If we don't, max_cmd_size gets set to 4 (and we get
76031+ * a compiler warning) so a scan never occurs.
76032+ */
76033+ hpnt->max_cmd_len = 260;
76034+
76035+ ret = scsi_add_host(hpnt, &sess->dev);
76036+ if (ret) {
76037+ PRINT_ERROR("%s", "scsi_add_host() failed");
76038+ ret = -ENODEV;
76039+ scsi_host_put(hpnt);
76040+ goto out;
76041+ }
76042+
76043+out:
76044+ TRACE_EXIT_RES(ret);
76045+ return ret;
76046+}
76047+
76048+static int scst_local_driver_remove(struct device *dev)
76049+{
76050+ struct scst_local_sess *sess;
76051+
76052+ TRACE_ENTRY();
76053+
76054+ sess = to_scst_lcl_sess(dev);
76055+ if (!sess) {
76056+ PRINT_ERROR("%s", "Unable to locate sess info");
76057+ return -ENODEV;
76058+ }
76059+
76060+ scsi_remove_host(sess->shost);
76061+ scsi_host_put(sess->shost);
76062+
76063+ TRACE_EXIT();
76064+ return 0;
76065+}
76066+
76067+static int scst_local_bus_match(struct device *dev,
76068+ struct device_driver *dev_driver)
76069+{
76070+ TRACE_ENTRY();
76071+
76072+ TRACE_EXIT();
76073+ return 1;
76074+}
76075+
76076+static struct bus_type scst_local_lld_bus = {
76077+ .name = "scst_local_bus",
76078+ .match = scst_local_bus_match,
76079+ .probe = scst_local_driver_probe,
76080+ .remove = scst_local_driver_remove,
76081+};
76082+
76083+static struct device_driver scst_local_driver = {
76084+ .name = SCST_LOCAL_NAME,
76085+ .bus = &scst_local_lld_bus,
76086+};
76087+
76088+static struct device *scst_local_root;
76089+
76090+static void scst_local_release_adapter(struct device *dev)
76091+{
76092+ struct scst_local_sess *sess;
76093+
76094+ TRACE_ENTRY();
76095+
76096+ sess = to_scst_lcl_sess(dev);
76097+ if (sess == NULL)
76098+ goto out;
76099+
76100+ spin_lock(&sess->aen_lock);
76101+ sess->unregistering = 1;
76102+ scst_process_aens(sess, true);
76103+ spin_unlock(&sess->aen_lock);
76104+
76105+ cancel_work_sync(&sess->aen_work);
76106+
76107+ scst_unregister_session(sess->scst_sess, TRUE, NULL);
76108+
76109+ kfree(sess);
76110+
76111+out:
76112+ TRACE_EXIT();
76113+ return;
76114+}
76115+
76116+static int __scst_local_add_adapter(struct scst_local_tgt *tgt,
76117+ const char *initiator_name, struct scst_local_sess **out_sess,
76118+ bool locked)
76119+{
76120+ int res;
76121+ struct scst_local_sess *sess;
76122+
76123+ TRACE_ENTRY();
76124+
76125+ sess = kzalloc(sizeof(*sess), GFP_KERNEL);
76126+ if (NULL == sess) {
76127+ PRINT_ERROR("Unable to alloc scst_lcl_host (size %zu)",
76128+ sizeof(*sess));
76129+ res = -ENOMEM;
76130+ goto out;
76131+ }
76132+
76133+ sess->tgt = tgt;
76134+ sess->number = atomic_inc_return(&scst_local_sess_num);
76135+ mutex_init(&sess->tr_id_mutex);
76136+
76137+ /*
76138+ * Init this stuff we need for scheduling AEN work
76139+ */
76140+ INIT_WORK(&sess->aen_work, scst_aen_work_fn);
76141+ spin_lock_init(&sess->aen_lock);
76142+ INIT_LIST_HEAD(&sess->aen_work_list);
76143+
76144+ sess->scst_sess = scst_register_session(tgt->scst_tgt, 0,
76145+ initiator_name, (void *)sess, NULL, NULL);
76146+ if (sess->scst_sess == NULL) {
76147+ PRINT_ERROR("%s", "scst_register_session failed");
76148+ kfree(sess);
76149+ res = -EFAULT;
76150+ goto out_free;
76151+ }
76152+
76153+ sess->dev.bus = &scst_local_lld_bus;
76154+ sess->dev.parent = scst_local_root;
76155+ sess->dev.release = &scst_local_release_adapter;
76156+ sess->dev.init_name = kobject_name(&sess->scst_sess->sess_kobj);
76157+
76158+ res = device_register(&sess->dev);
76159+ if (res != 0)
76160+ goto unregister_session;
76161+
76162+ res = sysfs_create_link(scst_sysfs_get_sess_kobj(sess->scst_sess),
76163+ &sess->shost->shost_dev.kobj, "host");
76164+ if (res != 0) {
76165+ PRINT_ERROR("Unable to create \"host\" link for target "
76166+ "%s", scst_get_tgt_name(tgt->scst_tgt));
76167+ goto unregister_dev;
76168+ }
76169+
76170+ if (!locked)
76171+ mutex_lock(&scst_local_mutex);
76172+ list_add_tail(&sess->sessions_list_entry, &tgt->sessions_list);
76173+ if (!locked)
76174+ mutex_unlock(&scst_local_mutex);
76175+
76176+ if (scst_initiator_has_luns(tgt->scst_tgt, initiator_name))
76177+ scsi_scan_target(&sess->shost->shost_gendev, 0, 0,
76178+ SCAN_WILD_CARD, 1);
76179+
76180+out:
76181+ TRACE_EXIT_RES(res);
76182+ return res;
76183+
76184+unregister_dev:
76185+ device_unregister(&sess->dev);
76186+
76187+unregister_session:
76188+ scst_unregister_session(sess->scst_sess, TRUE, NULL);
76189+
76190+out_free:
76191+ kfree(sess);
76192+ goto out;
76193+}
76194+
76195+static int scst_local_add_adapter(struct scst_local_tgt *tgt,
76196+ const char *initiator_name, struct scst_local_sess **out_sess)
76197+{
76198+ return __scst_local_add_adapter(tgt, initiator_name, out_sess, false);
76199+}
76200+
76201+/* Must be called under scst_local_mutex */
76202+static void scst_local_remove_adapter(struct scst_local_sess *sess)
76203+{
76204+ TRACE_ENTRY();
76205+
76206+ list_del(&sess->sessions_list_entry);
76207+
76208+ device_unregister(&sess->dev);
76209+
76210+ TRACE_EXIT();
76211+ return;
76212+}
76213+
76214+static int scst_local_add_target(const char *target_name,
76215+ struct scst_local_tgt **out_tgt)
76216+{
76217+ int res;
76218+ struct scst_local_tgt *tgt;
76219+
76220+ TRACE_ENTRY();
76221+
76222+ tgt = kzalloc(sizeof(*tgt), GFP_KERNEL);
76223+ if (NULL == tgt) {
76224+ PRINT_ERROR("Unable to alloc tgt (size %zu)", sizeof(*tgt));
76225+ res = -ENOMEM;
76226+ goto out;
76227+ }
76228+
76229+ INIT_LIST_HEAD(&tgt->sessions_list);
76230+
76231+ tgt->scst_tgt = scst_register_target(&scst_local_targ_tmpl, target_name);
76232+ if (tgt->scst_tgt == NULL) {
76233+ PRINT_ERROR("%s", "scst_register_target() failed:");
76234+ res = -EFAULT;
76235+ goto out_free;
76236+ }
76237+
76238+ scst_tgt_set_tgt_priv(tgt->scst_tgt, tgt);
76239+
76240+ mutex_lock(&scst_local_mutex);
76241+ list_add_tail(&tgt->tgts_list_entry, &scst_local_tgts_list);
76242+ mutex_unlock(&scst_local_mutex);
76243+
76244+ if (out_tgt != NULL)
76245+ *out_tgt = tgt;
76246+
76247+ res = 0;
76248+
76249+out:
76250+ TRACE_EXIT_RES(res);
76251+ return res;
76252+
76253+out_free:
76254+ kfree(tgt);
76255+ goto out;
76256+}
76257+
76258+/* Must be called under scst_local_mutex */
76259+static void __scst_local_remove_target(struct scst_local_tgt *tgt)
76260+{
76261+ struct scst_local_sess *sess, *ts;
76262+
76263+ TRACE_ENTRY();
76264+
76265+ list_for_each_entry_safe(sess, ts, &tgt->sessions_list,
76266+ sessions_list_entry) {
76267+ scst_local_remove_adapter(sess);
76268+ }
76269+
76270+ list_del(&tgt->tgts_list_entry);
76271+
76272+ scst_unregister_target(tgt->scst_tgt);
76273+
76274+ kfree(tgt);
76275+
76276+ TRACE_EXIT();
76277+ return;
76278+}
76279+
76280+static void scst_local_remove_target(struct scst_local_tgt *tgt)
76281+{
76282+ TRACE_ENTRY();
76283+
76284+ mutex_lock(&scst_local_mutex);
76285+ __scst_local_remove_target(tgt);
76286+ mutex_unlock(&scst_local_mutex);
76287+
76288+ TRACE_EXIT();
76289+ return;
76290+}
76291+
76292+static int __init scst_local_init(void)
76293+{
76294+ int ret;
76295+ struct scst_local_tgt *tgt;
76296+
76297+ TRACE_ENTRY();
76298+
76299+ scst_local_root = root_device_register(SCST_LOCAL_NAME);
76300+ if (IS_ERR(scst_local_root)) {
76301+ ret = PTR_ERR(scst_local_root);
76302+ goto out;
76303+ }
76304+
76305+ ret = bus_register(&scst_local_lld_bus);
76306+ if (ret < 0) {
76307+ PRINT_ERROR("bus_register() error: %d", ret);
76308+ goto dev_unreg;
76309+ }
76310+
76311+ ret = driver_register(&scst_local_driver);
76312+ if (ret < 0) {
76313+ PRINT_ERROR("driver_register() error: %d", ret);
76314+ goto bus_unreg;
76315+ }
76316+
76317+ ret = scst_register_target_template(&scst_local_targ_tmpl);
76318+ if (ret != 0) {
76319+ PRINT_ERROR("Unable to register target template: %d", ret);
76320+ goto driver_unreg;
76321+ }
76322+
76323+ /*
76324+ * If we are using sysfs, then don't add a default target unless
76325+ * we are told to do so. When using procfs, we always add a default
76326+ * target because that was what the earliest versions did. Just
76327+ * remove the preprocessor directives when no longer needed.
76328+ */
76329+ if (!scst_local_add_default_tgt)
76330+ goto out;
76331+
76332+ ret = scst_local_add_target("scst_local_tgt", &tgt);
76333+ if (ret != 0)
76334+ goto tgt_templ_unreg;
76335+
76336+ ret = scst_local_add_adapter(tgt, "scst_local_host", NULL);
76337+ if (ret != 0)
76338+ goto tgt_unreg;
76339+
76340+out:
76341+ TRACE_EXIT_RES(ret);
76342+ return ret;
76343+
76344+tgt_unreg:
76345+ scst_local_remove_target(tgt);
76346+
76347+tgt_templ_unreg:
76348+ scst_unregister_target_template(&scst_local_targ_tmpl);
76349+
76350+driver_unreg:
76351+ driver_unregister(&scst_local_driver);
76352+
76353+bus_unreg:
76354+ bus_unregister(&scst_local_lld_bus);
76355+
76356+dev_unreg:
76357+ root_device_unregister(scst_local_root);
76358+
76359+ goto out;
76360+}
76361+
76362+static void __exit scst_local_exit(void)
76363+{
76364+ struct scst_local_tgt *tgt, *tt;
76365+
76366+ TRACE_ENTRY();
76367+
76368+ down_write(&scst_local_exit_rwsem);
76369+
76370+ mutex_lock(&scst_local_mutex);
76371+ list_for_each_entry_safe(tgt, tt, &scst_local_tgts_list,
76372+ tgts_list_entry) {
76373+ __scst_local_remove_target(tgt);
76374+ }
76375+ mutex_unlock(&scst_local_mutex);
76376+
76377+ driver_unregister(&scst_local_driver);
76378+ bus_unregister(&scst_local_lld_bus);
76379+ root_device_unregister(scst_local_root);
76380+
76381+ /* Now unregister the target template */
76382+ scst_unregister_target_template(&scst_local_targ_tmpl);
76383+
76384+ /* To make lockdep happy */
76385+ up_write(&scst_local_exit_rwsem);
76386+
76387+ TRACE_EXIT();
76388+ return;
76389+}
76390+
76391+device_initcall(scst_local_init);
76392+module_exit(scst_local_exit);
76393+
76394diff -uprN orig/linux-2.6.35/Documentation/scst/README.scst_local linux-2.6.35/Documentation/scst/README.scst_local
76395--- orig/linux-2.6.35/Documentation/scst/README.scst_local
76396+++ linux-2.6.35/Documentation/scst/README.scst_local
76397@@ -0,0 +1,259 @@
76398+SCST Local ...
76399+Richard Sharpe, 30-Nov-2008
76400+
76401+This is the SCST Local driver. Its function is to allow you to access devices
76402+that are exported via SCST directly on the same Linux system that they are
76403+exported from.
76404+
76405+No assumptions are made in the code about the device types on the target, so
76406+any device handlers that you load in SCST should be visible, including tapes
76407+and so forth.
76408+
76409+You can freely use any sg, sd, st, etc. devices imported from target,
76410+except the following: you can't mount file systems or put swap on them.
76411+This is a limitation of Linux memory/cache manager. See SCST README file
76412+for details.
76413+
76414+To build, simply issue 'make' in the scst_local directory.
76415+
76416+Try 'modinfo scst_local' for a listing of module parameters so far.
76417+
76418+Here is how I have used it so far:
76419+
76420+1. Load up scst:
76421+
76422+ modprobe scst
76423+ modprobe scst_vdisk
76424+
76425+2. Create a virtual disk (or your own device handler):
76426+
76427+ dd if=/dev/zero of=/some/path/vdisk1.img bs=16384 count=1000000
76428+ echo "add_device vm_disk1 filename=/some/path/vdisk1.img" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
76429+
76430+3. Load the scst_local driver:
76431+
76432+ insmod scst_local
76433+ echo "add vm_disk1 0" >/sys/kernel/scst_tgt/targets/scst_local/scst_local_tgt/luns/mgmt
76434+
76435+4. Check what you have
76436+
76437+ cat /proc/scsi/scsi
76438+ Attached devices:
76439+ Host: scsi0 Channel: 00 Id: 00 Lun: 00
76440+ Vendor: ATA Model: ST9320320AS Rev: 0303
76441+ Type: Direct-Access ANSI SCSI revision: 05
76442+ Host: scsi4 Channel: 00 Id: 00 Lun: 00
76443+ Vendor: TSSTcorp Model: CD/DVDW TS-L632D Rev: TO04
76444+ Type: CD-ROM ANSI SCSI revision: 05
76445+ Host: scsi7 Channel: 00 Id: 00 Lun: 00
76446+ Vendor: SCST_FIO Model: vm_disk1 Rev: 200
76447+ Type: Direct-Access ANSI SCSI revision: 04
76448+
76449+Or instead of manually "add_device" in (2) and step (3) write a
76450+scstadmin config:
76451+
76452+HANDLER vdisk_fileio {
76453+ DEVICE vm_disk1 {
76454+ filename /some/path/vdisk1.img
76455+ }
76456+}
76457+
76458+TARGET_DRIVER scst_local {
76459+ TARGET scst_local_tgt {
76460+ LUN 0 vm_disk1
76461+ }
76462+}
76463+
76464+then:
76465+
76466+ insmod scst_local
76467+ scstadmin -config conf_file.cfg
76468+
76469+More advanced examples:
76470+
76471+For (3) you can:
76472+
76473+ insmod scst_local add_default_tgt=0
76474+ echo "add_target scst_local_tgt session_name=scst_local_host" >/sys/kernel/scst_tgt/targets/scst_local//mgmt
76475+ echo "add vm_disk1 0" >/sys/kernel/scst_tgt/targets/scst_local/scst_local_tgt/luns/mgmt
76476+
76477+Scst_local module's parameter add_default_tgt disables creation of
76478+default target "scst_local_tgt" and session "scst_local_host", so you
76479+needed to create it manually.
76480+
76481+There can be any number of targets and sessions created. Each SCST
76482+session corresponds to SCSI host. You can change which LUNs assigned to
76483+each session by using SCST access control. This mode is intended for
76484+user space target drivers (see below).
76485+
76486+Alternatively, you can write an scstadmin's config file conf_file.cfg:
76487+
76488+HANDLER vdisk_fileio {
76489+ DEVICE vm_disk1 {
76490+ filename /some/path/vdisk1.img
76491+ }
76492+}
76493+
76494+TARGET_DRIVER scst_local {
76495+ TARGET scst_local_tgt {
76496+ session_name scst_local_host
76497+
76498+ LUN 0 vm_disk1
76499+ }
76500+}
76501+
76502+then:
76503+
76504+ insmod scst_local add_default_tgt=0
76505+ scstadmin -config conf_file.cfg
76506+
76507+NOTE! Although scstadmin allows to create scst_local's sessions using
76508+"session_name" expression, it doesn't save existing sessions during
76509+writing config file by "write_config" command. If you need this
76510+functionality, feel free to send a request for it in SCST development
76511+mailing list.
76512+
76513+5. Have fun.
76514+
76515+Some of this was coded while in Santa Clara, some in Bangalore, and some in
76516+Hyderabad. Noe doubt some will be coded on the way back to Santa Clara.
76517+
76518+The code still has bugs, so if you encounter any, email me the fixes at:
76519+
76520+ realrichardsharpe@gmail.com
76521+
76522+I am thinking of renaming this to something more interesting.
76523+
76524+Sysfs interface
76525+===============
76526+
76527+See SCST's README for a common SCST sysfs description.
76528+
76529+Root of this driver is /sys/kernel/scst_tgt/targets/scst_local. It has
76530+the following additional entry:
76531+
76532+ - stats - read-only attribute with some statistical information.
76533+
76534+Each target subdirectory contains the following additional entries:
76535+
76536+ - phys_transport_version - contains and allows to change physical
76537+ transport version descriptor. It determines by which phisical
76538+ interface this target will look like. See SPC for more details. By
76539+ default, it is not defined (0).
76540+
76541+ - scsi_transport_version - contains and allows to change SCSI
76542+ transport version descriptor. It determines by which SCSI
76543+ transport this target will look like. See SPC for more details. By
76544+ default, it is SAS.
76545+
76546+Each session subdirectory contains the following additional entries:
76547+
76548+ - transport_id - contains this host's TransportID. This TransportID
76549+ used to identify initiator in Persisten Reservation commands. If you
76550+ change scsi_transport_version for a target, make sure you set for all
76551+ its sessions correct TransportID. See SPC for more details.
76552+
76553+ - host - links to the corresponding SCSI host. Using it you can find
76554+ local sg/bsg/sd/etc. devices of this session. For instance, this
76555+ links points out to host12, so you can find your sg devices by:
76556+
76557+$ lsscsi -g|grep "\[12:"
76558+[12:0:0:0] disk SCST_FIO rd1 200 /dev/sdc /dev/sg2
76559+[12:0:0:1] disk SCST_FIO nullio 200 /dev/sdd /dev/sg3
76560+
76561+They are /dev/sg2 and /dev/sg3.
76562+
76563+The following management commands available via /sys/kernel/scst_tgt/targets/scst_local/mgmt:
76564+
76565+ - add_target target_name [session_name=sess_name; [session_name=sess_name1;] [...]] -
76566+ creates a target with optionally one or more sessions.
76567+
76568+ - del_target target_name - deletes a target.
76569+
76570+ - add_session target_name session_name - adds to target target_name
76571+ session (SCSI host) with name session_name.
76572+
76573+ - del_session target_name session_name - deletes session session_name
76574+ from target target_name.
76575+
76576+Note on performance
76577+===================
76578+
76579+Although this driver implemented in the most performance effective way,
76580+including zero-copy passing data between SCSI/block subsystems and SCST,
76581+in many cases it is NOT suited to measure performance as a NULL link.
76582+For example, it is not suited for max IOPS measurements. This is because
76583+for such cases not performance of the link between the target and
76584+initiator is the bottleneck, but CPU or memory speed on the target or
76585+initiator. For scst_local you have both initiator and target on the same
76586+system, which means each your initiator and target are much less
76587+CPU/memory powerful.
76588+
76589+User space target drivers
76590+=========================
76591+
76592+Scst_local can be used to write full featured SCST target drivers in
76593+user space:
76594+
76595+1. For each SCSI target a user space target driver should create an
76596+ scst_local's target using "add_target" command.
76597+
76598+2. Then the user space target driver should, if needed, set its SCSI and
76599+ physical transport version descriptors using attributes
76600+ scsi_transport_version and phys_transport_version correspondingly in
76601+ /sys/kernel/scst_tgt/targets/scst_local/target_name directory.
76602+
76603+3. For incoming session (I_T nexus) from an initiator the user space
76604+ target driver should create scst_local's session using "add_session"
76605+ command.
76606+
76607+4. Then, if needed, the user space target driver should set TransportID
76608+ for this session (I_T nexus) using attribute
76609+ /sys/kernel/scst_tgt/targets/scst_local/target_name/sessions/session_name/transport_id
76610+
76611+5. Then the user space target driver should find out sg/bsg devices for
76612+ the LUNs the created session has using link
76613+ /sys/kernel/scst_tgt/targets/scst_local/target_name/sessions/session_name/host
76614+ as described above.
76615+
76616+6. Then the user space target driver can start serving the initiator using
76617+ found sg/bsg devices.
76618+
76619+For other connected initiators steps 3-6 should be repeated.
76620+
76621+Change log
76622+==========
76623+
76624+V0.1 24-Sep-2008 (Hyderabad) Initial coding, pretty chatty and messy,
76625+ but worked.
76626+
76627+V0.2 25-Sep-2008 (Hong Kong) Cleaned up the code a lot, reduced the log
76628+ chatter, fixed a bug where multiple LUNs did not
76629+ work. Also, added logging control. Tested with
76630+ five virtual disks. They all came up as /dev/sdb
76631+ through /dev/sdf and I could dd to them. Also
76632+ fixed a bug preventing multiple adapters.
76633+
76634+V0.3 26-Sep-2008 (Santa Clara) Added back a copyright plus cleaned up some
76635+ unused functions and structures.
76636+
76637+V0.4 5-Oct-2008 (Santa Clara) Changed name to scst_local as suggested, cleaned
76638+ up some unused variables (made them used) and
76639+ change allocation to a kmem_cache pool.
76640+
76641+V0.5 5-Oct-2008 (Santa Clara) Added mgmt commands to handle dev reset and
76642+ aborts. Not sure if aborts works. Also corrected
76643+ the version info and renamed readme to README.
76644+
76645+V0.6 7-Oct-2008 (Santa Clara) Removed some redundant code and made some
76646+ changes suggested by Vladislav.
76647+
76648+V0.7 11-Oct-2008 (Santa Clara) Moved into the scst tree. Cleaned up some
76649+ unused functions, used TRACE macros etc.
76650+
76651+V0.9 30-Nov-2008 (Mtn View) Cleaned up an additional problem with symbols not
76652+ being defined in older version of the kernel. Also
76653+ fixed some English and cleaned up this doc.
76654+
76655+V1.0 10-Sep-2010 (Moscow) Sysfs management added. Reviewed and cleaned up.
76656+
diff --git a/testing/linux-scst/scst_exec_req_fifo-2.6.34.patch b/testing/linux-scst/scst_exec_req_fifo-2.6.34.patch
deleted file mode 100644
index 3a734bb645..0000000000
--- a/testing/linux-scst/scst_exec_req_fifo-2.6.34.patch
+++ /dev/null
@@ -1,529 +0,0 @@
1diff -upkr linux-2.6.34/block/blk-map.c linux-2.6.34/block/blk-map.c
2--- linux-2.6.34/block/blk-map.c 2010-05-17 01:17:36.000000000 +0400
3+++ linux-2.6.34/block/blk-map.c 2010-05-24 15:19:49.000000000 +0400
4@@ -5,6 +5,8 @@
5 #include <linux/module.h>
6 #include <linux/bio.h>
7 #include <linux/blkdev.h>
8+#include <linux/scatterlist.h>
9+#include <linux/slab.h>
10 #include <scsi/sg.h> /* for struct sg_iovec */
11
12 #include "blk.h"
13@@ -271,6 +273,336 @@ int blk_rq_unmap_user(struct bio *bio)
14 }
15 EXPORT_SYMBOL(blk_rq_unmap_user);
16
17+struct blk_kern_sg_work {
18+ atomic_t bios_inflight;
19+ struct sg_table sg_table;
20+ struct scatterlist *src_sgl;
21+};
22+
23+static void blk_free_kern_sg_work(struct blk_kern_sg_work *bw)
24+{
25+ sg_free_table(&bw->sg_table);
26+ kfree(bw);
27+ return;
28+}
29+
30+static void blk_bio_map_kern_endio(struct bio *bio, int err)
31+{
32+ struct blk_kern_sg_work *bw = bio->bi_private;
33+
34+ if (bw != NULL) {
35+ /* Decrement the bios in processing and, if zero, free */
36+ BUG_ON(atomic_read(&bw->bios_inflight) <= 0);
37+ if (atomic_dec_and_test(&bw->bios_inflight)) {
38+ if ((bio_data_dir(bio) == READ) && (err == 0)) {
39+ unsigned long flags;
40+
41+ local_irq_save(flags); /* to protect KMs */
42+ sg_copy(bw->src_sgl, bw->sg_table.sgl, 0, 0,
43+ KM_BIO_DST_IRQ, KM_BIO_SRC_IRQ);
44+ local_irq_restore(flags);
45+ }
46+ blk_free_kern_sg_work(bw);
47+ }
48+ }
49+
50+ bio_put(bio);
51+ return;
52+}
53+
54+static int blk_rq_copy_kern_sg(struct request *rq, struct scatterlist *sgl,
55+ int nents, struct blk_kern_sg_work **pbw,
56+ gfp_t gfp, gfp_t page_gfp)
57+{
58+ int res = 0, i;
59+ struct scatterlist *sg;
60+ struct scatterlist *new_sgl;
61+ int new_sgl_nents;
62+ size_t len = 0, to_copy;
63+ struct blk_kern_sg_work *bw;
64+
65+ bw = kzalloc(sizeof(*bw), gfp);
66+ if (bw == NULL)
67+ goto out;
68+
69+ bw->src_sgl = sgl;
70+
71+ for_each_sg(sgl, sg, nents, i)
72+ len += sg->length;
73+ to_copy = len;
74+
75+ new_sgl_nents = PFN_UP(len);
76+
77+ res = sg_alloc_table(&bw->sg_table, new_sgl_nents, gfp);
78+ if (res != 0)
79+ goto out_free_bw;
80+
81+ new_sgl = bw->sg_table.sgl;
82+
83+ for_each_sg(new_sgl, sg, new_sgl_nents, i) {
84+ struct page *pg;
85+
86+ pg = alloc_page(page_gfp);
87+ if (pg == NULL)
88+ goto err_free_new_sgl;
89+
90+ sg_assign_page(sg, pg);
91+ sg->length = min_t(size_t, PAGE_SIZE, len);
92+
93+ len -= PAGE_SIZE;
94+ }
95+
96+ if (rq_data_dir(rq) == WRITE) {
97+ /*
98+ * We need to limit amount of copied data to to_copy, because
99+ * sgl might have the last element in sgl not marked as last in
100+ * SG chaining.
101+ */
102+ sg_copy(new_sgl, sgl, 0, to_copy,
103+ KM_USER0, KM_USER1);
104+ }
105+
106+ *pbw = bw;
107+ /*
108+ * REQ_COPY_USER name is misleading. It should be something like
109+ * REQ_HAS_TAIL_SPACE_FOR_PADDING.
110+ */
111+ rq->cmd_flags |= REQ_COPY_USER;
112+
113+out:
114+ return res;
115+
116+err_free_new_sgl:
117+ for_each_sg(new_sgl, sg, new_sgl_nents, i) {
118+ struct page *pg = sg_page(sg);
119+ if (pg == NULL)
120+ break;
121+ __free_page(pg);
122+ }
123+ sg_free_table(&bw->sg_table);
124+
125+out_free_bw:
126+ kfree(bw);
127+ res = -ENOMEM;
128+ goto out;
129+}
130+
131+static int __blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
132+ int nents, struct blk_kern_sg_work *bw, gfp_t gfp)
133+{
134+ int res;
135+ struct request_queue *q = rq->q;
136+ int rw = rq_data_dir(rq);
137+ int max_nr_vecs, i;
138+ size_t tot_len;
139+ bool need_new_bio;
140+ struct scatterlist *sg, *prev_sg = NULL;
141+ struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
142+ int bios;
143+
144+ if (unlikely((sgl == NULL) || (sgl->length == 0) || (nents <= 0))) {
145+ WARN_ON(1);
146+ res = -EINVAL;
147+ goto out;
148+ }
149+
150+ /*
151+ * Let's keep each bio allocation inside a single page to decrease
152+ * probability of failure.
153+ */
154+ max_nr_vecs = min_t(size_t,
155+ ((PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec)),
156+ BIO_MAX_PAGES);
157+
158+ need_new_bio = true;
159+ tot_len = 0;
160+ bios = 0;
161+ for_each_sg(sgl, sg, nents, i) {
162+ struct page *page = sg_page(sg);
163+ void *page_addr = page_address(page);
164+ size_t len = sg->length, l;
165+ size_t offset = sg->offset;
166+
167+ tot_len += len;
168+ prev_sg = sg;
169+
170+ /*
171+ * Each segment must be aligned on DMA boundary and
172+ * not on stack. The last one may have unaligned
173+ * length as long as the total length is aligned to
174+ * DMA padding alignment.
175+ */
176+ if (i == nents - 1)
177+ l = 0;
178+ else
179+ l = len;
180+ if (((sg->offset | l) & queue_dma_alignment(q)) ||
181+ (page_addr && object_is_on_stack(page_addr + sg->offset))) {
182+ res = -EINVAL;
183+ goto out_free_bios;
184+ }
185+
186+ while (len > 0) {
187+ size_t bytes;
188+ int rc;
189+
190+ if (need_new_bio) {
191+ bio = bio_kmalloc(gfp, max_nr_vecs);
192+ if (bio == NULL) {
193+ res = -ENOMEM;
194+ goto out_free_bios;
195+ }
196+
197+ if (rw == WRITE)
198+ bio->bi_rw |= 1 << BIO_RW;
199+
200+ bios++;
201+ bio->bi_private = bw;
202+ bio->bi_end_io = blk_bio_map_kern_endio;
203+
204+ if (hbio == NULL)
205+ hbio = tbio = bio;
206+ else
207+ tbio = tbio->bi_next = bio;
208+ }
209+
210+ bytes = min_t(size_t, len, PAGE_SIZE - offset);
211+
212+ rc = bio_add_pc_page(q, bio, page, bytes, offset);
213+ if (rc < bytes) {
214+ if (unlikely(need_new_bio || (rc < 0))) {
215+ if (rc < 0)
216+ res = rc;
217+ else
218+ res = -EIO;
219+ goto out_free_bios;
220+ } else {
221+ need_new_bio = true;
222+ len -= rc;
223+ offset += rc;
224+ continue;
225+ }
226+ }
227+
228+ need_new_bio = false;
229+ offset = 0;
230+ len -= bytes;
231+ page = nth_page(page, 1);
232+ }
233+ }
234+
235+ if (hbio == NULL) {
236+ res = -EINVAL;
237+ goto out_free_bios;
238+ }
239+
240+ /* Total length must be aligned on DMA padding alignment */
241+ if ((tot_len & q->dma_pad_mask) &&
242+ !(rq->cmd_flags & REQ_COPY_USER)) {
243+ res = -EINVAL;
244+ goto out_free_bios;
245+ }
246+
247+ if (bw != NULL)
248+ atomic_set(&bw->bios_inflight, bios);
249+
250+ while (hbio != NULL) {
251+ bio = hbio;
252+ hbio = hbio->bi_next;
253+ bio->bi_next = NULL;
254+
255+ blk_queue_bounce(q, &bio);
256+
257+ res = blk_rq_append_bio(q, rq, bio);
258+ if (unlikely(res != 0)) {
259+ bio->bi_next = hbio;
260+ hbio = bio;
261+ /* We can have one or more bios bounced */
262+ goto out_unmap_bios;
263+ }
264+ }
265+
266+ rq->buffer = NULL;
267+out:
268+ return res;
269+
270+out_free_bios:
271+ while (hbio != NULL) {
272+ bio = hbio;
273+ hbio = hbio->bi_next;
274+ bio_put(bio);
275+ }
276+ goto out;
277+
278+out_unmap_bios:
279+ blk_rq_unmap_kern_sg(rq, res);
280+ goto out;
281+}
282+
283+/**
284+ * blk_rq_map_kern_sg - map kernel data to a request, for REQ_TYPE_BLOCK_PC
285+ * @rq: request to fill
286+ * @sgl: area to map
287+ * @nents: number of elements in @sgl
288+ * @gfp: memory allocation flags
289+ *
290+ * Description:
291+ * Data will be mapped directly if possible. Otherwise a bounce
292+ * buffer will be used.
293+ */
294+int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
295+ int nents, gfp_t gfp)
296+{
297+ int res;
298+
299+ res = __blk_rq_map_kern_sg(rq, sgl, nents, NULL, gfp);
300+ if (unlikely(res != 0)) {
301+ struct blk_kern_sg_work *bw = NULL;
302+
303+ res = blk_rq_copy_kern_sg(rq, sgl, nents, &bw,
304+ gfp, rq->q->bounce_gfp | gfp);
305+ if (unlikely(res != 0))
306+ goto out;
307+
308+ res = __blk_rq_map_kern_sg(rq, bw->sg_table.sgl,
309+ bw->sg_table.nents, bw, gfp);
310+ if (res != 0) {
311+ blk_free_kern_sg_work(bw);
312+ goto out;
313+ }
314+ }
315+
316+ rq->buffer = NULL;
317+
318+out:
319+ return res;
320+}
321+EXPORT_SYMBOL(blk_rq_map_kern_sg);
322+
323+/**
324+ * blk_rq_unmap_kern_sg - unmap a request with kernel sg
325+ * @rq: request to unmap
326+ * @err: non-zero error code
327+ *
328+ * Description:
329+ * Unmap a rq previously mapped by blk_rq_map_kern_sg(). Must be called
330+ * only in case of an error!
331+ */
332+void blk_rq_unmap_kern_sg(struct request *rq, int err)
333+{
334+ struct bio *bio = rq->bio;
335+
336+ while (bio) {
337+ struct bio *b = bio;
338+ bio = bio->bi_next;
339+ b->bi_end_io(b, err);
340+ }
341+ rq->bio = NULL;
342+
343+ return;
344+}
345+EXPORT_SYMBOL(blk_rq_unmap_kern_sg);
346+
347 /**
348 * blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage
349 * @q: request queue where request should be inserted
350diff -upkr linux-2.6.34/include/linux/blkdev.h linux-2.6.34/include/linux/blkdev.h
351--- linux-2.6.34/include/linux/blkdev.h 2010-05-17 01:17:36.000000000 +0400
352+++ linux-2.6.34/include/linux/blkdev.h 2010-05-24 14:51:22.000000000 +0400
353@@ -713,6 +713,8 @@ extern unsigned long blk_max_low_pfn, bl
354 #define BLK_DEFAULT_SG_TIMEOUT (60 * HZ)
355 #define BLK_MIN_SG_TIMEOUT (7 * HZ)
356
357+#define SCSI_EXEC_REQ_FIFO_DEFINED
358+
359 #ifdef CONFIG_BOUNCE
360 extern int init_emergency_isa_pool(void);
361 extern void blk_queue_bounce(struct request_queue *q, struct bio **bio);
362@@ -828,6 +830,9 @@ extern int blk_rq_map_kern(struct reques
363 extern int blk_rq_map_user_iov(struct request_queue *, struct request *,
364 struct rq_map_data *, struct sg_iovec *, int,
365 unsigned int, gfp_t);
366+extern int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
367+ int nents, gfp_t gfp);
368+extern void blk_rq_unmap_kern_sg(struct request *rq, int err);
369 extern int blk_execute_rq(struct request_queue *, struct gendisk *,
370 struct request *, int);
371 extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *,
372diff -upkr linux-2.6.34/include/linux/scatterlist.h linux-2.6.34/include/linux/scatterlist.h
373--- linux-2.6.34/include/linux/scatterlist.h 2010-05-17 01:17:36.000000000 +0400
374+++ linux-2.6.34/include/linux/scatterlist.h 2010-05-24 14:51:22.000000000 +0400
375@@ -3,6 +3,7 @@
376
377 #include <asm/types.h>
378 #include <asm/scatterlist.h>
379+#include <asm/kmap_types.h>
380 #include <linux/mm.h>
381 #include <linux/string.h>
382 #include <asm/io.h>
383@@ -218,6 +219,10 @@ size_t sg_copy_from_buffer(struct scatte
384 size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
385 void *buf, size_t buflen);
386
387+int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg,
388+ int nents_to_copy, size_t copy_len,
389+ enum km_type d_km_type, enum km_type s_km_type);
390+
391 /*
392 * Maximum number of entries that will be allocated in one piece, if
393 * a list larger than this is required then chaining will be utilized.
394diff -upkr linux-2.6.34/lib/scatterlist.c linux-2.6.34/lib/scatterlist.c
395--- linux-2.6.34/lib/scatterlist.c 2010-05-17 01:17:36.000000000 +0400
396+++ linux-2.6.34/lib/scatterlist.c 2010-05-24 14:51:22.000000000 +0400
397@@ -494,3 +494,132 @@ size_t sg_copy_to_buffer(struct scatterl
398 return sg_copy_buffer(sgl, nents, buf, buflen, 1);
399 }
400 EXPORT_SYMBOL(sg_copy_to_buffer);
401+
402+/*
403+ * Can switch to the next dst_sg element, so, to copy to strictly only
404+ * one dst_sg element, it must be either last in the chain, or
405+ * copy_len == dst_sg->length.
406+ */
407+static int sg_copy_elem(struct scatterlist **pdst_sg, size_t *pdst_len,
408+ size_t *pdst_offs, struct scatterlist *src_sg,
409+ size_t copy_len,
410+ enum km_type d_km_type, enum km_type s_km_type)
411+{
412+ int res = 0;
413+ struct scatterlist *dst_sg;
414+ size_t src_len, dst_len, src_offs, dst_offs;
415+ struct page *src_page, *dst_page;
416+
417+ dst_sg = *pdst_sg;
418+ dst_len = *pdst_len;
419+ dst_offs = *pdst_offs;
420+ dst_page = sg_page(dst_sg);
421+
422+ src_page = sg_page(src_sg);
423+ src_len = src_sg->length;
424+ src_offs = src_sg->offset;
425+
426+ do {
427+ void *saddr, *daddr;
428+ size_t n;
429+
430+ saddr = kmap_atomic(src_page +
431+ (src_offs >> PAGE_SHIFT), s_km_type) +
432+ (src_offs & ~PAGE_MASK);
433+ daddr = kmap_atomic(dst_page +
434+ (dst_offs >> PAGE_SHIFT), d_km_type) +
435+ (dst_offs & ~PAGE_MASK);
436+
437+ if (((src_offs & ~PAGE_MASK) == 0) &&
438+ ((dst_offs & ~PAGE_MASK) == 0) &&
439+ (src_len >= PAGE_SIZE) && (dst_len >= PAGE_SIZE) &&
440+ (copy_len >= PAGE_SIZE)) {
441+ copy_page(daddr, saddr);
442+ n = PAGE_SIZE;
443+ } else {
444+ n = min_t(size_t, PAGE_SIZE - (dst_offs & ~PAGE_MASK),
445+ PAGE_SIZE - (src_offs & ~PAGE_MASK));
446+ n = min(n, src_len);
447+ n = min(n, dst_len);
448+ n = min_t(size_t, n, copy_len);
449+ memcpy(daddr, saddr, n);
450+ }
451+ dst_offs += n;
452+ src_offs += n;
453+
454+ kunmap_atomic(saddr, s_km_type);
455+ kunmap_atomic(daddr, d_km_type);
456+
457+ res += n;
458+ copy_len -= n;
459+ if (copy_len == 0)
460+ goto out;
461+
462+ src_len -= n;
463+ dst_len -= n;
464+ if (dst_len == 0) {
465+ dst_sg = sg_next(dst_sg);
466+ if (dst_sg == NULL)
467+ goto out;
468+ dst_page = sg_page(dst_sg);
469+ dst_len = dst_sg->length;
470+ dst_offs = dst_sg->offset;
471+ }
472+ } while (src_len > 0);
473+
474+out:
475+ *pdst_sg = dst_sg;
476+ *pdst_len = dst_len;
477+ *pdst_offs = dst_offs;
478+ return res;
479+}
480+
481+/**
482+ * sg_copy - copy one SG vector to another
483+ * @dst_sg: destination SG
484+ * @src_sg: source SG
485+ * @nents_to_copy: maximum number of entries to copy
486+ * @copy_len: maximum amount of data to copy. If 0, then copy all.
487+ * @d_km_type: kmap_atomic type for the destination SG
488+ * @s_km_type: kmap_atomic type for the source SG
489+ *
490+ * Description:
491+ * Data from the source SG vector will be copied to the destination SG
492+ * vector. End of the vectors will be determined by sg_next() returning
493+ * NULL. Returns number of bytes copied.
494+ */
495+int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg,
496+ int nents_to_copy, size_t copy_len,
497+ enum km_type d_km_type, enum km_type s_km_type)
498+{
499+ int res = 0;
500+ size_t dst_len, dst_offs;
501+
502+ if (copy_len == 0)
503+ copy_len = 0x7FFFFFFF; /* copy all */
504+
505+ if (nents_to_copy == 0)
506+ nents_to_copy = 0x7FFFFFFF; /* copy all */
507+
508+ dst_len = dst_sg->length;
509+ dst_offs = dst_sg->offset;
510+
511+ do {
512+ int copied = sg_copy_elem(&dst_sg, &dst_len, &dst_offs,
513+ src_sg, copy_len, d_km_type, s_km_type);
514+ copy_len -= copied;
515+ res += copied;
516+ if ((copy_len == 0) || (dst_sg == NULL))
517+ goto out;
518+
519+ nents_to_copy--;
520+ if (nents_to_copy == 0)
521+ goto out;
522+
523+ src_sg = sg_next(src_sg);
524+ } while (src_sg != NULL);
525+
526+out:
527+ return res;
528+}
529+EXPORT_SYMBOL(sg_copy);
diff --git a/testing/linux-scst/setlocalversion.patch b/testing/linux-scst/setlocalversion.patch
new file mode 100644
index 0000000000..d82eb170ab
--- /dev/null
+++ b/testing/linux-scst/setlocalversion.patch
@@ -0,0 +1,11 @@
1--- ./scripts/setlocalversion.orig
2+++ ./scripts/setlocalversion
3@@ -43,7 +43,7 @@
4 fi
5
6 # Check for git and a git repo.
7- if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
8+ if [ -d "$srctree"/.git ] && head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
9
10 # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
11 # it, because this version is defined in the top level Makefile.
diff --git a/testing/linux-scst/unionfs-2.5.7_for_2.6.35.8.patch b/testing/linux-scst/unionfs-2.5.7_for_2.6.35.8.patch
new file mode 100644
index 0000000000..52fd9d8aa1
--- /dev/null
+++ b/testing/linux-scst/unionfs-2.5.7_for_2.6.35.8.patch
@@ -0,0 +1,11269 @@
1diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
2index 4303614..5ade4a8 100644
3--- a/Documentation/filesystems/00-INDEX
4+++ b/Documentation/filesystems/00-INDEX
5@@ -112,6 +112,8 @@ udf.txt
6 - info and mount options for the UDF filesystem.
7 ufs.txt
8 - info on the ufs filesystem.
9+unionfs/
10+ - info on the unionfs filesystem
11 vfat.txt
12 - info on using the VFAT filesystem used in Windows NT and Windows 95
13 vfs.txt
14diff --git a/Documentation/filesystems/unionfs/00-INDEX b/Documentation/filesystems/unionfs/00-INDEX
15new file mode 100644
16index 0000000..96fdf67
17--- /dev/null
18+++ b/Documentation/filesystems/unionfs/00-INDEX
19@@ -0,0 +1,10 @@
20+00-INDEX
21+ - this file.
22+concepts.txt
23+ - A brief introduction of concepts.
24+issues.txt
25+ - A summary of known issues with unionfs.
26+rename.txt
27+ - Information regarding rename operations.
28+usage.txt
29+ - Usage information and examples.
30diff --git a/Documentation/filesystems/unionfs/concepts.txt b/Documentation/filesystems/unionfs/concepts.txt
31new file mode 100644
32index 0000000..b853788
33--- /dev/null
34+++ b/Documentation/filesystems/unionfs/concepts.txt
35@@ -0,0 +1,287 @@
36+Unionfs 2.x CONCEPTS:
37+=====================
38+
39+This file describes the concepts needed by a namespace unification file
40+system.
41+
42+
43+Branch Priority:
44+================
45+
46+Each branch is assigned a unique priority - starting from 0 (highest
47+priority). No two branches can have the same priority.
48+
49+
50+Branch Mode:
51+============
52+
53+Each branch is assigned a mode - read-write or read-only. This allows
54+directories on media mounted read-write to be used in a read-only manner.
55+
56+
57+Whiteouts:
58+==========
59+
60+A whiteout removes a file name from the namespace. Whiteouts are needed when
61+one attempts to remove a file on a read-only branch.
62+
63+Suppose we have a two-branch union, where branch 0 is read-write and branch
64+1 is read-only. And a file 'foo' on branch 1:
65+
66+./b0/
67+./b1/
68+./b1/foo
69+
70+The unified view would simply be:
71+
72+./union/
73+./union/foo
74+
75+Since 'foo' is stored on a read-only branch, it cannot be removed. A
76+whiteout is used to remove the name 'foo' from the unified namespace. Again,
77+since branch 1 is read-only, the whiteout cannot be created there. So, we
78+try on a higher priority (lower numerically) branch and create the whiteout
79+there.
80+
81+./b0/
82+./b0/.wh.foo
83+./b1/
84+./b1/foo
85+
86+Later, when Unionfs traverses branches (due to lookup or readdir), it
87+eliminate 'foo' from the namespace (as well as the whiteout itself.)
88+
89+
90+Opaque Directories:
91+===================
92+
93+Assume we have a unionfs mount comprising of two branches. Branch 0 is
94+empty; branch 1 has the directory /a and file /a/f. Let's say we mount a
95+union of branch 0 as read-write and branch 1 as read-only. Now, let's say
96+we try to perform the following operation in the union:
97+
98+ rm -fr a
99+
100+Because branch 1 is not writable, we cannot physically remove the file /a/f
101+or the directory /a. So instead, we will create a whiteout in branch 0
102+named /.wh.a, masking out the name "a" from branch 1. Next, let's say we
103+try to create a directory named "a" as follows:
104+
105+ mkdir a
106+
107+Because we have a whiteout for "a" already, Unionfs behaves as if "a"
108+doesn't exist, and thus will delete the whiteout and replace it with an
109+actual directory named "a".
110+
111+The problem now is that if you try to "ls" in the union, Unionfs will
112+perform is normal directory name unification, for *all* directories named
113+"a" in all branches. This will cause the file /a/f from branch 1 to
114+re-appear in the union's namespace, which violates Unix semantics.
115+
116+To avoid this problem, we have a different form of whiteouts for
117+directories, called "opaque directories" (same as BSD Union Mount does).
118+Whenever we replace a whiteout with a directory, that directory is marked as
119+opaque. In Unionfs 2.x, it means that we create a file named
120+/a/.wh.__dir_opaque in branch 0, after having created directory /a there.
121+When unionfs notices that a directory is opaque, it stops all namespace
122+operations (including merging readdir contents) at that opaque directory.
123+This prevents re-exposing names from masked out directories.
124+
125+
126+Duplicate Elimination:
127+======================
128+
129+It is possible for files on different branches to have the same name.
130+Unionfs then has to select which instance of the file to show to the user.
131+Given the fact that each branch has a priority associated with it, the
132+simplest solution is to take the instance from the highest priority
133+(numerically lowest value) and "hide" the others.
134+
135+
136+Unlinking:
137+=========
138+
139+Unlink operation on non-directory instances is optimized to remove the
140+maximum possible objects in case multiple underlying branches have the same
141+file name. The unlink operation will first try to delete file instances
142+from highest priority branch and then move further to delete from remaining
143+branches in order of their decreasing priority. Consider a case (F..D..F),
144+where F is a file and D is a directory of the same name; here, some
145+intermediate branch could have an empty directory instance with the same
146+name, so this operation also tries to delete this directory instance and
147+proceed further to delete from next possible lower priority branch. The
148+unionfs unlink operation will smoothly delete the files with same name from
149+all possible underlying branches. In case if some error occurs, it creates
150+whiteout in highest priority branch that will hide file instance in rest of
151+the branches. An error could occur either if an unlink operations in any of
152+the underlying branch failed or if a branch has no write permission.
153+
154+This unlinking policy is known as "delete all" and it has the benefit of
155+overall reducing the number of inodes used by duplicate files, and further
156+reducing the total number of inodes consumed by whiteouts. The cost is of
157+extra processing, but testing shows this extra processing is well worth the
158+savings.
159+
160+
161+Copyup:
162+=======
163+
164+When a change is made to the contents of a file's data or meta-data, they
165+have to be stored somewhere. The best way is to create a copy of the
166+original file on a branch that is writable, and then redirect the write
167+though to this copy. The copy must be made on a higher priority branch so
168+that lookup and readdir return this newer "version" of the file rather than
169+the original (see duplicate elimination).
170+
171+An entire unionfs mount can be read-only or read-write. If it's read-only,
172+then none of the branches will be written to, even if some of the branches
173+are physically writeable. If the unionfs mount is read-write, then the
174+leftmost (highest priority) branch must be writeable (for copyup to take
175+place); the remaining branches can be any mix of read-write and read-only.
176+
177+In a writeable mount, unionfs will create new files/dir in the leftmost
178+branch. If one tries to modify a file in a read-only branch/media, unionfs
179+will copyup the file to the leftmost branch and modify it there. If you try
180+to modify a file from a writeable branch which is not the leftmost branch,
181+then unionfs will modify it in that branch; this is useful if you, say,
182+unify differnet packages (e.g., apache, sendmail, ftpd, etc.) and you want
183+changes to specific package files to remain logically in the directory where
184+they came from.
185+
186+Cache Coherency:
187+================
188+
189+Unionfs users often want to be able to modify files and directories directly
190+on the lower branches, and have those changes be visible at the Unionfs
191+level. This means that data (e.g., pages) and meta-data (dentries, inodes,
192+open files, etc.) have to be synchronized between the upper and lower
193+layers. In other words, the newest changes from a layer below have to be
194+propagated to the Unionfs layer above. If the two layers are not in sync, a
195+cache incoherency ensues, which could lead to application failures and even
196+oopses. The Linux kernel, however, has a rather limited set of mechanisms
197+to ensure this inter-layer cache coherency---so Unionfs has to do most of
198+the hard work on its own.
199+
200+Maintaining Invariants:
201+
202+The way Unionfs ensures cache coherency is as follows. At each entry point
203+to a Unionfs file system method, we call a utility function to validate the
204+primary objects of this method. Generally, we call unionfs_file_revalidate
205+on open files, and __unionfs_d_revalidate_chain on dentries (which also
206+validates inodes). These utility functions check to see whether the upper
207+Unionfs object is in sync with any of the lower objects that it represents.
208+The checks we perform include whether the Unionfs superblock has a newer
209+generation number, or if any of the lower objects mtime's or ctime's are
210+newer. (Note: generation numbers change when branch-management commands are
211+issued, so in a way, maintaining cache coherency is also very important for
212+branch-management.) If indeed we determine that any Unionfs object is no
213+longer in sync with its lower counterparts, then we rebuild that object
214+similarly to how we do so for branch-management.
215+
216+While rebuilding Unionfs's objects, we also purge any page mappings and
217+truncate inode pages (see fs/unionfs/dentry.c:purge_inode_data). This is to
218+ensure that Unionfs will re-get the newer data from the lower branches. We
219+perform this purging only if the Unionfs operation in question is a reading
220+operation; if Unionfs is performing a data writing operation (e.g., ->write,
221+->commit_write, etc.) then we do NOT flush the lower mappings/pages: this is
222+because (1) a self-deadlock could occur and (2) the upper Unionfs pages are
223+considered more authoritative anyway, as they are newer and will overwrite
224+any lower pages.
225+
226+Unionfs maintains the following important invariant regarding mtime's,
227+ctime's, and atime's: the upper inode object's times are the max() of all of
228+the lower ones. For non-directory objects, there's only one object below,
229+so the mapping is simple; for directory objects, there could me multiple
230+lower objects and we have to sync up with the newest one of all the lower
231+ones. This invariant is important to maintain, especially for directories
232+(besides, we need this to be POSIX compliant). A union could comprise
233+multiple writable branches, each of which could change. If we don't reflect
234+the newest possible mtime/ctime, some applications could fail. For example,
235+NFSv2/v3 exports check for newer directory mtimes on the server to determine
236+if the client-side attribute cache should be purged.
237+
238+To maintain these important invariants, of course, Unionfs carefully
239+synchronizes upper and lower times in various places. For example, if we
240+copy-up a file to a top-level branch, the parent directory where the file
241+was copied up to will now have a new mtime: so after a successful copy-up,
242+we sync up with the new top-level branch's parent directory mtime.
243+
244+Implementation:
245+
246+This cache-coherency implementation is efficient because it defers any
247+synchronizing between the upper and lower layers until absolutely needed.
248+Consider the example a common situation where users perform a lot of lower
249+changes, such as untarring a whole package. While these take place,
250+typically the user doesn't access the files via Unionfs; only after the
251+lower changes are done, does the user try to access the lower files. With
252+our cache-coherency implementation, the entirety of the changes to the lower
253+branches will not result in a single CPU cycle spent at the Unionfs level
254+until the user invokes a system call that goes through Unionfs.
255+
256+We have considered two alternate cache-coherency designs. (1) Using the
257+dentry/inode notify functionality to register interest in finding out about
258+any lower changes. This is a somewhat limited and also a heavy-handed
259+approach which could result in many notifications to the Unionfs layer upon
260+each small change at the lower layer (imagine a file being modified multiple
261+times in rapid succession). (2) Rewriting the VFS to support explicit
262+callbacks from lower objects to upper objects. We began exploring such an
263+implementation, but found it to be very complicated--it would have resulted
264+in massive VFS/MM changes which are unlikely to be accepted by the LKML
265+community. We therefore believe that our current cache-coherency design and
266+implementation represent the best approach at this time.
267+
268+Limitations:
269+
270+Our implementation works in that as long as a user process will have caused
271+Unionfs to be called, directly or indirectly, even to just do
272+->d_revalidate; then we will have purged the current Unionfs data and the
273+process will see the new data. For example, a process that continually
274+re-reads the same file's data will see the NEW data as soon as the lower
275+file had changed, upon the next read(2) syscall (even if the file is still
276+open!) However, this doesn't work when the process re-reads the open file's
277+data via mmap(2) (unless the user unmaps/closes the file and remaps/reopens
278+it). Once we respond to ->readpage(s), then the kernel maps the page into
279+the process's address space and there doesn't appear to be a way to force
280+the kernel to invalidate those pages/mappings, and force the process to
281+re-issue ->readpage. If there's a way to invalidate active mappings and
282+force a ->readpage, let us know please (invalidate_inode_pages2 doesn't do
283+the trick).
284+
285+Our current Unionfs code has to perform many file-revalidation calls. It
286+would be really nice if the VFS would export an optional file system hook
287+->file_revalidate (similarly to dentry->d_revalidate) that will be called
288+before each VFS op that has a "struct file" in it.
289+
290+Certain file systems have micro-second granularity (or better) for inode
291+times, and asynchronous actions could cause those times to change with some
292+small delay. In such cases, Unionfs may see a changed inode time that only
293+differs by a tiny fraction of a second: such a change may be a false
294+positive indication that the lower object has changed, whereas if unionfs
295+waits a little longer, that false indication will not be seen. (These false
296+positives are harmless, because they would at most cause unionfs to
297+re-validate an object that may need no revalidation, and print a debugging
298+message that clutters the console/logs.) Therefore, to minimize the chances
299+of these situations, we delay the detection of changed times by a small
300+factor of a few seconds, called UNIONFS_MIN_CC_TIME (which defaults to 3
301+seconds, as does NFS). This means that we will detect the change, only a
302+couple of seconds later, if indeed the time change persists in the lower
303+file object. This delayed detection has an added performance benefit: we
304+reduce the number of times that unionfs has to revalidate objects, in case
305+there's a lot of concurrent activity on both the upper and lower objects,
306+for the same file(s). Lastly, this delayed time attribute detection is
307+similar to how NFS clients operate (e.g., acregmin).
308+
309+Finally, there is no way currently in Linux to prevent lower directories
310+from being moved around (i.e., topology changes); there's no way to prevent
311+modifications to directory sub-trees of whole file systems which are mounted
312+read-write. It is therefore possible for in-flight operations in unionfs to
313+take place, while a lower directory is being moved around. Therefore, if
314+you try to, say, create a new file in a directory through unionfs, while the
315+directory is being moved around directly, then the new file may get created
316+in the new location where that directory was moved to. This is a somewhat
317+similar behaviour in NFS: an NFS client could be creating a new file while
318+th NFS server is moving th directory around; the file will get successfully
319+created in the new location. (The one exception in unionfs is that if the
320+branch is marked read-only by unionfs, then a copyup will take place.)
321+
322+For more information, see <http://unionfs.filesystems.org/>.
323diff --git a/Documentation/filesystems/unionfs/issues.txt b/Documentation/filesystems/unionfs/issues.txt
324new file mode 100644
325index 0000000..f4b7e7e
326--- /dev/null
327+++ b/Documentation/filesystems/unionfs/issues.txt
328@@ -0,0 +1,28 @@
329+KNOWN Unionfs 2.x ISSUES:
330+=========================
331+
332+1. Unionfs should not use lookup_one_len() on the underlying f/s as it
333+ confuses NFSv4. Currently, unionfs_lookup() passes lookup intents to the
334+ lower file-system, this eliminates part of the problem. The remaining
335+ calls to lookup_one_len may need to be changed to pass an intent. We are
336+ currently introducing VFS changes to fs/namei.c's do_path_lookup() to
337+ allow proper file lookup and opening in stackable file systems.
338+
339+2. Lockdep (a debugging feature) isn't aware of stacking, and so it
340+ incorrectly complains about locking problems. The problem boils down to
341+ this: Lockdep considers all objects of a certain type to be in the same
342+ class, for example, all inodes. Lockdep doesn't like to see a lock held
343+ on two inodes within the same task, and warns that it could lead to a
344+ deadlock. However, stackable file systems do precisely that: they lock
345+ an upper object, and then a lower object, in a strict order to avoid
346+ locking problems; in addition, Unionfs, as a fan-out file system, may
347+ have to lock several lower inodes. We are currently looking into Lockdep
348+ to see how to make it aware of stackable file systems. For now, we
349+ temporarily disable lockdep when calling vfs methods on lower objects,
350+ but only for those places where lockdep complained. While this solution
351+ may seem unclean, it is not without precedent: other places in the kernel
352+ also do similar temporary disabling, of course after carefully having
353+ checked that it is the right thing to do. Anyway, you get any warnings
354+ from Lockdep, please report them to the Unionfs maintainers.
355+
356+For more information, see <http://unionfs.filesystems.org/>.
357diff --git a/Documentation/filesystems/unionfs/rename.txt b/Documentation/filesystems/unionfs/rename.txt
358new file mode 100644
359index 0000000..e20bb82
360--- /dev/null
361+++ b/Documentation/filesystems/unionfs/rename.txt
362@@ -0,0 +1,31 @@
363+Rename is a complex beast. The following table shows which rename(2) operations
364+should succeed and which should fail.
365+
366+o: success
367+E: error (either unionfs or vfs)
368+X: EXDEV
369+
370+none = file does not exist
371+file = file is a file
372+dir = file is a empty directory
373+child= file is a non-empty directory
374+wh = file is a directory containing only whiteouts; this makes it logically
375+ empty
376+
377+ none file dir child wh
378+file o o E E E
379+dir o E o E o
380+child X E X E X
381+wh o E o E o
382+
383+
384+Renaming directories:
385+=====================
386+
387+Whenever a empty (either physically or logically) directory is being renamed,
388+the following sequence of events should take place:
389+
390+1) Remove whiteouts from both source and destination directory
391+2) Rename source to destination
392+3) Make destination opaque to prevent anything under it from showing up
393+
394diff --git a/Documentation/filesystems/unionfs/usage.txt b/Documentation/filesystems/unionfs/usage.txt
395new file mode 100644
396index 0000000..1adde69
397--- /dev/null
398+++ b/Documentation/filesystems/unionfs/usage.txt
399@@ -0,0 +1,134 @@
400+Unionfs is a stackable unification file system, which can appear to merge
401+the contents of several directories (branches), while keeping their physical
402+content separate. Unionfs is useful for unified source tree management,
403+merged contents of split CD-ROM, merged separate software package
404+directories, data grids, and more. Unionfs allows any mix of read-only and
405+read-write branches, as well as insertion and deletion of branches anywhere
406+in the fan-out. To maintain Unix semantics, Unionfs handles elimination of
407+duplicates, partial-error conditions, and more.
408+
409+GENERAL SYNTAX
410+==============
411+
412+# mount -t unionfs -o <OPTIONS>,<BRANCH-OPTIONS> none MOUNTPOINT
413+
414+OPTIONS can be any legal combination of:
415+
416+- ro # mount file system read-only
417+- rw # mount file system read-write
418+- remount # remount the file system (see Branch Management below)
419+- incgen # increment generation no. (see Cache Consistency below)
420+
421+BRANCH-OPTIONS can be either (1) a list of branches given to the "dirs="
422+option, or (2) a list of individual branch manipulation commands, combined
423+with the "remount" option, and is further described in the "Branch
424+Management" section below.
425+
426+The syntax for the "dirs=" mount option is:
427+
428+ dirs=branch[=ro|=rw][:...]
429+
430+The "dirs=" option takes a colon-delimited list of directories to compose
431+the union, with an optional branch mode for each of those directories.
432+Directories that come earlier (specified first, on the left) in the list
433+have a higher precedence than those which come later. Additionally,
434+read-only or read-write permissions of the branch can be specified by
435+appending =ro or =rw (default) to each directory. See the Copyup section in
436+concepts.txt, for a description of Unionfs's behavior when mixing read-only
437+and read-write branches and mounts.
438+
439+Syntax:
440+
441+ dirs=/branch1[=ro|=rw]:/branch2[=ro|=rw]:...:/branchN[=ro|=rw]
442+
443+Example:
444+
445+ dirs=/writable_branch=rw:/read-only_branch=ro
446+
447+
448+BRANCH MANAGEMENT
449+=================
450+
451+Once you mount your union for the first time, using the "dirs=" option, you
452+can then change the union's overall mode or reconfigure the branches, using
453+the remount option, as follows.
454+
455+To downgrade a union from read-write to read-only:
456+
457+# mount -t unionfs -o remount,ro none MOUNTPOINT
458+
459+To upgrade a union from read-only to read-write:
460+
461+# mount -t unionfs -o remount,rw none MOUNTPOINT
462+
463+To delete a branch /foo, regardless where it is in the current union:
464+
465+# mount -t unionfs -o remount,del=/foo none MOUNTPOINT
466+
467+To insert (add) a branch /foo before /bar:
468+
469+# mount -t unionfs -o remount,add=/bar:/foo none MOUNTPOINT
470+
471+To insert (add) a branch /foo (with the "rw" mode flag) before /bar:
472+
473+# mount -t unionfs -o remount,add=/bar:/foo=rw none MOUNTPOINT
474+
475+To insert (add) a branch /foo (in "rw" mode) at the very beginning (i.e., a
476+new highest-priority branch), you can use the above syntax, or use a short
477+hand version as follows:
478+
479+# mount -t unionfs -o remount,add=/foo none MOUNTPOINT
480+
481+To append a branch to the very end (new lowest-priority branch):
482+
483+# mount -t unionfs -o remount,add=:/foo none MOUNTPOINT
484+
485+To append a branch to the very end (new lowest-priority branch), in
486+read-only mode:
487+
488+# mount -t unionfs -o remount,add=:/foo=ro none MOUNTPOINT
489+
490+Finally, to change the mode of one existing branch, say /foo, from read-only
491+to read-write, and change /bar from read-write to read-only:
492+
493+# mount -t unionfs -o remount,mode=/foo=rw,mode=/bar=ro none MOUNTPOINT
494+
495+Note: in Unionfs 2.x, you cannot set the leftmost branch to readonly because
496+then Unionfs won't have any writable place for copyups to take place.
497+Moreover, the VFS can get confused when it tries to modify something in a
498+file system mounted read-write, but isn't permitted to write to it.
499+Instead, you should set the whole union as readonly, as described above.
500+If, however, you must set the leftmost branch as readonly, perhaps so you
501+can get a snapshot of it at a point in time, then you should insert a new
502+writable top-level branch, and mark the one you want as readonly. This can
503+be accomplished as follows, assuming that /foo is your current leftmost
504+branch:
505+
506+# mount -t tmpfs -o size=NNN /new
507+# mount -t unionfs -o remount,add=/new,mode=/foo=ro none MOUNTPOINT
508+<do what you want safely in /foo>
509+# mount -t unionfs -o remount,del=/new,mode=/foo=rw none MOUNTPOINT
510+<check if there's anything in /new you want to preserve>
511+# umount /new
512+
513+CACHE CONSISTENCY
514+=================
515+
516+If you modify any file on any of the lower branches directly, while there is
517+a Unionfs 2.x mounted above any of those branches, you should tell Unionfs
518+to purge its caches and re-get the objects. To do that, you have to
519+increment the generation number of the superblock using the following
520+command:
521+
522+# mount -t unionfs -o remount,incgen none MOUNTPOINT
523+
524+Note that the older way of incrementing the generation number using an
525+ioctl, is no longer supported in Unionfs 2.0 and newer. Ioctls in general
526+are not encouraged. Plus, an ioctl is per-file concept, whereas the
527+generation number is a per-file-system concept. Worse, such an ioctl
528+requires an open file, which then has to be invalidated by the very nature
529+of the generation number increase (read: the old generation increase ioctl
530+was pretty racy).
531+
532+
533+For more information, see <http://unionfs.filesystems.org/>.
534diff --git a/MAINTAINERS b/MAINTAINERS
535index 02f75fc..8c5efe7 100644
536--- a/MAINTAINERS
537+++ b/MAINTAINERS
538@@ -5766,6 +5766,14 @@ F: Documentation/cdrom/
539 F: drivers/cdrom/cdrom.c
540 F: include/linux/cdrom.h
541
542+UNIONFS
543+P: Erez Zadok
544+M: ezk@cs.sunysb.edu
545+L: unionfs@filesystems.org
546+W: http://unionfs.filesystems.org/
547+T: git git.kernel.org/pub/scm/linux/kernel/git/ezk/unionfs.git
548+S: Maintained
549+
550 UNSORTED BLOCK IMAGES (UBI)
551 M: Artem Bityutskiy <dedekind1@gmail.com>
552 W: http://www.linux-mtd.infradead.org/
553diff --git a/fs/Kconfig b/fs/Kconfig
554index 5f85b59..7b4501b 100644
555--- a/fs/Kconfig
556+++ b/fs/Kconfig
557@@ -169,6 +169,7 @@ if MISC_FILESYSTEMS
558 source "fs/adfs/Kconfig"
559 source "fs/affs/Kconfig"
560 source "fs/ecryptfs/Kconfig"
561+source "fs/unionfs/Kconfig"
562 source "fs/hfs/Kconfig"
563 source "fs/hfsplus/Kconfig"
564 source "fs/befs/Kconfig"
565diff --git a/fs/Makefile b/fs/Makefile
566index e6ec1d3..787332e 100644
567--- a/fs/Makefile
568+++ b/fs/Makefile
569@@ -84,6 +84,7 @@ obj-$(CONFIG_ISO9660_FS) += isofs/
570 obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+
571 obj-$(CONFIG_HFS_FS) += hfs/
572 obj-$(CONFIG_ECRYPT_FS) += ecryptfs/
573+obj-$(CONFIG_UNION_FS) += unionfs/
574 obj-$(CONFIG_VXFS_FS) += freevxfs/
575 obj-$(CONFIG_NFS_FS) += nfs/
576 obj-$(CONFIG_EXPORTFS) += exportfs/
577diff --git a/fs/namei.c b/fs/namei.c
578index 868d0cb..b5e09e1 100644
579--- a/fs/namei.c
580+++ b/fs/namei.c
581@@ -386,6 +386,7 @@ void release_open_intent(struct nameidata *nd)
582 else
583 fput(nd->intent.open.file);
584 }
585+EXPORT_SYMBOL_GPL(release_open_intent);
586
587 static inline struct dentry *
588 do_revalidate(struct dentry *dentry, struct nameidata *nd)
589diff --git a/fs/splice.c b/fs/splice.c
590index efdbfec..1ff6bca 100644
591--- a/fs/splice.c
592+++ b/fs/splice.c
593@@ -1104,8 +1104,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
594 /*
595 * Attempt to initiate a splice from pipe to file.
596 */
597-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
598- loff_t *ppos, size_t len, unsigned int flags)
599+long vfs_splice_from(struct pipe_inode_info *pipe, struct file *out,
600+ loff_t *ppos, size_t len, unsigned int flags)
601 {
602 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
603 loff_t *, size_t, unsigned int);
604@@ -1128,13 +1128,14 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
605
606 return splice_write(pipe, out, ppos, len, flags);
607 }
608+EXPORT_SYMBOL_GPL(vfs_splice_from);
609
610 /*
611 * Attempt to initiate a splice from a file to a pipe.
612 */
613-static long do_splice_to(struct file *in, loff_t *ppos,
614- struct pipe_inode_info *pipe, size_t len,
615- unsigned int flags)
616+long vfs_splice_to(struct file *in, loff_t *ppos,
617+ struct pipe_inode_info *pipe, size_t len,
618+ unsigned int flags)
619 {
620 ssize_t (*splice_read)(struct file *, loff_t *,
621 struct pipe_inode_info *, size_t, unsigned int);
622@@ -1154,6 +1155,7 @@ static long do_splice_to(struct file *in, loff_t *ppos,
623
624 return splice_read(in, ppos, pipe, len, flags);
625 }
626+EXPORT_SYMBOL_GPL(vfs_splice_to);
627
628 /**
629 * splice_direct_to_actor - splices data directly between two non-pipes
630@@ -1223,7 +1225,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
631 size_t read_len;
632 loff_t pos = sd->pos, prev_pos = pos;
633
634- ret = do_splice_to(in, &pos, pipe, len, flags);
635+ ret = vfs_splice_to(in, &pos, pipe, len, flags);
636 if (unlikely(ret <= 0))
637 goto out_release;
638
639@@ -1282,8 +1284,8 @@ static int direct_splice_actor(struct pipe_inode_info *pipe,
640 {
641 struct file *file = sd->u.file;
642
643- return do_splice_from(pipe, file, &file->f_pos, sd->total_len,
644- sd->flags);
645+ return vfs_splice_from(pipe, file, &file->f_pos, sd->total_len,
646+ sd->flags);
647 }
648
649 /**
650@@ -1380,7 +1382,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
651 } else
652 off = &out->f_pos;
653
654- ret = do_splice_from(ipipe, out, off, len, flags);
655+ ret = vfs_splice_from(ipipe, out, off, len, flags);
656
657 if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
658 ret = -EFAULT;
659@@ -1400,7 +1402,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
660 } else
661 off = &in->f_pos;
662
663- ret = do_splice_to(in, off, opipe, len, flags);
664+ ret = vfs_splice_to(in, off, opipe, len, flags);
665
666 if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
667 ret = -EFAULT;
668diff --git a/fs/stack.c b/fs/stack.c
669index 4a6f7f4..7eeef12 100644
670--- a/fs/stack.c
671+++ b/fs/stack.c
672@@ -1,8 +1,20 @@
673+/*
674+ * Copyright (c) 2006-2009 Erez Zadok
675+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
676+ * Copyright (c) 2006-2009 Stony Brook University
677+ * Copyright (c) 2006-2009 The Research Foundation of SUNY
678+ *
679+ * This program is free software; you can redistribute it and/or modify
680+ * it under the terms of the GNU General Public License version 2 as
681+ * published by the Free Software Foundation.
682+ */
683+
684 #include <linux/module.h>
685 #include <linux/fs.h>
686 #include <linux/fs_stack.h>
687
688-/* does _NOT_ require i_mutex to be held.
689+/*
690+ * does _NOT_ require i_mutex to be held.
691 *
692 * This function cannot be inlined since i_size_{read,write} is rather
693 * heavy-weight on 32-bit systems
694diff --git a/fs/unionfs/Kconfig b/fs/unionfs/Kconfig
695new file mode 100644
696index 0000000..f3c1ac4
697--- /dev/null
698+++ b/fs/unionfs/Kconfig
699@@ -0,0 +1,24 @@
700+config UNION_FS
701+ tristate "Union file system (EXPERIMENTAL)"
702+ depends on EXPERIMENTAL
703+ help
704+ Unionfs is a stackable unification file system, which appears to
705+ merge the contents of several directories (branches), while keeping
706+ their physical content separate.
707+
708+ See <http://unionfs.filesystems.org> for details
709+
710+config UNION_FS_XATTR
711+ bool "Unionfs extended attributes"
712+ depends on UNION_FS
713+ help
714+ Extended attributes are name:value pairs associated with inodes by
715+ the kernel or by users (see the attr(5) manual page).
716+
717+ If unsure, say N.
718+
719+config UNION_FS_DEBUG
720+ bool "Debug Unionfs"
721+ depends on UNION_FS
722+ help
723+ If you say Y here, you can turn on debugging output from Unionfs.
724diff --git a/fs/unionfs/Makefile b/fs/unionfs/Makefile
725new file mode 100644
726index 0000000..d34e085
727--- /dev/null
728+++ b/fs/unionfs/Makefile
729@@ -0,0 +1,17 @@
730+UNIONFS_VERSION="2.5.7 (for 2.6.35.8)"
731+
732+EXTRA_CFLAGS += -DUNIONFS_VERSION=\"$(UNIONFS_VERSION)\"
733+
734+obj-$(CONFIG_UNION_FS) += unionfs.o
735+
736+unionfs-y := subr.o dentry.o file.o inode.o main.o super.o \
737+ rdstate.o copyup.o dirhelper.o rename.o unlink.o \
738+ lookup.o commonfops.o dirfops.o sioq.o mmap.o whiteout.o
739+
740+unionfs-$(CONFIG_UNION_FS_XATTR) += xattr.o
741+
742+unionfs-$(CONFIG_UNION_FS_DEBUG) += debug.o
743+
744+ifeq ($(CONFIG_UNION_FS_DEBUG),y)
745+EXTRA_CFLAGS += -DDEBUG
746+endif
747diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
748new file mode 100644
749index 0000000..740c4ad
750--- /dev/null
751+++ b/fs/unionfs/commonfops.c
752@@ -0,0 +1,896 @@
753+/*
754+ * Copyright (c) 2003-2010 Erez Zadok
755+ * Copyright (c) 2003-2006 Charles P. Wright
756+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
757+ * Copyright (c) 2005-2006 Junjiro Okajima
758+ * Copyright (c) 2005 Arun M. Krishnakumar
759+ * Copyright (c) 2004-2006 David P. Quigley
760+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
761+ * Copyright (c) 2003 Puja Gupta
762+ * Copyright (c) 2003 Harikesavan Krishnan
763+ * Copyright (c) 2003-2010 Stony Brook University
764+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
765+ *
766+ * This program is free software; you can redistribute it and/or modify
767+ * it under the terms of the GNU General Public License version 2 as
768+ * published by the Free Software Foundation.
769+ */
770+
771+#include "union.h"
772+
773+/*
774+ * 1) Copyup the file
775+ * 2) Rename the file to '.unionfs<original inode#><counter>' - obviously
776+ * stolen from NFS's silly rename
777+ */
778+static int copyup_deleted_file(struct file *file, struct dentry *dentry,
779+ struct dentry *parent, int bstart, int bindex)
780+{
781+ static unsigned int counter;
782+ const int i_inosize = sizeof(dentry->d_inode->i_ino) * 2;
783+ const int countersize = sizeof(counter) * 2;
784+ const int nlen = sizeof(".unionfs") + i_inosize + countersize - 1;
785+ char name[nlen + 1];
786+ int err;
787+ struct dentry *tmp_dentry = NULL;
788+ struct dentry *lower_dentry;
789+ struct dentry *lower_dir_dentry = NULL;
790+
791+ lower_dentry = unionfs_lower_dentry_idx(dentry, bstart);
792+
793+ sprintf(name, ".unionfs%*.*lx",
794+ i_inosize, i_inosize, lower_dentry->d_inode->i_ino);
795+
796+ /*
797+ * Loop, looking for an unused temp name to copyup to.
798+ *
799+ * It's somewhat silly that we look for a free temp tmp name in the
800+ * source branch (bstart) instead of the dest branch (bindex), where
801+ * the final name will be created. We _will_ catch it if somehow
802+ * the name exists in the dest branch, but it'd be nice to catch it
803+ * sooner than later.
804+ */
805+retry:
806+ tmp_dentry = NULL;
807+ do {
808+ char *suffix = name + nlen - countersize;
809+
810+ dput(tmp_dentry);
811+ counter++;
812+ sprintf(suffix, "%*.*x", countersize, countersize, counter);
813+
814+ pr_debug("unionfs: trying to rename %s to %s\n",
815+ dentry->d_name.name, name);
816+
817+ tmp_dentry = lookup_lck_len(name, lower_dentry->d_parent,
818+ nlen);
819+ if (IS_ERR(tmp_dentry)) {
820+ err = PTR_ERR(tmp_dentry);
821+ goto out;
822+ }
823+ } while (tmp_dentry->d_inode != NULL); /* need negative dentry */
824+ dput(tmp_dentry);
825+
826+ err = copyup_named_file(parent->d_inode, file, name, bstart, bindex,
827+ i_size_read(file->f_path.dentry->d_inode));
828+ if (err) {
829+ if (unlikely(err == -EEXIST))
830+ goto retry;
831+ goto out;
832+ }
833+
834+ /* bring it to the same state as an unlinked file */
835+ lower_dentry = unionfs_lower_dentry_idx(dentry, dbstart(dentry));
836+ if (!unionfs_lower_inode_idx(dentry->d_inode, bindex)) {
837+ atomic_inc(&lower_dentry->d_inode->i_count);
838+ unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
839+ lower_dentry->d_inode);
840+ }
841+ lower_dir_dentry = lock_parent(lower_dentry);
842+ err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
843+ unlock_dir(lower_dir_dentry);
844+
845+out:
846+ if (!err)
847+ unionfs_check_dentry(dentry);
848+ return err;
849+}
850+
851+/*
852+ * put all references held by upper struct file and free lower file pointer
853+ * array
854+ */
855+static void cleanup_file(struct file *file)
856+{
857+ int bindex, bstart, bend;
858+ struct file **lower_files;
859+ struct file *lower_file;
860+ struct super_block *sb = file->f_path.dentry->d_sb;
861+
862+ lower_files = UNIONFS_F(file)->lower_files;
863+ bstart = fbstart(file);
864+ bend = fbend(file);
865+
866+ for (bindex = bstart; bindex <= bend; bindex++) {
867+ int i; /* holds (possibly) updated branch index */
868+ int old_bid;
869+
870+ lower_file = unionfs_lower_file_idx(file, bindex);
871+ if (!lower_file)
872+ continue;
873+
874+ /*
875+ * Find new index of matching branch with an open
876+ * file, since branches could have been added or
877+ * deleted causing the one with open files to shift.
878+ */
879+ old_bid = UNIONFS_F(file)->saved_branch_ids[bindex];
880+ i = branch_id_to_idx(sb, old_bid);
881+ if (unlikely(i < 0)) {
882+ printk(KERN_ERR "unionfs: no superblock for "
883+ "file %p\n", file);
884+ continue;
885+ }
886+
887+ /* decrement count of open files */
888+ branchput(sb, i);
889+ /*
890+ * fput will perform an mntput for us on the correct branch.
891+ * Although we're using the file's old branch configuration,
892+ * bindex, which is the old index, correctly points to the
893+ * right branch in the file's branch list. In other words,
894+ * we're going to mntput the correct branch even if branches
895+ * have been added/removed.
896+ */
897+ fput(lower_file);
898+ UNIONFS_F(file)->lower_files[bindex] = NULL;
899+ UNIONFS_F(file)->saved_branch_ids[bindex] = -1;
900+ }
901+
902+ UNIONFS_F(file)->lower_files = NULL;
903+ kfree(lower_files);
904+ kfree(UNIONFS_F(file)->saved_branch_ids);
905+ /* set to NULL because caller needs to know if to kfree on error */
906+ UNIONFS_F(file)->saved_branch_ids = NULL;
907+}
908+
909+/* open all lower files for a given file */
910+static int open_all_files(struct file *file)
911+{
912+ int bindex, bstart, bend, err = 0;
913+ struct file *lower_file;
914+ struct dentry *lower_dentry;
915+ struct dentry *dentry = file->f_path.dentry;
916+ struct super_block *sb = dentry->d_sb;
917+
918+ bstart = dbstart(dentry);
919+ bend = dbend(dentry);
920+
921+ for (bindex = bstart; bindex <= bend; bindex++) {
922+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
923+ if (!lower_dentry)
924+ continue;
925+
926+ dget(lower_dentry);
927+ unionfs_mntget(dentry, bindex);
928+ branchget(sb, bindex);
929+
930+ lower_file =
931+ dentry_open(lower_dentry,
932+ unionfs_lower_mnt_idx(dentry, bindex),
933+ file->f_flags, current_cred());
934+ if (IS_ERR(lower_file)) {
935+ branchput(sb, bindex);
936+ err = PTR_ERR(lower_file);
937+ goto out;
938+ } else {
939+ unionfs_set_lower_file_idx(file, bindex, lower_file);
940+ }
941+ }
942+out:
943+ return err;
944+}
945+
946+/* open the highest priority file for a given upper file */
947+static int open_highest_file(struct file *file, bool willwrite)
948+{
949+ int bindex, bstart, bend, err = 0;
950+ struct file *lower_file;
951+ struct dentry *lower_dentry;
952+ struct dentry *dentry = file->f_path.dentry;
953+ struct dentry *parent = dget_parent(dentry);
954+ struct inode *parent_inode = parent->d_inode;
955+ struct super_block *sb = dentry->d_sb;
956+
957+ bstart = dbstart(dentry);
958+ bend = dbend(dentry);
959+
960+ lower_dentry = unionfs_lower_dentry(dentry);
961+ if (willwrite && IS_WRITE_FLAG(file->f_flags) && is_robranch(dentry)) {
962+ for (bindex = bstart - 1; bindex >= 0; bindex--) {
963+ err = copyup_file(parent_inode, file, bstart, bindex,
964+ i_size_read(dentry->d_inode));
965+ if (!err)
966+ break;
967+ }
968+ atomic_set(&UNIONFS_F(file)->generation,
969+ atomic_read(&UNIONFS_I(dentry->d_inode)->
970+ generation));
971+ goto out;
972+ }
973+
974+ dget(lower_dentry);
975+ unionfs_mntget(dentry, bstart);
976+ lower_file = dentry_open(lower_dentry,
977+ unionfs_lower_mnt_idx(dentry, bstart),
978+ file->f_flags, current_cred());
979+ if (IS_ERR(lower_file)) {
980+ err = PTR_ERR(lower_file);
981+ goto out;
982+ }
983+ branchget(sb, bstart);
984+ unionfs_set_lower_file(file, lower_file);
985+ /* Fix up the position. */
986+ lower_file->f_pos = file->f_pos;
987+
988+ memcpy(&lower_file->f_ra, &file->f_ra, sizeof(struct file_ra_state));
989+out:
990+ dput(parent);
991+ return err;
992+}
993+
994+/* perform a delayed copyup of a read-write file on a read-only branch */
995+static int do_delayed_copyup(struct file *file, struct dentry *parent)
996+{
997+ int bindex, bstart, bend, err = 0;
998+ struct dentry *dentry = file->f_path.dentry;
999+ struct inode *parent_inode = parent->d_inode;
1000+
1001+ bstart = fbstart(file);
1002+ bend = fbend(file);
1003+
1004+ BUG_ON(!S_ISREG(dentry->d_inode->i_mode));
1005+
1006+ unionfs_check_file(file);
1007+ for (bindex = bstart - 1; bindex >= 0; bindex--) {
1008+ if (!d_deleted(dentry))
1009+ err = copyup_file(parent_inode, file, bstart,
1010+ bindex,
1011+ i_size_read(dentry->d_inode));
1012+ else
1013+ err = copyup_deleted_file(file, dentry, parent,
1014+ bstart, bindex);
1015+ /* if succeeded, set lower open-file flags and break */
1016+ if (!err) {
1017+ struct file *lower_file;
1018+ lower_file = unionfs_lower_file_idx(file, bindex);
1019+ lower_file->f_flags = file->f_flags;
1020+ break;
1021+ }
1022+ }
1023+ if (err || (bstart <= fbstart(file)))
1024+ goto out;
1025+ bend = fbend(file);
1026+ for (bindex = bstart; bindex <= bend; bindex++) {
1027+ if (unionfs_lower_file_idx(file, bindex)) {
1028+ branchput(dentry->d_sb, bindex);
1029+ fput(unionfs_lower_file_idx(file, bindex));
1030+ unionfs_set_lower_file_idx(file, bindex, NULL);
1031+ }
1032+ }
1033+ path_put_lowers(dentry, bstart, bend, false);
1034+ iput_lowers(dentry->d_inode, bstart, bend, false);
1035+ /* for reg file, we only open it "once" */
1036+ fbend(file) = fbstart(file);
1037+ dbend(dentry) = dbstart(dentry);
1038+ ibend(dentry->d_inode) = ibstart(dentry->d_inode);
1039+
1040+out:
1041+ unionfs_check_file(file);
1042+ return err;
1043+}
1044+
1045+/*
1046+ * Helper function for unionfs_file_revalidate/locked.
1047+ * Expects dentry/parent to be locked already, and revalidated.
1048+ */
1049+static int __unionfs_file_revalidate(struct file *file, struct dentry *dentry,
1050+ struct dentry *parent,
1051+ struct super_block *sb, int sbgen,
1052+ int dgen, bool willwrite)
1053+{
1054+ int fgen;
1055+ int bstart, bend, orig_brid;
1056+ int size;
1057+ int err = 0;
1058+
1059+ fgen = atomic_read(&UNIONFS_F(file)->generation);
1060+
1061+ /*
1062+ * There are two cases we are interested in. The first is if the
1063+ * generation is lower than the super-block. The second is if
1064+ * someone has copied up this file from underneath us, we also need
1065+ * to refresh things.
1066+ */
1067+ if (d_deleted(dentry) ||
1068+ (sbgen <= fgen &&
1069+ dbstart(dentry) == fbstart(file) &&
1070+ unionfs_lower_file(file)))
1071+ goto out_may_copyup;
1072+
1073+ /* save orig branch ID */
1074+ orig_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)];
1075+
1076+ /* First we throw out the existing files. */
1077+ cleanup_file(file);
1078+
1079+ /* Now we reopen the file(s) as in unionfs_open. */
1080+ bstart = fbstart(file) = dbstart(dentry);
1081+ bend = fbend(file) = dbend(dentry);
1082+
1083+ size = sizeof(struct file *) * sbmax(sb);
1084+ UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
1085+ if (unlikely(!UNIONFS_F(file)->lower_files)) {
1086+ err = -ENOMEM;
1087+ goto out;
1088+ }
1089+ size = sizeof(int) * sbmax(sb);
1090+ UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
1091+ if (unlikely(!UNIONFS_F(file)->saved_branch_ids)) {
1092+ err = -ENOMEM;
1093+ goto out;
1094+ }
1095+
1096+ if (S_ISDIR(dentry->d_inode->i_mode)) {
1097+ /* We need to open all the files. */
1098+ err = open_all_files(file);
1099+ if (err)
1100+ goto out;
1101+ } else {
1102+ int new_brid;
1103+ /* We only open the highest priority branch. */
1104+ err = open_highest_file(file, willwrite);
1105+ if (err)
1106+ goto out;
1107+ new_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)];
1108+ if (unlikely(new_brid != orig_brid && sbgen > fgen)) {
1109+ /*
1110+ * If we re-opened the file on a different branch
1111+ * than the original one, and this was due to a new
1112+ * branch inserted, then update the mnt counts of
1113+ * the old and new branches accordingly.
1114+ */
1115+ unionfs_mntget(dentry, bstart);
1116+ unionfs_mntput(sb->s_root,
1117+ branch_id_to_idx(sb, orig_brid));
1118+ }
1119+ /* regular files have only one open lower file */
1120+ fbend(file) = fbstart(file);
1121+ }
1122+ atomic_set(&UNIONFS_F(file)->generation,
1123+ atomic_read(&UNIONFS_I(dentry->d_inode)->generation));
1124+
1125+out_may_copyup:
1126+ /* Copyup on the first write to a file on a readonly branch. */
1127+ if (willwrite && IS_WRITE_FLAG(file->f_flags) &&
1128+ !IS_WRITE_FLAG(unionfs_lower_file(file)->f_flags) &&
1129+ is_robranch(dentry)) {
1130+ pr_debug("unionfs: do delay copyup of \"%s\"\n",
1131+ dentry->d_name.name);
1132+ err = do_delayed_copyup(file, parent);
1133+ /* regular files have only one open lower file */
1134+ if (!err && !S_ISDIR(dentry->d_inode->i_mode))
1135+ fbend(file) = fbstart(file);
1136+ }
1137+
1138+out:
1139+ if (err) {
1140+ kfree(UNIONFS_F(file)->lower_files);
1141+ kfree(UNIONFS_F(file)->saved_branch_ids);
1142+ }
1143+ return err;
1144+}
1145+
1146+/*
1147+ * Revalidate the struct file
1148+ * @file: file to revalidate
1149+ * @parent: parent dentry (locked by caller)
1150+ * @willwrite: true if caller may cause changes to the file; false otherwise.
1151+ * Caller must lock/unlock dentry's branch configuration.
1152+ */
1153+int unionfs_file_revalidate(struct file *file, struct dentry *parent,
1154+ bool willwrite)
1155+{
1156+ struct super_block *sb;
1157+ struct dentry *dentry;
1158+ int sbgen, dgen;
1159+ int err = 0;
1160+
1161+ dentry = file->f_path.dentry;
1162+ sb = dentry->d_sb;
1163+ verify_locked(dentry);
1164+ verify_locked(parent);
1165+
1166+ /*
1167+ * First revalidate the dentry inside struct file,
1168+ * but not unhashed dentries.
1169+ */
1170+ if (!d_deleted(dentry) &&
1171+ !__unionfs_d_revalidate(dentry, parent, willwrite)) {
1172+ err = -ESTALE;
1173+ goto out;
1174+ }
1175+
1176+ sbgen = atomic_read(&UNIONFS_SB(sb)->generation);
1177+ dgen = atomic_read(&UNIONFS_D(dentry)->generation);
1178+
1179+ if (unlikely(sbgen > dgen)) { /* XXX: should never happen */
1180+ pr_debug("unionfs: failed to revalidate dentry (%s)\n",
1181+ dentry->d_name.name);
1182+ err = -ESTALE;
1183+ goto out;
1184+ }
1185+
1186+ err = __unionfs_file_revalidate(file, dentry, parent, sb,
1187+ sbgen, dgen, willwrite);
1188+out:
1189+ return err;
1190+}
1191+
1192+/* unionfs_open helper function: open a directory */
1193+static int __open_dir(struct inode *inode, struct file *file)
1194+{
1195+ struct dentry *lower_dentry;
1196+ struct file *lower_file;
1197+ int bindex, bstart, bend;
1198+ struct vfsmount *mnt;
1199+
1200+ bstart = fbstart(file) = dbstart(file->f_path.dentry);
1201+ bend = fbend(file) = dbend(file->f_path.dentry);
1202+
1203+ for (bindex = bstart; bindex <= bend; bindex++) {
1204+ lower_dentry =
1205+ unionfs_lower_dentry_idx(file->f_path.dentry, bindex);
1206+ if (!lower_dentry)
1207+ continue;
1208+
1209+ dget(lower_dentry);
1210+ unionfs_mntget(file->f_path.dentry, bindex);
1211+ mnt = unionfs_lower_mnt_idx(file->f_path.dentry, bindex);
1212+ lower_file = dentry_open(lower_dentry, mnt, file->f_flags,
1213+ current_cred());
1214+ if (IS_ERR(lower_file))
1215+ return PTR_ERR(lower_file);
1216+
1217+ unionfs_set_lower_file_idx(file, bindex, lower_file);
1218+
1219+ /*
1220+ * The branchget goes after the open, because otherwise
1221+ * we would miss the reference on release.
1222+ */
1223+ branchget(inode->i_sb, bindex);
1224+ }
1225+
1226+ return 0;
1227+}
1228+
1229+/* unionfs_open helper function: open a file */
1230+static int __open_file(struct inode *inode, struct file *file,
1231+ struct dentry *parent)
1232+{
1233+ struct dentry *lower_dentry;
1234+ struct file *lower_file;
1235+ int lower_flags;
1236+ int bindex, bstart, bend;
1237+
1238+ lower_dentry = unionfs_lower_dentry(file->f_path.dentry);
1239+ lower_flags = file->f_flags;
1240+
1241+ bstart = fbstart(file) = dbstart(file->f_path.dentry);
1242+ bend = fbend(file) = dbend(file->f_path.dentry);
1243+
1244+ /*
1245+ * check for the permission for lower file. If the error is
1246+ * COPYUP_ERR, copyup the file.
1247+ */
1248+ if (lower_dentry->d_inode && is_robranch(file->f_path.dentry)) {
1249+ /*
1250+ * if the open will change the file, copy it up otherwise
1251+ * defer it.
1252+ */
1253+ if (lower_flags & O_TRUNC) {
1254+ int size = 0;
1255+ int err = -EROFS;
1256+
1257+ /* copyup the file */
1258+ for (bindex = bstart - 1; bindex >= 0; bindex--) {
1259+ err = copyup_file(parent->d_inode, file,
1260+ bstart, bindex, size);
1261+ if (!err)
1262+ break;
1263+ }
1264+ return err;
1265+ } else {
1266+ /*
1267+ * turn off writeable flags, to force delayed copyup
1268+ * by caller.
1269+ */
1270+ lower_flags &= ~(OPEN_WRITE_FLAGS);
1271+ }
1272+ }
1273+
1274+ dget(lower_dentry);
1275+
1276+ /*
1277+ * dentry_open will decrement mnt refcnt if err.
1278+ * otherwise fput() will do an mntput() for us upon file close.
1279+ */
1280+ unionfs_mntget(file->f_path.dentry, bstart);
1281+ lower_file =
1282+ dentry_open(lower_dentry,
1283+ unionfs_lower_mnt_idx(file->f_path.dentry, bstart),
1284+ lower_flags, current_cred());
1285+ if (IS_ERR(lower_file))
1286+ return PTR_ERR(lower_file);
1287+
1288+ unionfs_set_lower_file(file, lower_file);
1289+ branchget(inode->i_sb, bstart);
1290+
1291+ return 0;
1292+}
1293+
1294+int unionfs_open(struct inode *inode, struct file *file)
1295+{
1296+ int err = 0;
1297+ struct file *lower_file = NULL;
1298+ struct dentry *dentry = file->f_path.dentry;
1299+ struct dentry *parent;
1300+ int bindex = 0, bstart = 0, bend = 0;
1301+ int size;
1302+ int valid = 0;
1303+
1304+ unionfs_read_lock(inode->i_sb, UNIONFS_SMUTEX_PARENT);
1305+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
1306+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
1307+
1308+ /* don't open unhashed/deleted files */
1309+ if (d_deleted(dentry)) {
1310+ err = -ENOENT;
1311+ goto out_nofree;
1312+ }
1313+
1314+ /* XXX: should I change 'false' below to the 'willwrite' flag? */
1315+ valid = __unionfs_d_revalidate(dentry, parent, false);
1316+ if (unlikely(!valid)) {
1317+ err = -ESTALE;
1318+ goto out_nofree;
1319+ }
1320+
1321+ file->private_data =
1322+ kzalloc(sizeof(struct unionfs_file_info), GFP_KERNEL);
1323+ if (unlikely(!UNIONFS_F(file))) {
1324+ err = -ENOMEM;
1325+ goto out_nofree;
1326+ }
1327+ fbstart(file) = -1;
1328+ fbend(file) = -1;
1329+ atomic_set(&UNIONFS_F(file)->generation,
1330+ atomic_read(&UNIONFS_I(inode)->generation));
1331+
1332+ size = sizeof(struct file *) * sbmax(inode->i_sb);
1333+ UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
1334+ if (unlikely(!UNIONFS_F(file)->lower_files)) {
1335+ err = -ENOMEM;
1336+ goto out;
1337+ }
1338+ size = sizeof(int) * sbmax(inode->i_sb);
1339+ UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
1340+ if (unlikely(!UNIONFS_F(file)->saved_branch_ids)) {
1341+ err = -ENOMEM;
1342+ goto out;
1343+ }
1344+
1345+ bstart = fbstart(file) = dbstart(dentry);
1346+ bend = fbend(file) = dbend(dentry);
1347+
1348+ /*
1349+ * open all directories and make the unionfs file struct point to
1350+ * these lower file structs
1351+ */
1352+ if (S_ISDIR(inode->i_mode))
1353+ err = __open_dir(inode, file); /* open a dir */
1354+ else
1355+ err = __open_file(inode, file, parent); /* open a file */
1356+
1357+ /* freeing the allocated resources, and fput the opened files */
1358+ if (err) {
1359+ for (bindex = bstart; bindex <= bend; bindex++) {
1360+ lower_file = unionfs_lower_file_idx(file, bindex);
1361+ if (!lower_file)
1362+ continue;
1363+
1364+ branchput(dentry->d_sb, bindex);
1365+ /* fput calls dput for lower_dentry */
1366+ fput(lower_file);
1367+ }
1368+ }
1369+
1370+out:
1371+ if (err) {
1372+ kfree(UNIONFS_F(file)->lower_files);
1373+ kfree(UNIONFS_F(file)->saved_branch_ids);
1374+ kfree(UNIONFS_F(file));
1375+ }
1376+out_nofree:
1377+ if (!err) {
1378+ unionfs_postcopyup_setmnt(dentry);
1379+ unionfs_copy_attr_times(inode);
1380+ unionfs_check_file(file);
1381+ unionfs_check_inode(inode);
1382+ }
1383+ unionfs_unlock_dentry(dentry);
1384+ unionfs_unlock_parent(dentry, parent);
1385+ unionfs_read_unlock(inode->i_sb);
1386+ return err;
1387+}
1388+
1389+/*
1390+ * release all lower object references & free the file info structure
1391+ *
1392+ * No need to grab sb info's rwsem.
1393+ */
1394+int unionfs_file_release(struct inode *inode, struct file *file)
1395+{
1396+ struct file *lower_file = NULL;
1397+ struct unionfs_file_info *fileinfo;
1398+ struct unionfs_inode_info *inodeinfo;
1399+ struct super_block *sb = inode->i_sb;
1400+ struct dentry *dentry = file->f_path.dentry;
1401+ struct dentry *parent;
1402+ int bindex, bstart, bend;
1403+ int fgen, err = 0;
1404+
1405+ /*
1406+ * Since mm/memory.c:might_fault() (under PROVE_LOCKING) was
1407+ * modified in 2.6.29-rc1 to call might_lock_read on mmap_sem, this
1408+ * has been causing false positives in file system stacking layers.
1409+ * In particular, our ->mmap is called after sys_mmap2 already holds
1410+ * mmap_sem, then we lock our own mutexes; but earlier, it's
1411+ * possible for lockdep to have locked our mutexes first, and then
1412+ * we call a lower ->readdir which could call might_fault. The
1413+ * different ordering of the locks is what lockdep complains about
1414+ * -- unnecessarily. Therefore, we have no choice but to tell
1415+ * lockdep to temporarily turn off lockdep here. Note: the comments
1416+ * inside might_sleep also suggest that it would have been
1417+ * nicer to only annotate paths that needs that might_lock_read.
1418+ */
1419+ lockdep_off();
1420+ unionfs_read_lock(sb, UNIONFS_SMUTEX_PARENT);
1421+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
1422+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
1423+
1424+ /*
1425+ * We try to revalidate, but the VFS ignores return return values
1426+ * from file->release, so we must always try to succeed here,
1427+ * including to do the kfree and dput below. So if revalidation
1428+ * failed, all we can do is print some message and keep going.
1429+ */
1430+ err = unionfs_file_revalidate(file, parent,
1431+ UNIONFS_F(file)->wrote_to_file);
1432+ if (!err)
1433+ unionfs_check_file(file);
1434+ fileinfo = UNIONFS_F(file);
1435+ BUG_ON(file->f_path.dentry->d_inode != inode);
1436+ inodeinfo = UNIONFS_I(inode);
1437+
1438+ /* fput all the lower files */
1439+ fgen = atomic_read(&fileinfo->generation);
1440+ bstart = fbstart(file);
1441+ bend = fbend(file);
1442+
1443+ for (bindex = bstart; bindex <= bend; bindex++) {
1444+ lower_file = unionfs_lower_file_idx(file, bindex);
1445+
1446+ if (lower_file) {
1447+ unionfs_set_lower_file_idx(file, bindex, NULL);
1448+ fput(lower_file);
1449+ branchput(sb, bindex);
1450+ }
1451+
1452+ /* if there are no more refs to the dentry, dput it */
1453+ if (d_deleted(dentry)) {
1454+ dput(unionfs_lower_dentry_idx(dentry, bindex));
1455+ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
1456+ }
1457+ }
1458+
1459+ kfree(fileinfo->lower_files);
1460+ kfree(fileinfo->saved_branch_ids);
1461+
1462+ if (fileinfo->rdstate) {
1463+ fileinfo->rdstate->access = jiffies;
1464+ spin_lock(&inodeinfo->rdlock);
1465+ inodeinfo->rdcount++;
1466+ list_add_tail(&fileinfo->rdstate->cache,
1467+ &inodeinfo->readdircache);
1468+ mark_inode_dirty(inode);
1469+ spin_unlock(&inodeinfo->rdlock);
1470+ fileinfo->rdstate = NULL;
1471+ }
1472+ kfree(fileinfo);
1473+
1474+ unionfs_unlock_dentry(dentry);
1475+ unionfs_unlock_parent(dentry, parent);
1476+ unionfs_read_unlock(sb);
1477+ lockdep_on();
1478+ return err;
1479+}
1480+
1481+/* pass the ioctl to the lower fs */
1482+static long do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1483+{
1484+ struct file *lower_file;
1485+ int err;
1486+
1487+ lower_file = unionfs_lower_file(file);
1488+
1489+ err = -ENOTTY;
1490+ if (!lower_file || !lower_file->f_op)
1491+ goto out;
1492+ if (lower_file->f_op->unlocked_ioctl) {
1493+ err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
1494+ } else if (lower_file->f_op->ioctl) {
1495+ lock_kernel();
1496+ err = lower_file->f_op->ioctl(
1497+ lower_file->f_path.dentry->d_inode,
1498+ lower_file, cmd, arg);
1499+ unlock_kernel();
1500+ }
1501+
1502+out:
1503+ return err;
1504+}
1505+
1506+/*
1507+ * return to user-space the branch indices containing the file in question
1508+ *
1509+ * We use fd_set and therefore we are limited to the number of the branches
1510+ * to FD_SETSIZE, which is currently 1024 - plenty for most people
1511+ */
1512+static int unionfs_ioctl_queryfile(struct file *file, struct dentry *parent,
1513+ unsigned int cmd, unsigned long arg)
1514+{
1515+ int err = 0;
1516+ fd_set branchlist;
1517+ int bstart = 0, bend = 0, bindex = 0;
1518+ int orig_bstart, orig_bend;
1519+ struct dentry *dentry, *lower_dentry;
1520+ struct vfsmount *mnt;
1521+
1522+ dentry = file->f_path.dentry;
1523+ orig_bstart = dbstart(dentry);
1524+ orig_bend = dbend(dentry);
1525+ err = unionfs_partial_lookup(dentry, parent);
1526+ if (err)
1527+ goto out;
1528+ bstart = dbstart(dentry);
1529+ bend = dbend(dentry);
1530+
1531+ FD_ZERO(&branchlist);
1532+
1533+ for (bindex = bstart; bindex <= bend; bindex++) {
1534+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
1535+ if (!lower_dentry)
1536+ continue;
1537+ if (likely(lower_dentry->d_inode))
1538+ FD_SET(bindex, &branchlist);
1539+ /* purge any lower objects after partial_lookup */
1540+ if (bindex < orig_bstart || bindex > orig_bend) {
1541+ dput(lower_dentry);
1542+ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
1543+ iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
1544+ unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
1545+ NULL);
1546+ mnt = unionfs_lower_mnt_idx(dentry, bindex);
1547+ if (!mnt)
1548+ continue;
1549+ unionfs_mntput(dentry, bindex);
1550+ unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
1551+ }
1552+ }
1553+ /* restore original dentry's offsets */
1554+ dbstart(dentry) = orig_bstart;
1555+ dbend(dentry) = orig_bend;
1556+ ibstart(dentry->d_inode) = orig_bstart;
1557+ ibend(dentry->d_inode) = orig_bend;
1558+
1559+ err = copy_to_user((void __user *)arg, &branchlist, sizeof(fd_set));
1560+ if (unlikely(err))
1561+ err = -EFAULT;
1562+
1563+out:
1564+ return err < 0 ? err : bend;
1565+}
1566+
1567+long unionfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1568+{
1569+ long err;
1570+ struct dentry *dentry = file->f_path.dentry;
1571+ struct dentry *parent;
1572+
1573+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
1574+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
1575+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
1576+
1577+ err = unionfs_file_revalidate(file, parent, true);
1578+ if (unlikely(err))
1579+ goto out;
1580+
1581+ /* check if asked for local commands */
1582+ switch (cmd) {
1583+ case UNIONFS_IOCTL_INCGEN:
1584+ /* Increment the superblock generation count */
1585+ pr_info("unionfs: incgen ioctl deprecated; "
1586+ "use \"-o remount,incgen\"\n");
1587+ err = -ENOSYS;
1588+ break;
1589+
1590+ case UNIONFS_IOCTL_QUERYFILE:
1591+ /* Return list of branches containing the given file */
1592+ err = unionfs_ioctl_queryfile(file, parent, cmd, arg);
1593+ break;
1594+
1595+ default:
1596+ /* pass the ioctl down */
1597+ err = do_ioctl(file, cmd, arg);
1598+ break;
1599+ }
1600+
1601+out:
1602+ unionfs_check_file(file);
1603+ unionfs_unlock_dentry(dentry);
1604+ unionfs_unlock_parent(dentry, parent);
1605+ unionfs_read_unlock(dentry->d_sb);
1606+ return err;
1607+}
1608+
1609+int unionfs_flush(struct file *file, fl_owner_t id)
1610+{
1611+ int err = 0;
1612+ struct file *lower_file = NULL;
1613+ struct dentry *dentry = file->f_path.dentry;
1614+ struct dentry *parent;
1615+ int bindex, bstart, bend;
1616+
1617+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
1618+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
1619+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
1620+
1621+ err = unionfs_file_revalidate(file, parent,
1622+ UNIONFS_F(file)->wrote_to_file);
1623+ if (unlikely(err))
1624+ goto out;
1625+ unionfs_check_file(file);
1626+
1627+ bstart = fbstart(file);
1628+ bend = fbend(file);
1629+ for (bindex = bstart; bindex <= bend; bindex++) {
1630+ lower_file = unionfs_lower_file_idx(file, bindex);
1631+
1632+ if (lower_file && lower_file->f_op &&
1633+ lower_file->f_op->flush) {
1634+ err = lower_file->f_op->flush(lower_file, id);
1635+ if (err)
1636+ goto out;
1637+ }
1638+
1639+ }
1640+
1641+out:
1642+ if (!err)
1643+ unionfs_check_file(file);
1644+ unionfs_unlock_dentry(dentry);
1645+ unionfs_unlock_parent(dentry, parent);
1646+ unionfs_read_unlock(dentry->d_sb);
1647+ return err;
1648+}
1649diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
1650new file mode 100644
1651index 0000000..bba3a75
1652--- /dev/null
1653+++ b/fs/unionfs/copyup.c
1654@@ -0,0 +1,896 @@
1655+/*
1656+ * Copyright (c) 2003-2010 Erez Zadok
1657+ * Copyright (c) 2003-2006 Charles P. Wright
1658+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
1659+ * Copyright (c) 2005-2006 Junjiro Okajima
1660+ * Copyright (c) 2005 Arun M. Krishnakumar
1661+ * Copyright (c) 2004-2006 David P. Quigley
1662+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
1663+ * Copyright (c) 2003 Puja Gupta
1664+ * Copyright (c) 2003 Harikesavan Krishnan
1665+ * Copyright (c) 2003-2010 Stony Brook University
1666+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
1667+ *
1668+ * This program is free software; you can redistribute it and/or modify
1669+ * it under the terms of the GNU General Public License version 2 as
1670+ * published by the Free Software Foundation.
1671+ */
1672+
1673+#include "union.h"
1674+
1675+/*
1676+ * For detailed explanation of copyup see:
1677+ * Documentation/filesystems/unionfs/concepts.txt
1678+ */
1679+
1680+#ifdef CONFIG_UNION_FS_XATTR
1681+/* copyup all extended attrs for a given dentry */
1682+static int copyup_xattrs(struct dentry *old_lower_dentry,
1683+ struct dentry *new_lower_dentry)
1684+{
1685+ int err = 0;
1686+ ssize_t list_size = -1;
1687+ char *name_list = NULL;
1688+ char *attr_value = NULL;
1689+ char *name_list_buf = NULL;
1690+
1691+ /* query the actual size of the xattr list */
1692+ list_size = vfs_listxattr(old_lower_dentry, NULL, 0);
1693+ if (list_size <= 0) {
1694+ err = list_size;
1695+ goto out;
1696+ }
1697+
1698+ /* allocate space for the actual list */
1699+ name_list = unionfs_xattr_alloc(list_size + 1, XATTR_LIST_MAX);
1700+ if (unlikely(!name_list || IS_ERR(name_list))) {
1701+ err = PTR_ERR(name_list);
1702+ goto out;
1703+ }
1704+
1705+ name_list_buf = name_list; /* save for kfree at end */
1706+
1707+ /* now get the actual xattr list of the source file */
1708+ list_size = vfs_listxattr(old_lower_dentry, name_list, list_size);
1709+ if (list_size <= 0) {
1710+ err = list_size;
1711+ goto out;
1712+ }
1713+
1714+ /* allocate space to hold each xattr's value */
1715+ attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX);
1716+ if (unlikely(!attr_value || IS_ERR(attr_value))) {
1717+ err = PTR_ERR(name_list);
1718+ goto out;
1719+ }
1720+
1721+ /* in a loop, get and set each xattr from src to dst file */
1722+ while (*name_list) {
1723+ ssize_t size;
1724+
1725+ /* Lock here since vfs_getxattr doesn't lock for us */
1726+ mutex_lock(&old_lower_dentry->d_inode->i_mutex);
1727+ size = vfs_getxattr(old_lower_dentry, name_list,
1728+ attr_value, XATTR_SIZE_MAX);
1729+ mutex_unlock(&old_lower_dentry->d_inode->i_mutex);
1730+ if (size < 0) {
1731+ err = size;
1732+ goto out;
1733+ }
1734+ if (size > XATTR_SIZE_MAX) {
1735+ err = -E2BIG;
1736+ goto out;
1737+ }
1738+ /* Don't lock here since vfs_setxattr does it for us. */
1739+ err = vfs_setxattr(new_lower_dentry, name_list, attr_value,
1740+ size, 0);
1741+ /*
1742+ * Selinux depends on "security.*" xattrs, so to maintain
1743+ * the security of copied-up files, if Selinux is active,
1744+ * then we must copy these xattrs as well. So we need to
1745+ * temporarily get FOWNER privileges.
1746+ * XXX: move entire copyup code to SIOQ.
1747+ */
1748+ if (err == -EPERM && !capable(CAP_FOWNER)) {
1749+ const struct cred *old_creds;
1750+ struct cred *new_creds;
1751+
1752+ new_creds = prepare_creds();
1753+ if (unlikely(!new_creds)) {
1754+ err = -ENOMEM;
1755+ goto out;
1756+ }
1757+ cap_raise(new_creds->cap_effective, CAP_FOWNER);
1758+ old_creds = override_creds(new_creds);
1759+ err = vfs_setxattr(new_lower_dentry, name_list,
1760+ attr_value, size, 0);
1761+ revert_creds(old_creds);
1762+ }
1763+ if (err < 0)
1764+ goto out;
1765+ name_list += strlen(name_list) + 1;
1766+ }
1767+out:
1768+ unionfs_xattr_kfree(name_list_buf);
1769+ unionfs_xattr_kfree(attr_value);
1770+ /* Ignore if xattr isn't supported */
1771+ if (err == -ENOTSUPP || err == -EOPNOTSUPP)
1772+ err = 0;
1773+ return err;
1774+}
1775+#endif /* CONFIG_UNION_FS_XATTR */
1776+
1777+/*
1778+ * Determine the mode based on the copyup flags, and the existing dentry.
1779+ *
1780+ * Handle file systems which may not support certain options. For example
1781+ * jffs2 doesn't allow one to chmod a symlink. So we ignore such harmless
1782+ * errors, rather than propagating them up, which results in copyup errors
1783+ * and errors returned back to users.
1784+ */
1785+static int copyup_permissions(struct super_block *sb,
1786+ struct dentry *old_lower_dentry,
1787+ struct dentry *new_lower_dentry)
1788+{
1789+ struct inode *i = old_lower_dentry->d_inode;
1790+ struct iattr newattrs;
1791+ int err;
1792+
1793+ newattrs.ia_atime = i->i_atime;
1794+ newattrs.ia_mtime = i->i_mtime;
1795+ newattrs.ia_ctime = i->i_ctime;
1796+ newattrs.ia_gid = i->i_gid;
1797+ newattrs.ia_uid = i->i_uid;
1798+ newattrs.ia_valid = ATTR_CTIME | ATTR_ATIME | ATTR_MTIME |
1799+ ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_FORCE |
1800+ ATTR_GID | ATTR_UID;
1801+ mutex_lock(&new_lower_dentry->d_inode->i_mutex);
1802+ err = notify_change(new_lower_dentry, &newattrs);
1803+ if (err)
1804+ goto out;
1805+
1806+ /* now try to change the mode and ignore EOPNOTSUPP on symlinks */
1807+ newattrs.ia_mode = i->i_mode;
1808+ newattrs.ia_valid = ATTR_MODE | ATTR_FORCE;
1809+ err = notify_change(new_lower_dentry, &newattrs);
1810+ if (err == -EOPNOTSUPP &&
1811+ S_ISLNK(new_lower_dentry->d_inode->i_mode)) {
1812+ printk(KERN_WARNING
1813+ "unionfs: changing \"%s\" symlink mode unsupported\n",
1814+ new_lower_dentry->d_name.name);
1815+ err = 0;
1816+ }
1817+
1818+out:
1819+ mutex_unlock(&new_lower_dentry->d_inode->i_mutex);
1820+ return err;
1821+}
1822+
1823+/*
1824+ * create the new device/file/directory - use copyup_permission to copyup
1825+ * times, and mode
1826+ *
1827+ * if the object being copied up is a regular file, the file is only created,
1828+ * the contents have to be copied up separately
1829+ */
1830+static int __copyup_ndentry(struct dentry *old_lower_dentry,
1831+ struct dentry *new_lower_dentry,
1832+ struct dentry *new_lower_parent_dentry,
1833+ char *symbuf)
1834+{
1835+ int err = 0;
1836+ umode_t old_mode = old_lower_dentry->d_inode->i_mode;
1837+ struct sioq_args args;
1838+
1839+ if (S_ISDIR(old_mode)) {
1840+ args.mkdir.parent = new_lower_parent_dentry->d_inode;
1841+ args.mkdir.dentry = new_lower_dentry;
1842+ args.mkdir.mode = old_mode;
1843+
1844+ run_sioq(__unionfs_mkdir, &args);
1845+ err = args.err;
1846+ } else if (S_ISLNK(old_mode)) {
1847+ args.symlink.parent = new_lower_parent_dentry->d_inode;
1848+ args.symlink.dentry = new_lower_dentry;
1849+ args.symlink.symbuf = symbuf;
1850+
1851+ run_sioq(__unionfs_symlink, &args);
1852+ err = args.err;
1853+ } else if (S_ISBLK(old_mode) || S_ISCHR(old_mode) ||
1854+ S_ISFIFO(old_mode) || S_ISSOCK(old_mode)) {
1855+ args.mknod.parent = new_lower_parent_dentry->d_inode;
1856+ args.mknod.dentry = new_lower_dentry;
1857+ args.mknod.mode = old_mode;
1858+ args.mknod.dev = old_lower_dentry->d_inode->i_rdev;
1859+
1860+ run_sioq(__unionfs_mknod, &args);
1861+ err = args.err;
1862+ } else if (S_ISREG(old_mode)) {
1863+ struct nameidata nd;
1864+ err = init_lower_nd(&nd, LOOKUP_CREATE);
1865+ if (unlikely(err < 0))
1866+ goto out;
1867+ args.create.nd = &nd;
1868+ args.create.parent = new_lower_parent_dentry->d_inode;
1869+ args.create.dentry = new_lower_dentry;
1870+ args.create.mode = old_mode;
1871+
1872+ run_sioq(__unionfs_create, &args);
1873+ err = args.err;
1874+ release_lower_nd(&nd, err);
1875+ } else {
1876+ printk(KERN_CRIT "unionfs: unknown inode type %d\n",
1877+ old_mode);
1878+ BUG();
1879+ }
1880+
1881+out:
1882+ return err;
1883+}
1884+
1885+static int __copyup_reg_data(struct dentry *dentry,
1886+ struct dentry *new_lower_dentry, int new_bindex,
1887+ struct dentry *old_lower_dentry, int old_bindex,
1888+ struct file **copyup_file, loff_t len)
1889+{
1890+ struct super_block *sb = dentry->d_sb;
1891+ struct file *input_file;
1892+ struct file *output_file;
1893+ struct vfsmount *output_mnt;
1894+ mm_segment_t old_fs;
1895+ char *buf = NULL;
1896+ ssize_t read_bytes, write_bytes;
1897+ loff_t size;
1898+ int err = 0;
1899+
1900+ /* open old file */
1901+ unionfs_mntget(dentry, old_bindex);
1902+ branchget(sb, old_bindex);
1903+ /* dentry_open calls dput and mntput if it returns an error */
1904+ input_file = dentry_open(old_lower_dentry,
1905+ unionfs_lower_mnt_idx(dentry, old_bindex),
1906+ O_RDONLY | O_LARGEFILE, current_cred());
1907+ if (IS_ERR(input_file)) {
1908+ dput(old_lower_dentry);
1909+ err = PTR_ERR(input_file);
1910+ goto out;
1911+ }
1912+ if (unlikely(!input_file->f_op || !input_file->f_op->read)) {
1913+ err = -EINVAL;
1914+ goto out_close_in;
1915+ }
1916+
1917+ /* open new file */
1918+ dget(new_lower_dentry);
1919+ output_mnt = unionfs_mntget(sb->s_root, new_bindex);
1920+ branchget(sb, new_bindex);
1921+ output_file = dentry_open(new_lower_dentry, output_mnt,
1922+ O_RDWR | O_LARGEFILE, current_cred());
1923+ if (IS_ERR(output_file)) {
1924+ err = PTR_ERR(output_file);
1925+ goto out_close_in2;
1926+ }
1927+ if (unlikely(!output_file->f_op || !output_file->f_op->write)) {
1928+ err = -EINVAL;
1929+ goto out_close_out;
1930+ }
1931+
1932+ /* allocating a buffer */
1933+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
1934+ if (unlikely(!buf)) {
1935+ err = -ENOMEM;
1936+ goto out_close_out;
1937+ }
1938+
1939+ input_file->f_pos = 0;
1940+ output_file->f_pos = 0;
1941+
1942+ old_fs = get_fs();
1943+ set_fs(KERNEL_DS);
1944+
1945+ size = len;
1946+ err = 0;
1947+ do {
1948+ if (len >= PAGE_SIZE)
1949+ size = PAGE_SIZE;
1950+ else if ((len < PAGE_SIZE) && (len > 0))
1951+ size = len;
1952+
1953+ len -= PAGE_SIZE;
1954+
1955+ read_bytes =
1956+ input_file->f_op->read(input_file,
1957+ (char __user *)buf, size,
1958+ &input_file->f_pos);
1959+ if (read_bytes <= 0) {
1960+ err = read_bytes;
1961+ break;
1962+ }
1963+
1964+ /* see Documentation/filesystems/unionfs/issues.txt */
1965+ lockdep_off();
1966+ write_bytes =
1967+ output_file->f_op->write(output_file,
1968+ (char __user *)buf,
1969+ read_bytes,
1970+ &output_file->f_pos);
1971+ lockdep_on();
1972+ if ((write_bytes < 0) || (write_bytes < read_bytes)) {
1973+ err = write_bytes;
1974+ break;
1975+ }
1976+ } while ((read_bytes > 0) && (len > 0));
1977+
1978+ set_fs(old_fs);
1979+
1980+ kfree(buf);
1981+
1982+ if (!err)
1983+ err = output_file->f_op->fsync(output_file, 0);
1984+
1985+ if (err)
1986+ goto out_close_out;
1987+
1988+ if (copyup_file) {
1989+ *copyup_file = output_file;
1990+ goto out_close_in;
1991+ }
1992+
1993+out_close_out:
1994+ fput(output_file);
1995+
1996+out_close_in2:
1997+ branchput(sb, new_bindex);
1998+
1999+out_close_in:
2000+ fput(input_file);
2001+
2002+out:
2003+ branchput(sb, old_bindex);
2004+
2005+ return err;
2006+}
2007+
2008+/*
2009+ * dput the lower references for old and new dentry & clear a lower dentry
2010+ * pointer
2011+ */
2012+static void __clear(struct dentry *dentry, struct dentry *old_lower_dentry,
2013+ int old_bstart, int old_bend,
2014+ struct dentry *new_lower_dentry, int new_bindex)
2015+{
2016+ /* get rid of the lower dentry and all its traces */
2017+ unionfs_set_lower_dentry_idx(dentry, new_bindex, NULL);
2018+ dbstart(dentry) = old_bstart;
2019+ dbend(dentry) = old_bend;
2020+
2021+ dput(new_lower_dentry);
2022+ dput(old_lower_dentry);
2023+}
2024+
2025+/*
2026+ * Copy up a dentry to a file of specified name.
2027+ *
2028+ * @dir: used to pull the ->i_sb to access other branches
2029+ * @dentry: the non-negative dentry whose lower_inode we should copy
2030+ * @bstart: the branch of the lower_inode to copy from
2031+ * @new_bindex: the branch to create the new file in
2032+ * @name: the name of the file to create
2033+ * @namelen: length of @name
2034+ * @copyup_file: the "struct file" to return (optional)
2035+ * @len: how many bytes to copy-up?
2036+ */
2037+int copyup_dentry(struct inode *dir, struct dentry *dentry, int bstart,
2038+ int new_bindex, const char *name, int namelen,
2039+ struct file **copyup_file, loff_t len)
2040+{
2041+ struct dentry *new_lower_dentry;
2042+ struct dentry *old_lower_dentry = NULL;
2043+ struct super_block *sb;
2044+ int err = 0;
2045+ int old_bindex;
2046+ int old_bstart;
2047+ int old_bend;
2048+ struct dentry *new_lower_parent_dentry = NULL;
2049+ mm_segment_t oldfs;
2050+ char *symbuf = NULL;
2051+
2052+ verify_locked(dentry);
2053+
2054+ old_bindex = bstart;
2055+ old_bstart = dbstart(dentry);
2056+ old_bend = dbend(dentry);
2057+
2058+ BUG_ON(new_bindex < 0);
2059+ BUG_ON(new_bindex >= old_bindex);
2060+
2061+ sb = dir->i_sb;
2062+
2063+ err = is_robranch_super(sb, new_bindex);
2064+ if (err)
2065+ goto out;
2066+
2067+ /* Create the directory structure above this dentry. */
2068+ new_lower_dentry = create_parents(dir, dentry, name, new_bindex);
2069+ if (IS_ERR(new_lower_dentry)) {
2070+ err = PTR_ERR(new_lower_dentry);
2071+ goto out;
2072+ }
2073+
2074+ old_lower_dentry = unionfs_lower_dentry_idx(dentry, old_bindex);
2075+ /* we conditionally dput this old_lower_dentry at end of function */
2076+ dget(old_lower_dentry);
2077+
2078+ /* For symlinks, we must read the link before we lock the directory. */
2079+ if (S_ISLNK(old_lower_dentry->d_inode->i_mode)) {
2080+
2081+ symbuf = kmalloc(PATH_MAX, GFP_KERNEL);
2082+ if (unlikely(!symbuf)) {
2083+ __clear(dentry, old_lower_dentry,
2084+ old_bstart, old_bend,
2085+ new_lower_dentry, new_bindex);
2086+ err = -ENOMEM;
2087+ goto out_free;
2088+ }
2089+
2090+ oldfs = get_fs();
2091+ set_fs(KERNEL_DS);
2092+ err = old_lower_dentry->d_inode->i_op->readlink(
2093+ old_lower_dentry,
2094+ (char __user *)symbuf,
2095+ PATH_MAX);
2096+ set_fs(oldfs);
2097+ if (err < 0) {
2098+ __clear(dentry, old_lower_dentry,
2099+ old_bstart, old_bend,
2100+ new_lower_dentry, new_bindex);
2101+ goto out_free;
2102+ }
2103+ symbuf[err] = '\0';
2104+ }
2105+
2106+ /* Now we lock the parent, and create the object in the new branch. */
2107+ new_lower_parent_dentry = lock_parent(new_lower_dentry);
2108+
2109+ /* create the new inode */
2110+ err = __copyup_ndentry(old_lower_dentry, new_lower_dentry,
2111+ new_lower_parent_dentry, symbuf);
2112+
2113+ if (err) {
2114+ __clear(dentry, old_lower_dentry,
2115+ old_bstart, old_bend,
2116+ new_lower_dentry, new_bindex);
2117+ goto out_unlock;
2118+ }
2119+
2120+ /* We actually copyup the file here. */
2121+ if (S_ISREG(old_lower_dentry->d_inode->i_mode))
2122+ err = __copyup_reg_data(dentry, new_lower_dentry, new_bindex,
2123+ old_lower_dentry, old_bindex,
2124+ copyup_file, len);
2125+ if (err)
2126+ goto out_unlink;
2127+
2128+ /* Set permissions. */
2129+ err = copyup_permissions(sb, old_lower_dentry, new_lower_dentry);
2130+ if (err)
2131+ goto out_unlink;
2132+
2133+#ifdef CONFIG_UNION_FS_XATTR
2134+ /* Selinux uses extended attributes for permissions. */
2135+ err = copyup_xattrs(old_lower_dentry, new_lower_dentry);
2136+ if (err)
2137+ goto out_unlink;
2138+#endif /* CONFIG_UNION_FS_XATTR */
2139+
2140+ /* do not allow files getting deleted to be re-interposed */
2141+ if (!d_deleted(dentry))
2142+ unionfs_reinterpose(dentry);
2143+
2144+ goto out_unlock;
2145+
2146+out_unlink:
2147+ /*
2148+ * copyup failed, because we possibly ran out of space or
2149+ * quota, or something else happened so let's unlink; we don't
2150+ * really care about the return value of vfs_unlink
2151+ */
2152+ vfs_unlink(new_lower_parent_dentry->d_inode, new_lower_dentry);
2153+
2154+ if (copyup_file) {
2155+ /* need to close the file */
2156+
2157+ fput(*copyup_file);
2158+ branchput(sb, new_bindex);
2159+ }
2160+
2161+ /*
2162+ * TODO: should we reset the error to something like -EIO?
2163+ *
2164+ * If we don't reset, the user may get some nonsensical errors, but
2165+ * on the other hand, if we reset to EIO, we guarantee that the user
2166+ * will get a "confusing" error message.
2167+ */
2168+
2169+out_unlock:
2170+ unlock_dir(new_lower_parent_dentry);
2171+
2172+out_free:
2173+ /*
2174+ * If old_lower_dentry was not a file, then we need to dput it. If
2175+ * it was a file, then it was already dput indirectly by other
2176+ * functions we call above which operate on regular files.
2177+ */
2178+ if (old_lower_dentry && old_lower_dentry->d_inode &&
2179+ !S_ISREG(old_lower_dentry->d_inode->i_mode))
2180+ dput(old_lower_dentry);
2181+ kfree(symbuf);
2182+
2183+ if (err) {
2184+ /*
2185+ * if directory creation succeeded, but inode copyup failed,
2186+ * then purge new dentries.
2187+ */
2188+ if (dbstart(dentry) < old_bstart &&
2189+ ibstart(dentry->d_inode) > dbstart(dentry))
2190+ __clear(dentry, NULL, old_bstart, old_bend,
2191+ unionfs_lower_dentry(dentry), dbstart(dentry));
2192+ goto out;
2193+ }
2194+ if (!S_ISDIR(dentry->d_inode->i_mode)) {
2195+ unionfs_postcopyup_release(dentry);
2196+ if (!unionfs_lower_inode(dentry->d_inode)) {
2197+ /*
2198+ * If we got here, then we copied up to an
2199+ * unlinked-open file, whose name is .unionfsXXXXX.
2200+ */
2201+ struct inode *inode = new_lower_dentry->d_inode;
2202+ atomic_inc(&inode->i_count);
2203+ unionfs_set_lower_inode_idx(dentry->d_inode,
2204+ ibstart(dentry->d_inode),
2205+ inode);
2206+ }
2207+ }
2208+ unionfs_postcopyup_setmnt(dentry);
2209+ /* sync inode times from copied-up inode to our inode */
2210+ unionfs_copy_attr_times(dentry->d_inode);
2211+ unionfs_check_inode(dir);
2212+ unionfs_check_dentry(dentry);
2213+out:
2214+ return err;
2215+}
2216+
2217+/*
2218+ * This function creates a copy of a file represented by 'file' which
2219+ * currently resides in branch 'bstart' to branch 'new_bindex.' The copy
2220+ * will be named "name".
2221+ */
2222+int copyup_named_file(struct inode *dir, struct file *file, char *name,
2223+ int bstart, int new_bindex, loff_t len)
2224+{
2225+ int err = 0;
2226+ struct file *output_file = NULL;
2227+
2228+ err = copyup_dentry(dir, file->f_path.dentry, bstart, new_bindex,
2229+ name, strlen(name), &output_file, len);
2230+ if (!err) {
2231+ fbstart(file) = new_bindex;
2232+ unionfs_set_lower_file_idx(file, new_bindex, output_file);
2233+ }
2234+
2235+ return err;
2236+}
2237+
2238+/*
2239+ * This function creates a copy of a file represented by 'file' which
2240+ * currently resides in branch 'bstart' to branch 'new_bindex'.
2241+ */
2242+int copyup_file(struct inode *dir, struct file *file, int bstart,
2243+ int new_bindex, loff_t len)
2244+{
2245+ int err = 0;
2246+ struct file *output_file = NULL;
2247+ struct dentry *dentry = file->f_path.dentry;
2248+
2249+ err = copyup_dentry(dir, dentry, bstart, new_bindex,
2250+ dentry->d_name.name, dentry->d_name.len,
2251+ &output_file, len);
2252+ if (!err) {
2253+ fbstart(file) = new_bindex;
2254+ unionfs_set_lower_file_idx(file, new_bindex, output_file);
2255+ }
2256+
2257+ return err;
2258+}
2259+
2260+/* purge a dentry's lower-branch states (dput/mntput, etc.) */
2261+static void __cleanup_dentry(struct dentry *dentry, int bindex,
2262+ int old_bstart, int old_bend)
2263+{
2264+ int loop_start;
2265+ int loop_end;
2266+ int new_bstart = -1;
2267+ int new_bend = -1;
2268+ int i;
2269+
2270+ loop_start = min(old_bstart, bindex);
2271+ loop_end = max(old_bend, bindex);
2272+
2273+ /*
2274+ * This loop sets the bstart and bend for the new dentry by
2275+ * traversing from left to right. It also dputs all negative
2276+ * dentries except bindex
2277+ */
2278+ for (i = loop_start; i <= loop_end; i++) {
2279+ if (!unionfs_lower_dentry_idx(dentry, i))
2280+ continue;
2281+
2282+ if (i == bindex) {
2283+ new_bend = i;
2284+ if (new_bstart < 0)
2285+ new_bstart = i;
2286+ continue;
2287+ }
2288+
2289+ if (!unionfs_lower_dentry_idx(dentry, i)->d_inode) {
2290+ dput(unionfs_lower_dentry_idx(dentry, i));
2291+ unionfs_set_lower_dentry_idx(dentry, i, NULL);
2292+
2293+ unionfs_mntput(dentry, i);
2294+ unionfs_set_lower_mnt_idx(dentry, i, NULL);
2295+ } else {
2296+ if (new_bstart < 0)
2297+ new_bstart = i;
2298+ new_bend = i;
2299+ }
2300+ }
2301+
2302+ if (new_bstart < 0)
2303+ new_bstart = bindex;
2304+ if (new_bend < 0)
2305+ new_bend = bindex;
2306+ dbstart(dentry) = new_bstart;
2307+ dbend(dentry) = new_bend;
2308+
2309+}
2310+
2311+/* set lower inode ptr and update bstart & bend if necessary */
2312+static void __set_inode(struct dentry *upper, struct dentry *lower,
2313+ int bindex)
2314+{
2315+ unionfs_set_lower_inode_idx(upper->d_inode, bindex,
2316+ igrab(lower->d_inode));
2317+ if (likely(ibstart(upper->d_inode) > bindex))
2318+ ibstart(upper->d_inode) = bindex;
2319+ if (likely(ibend(upper->d_inode) < bindex))
2320+ ibend(upper->d_inode) = bindex;
2321+
2322+}
2323+
2324+/* set lower dentry ptr and update bstart & bend if necessary */
2325+static void __set_dentry(struct dentry *upper, struct dentry *lower,
2326+ int bindex)
2327+{
2328+ unionfs_set_lower_dentry_idx(upper, bindex, lower);
2329+ if (likely(dbstart(upper) > bindex))
2330+ dbstart(upper) = bindex;
2331+ if (likely(dbend(upper) < bindex))
2332+ dbend(upper) = bindex;
2333+}
2334+
2335+/*
2336+ * This function replicates the directory structure up-to given dentry
2337+ * in the bindex branch.
2338+ */
2339+struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
2340+ const char *name, int bindex)
2341+{
2342+ int err;
2343+ struct dentry *child_dentry;
2344+ struct dentry *parent_dentry;
2345+ struct dentry *lower_parent_dentry = NULL;
2346+ struct dentry *lower_dentry = NULL;
2347+ const char *childname;
2348+ unsigned int childnamelen;
2349+ int nr_dentry;
2350+ int count = 0;
2351+ int old_bstart;
2352+ int old_bend;
2353+ struct dentry **path = NULL;
2354+ struct super_block *sb;
2355+
2356+ verify_locked(dentry);
2357+
2358+ err = is_robranch_super(dir->i_sb, bindex);
2359+ if (err) {
2360+ lower_dentry = ERR_PTR(err);
2361+ goto out;
2362+ }
2363+
2364+ old_bstart = dbstart(dentry);
2365+ old_bend = dbend(dentry);
2366+
2367+ lower_dentry = ERR_PTR(-ENOMEM);
2368+
2369+ /* There is no sense allocating any less than the minimum. */
2370+ nr_dentry = 1;
2371+ path = kmalloc(nr_dentry * sizeof(struct dentry *), GFP_KERNEL);
2372+ if (unlikely(!path))
2373+ goto out;
2374+
2375+ /* assume the negative dentry of unionfs as the parent dentry */
2376+ parent_dentry = dentry;
2377+
2378+ /*
2379+ * This loop finds the first parent that exists in the given branch.
2380+ * We start building the directory structure from there. At the end
2381+ * of the loop, the following should hold:
2382+ * - child_dentry is the first nonexistent child
2383+ * - parent_dentry is the first existent parent
2384+ * - path[0] is the = deepest child
2385+ * - path[count] is the first child to create
2386+ */
2387+ do {
2388+ child_dentry = parent_dentry;
2389+
2390+ /* find the parent directory dentry in unionfs */
2391+ parent_dentry = dget_parent(child_dentry);
2392+
2393+ /* find out the lower_parent_dentry in the given branch */
2394+ lower_parent_dentry =
2395+ unionfs_lower_dentry_idx(parent_dentry, bindex);
2396+
2397+ /* grow path table */
2398+ if (count == nr_dentry) {
2399+ void *p;
2400+
2401+ nr_dentry *= 2;
2402+ p = krealloc(path, nr_dentry * sizeof(struct dentry *),
2403+ GFP_KERNEL);
2404+ if (unlikely(!p)) {
2405+ lower_dentry = ERR_PTR(-ENOMEM);
2406+ goto out;
2407+ }
2408+ path = p;
2409+ }
2410+
2411+ /* store the child dentry */
2412+ path[count++] = child_dentry;
2413+ } while (!lower_parent_dentry);
2414+ count--;
2415+
2416+ sb = dentry->d_sb;
2417+
2418+ /*
2419+ * This code goes between the begin/end labels and basically
2420+ * emulates a while(child_dentry != dentry), only cleaner and
2421+ * shorter than what would be a much longer while loop.
2422+ */
2423+begin:
2424+ /* get lower parent dir in the current branch */
2425+ lower_parent_dentry = unionfs_lower_dentry_idx(parent_dentry, bindex);
2426+ dput(parent_dentry);
2427+
2428+ /* init the values to lookup */
2429+ childname = child_dentry->d_name.name;
2430+ childnamelen = child_dentry->d_name.len;
2431+
2432+ if (child_dentry != dentry) {
2433+ /* lookup child in the underlying file system */
2434+ lower_dentry = lookup_lck_len(childname, lower_parent_dentry,
2435+ childnamelen);
2436+ if (IS_ERR(lower_dentry))
2437+ goto out;
2438+ } else {
2439+ /*
2440+ * Is the name a whiteout of the child name ? lookup the
2441+ * whiteout child in the underlying file system
2442+ */
2443+ lower_dentry = lookup_lck_len(name, lower_parent_dentry,
2444+ strlen(name));
2445+ if (IS_ERR(lower_dentry))
2446+ goto out;
2447+
2448+ /* Replace the current dentry (if any) with the new one */
2449+ dput(unionfs_lower_dentry_idx(dentry, bindex));
2450+ unionfs_set_lower_dentry_idx(dentry, bindex,
2451+ lower_dentry);
2452+
2453+ __cleanup_dentry(dentry, bindex, old_bstart, old_bend);
2454+ goto out;
2455+ }
2456+
2457+ if (lower_dentry->d_inode) {
2458+ /*
2459+ * since this already exists we dput to avoid
2460+ * multiple references on the same dentry
2461+ */
2462+ dput(lower_dentry);
2463+ } else {
2464+ struct sioq_args args;
2465+
2466+ /* it's a negative dentry, create a new dir */
2467+ lower_parent_dentry = lock_parent(lower_dentry);
2468+
2469+ args.mkdir.parent = lower_parent_dentry->d_inode;
2470+ args.mkdir.dentry = lower_dentry;
2471+ args.mkdir.mode = child_dentry->d_inode->i_mode;
2472+
2473+ run_sioq(__unionfs_mkdir, &args);
2474+ err = args.err;
2475+
2476+ if (!err)
2477+ err = copyup_permissions(dir->i_sb, child_dentry,
2478+ lower_dentry);
2479+ unlock_dir(lower_parent_dentry);
2480+ if (err) {
2481+ dput(lower_dentry);
2482+ lower_dentry = ERR_PTR(err);
2483+ goto out;
2484+ }
2485+
2486+ }
2487+
2488+ __set_inode(child_dentry, lower_dentry, bindex);
2489+ __set_dentry(child_dentry, lower_dentry, bindex);
2490+ /*
2491+ * update times of this dentry, but also the parent, because if
2492+ * we changed, the parent may have changed too.
2493+ */
2494+ fsstack_copy_attr_times(parent_dentry->d_inode,
2495+ lower_parent_dentry->d_inode);
2496+ unionfs_copy_attr_times(child_dentry->d_inode);
2497+
2498+ parent_dentry = child_dentry;
2499+ child_dentry = path[--count];
2500+ goto begin;
2501+out:
2502+ /* cleanup any leftover locks from the do/while loop above */
2503+ if (IS_ERR(lower_dentry))
2504+ while (count)
2505+ dput(path[count--]);
2506+ kfree(path);
2507+ return lower_dentry;
2508+}
2509+
2510+/*
2511+ * Post-copyup helper to ensure we have valid mnts: set lower mnt of
2512+ * dentry+parents to the first parent node that has an mnt.
2513+ */
2514+void unionfs_postcopyup_setmnt(struct dentry *dentry)
2515+{
2516+ struct dentry *parent, *hasone;
2517+ int bindex = dbstart(dentry);
2518+
2519+ if (unionfs_lower_mnt_idx(dentry, bindex))
2520+ return;
2521+ hasone = dentry->d_parent;
2522+ /* this loop should stop at root dentry */
2523+ while (!unionfs_lower_mnt_idx(hasone, bindex))
2524+ hasone = hasone->d_parent;
2525+ parent = dentry;
2526+ while (!unionfs_lower_mnt_idx(parent, bindex)) {
2527+ unionfs_set_lower_mnt_idx(parent, bindex,
2528+ unionfs_mntget(hasone, bindex));
2529+ parent = parent->d_parent;
2530+ }
2531+}
2532+
2533+/*
2534+ * Post-copyup helper to release all non-directory source objects of a
2535+ * copied-up file. Regular files should have only one lower object.
2536+ */
2537+void unionfs_postcopyup_release(struct dentry *dentry)
2538+{
2539+ int bstart, bend;
2540+
2541+ BUG_ON(S_ISDIR(dentry->d_inode->i_mode));
2542+ bstart = dbstart(dentry);
2543+ bend = dbend(dentry);
2544+
2545+ path_put_lowers(dentry, bstart + 1, bend, false);
2546+ iput_lowers(dentry->d_inode, bstart + 1, bend, false);
2547+
2548+ dbend(dentry) = bstart;
2549+ ibend(dentry->d_inode) = ibstart(dentry->d_inode) = bstart;
2550+}
2551diff --git a/fs/unionfs/debug.c b/fs/unionfs/debug.c
2552new file mode 100644
2553index 0000000..100d2c6
2554--- /dev/null
2555+++ b/fs/unionfs/debug.c
2556@@ -0,0 +1,532 @@
2557+/*
2558+ * Copyright (c) 2003-2010 Erez Zadok
2559+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
2560+ * Copyright (c) 2003-2010 Stony Brook University
2561+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
2562+ *
2563+ * This program is free software; you can redistribute it and/or modify
2564+ * it under the terms of the GNU General Public License version 2 as
2565+ * published by the Free Software Foundation.
2566+ */
2567+
2568+#include "union.h"
2569+
2570+/*
2571+ * Helper debugging functions for maintainers (and for users to report back
2572+ * useful information back to maintainers)
2573+ */
2574+
2575+/* it's always useful to know what part of the code called us */
2576+#define PRINT_CALLER(fname, fxn, line) \
2577+ do { \
2578+ if (!printed_caller) { \
2579+ pr_debug("PC:%s:%s:%d\n", (fname), (fxn), (line)); \
2580+ printed_caller = 1; \
2581+ } \
2582+ } while (0)
2583+
2584+/*
2585+ * __unionfs_check_{inode,dentry,file} perform exhaustive sanity checking on
2586+ * the fan-out of various Unionfs objects. We check that no lower objects
2587+ * exist outside the start/end branch range; that all objects within are
2588+ * non-NULL (with some allowed exceptions); that for every lower file
2589+ * there's a lower dentry+inode; that the start/end ranges match for all
2590+ * corresponding lower objects; that open files/symlinks have only one lower
2591+ * objects, but directories can have several; and more.
2592+ */
2593+void __unionfs_check_inode(const struct inode *inode,
2594+ const char *fname, const char *fxn, int line)
2595+{
2596+ int bindex;
2597+ int istart, iend;
2598+ struct inode *lower_inode;
2599+ struct super_block *sb;
2600+ int printed_caller = 0;
2601+ void *poison_ptr;
2602+
2603+ /* for inodes now */
2604+ BUG_ON(!inode);
2605+ sb = inode->i_sb;
2606+ istart = ibstart(inode);
2607+ iend = ibend(inode);
2608+ /* don't check inode if no lower branches */
2609+ if (istart < 0 && iend < 0)
2610+ return;
2611+ if (unlikely(istart > iend)) {
2612+ PRINT_CALLER(fname, fxn, line);
2613+ pr_debug(" Ci0: inode=%p istart/end=%d:%d\n",
2614+ inode, istart, iend);
2615+ }
2616+ if (unlikely((istart == -1 && iend != -1) ||
2617+ (istart != -1 && iend == -1))) {
2618+ PRINT_CALLER(fname, fxn, line);
2619+ pr_debug(" Ci1: inode=%p istart/end=%d:%d\n",
2620+ inode, istart, iend);
2621+ }
2622+ if (!S_ISDIR(inode->i_mode)) {
2623+ if (unlikely(iend != istart)) {
2624+ PRINT_CALLER(fname, fxn, line);
2625+ pr_debug(" Ci2: inode=%p istart=%d iend=%d\n",
2626+ inode, istart, iend);
2627+ }
2628+ }
2629+
2630+ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
2631+ if (unlikely(!UNIONFS_I(inode))) {
2632+ PRINT_CALLER(fname, fxn, line);
2633+ pr_debug(" Ci3: no inode_info %p\n", inode);
2634+ return;
2635+ }
2636+ if (unlikely(!UNIONFS_I(inode)->lower_inodes)) {
2637+ PRINT_CALLER(fname, fxn, line);
2638+ pr_debug(" Ci4: no lower_inodes %p\n", inode);
2639+ return;
2640+ }
2641+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
2642+ if (lower_inode) {
2643+ memset(&poison_ptr, POISON_INUSE, sizeof(void *));
2644+ if (unlikely(bindex < istart || bindex > iend)) {
2645+ PRINT_CALLER(fname, fxn, line);
2646+ pr_debug(" Ci5: inode/linode=%p:%p bindex=%d "
2647+ "istart/end=%d:%d\n", inode,
2648+ lower_inode, bindex, istart, iend);
2649+ } else if (unlikely(lower_inode == poison_ptr)) {
2650+ /* freed inode! */
2651+ PRINT_CALLER(fname, fxn, line);
2652+ pr_debug(" Ci6: inode/linode=%p:%p bindex=%d "
2653+ "istart/end=%d:%d\n", inode,
2654+ lower_inode, bindex, istart, iend);
2655+ }
2656+ continue;
2657+ }
2658+ /* if we get here, then lower_inode == NULL */
2659+ if (bindex < istart || bindex > iend)
2660+ continue;
2661+ /*
2662+ * directories can have NULL lower inodes in b/t start/end,
2663+ * but NOT if at the start/end range.
2664+ */
2665+ if (unlikely(S_ISDIR(inode->i_mode) &&
2666+ bindex > istart && bindex < iend))
2667+ continue;
2668+ PRINT_CALLER(fname, fxn, line);
2669+ pr_debug(" Ci7: inode/linode=%p:%p "
2670+ "bindex=%d istart/end=%d:%d\n",
2671+ inode, lower_inode, bindex, istart, iend);
2672+ }
2673+}
2674+
2675+void __unionfs_check_dentry(const struct dentry *dentry,
2676+ const char *fname, const char *fxn, int line)
2677+{
2678+ int bindex;
2679+ int dstart, dend, istart, iend;
2680+ struct dentry *lower_dentry;
2681+ struct inode *inode, *lower_inode;
2682+ struct super_block *sb;
2683+ struct vfsmount *lower_mnt;
2684+ int printed_caller = 0;
2685+ void *poison_ptr;
2686+
2687+ BUG_ON(!dentry);
2688+ sb = dentry->d_sb;
2689+ inode = dentry->d_inode;
2690+ dstart = dbstart(dentry);
2691+ dend = dbend(dentry);
2692+ /* don't check dentry/mnt if no lower branches */
2693+ if (dstart < 0 && dend < 0)
2694+ goto check_inode;
2695+ BUG_ON(dstart > dend);
2696+
2697+ if (unlikely((dstart == -1 && dend != -1) ||
2698+ (dstart != -1 && dend == -1))) {
2699+ PRINT_CALLER(fname, fxn, line);
2700+ pr_debug(" CD0: dentry=%p dstart/end=%d:%d\n",
2701+ dentry, dstart, dend);
2702+ }
2703+ /*
2704+ * check for NULL dentries inside the start/end range, or
2705+ * non-NULL dentries outside the start/end range.
2706+ */
2707+ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
2708+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
2709+ if (lower_dentry) {
2710+ if (unlikely(bindex < dstart || bindex > dend)) {
2711+ PRINT_CALLER(fname, fxn, line);
2712+ pr_debug(" CD1: dentry/lower=%p:%p(%p) "
2713+ "bindex=%d dstart/end=%d:%d\n",
2714+ dentry, lower_dentry,
2715+ (lower_dentry ? lower_dentry->d_inode :
2716+ (void *) -1L),
2717+ bindex, dstart, dend);
2718+ }
2719+ } else { /* lower_dentry == NULL */
2720+ if (bindex < dstart || bindex > dend)
2721+ continue;
2722+ /*
2723+ * Directories can have NULL lower inodes in b/t
2724+ * start/end, but NOT if at the start/end range.
2725+ * Ignore this rule, however, if this is a NULL
2726+ * dentry or a deleted dentry.
2727+ */
2728+ if (unlikely(!d_deleted((struct dentry *) dentry) &&
2729+ inode &&
2730+ !(inode && S_ISDIR(inode->i_mode) &&
2731+ bindex > dstart && bindex < dend))) {
2732+ PRINT_CALLER(fname, fxn, line);
2733+ pr_debug(" CD2: dentry/lower=%p:%p(%p) "
2734+ "bindex=%d dstart/end=%d:%d\n",
2735+ dentry, lower_dentry,
2736+ (lower_dentry ?
2737+ lower_dentry->d_inode :
2738+ (void *) -1L),
2739+ bindex, dstart, dend);
2740+ }
2741+ }
2742+ }
2743+
2744+ /* check for vfsmounts same as for dentries */
2745+ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
2746+ lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
2747+ if (lower_mnt) {
2748+ if (unlikely(bindex < dstart || bindex > dend)) {
2749+ PRINT_CALLER(fname, fxn, line);
2750+ pr_debug(" CM0: dentry/lmnt=%p:%p bindex=%d "
2751+ "dstart/end=%d:%d\n", dentry,
2752+ lower_mnt, bindex, dstart, dend);
2753+ }
2754+ } else { /* lower_mnt == NULL */
2755+ if (bindex < dstart || bindex > dend)
2756+ continue;
2757+ /*
2758+ * Directories can have NULL lower inodes in b/t
2759+ * start/end, but NOT if at the start/end range.
2760+ * Ignore this rule, however, if this is a NULL
2761+ * dentry.
2762+ */
2763+ if (unlikely(inode &&
2764+ !(inode && S_ISDIR(inode->i_mode) &&
2765+ bindex > dstart && bindex < dend))) {
2766+ PRINT_CALLER(fname, fxn, line);
2767+ pr_debug(" CM1: dentry/lmnt=%p:%p "
2768+ "bindex=%d dstart/end=%d:%d\n",
2769+ dentry, lower_mnt, bindex,
2770+ dstart, dend);
2771+ }
2772+ }
2773+ }
2774+
2775+check_inode:
2776+ /* for inodes now */
2777+ if (!inode)
2778+ return;
2779+ istart = ibstart(inode);
2780+ iend = ibend(inode);
2781+ /* don't check inode if no lower branches */
2782+ if (istart < 0 && iend < 0)
2783+ return;
2784+ BUG_ON(istart > iend);
2785+ if (unlikely((istart == -1 && iend != -1) ||
2786+ (istart != -1 && iend == -1))) {
2787+ PRINT_CALLER(fname, fxn, line);
2788+ pr_debug(" CI0: dentry/inode=%p:%p istart/end=%d:%d\n",
2789+ dentry, inode, istart, iend);
2790+ }
2791+ if (unlikely(istart != dstart)) {
2792+ PRINT_CALLER(fname, fxn, line);
2793+ pr_debug(" CI1: dentry/inode=%p:%p istart=%d dstart=%d\n",
2794+ dentry, inode, istart, dstart);
2795+ }
2796+ if (unlikely(iend != dend)) {
2797+ PRINT_CALLER(fname, fxn, line);
2798+ pr_debug(" CI2: dentry/inode=%p:%p iend=%d dend=%d\n",
2799+ dentry, inode, iend, dend);
2800+ }
2801+
2802+ if (!S_ISDIR(inode->i_mode)) {
2803+ if (unlikely(dend != dstart)) {
2804+ PRINT_CALLER(fname, fxn, line);
2805+ pr_debug(" CI3: dentry/inode=%p:%p dstart=%d dend=%d\n",
2806+ dentry, inode, dstart, dend);
2807+ }
2808+ if (unlikely(iend != istart)) {
2809+ PRINT_CALLER(fname, fxn, line);
2810+ pr_debug(" CI4: dentry/inode=%p:%p istart=%d iend=%d\n",
2811+ dentry, inode, istart, iend);
2812+ }
2813+ }
2814+
2815+ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
2816+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
2817+ if (lower_inode) {
2818+ memset(&poison_ptr, POISON_INUSE, sizeof(void *));
2819+ if (unlikely(bindex < istart || bindex > iend)) {
2820+ PRINT_CALLER(fname, fxn, line);
2821+ pr_debug(" CI5: dentry/linode=%p:%p bindex=%d "
2822+ "istart/end=%d:%d\n", dentry,
2823+ lower_inode, bindex, istart, iend);
2824+ } else if (unlikely(lower_inode == poison_ptr)) {
2825+ /* freed inode! */
2826+ PRINT_CALLER(fname, fxn, line);
2827+ pr_debug(" CI6: dentry/linode=%p:%p bindex=%d "
2828+ "istart/end=%d:%d\n", dentry,
2829+ lower_inode, bindex, istart, iend);
2830+ }
2831+ continue;
2832+ }
2833+ /* if we get here, then lower_inode == NULL */
2834+ if (bindex < istart || bindex > iend)
2835+ continue;
2836+ /*
2837+ * directories can have NULL lower inodes in b/t start/end,
2838+ * but NOT if at the start/end range.
2839+ */
2840+ if (unlikely(S_ISDIR(inode->i_mode) &&
2841+ bindex > istart && bindex < iend))
2842+ continue;
2843+ PRINT_CALLER(fname, fxn, line);
2844+ pr_debug(" CI7: dentry/linode=%p:%p "
2845+ "bindex=%d istart/end=%d:%d\n",
2846+ dentry, lower_inode, bindex, istart, iend);
2847+ }
2848+
2849+ /*
2850+ * If it's a directory, then intermediate objects b/t start/end can
2851+ * be NULL. But, check that all three are NULL: lower dentry, mnt,
2852+ * and inode.
2853+ */
2854+ if (dstart >= 0 && dend >= 0 && S_ISDIR(inode->i_mode))
2855+ for (bindex = dstart+1; bindex < dend; bindex++) {
2856+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
2857+ lower_dentry = unionfs_lower_dentry_idx(dentry,
2858+ bindex);
2859+ lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
2860+ if (unlikely(!((lower_inode && lower_dentry &&
2861+ lower_mnt) ||
2862+ (!lower_inode &&
2863+ !lower_dentry && !lower_mnt)))) {
2864+ PRINT_CALLER(fname, fxn, line);
2865+ pr_debug(" Cx: lmnt/ldentry/linode=%p:%p:%p "
2866+ "bindex=%d dstart/end=%d:%d\n",
2867+ lower_mnt, lower_dentry, lower_inode,
2868+ bindex, dstart, dend);
2869+ }
2870+ }
2871+ /* check if lower inode is newer than upper one (it shouldn't) */
2872+ if (unlikely(is_newer_lower(dentry) && !is_negative_lower(dentry))) {
2873+ PRINT_CALLER(fname, fxn, line);
2874+ for (bindex = ibstart(inode); bindex <= ibend(inode);
2875+ bindex++) {
2876+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
2877+ if (unlikely(!lower_inode))
2878+ continue;
2879+ pr_debug(" CI8: bindex=%d mtime/lmtime=%lu.%lu/%lu.%lu "
2880+ "ctime/lctime=%lu.%lu/%lu.%lu\n",
2881+ bindex,
2882+ inode->i_mtime.tv_sec,
2883+ inode->i_mtime.tv_nsec,
2884+ lower_inode->i_mtime.tv_sec,
2885+ lower_inode->i_mtime.tv_nsec,
2886+ inode->i_ctime.tv_sec,
2887+ inode->i_ctime.tv_nsec,
2888+ lower_inode->i_ctime.tv_sec,
2889+ lower_inode->i_ctime.tv_nsec);
2890+ }
2891+ }
2892+}
2893+
2894+void __unionfs_check_file(const struct file *file,
2895+ const char *fname, const char *fxn, int line)
2896+{
2897+ int bindex;
2898+ int dstart, dend, fstart, fend;
2899+ struct dentry *dentry;
2900+ struct file *lower_file;
2901+ struct inode *inode;
2902+ struct super_block *sb;
2903+ int printed_caller = 0;
2904+
2905+ BUG_ON(!file);
2906+ dentry = file->f_path.dentry;
2907+ sb = dentry->d_sb;
2908+ dstart = dbstart(dentry);
2909+ dend = dbend(dentry);
2910+ BUG_ON(dstart > dend);
2911+ fstart = fbstart(file);
2912+ fend = fbend(file);
2913+ BUG_ON(fstart > fend);
2914+
2915+ if (unlikely((fstart == -1 && fend != -1) ||
2916+ (fstart != -1 && fend == -1))) {
2917+ PRINT_CALLER(fname, fxn, line);
2918+ pr_debug(" CF0: file/dentry=%p:%p fstart/end=%d:%d\n",
2919+ file, dentry, fstart, fend);
2920+ }
2921+ if (unlikely(fstart != dstart)) {
2922+ PRINT_CALLER(fname, fxn, line);
2923+ pr_debug(" CF1: file/dentry=%p:%p fstart=%d dstart=%d\n",
2924+ file, dentry, fstart, dstart);
2925+ }
2926+ if (unlikely(fend != dend)) {
2927+ PRINT_CALLER(fname, fxn, line);
2928+ pr_debug(" CF2: file/dentry=%p:%p fend=%d dend=%d\n",
2929+ file, dentry, fend, dend);
2930+ }
2931+ inode = dentry->d_inode;
2932+ if (!S_ISDIR(inode->i_mode)) {
2933+ if (unlikely(fend != fstart)) {
2934+ PRINT_CALLER(fname, fxn, line);
2935+ pr_debug(" CF3: file/inode=%p:%p fstart=%d fend=%d\n",
2936+ file, inode, fstart, fend);
2937+ }
2938+ if (unlikely(dend != dstart)) {
2939+ PRINT_CALLER(fname, fxn, line);
2940+ pr_debug(" CF4: file/dentry=%p:%p dstart=%d dend=%d\n",
2941+ file, dentry, dstart, dend);
2942+ }
2943+ }
2944+
2945+ /*
2946+ * check for NULL dentries inside the start/end range, or
2947+ * non-NULL dentries outside the start/end range.
2948+ */
2949+ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
2950+ lower_file = unionfs_lower_file_idx(file, bindex);
2951+ if (lower_file) {
2952+ if (unlikely(bindex < fstart || bindex > fend)) {
2953+ PRINT_CALLER(fname, fxn, line);
2954+ pr_debug(" CF5: file/lower=%p:%p bindex=%d "
2955+ "fstart/end=%d:%d\n", file,
2956+ lower_file, bindex, fstart, fend);
2957+ }
2958+ } else { /* lower_file == NULL */
2959+ if (bindex >= fstart && bindex <= fend) {
2960+ /*
2961+ * directories can have NULL lower inodes in
2962+ * b/t start/end, but NOT if at the
2963+ * start/end range.
2964+ */
2965+ if (unlikely(!(S_ISDIR(inode->i_mode) &&
2966+ bindex > fstart &&
2967+ bindex < fend))) {
2968+ PRINT_CALLER(fname, fxn, line);
2969+ pr_debug(" CF6: file/lower=%p:%p "
2970+ "bindex=%d fstart/end=%d:%d\n",
2971+ file, lower_file, bindex,
2972+ fstart, fend);
2973+ }
2974+ }
2975+ }
2976+ }
2977+
2978+ __unionfs_check_dentry(dentry, fname, fxn, line);
2979+}
2980+
2981+void __unionfs_check_nd(const struct nameidata *nd,
2982+ const char *fname, const char *fxn, int line)
2983+{
2984+ struct file *file;
2985+ int printed_caller = 0;
2986+
2987+ if (unlikely(!nd))
2988+ return;
2989+ if (nd->flags & LOOKUP_OPEN) {
2990+ file = nd->intent.open.file;
2991+ if (unlikely(file->f_path.dentry &&
2992+ strcmp(file->f_path.dentry->d_sb->s_type->name,
2993+ UNIONFS_NAME))) {
2994+ PRINT_CALLER(fname, fxn, line);
2995+ pr_debug(" CND1: lower_file of type %s\n",
2996+ file->f_path.dentry->d_sb->s_type->name);
2997+ }
2998+ }
2999+}
3000+
3001+/* useful to track vfsmount leaks that could cause EBUSY on unmount */
3002+void __show_branch_counts(const struct super_block *sb,
3003+ const char *file, const char *fxn, int line)
3004+{
3005+ int i;
3006+ struct vfsmount *mnt;
3007+
3008+ pr_debug("BC:");
3009+ for (i = 0; i < sbmax(sb); i++) {
3010+ if (likely(sb->s_root))
3011+ mnt = UNIONFS_D(sb->s_root)->lower_paths[i].mnt;
3012+ else
3013+ mnt = NULL;
3014+ printk(KERN_CONT "%d:",
3015+ (mnt ? atomic_read(&mnt->mnt_count) : -99));
3016+ }
3017+ printk(KERN_CONT "%s:%s:%d\n", file, fxn, line);
3018+}
3019+
3020+void __show_inode_times(const struct inode *inode,
3021+ const char *file, const char *fxn, int line)
3022+{
3023+ struct inode *lower_inode;
3024+ int bindex;
3025+
3026+ for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
3027+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
3028+ if (unlikely(!lower_inode))
3029+ continue;
3030+ pr_debug("IT(%lu:%d): %s:%s:%d "
3031+ "um=%lu/%lu lm=%lu/%lu uc=%lu/%lu lc=%lu/%lu\n",
3032+ inode->i_ino, bindex,
3033+ file, fxn, line,
3034+ inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
3035+ lower_inode->i_mtime.tv_sec,
3036+ lower_inode->i_mtime.tv_nsec,
3037+ inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
3038+ lower_inode->i_ctime.tv_sec,
3039+ lower_inode->i_ctime.tv_nsec);
3040+ }
3041+}
3042+
3043+void __show_dinode_times(const struct dentry *dentry,
3044+ const char *file, const char *fxn, int line)
3045+{
3046+ struct inode *inode = dentry->d_inode;
3047+ struct inode *lower_inode;
3048+ int bindex;
3049+
3050+ for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
3051+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
3052+ if (!lower_inode)
3053+ continue;
3054+ pr_debug("DT(%s:%lu:%d): %s:%s:%d "
3055+ "um=%lu/%lu lm=%lu/%lu uc=%lu/%lu lc=%lu/%lu\n",
3056+ dentry->d_name.name, inode->i_ino, bindex,
3057+ file, fxn, line,
3058+ inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
3059+ lower_inode->i_mtime.tv_sec,
3060+ lower_inode->i_mtime.tv_nsec,
3061+ inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
3062+ lower_inode->i_ctime.tv_sec,
3063+ lower_inode->i_ctime.tv_nsec);
3064+ }
3065+}
3066+
3067+void __show_inode_counts(const struct inode *inode,
3068+ const char *file, const char *fxn, int line)
3069+{
3070+ struct inode *lower_inode;
3071+ int bindex;
3072+
3073+ if (unlikely(!inode)) {
3074+ pr_debug("SiC: Null inode\n");
3075+ return;
3076+ }
3077+ for (bindex = sbstart(inode->i_sb); bindex <= sbend(inode->i_sb);
3078+ bindex++) {
3079+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
3080+ if (unlikely(!lower_inode))
3081+ continue;
3082+ pr_debug("SIC(%lu:%d:%d): lc=%d %s:%s:%d\n",
3083+ inode->i_ino, bindex,
3084+ atomic_read(&(inode)->i_count),
3085+ atomic_read(&(lower_inode)->i_count),
3086+ file, fxn, line);
3087+ }
3088+}
3089diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
3090new file mode 100644
3091index 0000000..a0c3bba
3092--- /dev/null
3093+++ b/fs/unionfs/dentry.c
3094@@ -0,0 +1,397 @@
3095+/*
3096+ * Copyright (c) 2003-2010 Erez Zadok
3097+ * Copyright (c) 2003-2006 Charles P. Wright
3098+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
3099+ * Copyright (c) 2005-2006 Junjiro Okajima
3100+ * Copyright (c) 2005 Arun M. Krishnakumar
3101+ * Copyright (c) 2004-2006 David P. Quigley
3102+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
3103+ * Copyright (c) 2003 Puja Gupta
3104+ * Copyright (c) 2003 Harikesavan Krishnan
3105+ * Copyright (c) 2003-2010 Stony Brook University
3106+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
3107+ *
3108+ * This program is free software; you can redistribute it and/or modify
3109+ * it under the terms of the GNU General Public License version 2 as
3110+ * published by the Free Software Foundation.
3111+ */
3112+
3113+#include "union.h"
3114+
3115+bool is_negative_lower(const struct dentry *dentry)
3116+{
3117+ int bindex;
3118+ struct dentry *lower_dentry;
3119+
3120+ BUG_ON(!dentry);
3121+ /* cache coherency: check if file was deleted on lower branch */
3122+ if (dbstart(dentry) < 0)
3123+ return true;
3124+ for (bindex = dbstart(dentry); bindex <= dbend(dentry); bindex++) {
3125+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
3126+ /* unhashed (i.e., unlinked) lower dentries don't count */
3127+ if (lower_dentry && lower_dentry->d_inode &&
3128+ !d_deleted(lower_dentry) &&
3129+ !(lower_dentry->d_flags & DCACHE_NFSFS_RENAMED))
3130+ return false;
3131+ }
3132+ return true;
3133+}
3134+
3135+static inline void __dput_lowers(struct dentry *dentry, int start, int end)
3136+{
3137+ struct dentry *lower_dentry;
3138+ int bindex;
3139+
3140+ if (start < 0)
3141+ return;
3142+ for (bindex = start; bindex <= end; bindex++) {
3143+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
3144+ if (!lower_dentry)
3145+ continue;
3146+ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
3147+ dput(lower_dentry);
3148+ }
3149+}
3150+
3151+/*
3152+ * Purge and invalidate as many data pages of a unionfs inode. This is
3153+ * called when the lower inode has changed, and we want to force processes
3154+ * to re-get the new data.
3155+ */
3156+static inline void purge_inode_data(struct inode *inode)
3157+{
3158+ /* remove all non-private mappings */
3159+ unmap_mapping_range(inode->i_mapping, 0, 0, 0);
3160+ /* invalidate as many pages as possible */
3161+ invalidate_mapping_pages(inode->i_mapping, 0, -1);
3162+ /*
3163+ * Don't try to truncate_inode_pages here, because this could lead
3164+ * to a deadlock between some of address_space ops and dentry
3165+ * revalidation: the address space op is invoked with a lock on our
3166+ * own page, and truncate_inode_pages will block on locked pages.
3167+ */
3168+}
3169+
3170+/*
3171+ * Revalidate a single file/symlink/special dentry. Assume that info nodes
3172+ * of the @dentry and its @parent are locked. Assume parent is valid,
3173+ * otherwise return false (and let's hope the VFS will try to re-lookup this
3174+ * dentry). Returns true if valid, false otherwise.
3175+ */
3176+bool __unionfs_d_revalidate(struct dentry *dentry, struct dentry *parent,
3177+ bool willwrite)
3178+{
3179+ bool valid = true; /* default is valid */
3180+ struct dentry *lower_dentry;
3181+ struct dentry *result;
3182+ int bindex, bstart, bend;
3183+ int sbgen, dgen, pdgen;
3184+ int positive = 0;
3185+ int interpose_flag;
3186+
3187+ verify_locked(dentry);
3188+ verify_locked(parent);
3189+
3190+ /* if the dentry is unhashed, do NOT revalidate */
3191+ if (d_deleted(dentry))
3192+ goto out;
3193+
3194+ dgen = atomic_read(&UNIONFS_D(dentry)->generation);
3195+
3196+ if (is_newer_lower(dentry)) {
3197+ /* root dentry is always valid */
3198+ if (IS_ROOT(dentry)) {
3199+ unionfs_copy_attr_times(dentry->d_inode);
3200+ } else {
3201+ /*
3202+ * reset generation number to zero, guaranteed to be
3203+ * "old"
3204+ */
3205+ dgen = 0;
3206+ atomic_set(&UNIONFS_D(dentry)->generation, dgen);
3207+ }
3208+ if (!willwrite)
3209+ purge_inode_data(dentry->d_inode);
3210+ }
3211+
3212+ sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
3213+
3214+ BUG_ON(dbstart(dentry) == -1);
3215+ if (dentry->d_inode)
3216+ positive = 1;
3217+
3218+ /* if our dentry is valid, then validate all lower ones */
3219+ if (sbgen == dgen)
3220+ goto validate_lowers;
3221+
3222+ /* The root entry should always be valid */
3223+ BUG_ON(IS_ROOT(dentry));
3224+
3225+ /* We can't work correctly if our parent isn't valid. */
3226+ pdgen = atomic_read(&UNIONFS_D(parent)->generation);
3227+
3228+ /* Free the pointers for our inodes and this dentry. */
3229+ path_put_lowers_all(dentry, false);
3230+
3231+ interpose_flag = INTERPOSE_REVAL_NEG;
3232+ if (positive) {
3233+ interpose_flag = INTERPOSE_REVAL;
3234+ iput_lowers_all(dentry->d_inode, true);
3235+ }
3236+
3237+ if (realloc_dentry_private_data(dentry) != 0) {
3238+ valid = false;
3239+ goto out;
3240+ }
3241+
3242+ result = unionfs_lookup_full(dentry, parent, interpose_flag);
3243+ if (result) {
3244+ if (IS_ERR(result)) {
3245+ valid = false;
3246+ goto out;
3247+ }
3248+ /*
3249+ * current unionfs_lookup_backend() doesn't return
3250+ * a valid dentry
3251+ */
3252+ dput(dentry);
3253+ dentry = result;
3254+ }
3255+
3256+ if (unlikely(positive && is_negative_lower(dentry))) {
3257+ /* call make_bad_inode here ? */
3258+ d_drop(dentry);
3259+ valid = false;
3260+ goto out;
3261+ }
3262+
3263+ /*
3264+ * if we got here then we have revalidated our dentry and all lower
3265+ * ones, so we can return safely.
3266+ */
3267+ if (!valid) /* lower dentry revalidation failed */
3268+ goto out;
3269+
3270+ /*
3271+ * If the parent's gen no. matches the superblock's gen no., then
3272+ * we can update our denty's gen no. If they didn't match, then it
3273+ * was OK to revalidate this dentry with a stale parent, but we'll
3274+ * purposely not update our dentry's gen no. (so it can be redone);
3275+ * and, we'll mark our parent dentry as invalid so it'll force it
3276+ * (and our dentry) to be revalidated.
3277+ */
3278+ if (pdgen == sbgen)
3279+ atomic_set(&UNIONFS_D(dentry)->generation, sbgen);
3280+ goto out;
3281+
3282+validate_lowers:
3283+
3284+ /* The revalidation must occur across all branches */
3285+ bstart = dbstart(dentry);
3286+ bend = dbend(dentry);
3287+ BUG_ON(bstart == -1);
3288+ for (bindex = bstart; bindex <= bend; bindex++) {
3289+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
3290+ if (!lower_dentry || !lower_dentry->d_op
3291+ || !lower_dentry->d_op->d_revalidate)
3292+ continue;
3293+ /*
3294+ * Don't pass nameidata to lower file system, because we
3295+ * don't want an arbitrary lower file being opened or
3296+ * returned to us: it may be useless to us because of the
3297+ * fanout nature of unionfs (cf. file/directory open-file
3298+ * invariants). We will open lower files as and when needed
3299+ * later on.
3300+ */
3301+ if (!lower_dentry->d_op->d_revalidate(lower_dentry, NULL))
3302+ valid = false;
3303+ }
3304+
3305+ if (!dentry->d_inode ||
3306+ ibstart(dentry->d_inode) < 0 ||
3307+ ibend(dentry->d_inode) < 0) {
3308+ valid = false;
3309+ goto out;
3310+ }
3311+
3312+ if (valid) {
3313+ /*
3314+ * If we get here, and we copy the meta-data from the lower
3315+ * inode to our inode, then it is vital that we have already
3316+ * purged all unionfs-level file data. We do that in the
3317+ * caller (__unionfs_d_revalidate) by calling
3318+ * purge_inode_data.
3319+ */
3320+ unionfs_copy_attr_all(dentry->d_inode,
3321+ unionfs_lower_inode(dentry->d_inode));
3322+ fsstack_copy_inode_size(dentry->d_inode,
3323+ unionfs_lower_inode(dentry->d_inode));
3324+ }
3325+
3326+out:
3327+ return valid;
3328+}
3329+
3330+/*
3331+ * Determine if the lower inode objects have changed from below the unionfs
3332+ * inode. Return true if changed, false otherwise.
3333+ *
3334+ * We check if the mtime or ctime have changed. However, the inode times
3335+ * can be changed by anyone without much protection, including
3336+ * asynchronously. This can sometimes cause unionfs to find that the lower
3337+ * file system doesn't change its inode times quick enough, resulting in a
3338+ * false positive indication (which is harmless, it just makes unionfs do
3339+ * extra work in re-validating the objects). To minimize the chances of
3340+ * these situations, we still consider such small time changes valid, but we
3341+ * don't print debugging messages unless the time changes are greater than
3342+ * UNIONFS_MIN_CC_TIME (which defaults to 3 seconds, as with NFS's acregmin)
3343+ * because significant changes are more likely due to users manually
3344+ * touching lower files.
3345+ */
3346+bool is_newer_lower(const struct dentry *dentry)
3347+{
3348+ int bindex;
3349+ struct inode *inode;
3350+ struct inode *lower_inode;
3351+
3352+ /* ignore if we're called on semi-initialized dentries/inodes */
3353+ if (!dentry || !UNIONFS_D(dentry))
3354+ return false;
3355+ inode = dentry->d_inode;
3356+ if (!inode || !UNIONFS_I(inode)->lower_inodes ||
3357+ ibstart(inode) < 0 || ibend(inode) < 0)
3358+ return false;
3359+
3360+ for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
3361+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
3362+ if (!lower_inode)
3363+ continue;
3364+
3365+ /* check if mtime/ctime have changed */
3366+ if (unlikely(timespec_compare(&inode->i_mtime,
3367+ &lower_inode->i_mtime) < 0)) {
3368+ if ((lower_inode->i_mtime.tv_sec -
3369+ inode->i_mtime.tv_sec) > UNIONFS_MIN_CC_TIME) {
3370+ pr_info("unionfs: new lower inode mtime "
3371+ "(bindex=%d, name=%s)\n", bindex,
3372+ dentry->d_name.name);
3373+ show_dinode_times(dentry);
3374+ }
3375+ return true;
3376+ }
3377+ if (unlikely(timespec_compare(&inode->i_ctime,
3378+ &lower_inode->i_ctime) < 0)) {
3379+ if ((lower_inode->i_ctime.tv_sec -
3380+ inode->i_ctime.tv_sec) > UNIONFS_MIN_CC_TIME) {
3381+ pr_info("unionfs: new lower inode ctime "
3382+ "(bindex=%d, name=%s)\n", bindex,
3383+ dentry->d_name.name);
3384+ show_dinode_times(dentry);
3385+ }
3386+ return true;
3387+ }
3388+ }
3389+
3390+ /*
3391+ * Last check: if this is a positive dentry, but somehow all lower
3392+ * dentries are negative or unhashed, then this dentry needs to be
3393+ * revalidated, because someone probably deleted the objects from
3394+ * the lower branches directly.
3395+ */
3396+ if (is_negative_lower(dentry))
3397+ return true;
3398+
3399+ return false; /* default: lower is not newer */
3400+}
3401+
3402+static int unionfs_d_revalidate(struct dentry *dentry,
3403+ struct nameidata *nd_unused)
3404+{
3405+ bool valid = true;
3406+ int err = 1; /* 1 means valid for the VFS */
3407+ struct dentry *parent;
3408+
3409+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
3410+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
3411+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
3412+
3413+ valid = __unionfs_d_revalidate(dentry, parent, false);
3414+ if (valid) {
3415+ unionfs_postcopyup_setmnt(dentry);
3416+ unionfs_check_dentry(dentry);
3417+ } else {
3418+ d_drop(dentry);
3419+ err = valid;
3420+ }
3421+ unionfs_unlock_dentry(dentry);
3422+ unionfs_unlock_parent(dentry, parent);
3423+ unionfs_read_unlock(dentry->d_sb);
3424+
3425+ return err;
3426+}
3427+
3428+static void unionfs_d_release(struct dentry *dentry)
3429+{
3430+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
3431+ if (unlikely(!UNIONFS_D(dentry)))
3432+ goto out; /* skip if no lower branches */
3433+ /* must lock our branch configuration here */
3434+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
3435+
3436+ unionfs_check_dentry(dentry);
3437+ /* this could be a negative dentry, so check first */
3438+ if (dbstart(dentry) < 0) {
3439+ unionfs_unlock_dentry(dentry);
3440+ goto out; /* due to a (normal) failed lookup */
3441+ }
3442+
3443+ /* Release all the lower dentries */
3444+ path_put_lowers_all(dentry, true);
3445+
3446+ unionfs_unlock_dentry(dentry);
3447+
3448+out:
3449+ free_dentry_private_data(dentry);
3450+ unionfs_read_unlock(dentry->d_sb);
3451+ return;
3452+}
3453+
3454+/*
3455+ * Called when we're removing the last reference to our dentry. So we
3456+ * should drop all lower references too.
3457+ */
3458+static void unionfs_d_iput(struct dentry *dentry, struct inode *inode)
3459+{
3460+ int rc;
3461+
3462+ BUG_ON(!dentry);
3463+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
3464+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
3465+
3466+ if (!UNIONFS_D(dentry) || dbstart(dentry) < 0)
3467+ goto drop_lower_inodes;
3468+ path_put_lowers_all(dentry, false);
3469+
3470+drop_lower_inodes:
3471+ rc = atomic_read(&inode->i_count);
3472+ if (rc == 1 && inode->i_nlink == 1 && ibstart(inode) >= 0) {
3473+ /* see Documentation/filesystems/unionfs/issues.txt */
3474+ lockdep_off();
3475+ iput(unionfs_lower_inode(inode));
3476+ lockdep_on();
3477+ unionfs_set_lower_inode(inode, NULL);
3478+ /* XXX: may need to set start/end to -1? */
3479+ }
3480+
3481+ iput(inode);
3482+
3483+ unionfs_unlock_dentry(dentry);
3484+ unionfs_read_unlock(dentry->d_sb);
3485+}
3486+
3487+struct dentry_operations unionfs_dops = {
3488+ .d_revalidate = unionfs_d_revalidate,
3489+ .d_release = unionfs_d_release,
3490+ .d_iput = unionfs_d_iput,
3491+};
3492diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
3493new file mode 100644
3494index 0000000..7da0ff0
3495--- /dev/null
3496+++ b/fs/unionfs/dirfops.c
3497@@ -0,0 +1,302 @@
3498+/*
3499+ * Copyright (c) 2003-2010 Erez Zadok
3500+ * Copyright (c) 2003-2006 Charles P. Wright
3501+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
3502+ * Copyright (c) 2005-2006 Junjiro Okajima
3503+ * Copyright (c) 2005 Arun M. Krishnakumar
3504+ * Copyright (c) 2004-2006 David P. Quigley
3505+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
3506+ * Copyright (c) 2003 Puja Gupta
3507+ * Copyright (c) 2003 Harikesavan Krishnan
3508+ * Copyright (c) 2003-2010 Stony Brook University
3509+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
3510+ *
3511+ * This program is free software; you can redistribute it and/or modify
3512+ * it under the terms of the GNU General Public License version 2 as
3513+ * published by the Free Software Foundation.
3514+ */
3515+
3516+#include "union.h"
3517+
3518+/* Make sure our rdstate is playing by the rules. */
3519+static void verify_rdstate_offset(struct unionfs_dir_state *rdstate)
3520+{
3521+ BUG_ON(rdstate->offset >= DIREOF);
3522+ BUG_ON(rdstate->cookie >= MAXRDCOOKIE);
3523+}
3524+
3525+struct unionfs_getdents_callback {
3526+ struct unionfs_dir_state *rdstate;
3527+ void *dirent;
3528+ int entries_written;
3529+ int filldir_called;
3530+ int filldir_error;
3531+ filldir_t filldir;
3532+ struct super_block *sb;
3533+};
3534+
3535+/* based on generic filldir in fs/readir.c */
3536+static int unionfs_filldir(void *dirent, const char *oname, int namelen,
3537+ loff_t offset, u64 ino, unsigned int d_type)
3538+{
3539+ struct unionfs_getdents_callback *buf = dirent;
3540+ struct filldir_node *found = NULL;
3541+ int err = 0;
3542+ int is_whiteout;
3543+ char *name = (char *) oname;
3544+
3545+ buf->filldir_called++;
3546+
3547+ is_whiteout = is_whiteout_name(&name, &namelen);
3548+
3549+ found = find_filldir_node(buf->rdstate, name, namelen, is_whiteout);
3550+
3551+ if (found) {
3552+ /*
3553+ * If we had non-whiteout entry in dir cache, then mark it
3554+ * as a whiteout and but leave it in the dir cache.
3555+ */
3556+ if (is_whiteout && !found->whiteout)
3557+ found->whiteout = is_whiteout;
3558+ goto out;
3559+ }
3560+
3561+ /* if 'name' isn't a whiteout, filldir it. */
3562+ if (!is_whiteout) {
3563+ off_t pos = rdstate2offset(buf->rdstate);
3564+ u64 unionfs_ino = ino;
3565+
3566+ err = buf->filldir(buf->dirent, name, namelen, pos,
3567+ unionfs_ino, d_type);
3568+ buf->rdstate->offset++;
3569+ verify_rdstate_offset(buf->rdstate);
3570+ }
3571+ /*
3572+ * If we did fill it, stuff it in our hash, otherwise return an
3573+ * error.
3574+ */
3575+ if (err) {
3576+ buf->filldir_error = err;
3577+ goto out;
3578+ }
3579+ buf->entries_written++;
3580+ err = add_filldir_node(buf->rdstate, name, namelen,
3581+ buf->rdstate->bindex, is_whiteout);
3582+ if (err)
3583+ buf->filldir_error = err;
3584+
3585+out:
3586+ return err;
3587+}
3588+
3589+static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
3590+{
3591+ int err = 0;
3592+ struct file *lower_file = NULL;
3593+ struct dentry *dentry = file->f_path.dentry;
3594+ struct dentry *parent;
3595+ struct inode *inode = NULL;
3596+ struct unionfs_getdents_callback buf;
3597+ struct unionfs_dir_state *uds;
3598+ int bend;
3599+ loff_t offset;
3600+
3601+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
3602+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
3603+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
3604+
3605+ err = unionfs_file_revalidate(file, parent, false);
3606+ if (unlikely(err))
3607+ goto out;
3608+
3609+ inode = dentry->d_inode;
3610+
3611+ uds = UNIONFS_F(file)->rdstate;
3612+ if (!uds) {
3613+ if (file->f_pos == DIREOF) {
3614+ goto out;
3615+ } else if (file->f_pos > 0) {
3616+ uds = find_rdstate(inode, file->f_pos);
3617+ if (unlikely(!uds)) {
3618+ err = -ESTALE;
3619+ goto out;
3620+ }
3621+ UNIONFS_F(file)->rdstate = uds;
3622+ } else {
3623+ init_rdstate(file);
3624+ uds = UNIONFS_F(file)->rdstate;
3625+ }
3626+ }
3627+ bend = fbend(file);
3628+
3629+ while (uds->bindex <= bend) {
3630+ lower_file = unionfs_lower_file_idx(file, uds->bindex);
3631+ if (!lower_file) {
3632+ uds->bindex++;
3633+ uds->dirpos = 0;
3634+ continue;
3635+ }
3636+
3637+ /* prepare callback buffer */
3638+ buf.filldir_called = 0;
3639+ buf.filldir_error = 0;
3640+ buf.entries_written = 0;
3641+ buf.dirent = dirent;
3642+ buf.filldir = filldir;
3643+ buf.rdstate = uds;
3644+ buf.sb = inode->i_sb;
3645+
3646+ /* Read starting from where we last left off. */
3647+ offset = vfs_llseek(lower_file, uds->dirpos, SEEK_SET);
3648+ if (offset < 0) {
3649+ err = offset;
3650+ goto out;
3651+ }
3652+ err = vfs_readdir(lower_file, unionfs_filldir, &buf);
3653+
3654+ /* Save the position for when we continue. */
3655+ offset = vfs_llseek(lower_file, 0, SEEK_CUR);
3656+ if (offset < 0) {
3657+ err = offset;
3658+ goto out;
3659+ }
3660+ uds->dirpos = offset;
3661+
3662+ /* Copy the atime. */
3663+ fsstack_copy_attr_atime(inode,
3664+ lower_file->f_path.dentry->d_inode);
3665+
3666+ if (err < 0)
3667+ goto out;
3668+
3669+ if (buf.filldir_error)
3670+ break;
3671+
3672+ if (!buf.entries_written) {
3673+ uds->bindex++;
3674+ uds->dirpos = 0;
3675+ }
3676+ }
3677+
3678+ if (!buf.filldir_error && uds->bindex >= bend) {
3679+ /* Save the number of hash entries for next time. */
3680+ UNIONFS_I(inode)->hashsize = uds->hashentries;
3681+ free_rdstate(uds);
3682+ UNIONFS_F(file)->rdstate = NULL;
3683+ file->f_pos = DIREOF;
3684+ } else {
3685+ file->f_pos = rdstate2offset(uds);
3686+ }
3687+
3688+out:
3689+ if (!err)
3690+ unionfs_check_file(file);
3691+ unionfs_unlock_dentry(dentry);
3692+ unionfs_unlock_parent(dentry, parent);
3693+ unionfs_read_unlock(dentry->d_sb);
3694+ return err;
3695+}
3696+
3697+/*
3698+ * This is not meant to be a generic repositioning function. If you do
3699+ * things that aren't supported, then we return EINVAL.
3700+ *
3701+ * What is allowed:
3702+ * (1) seeking to the same position that you are currently at
3703+ * This really has no effect, but returns where you are.
3704+ * (2) seeking to the beginning of the file
3705+ * This throws out all state, and lets you begin again.
3706+ */
3707+static loff_t unionfs_dir_llseek(struct file *file, loff_t offset, int origin)
3708+{
3709+ struct unionfs_dir_state *rdstate;
3710+ struct dentry *dentry = file->f_path.dentry;
3711+ struct dentry *parent;
3712+ loff_t err;
3713+
3714+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
3715+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
3716+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
3717+
3718+ err = unionfs_file_revalidate(file, parent, false);
3719+ if (unlikely(err))
3720+ goto out;
3721+
3722+ rdstate = UNIONFS_F(file)->rdstate;
3723+
3724+ /*
3725+ * we let users seek to their current position, but not anywhere
3726+ * else.
3727+ */
3728+ if (!offset) {
3729+ switch (origin) {
3730+ case SEEK_SET:
3731+ if (rdstate) {
3732+ free_rdstate(rdstate);
3733+ UNIONFS_F(file)->rdstate = NULL;
3734+ }
3735+ init_rdstate(file);
3736+ err = 0;
3737+ break;
3738+ case SEEK_CUR:
3739+ err = file->f_pos;
3740+ break;
3741+ case SEEK_END:
3742+ /* Unsupported, because we would break everything. */
3743+ err = -EINVAL;
3744+ break;
3745+ }
3746+ } else {
3747+ switch (origin) {
3748+ case SEEK_SET:
3749+ if (rdstate) {
3750+ if (offset == rdstate2offset(rdstate))
3751+ err = offset;
3752+ else if (file->f_pos == DIREOF)
3753+ err = DIREOF;
3754+ else
3755+ err = -EINVAL;
3756+ } else {
3757+ struct inode *inode;
3758+ inode = dentry->d_inode;
3759+ rdstate = find_rdstate(inode, offset);
3760+ if (rdstate) {
3761+ UNIONFS_F(file)->rdstate = rdstate;
3762+ err = rdstate->offset;
3763+ } else {
3764+ err = -EINVAL;
3765+ }
3766+ }
3767+ break;
3768+ case SEEK_CUR:
3769+ case SEEK_END:
3770+ /* Unsupported, because we would break everything. */
3771+ err = -EINVAL;
3772+ break;
3773+ }
3774+ }
3775+
3776+out:
3777+ if (!err)
3778+ unionfs_check_file(file);
3779+ unionfs_unlock_dentry(dentry);
3780+ unionfs_unlock_parent(dentry, parent);
3781+ unionfs_read_unlock(dentry->d_sb);
3782+ return err;
3783+}
3784+
3785+/*
3786+ * Trimmed directory options, we shouldn't pass everything down since
3787+ * we don't want to operate on partial directories.
3788+ */
3789+struct file_operations unionfs_dir_fops = {
3790+ .llseek = unionfs_dir_llseek,
3791+ .read = generic_read_dir,
3792+ .readdir = unionfs_readdir,
3793+ .unlocked_ioctl = unionfs_ioctl,
3794+ .open = unionfs_open,
3795+ .release = unionfs_file_release,
3796+ .flush = unionfs_flush,
3797+ .fsync = unionfs_fsync,
3798+ .fasync = unionfs_fasync,
3799+};
3800diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
3801new file mode 100644
3802index 0000000..033343b
3803--- /dev/null
3804+++ b/fs/unionfs/dirhelper.c
3805@@ -0,0 +1,158 @@
3806+/*
3807+ * Copyright (c) 2003-2010 Erez Zadok
3808+ * Copyright (c) 2003-2006 Charles P. Wright
3809+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
3810+ * Copyright (c) 2005-2006 Junjiro Okajima
3811+ * Copyright (c) 2005 Arun M. Krishnakumar
3812+ * Copyright (c) 2004-2006 David P. Quigley
3813+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
3814+ * Copyright (c) 2003 Puja Gupta
3815+ * Copyright (c) 2003 Harikesavan Krishnan
3816+ * Copyright (c) 2003-2010 Stony Brook University
3817+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
3818+ *
3819+ * This program is free software; you can redistribute it and/or modify
3820+ * it under the terms of the GNU General Public License version 2 as
3821+ * published by the Free Software Foundation.
3822+ */
3823+
3824+#include "union.h"
3825+
3826+#define RD_NONE 0
3827+#define RD_CHECK_EMPTY 1
3828+/* The callback structure for check_empty. */
3829+struct unionfs_rdutil_callback {
3830+ int err;
3831+ int filldir_called;
3832+ struct unionfs_dir_state *rdstate;
3833+ int mode;
3834+};
3835+
3836+/* This filldir function makes sure only whiteouts exist within a directory. */
3837+static int readdir_util_callback(void *dirent, const char *oname, int namelen,
3838+ loff_t offset, u64 ino, unsigned int d_type)
3839+{
3840+ int err = 0;
3841+ struct unionfs_rdutil_callback *buf = dirent;
3842+ int is_whiteout;
3843+ struct filldir_node *found;
3844+ char *name = (char *) oname;
3845+
3846+ buf->filldir_called = 1;
3847+
3848+ if (name[0] == '.' && (namelen == 1 ||
3849+ (name[1] == '.' && namelen == 2)))
3850+ goto out;
3851+
3852+ is_whiteout = is_whiteout_name(&name, &namelen);
3853+
3854+ found = find_filldir_node(buf->rdstate, name, namelen, is_whiteout);
3855+ /* If it was found in the table there was a previous whiteout. */
3856+ if (found)
3857+ goto out;
3858+
3859+ /*
3860+ * if it wasn't found and isn't a whiteout, the directory isn't
3861+ * empty.
3862+ */
3863+ err = -ENOTEMPTY;
3864+ if ((buf->mode == RD_CHECK_EMPTY) && !is_whiteout)
3865+ goto out;
3866+
3867+ err = add_filldir_node(buf->rdstate, name, namelen,
3868+ buf->rdstate->bindex, is_whiteout);
3869+
3870+out:
3871+ buf->err = err;
3872+ return err;
3873+}
3874+
3875+/* Is a directory logically empty? */
3876+int check_empty(struct dentry *dentry, struct dentry *parent,
3877+ struct unionfs_dir_state **namelist)
3878+{
3879+ int err = 0;
3880+ struct dentry *lower_dentry = NULL;
3881+ struct vfsmount *mnt;
3882+ struct super_block *sb;
3883+ struct file *lower_file;
3884+ struct unionfs_rdutil_callback *buf = NULL;
3885+ int bindex, bstart, bend, bopaque;
3886+
3887+ sb = dentry->d_sb;
3888+
3889+
3890+ BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
3891+
3892+ err = unionfs_partial_lookup(dentry, parent);
3893+ if (err)
3894+ goto out;
3895+
3896+ bstart = dbstart(dentry);
3897+ bend = dbend(dentry);
3898+ bopaque = dbopaque(dentry);
3899+ if (0 <= bopaque && bopaque < bend)
3900+ bend = bopaque;
3901+
3902+ buf = kmalloc(sizeof(struct unionfs_rdutil_callback), GFP_KERNEL);
3903+ if (unlikely(!buf)) {
3904+ err = -ENOMEM;
3905+ goto out;
3906+ }
3907+ buf->err = 0;
3908+ buf->mode = RD_CHECK_EMPTY;
3909+ buf->rdstate = alloc_rdstate(dentry->d_inode, bstart);
3910+ if (unlikely(!buf->rdstate)) {
3911+ err = -ENOMEM;
3912+ goto out;
3913+ }
3914+
3915+ /* Process the lower directories with rdutil_callback as a filldir. */
3916+ for (bindex = bstart; bindex <= bend; bindex++) {
3917+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
3918+ if (!lower_dentry)
3919+ continue;
3920+ if (!lower_dentry->d_inode)
3921+ continue;
3922+ if (!S_ISDIR(lower_dentry->d_inode->i_mode))
3923+ continue;
3924+
3925+ dget(lower_dentry);
3926+ mnt = unionfs_mntget(dentry, bindex);
3927+ branchget(sb, bindex);
3928+ lower_file = dentry_open(lower_dentry, mnt, O_RDONLY, current_cred());
3929+ if (IS_ERR(lower_file)) {
3930+ err = PTR_ERR(lower_file);
3931+ branchput(sb, bindex);
3932+ goto out;
3933+ }
3934+
3935+ do {
3936+ buf->filldir_called = 0;
3937+ buf->rdstate->bindex = bindex;
3938+ err = vfs_readdir(lower_file,
3939+ readdir_util_callback, buf);
3940+ if (buf->err)
3941+ err = buf->err;
3942+ } while ((err >= 0) && buf->filldir_called);
3943+
3944+ /* fput calls dput for lower_dentry */
3945+ fput(lower_file);
3946+ branchput(sb, bindex);
3947+
3948+ if (err < 0)
3949+ goto out;
3950+ }
3951+
3952+out:
3953+ if (buf) {
3954+ if (namelist && !err)
3955+ *namelist = buf->rdstate;
3956+ else if (buf->rdstate)
3957+ free_rdstate(buf->rdstate);
3958+ kfree(buf);
3959+ }
3960+
3961+
3962+ return err;
3963+}
3964diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h
3965new file mode 100644
3966index 0000000..5b77eac
3967--- /dev/null
3968+++ b/fs/unionfs/fanout.h
3969@@ -0,0 +1,407 @@
3970+/*
3971+ * Copyright (c) 2003-2010 Erez Zadok
3972+ * Copyright (c) 2003-2006 Charles P. Wright
3973+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
3974+ * Copyright (c) 2005 Arun M. Krishnakumar
3975+ * Copyright (c) 2004-2006 David P. Quigley
3976+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
3977+ * Copyright (c) 2003 Puja Gupta
3978+ * Copyright (c) 2003 Harikesavan Krishnan
3979+ * Copyright (c) 2003-2010 Stony Brook University
3980+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
3981+ *
3982+ * This program is free software; you can redistribute it and/or modify
3983+ * it under the terms of the GNU General Public License version 2 as
3984+ * published by the Free Software Foundation.
3985+ */
3986+
3987+#ifndef _FANOUT_H_
3988+#define _FANOUT_H_
3989+
3990+/*
3991+ * Inode to private data
3992+ *
3993+ * Since we use containers and the struct inode is _inside_ the
3994+ * unionfs_inode_info structure, UNIONFS_I will always (given a non-NULL
3995+ * inode pointer), return a valid non-NULL pointer.
3996+ */
3997+static inline struct unionfs_inode_info *UNIONFS_I(const struct inode *inode)
3998+{
3999+ return container_of(inode, struct unionfs_inode_info, vfs_inode);
4000+}
4001+
4002+#define ibstart(ino) (UNIONFS_I(ino)->bstart)
4003+#define ibend(ino) (UNIONFS_I(ino)->bend)
4004+
4005+/* Dentry to private data */
4006+#define UNIONFS_D(dent) ((struct unionfs_dentry_info *)(dent)->d_fsdata)
4007+#define dbstart(dent) (UNIONFS_D(dent)->bstart)
4008+#define dbend(dent) (UNIONFS_D(dent)->bend)
4009+#define dbopaque(dent) (UNIONFS_D(dent)->bopaque)
4010+
4011+/* Superblock to private data */
4012+#define UNIONFS_SB(super) ((struct unionfs_sb_info *)(super)->s_fs_info)
4013+#define sbstart(sb) 0
4014+#define sbend(sb) (UNIONFS_SB(sb)->bend)
4015+#define sbmax(sb) (UNIONFS_SB(sb)->bend + 1)
4016+#define sbhbid(sb) (UNIONFS_SB(sb)->high_branch_id)
4017+
4018+/* File to private Data */
4019+#define UNIONFS_F(file) ((struct unionfs_file_info *)((file)->private_data))
4020+#define fbstart(file) (UNIONFS_F(file)->bstart)
4021+#define fbend(file) (UNIONFS_F(file)->bend)
4022+
4023+/* macros to manipulate branch IDs in stored in our superblock */
4024+static inline int branch_id(struct super_block *sb, int index)
4025+{
4026+ BUG_ON(!sb || index < 0);
4027+ return UNIONFS_SB(sb)->data[index].branch_id;
4028+}
4029+
4030+static inline void set_branch_id(struct super_block *sb, int index, int val)
4031+{
4032+ BUG_ON(!sb || index < 0);
4033+ UNIONFS_SB(sb)->data[index].branch_id = val;
4034+}
4035+
4036+static inline void new_branch_id(struct super_block *sb, int index)
4037+{
4038+ BUG_ON(!sb || index < 0);
4039+ set_branch_id(sb, index, ++UNIONFS_SB(sb)->high_branch_id);
4040+}
4041+
4042+/*
4043+ * Find new index of matching branch with an existing superblock of a known
4044+ * (possibly old) id. This is needed because branches could have been
4045+ * added/deleted causing the branches of any open files to shift.
4046+ *
4047+ * @sb: the new superblock which may have new/different branch IDs
4048+ * @id: the old/existing id we're looking for
4049+ * Returns index of newly found branch (0 or greater), -1 otherwise.
4050+ */
4051+static inline int branch_id_to_idx(struct super_block *sb, int id)
4052+{
4053+ int i;
4054+ for (i = 0; i < sbmax(sb); i++) {
4055+ if (branch_id(sb, i) == id)
4056+ return i;
4057+ }
4058+ /* in the non-ODF code, this should really never happen */
4059+ printk(KERN_WARNING "unionfs: cannot find branch with id %d\n", id);
4060+ return -1;
4061+}
4062+
4063+/* File to lower file. */
4064+static inline struct file *unionfs_lower_file(const struct file *f)
4065+{
4066+ BUG_ON(!f);
4067+ return UNIONFS_F(f)->lower_files[fbstart(f)];
4068+}
4069+
4070+static inline struct file *unionfs_lower_file_idx(const struct file *f,
4071+ int index)
4072+{
4073+ BUG_ON(!f || index < 0);
4074+ return UNIONFS_F(f)->lower_files[index];
4075+}
4076+
4077+static inline void unionfs_set_lower_file_idx(struct file *f, int index,
4078+ struct file *val)
4079+{
4080+ BUG_ON(!f || index < 0);
4081+ UNIONFS_F(f)->lower_files[index] = val;
4082+ /* save branch ID (may be redundant?) */
4083+ UNIONFS_F(f)->saved_branch_ids[index] =
4084+ branch_id((f)->f_path.dentry->d_sb, index);
4085+}
4086+
4087+static inline void unionfs_set_lower_file(struct file *f, struct file *val)
4088+{
4089+ BUG_ON(!f);
4090+ unionfs_set_lower_file_idx((f), fbstart(f), (val));
4091+}
4092+
4093+/* Inode to lower inode. */
4094+static inline struct inode *unionfs_lower_inode(const struct inode *i)
4095+{
4096+ BUG_ON(!i);
4097+ return UNIONFS_I(i)->lower_inodes[ibstart(i)];
4098+}
4099+
4100+static inline struct inode *unionfs_lower_inode_idx(const struct inode *i,
4101+ int index)
4102+{
4103+ BUG_ON(!i || index < 0);
4104+ return UNIONFS_I(i)->lower_inodes[index];
4105+}
4106+
4107+static inline void unionfs_set_lower_inode_idx(struct inode *i, int index,
4108+ struct inode *val)
4109+{
4110+ BUG_ON(!i || index < 0);
4111+ UNIONFS_I(i)->lower_inodes[index] = val;
4112+}
4113+
4114+static inline void unionfs_set_lower_inode(struct inode *i, struct inode *val)
4115+{
4116+ BUG_ON(!i);
4117+ UNIONFS_I(i)->lower_inodes[ibstart(i)] = val;
4118+}
4119+
4120+/* Superblock to lower superblock. */
4121+static inline struct super_block *unionfs_lower_super(
4122+ const struct super_block *sb)
4123+{
4124+ BUG_ON(!sb);
4125+ return UNIONFS_SB(sb)->data[sbstart(sb)].sb;
4126+}
4127+
4128+static inline struct super_block *unionfs_lower_super_idx(
4129+ const struct super_block *sb,
4130+ int index)
4131+{
4132+ BUG_ON(!sb || index < 0);
4133+ return UNIONFS_SB(sb)->data[index].sb;
4134+}
4135+
4136+static inline void unionfs_set_lower_super_idx(struct super_block *sb,
4137+ int index,
4138+ struct super_block *val)
4139+{
4140+ BUG_ON(!sb || index < 0);
4141+ UNIONFS_SB(sb)->data[index].sb = val;
4142+}
4143+
4144+static inline void unionfs_set_lower_super(struct super_block *sb,
4145+ struct super_block *val)
4146+{
4147+ BUG_ON(!sb);
4148+ UNIONFS_SB(sb)->data[sbstart(sb)].sb = val;
4149+}
4150+
4151+/* Branch count macros. */
4152+static inline int branch_count(const struct super_block *sb, int index)
4153+{
4154+ BUG_ON(!sb || index < 0);
4155+ return atomic_read(&UNIONFS_SB(sb)->data[index].open_files);
4156+}
4157+
4158+static inline void set_branch_count(struct super_block *sb, int index, int val)
4159+{
4160+ BUG_ON(!sb || index < 0);
4161+ atomic_set(&UNIONFS_SB(sb)->data[index].open_files, val);
4162+}
4163+
4164+static inline void branchget(struct super_block *sb, int index)
4165+{
4166+ BUG_ON(!sb || index < 0);
4167+ atomic_inc(&UNIONFS_SB(sb)->data[index].open_files);
4168+}
4169+
4170+static inline void branchput(struct super_block *sb, int index)
4171+{
4172+ BUG_ON(!sb || index < 0);
4173+ atomic_dec(&UNIONFS_SB(sb)->data[index].open_files);
4174+}
4175+
4176+/* Dentry macros */
4177+static inline void unionfs_set_lower_dentry_idx(struct dentry *dent, int index,
4178+ struct dentry *val)
4179+{
4180+ BUG_ON(!dent || index < 0);
4181+ UNIONFS_D(dent)->lower_paths[index].dentry = val;
4182+}
4183+
4184+static inline struct dentry *unionfs_lower_dentry_idx(
4185+ const struct dentry *dent,
4186+ int index)
4187+{
4188+ BUG_ON(!dent || index < 0);
4189+ return UNIONFS_D(dent)->lower_paths[index].dentry;
4190+}
4191+
4192+static inline struct dentry *unionfs_lower_dentry(const struct dentry *dent)
4193+{
4194+ BUG_ON(!dent);
4195+ return unionfs_lower_dentry_idx(dent, dbstart(dent));
4196+}
4197+
4198+static inline void unionfs_set_lower_mnt_idx(struct dentry *dent, int index,
4199+ struct vfsmount *mnt)
4200+{
4201+ BUG_ON(!dent || index < 0);
4202+ UNIONFS_D(dent)->lower_paths[index].mnt = mnt;
4203+}
4204+
4205+static inline struct vfsmount *unionfs_lower_mnt_idx(
4206+ const struct dentry *dent,
4207+ int index)
4208+{
4209+ BUG_ON(!dent || index < 0);
4210+ return UNIONFS_D(dent)->lower_paths[index].mnt;
4211+}
4212+
4213+static inline struct vfsmount *unionfs_lower_mnt(const struct dentry *dent)
4214+{
4215+ BUG_ON(!dent);
4216+ return unionfs_lower_mnt_idx(dent, dbstart(dent));
4217+}
4218+
4219+/* Macros for locking a dentry. */
4220+enum unionfs_dentry_lock_class {
4221+ UNIONFS_DMUTEX_NORMAL,
4222+ UNIONFS_DMUTEX_ROOT,
4223+ UNIONFS_DMUTEX_PARENT,
4224+ UNIONFS_DMUTEX_CHILD,
4225+ UNIONFS_DMUTEX_WHITEOUT,
4226+ UNIONFS_DMUTEX_REVAL_PARENT, /* for file/dentry revalidate */
4227+ UNIONFS_DMUTEX_REVAL_CHILD, /* for file/dentry revalidate */
4228+};
4229+
4230+static inline void unionfs_lock_dentry(struct dentry *d,
4231+ unsigned int subclass)
4232+{
4233+ BUG_ON(!d);
4234+ mutex_lock_nested(&UNIONFS_D(d)->lock, subclass);
4235+}
4236+
4237+static inline void unionfs_unlock_dentry(struct dentry *d)
4238+{
4239+ BUG_ON(!d);
4240+ mutex_unlock(&UNIONFS_D(d)->lock);
4241+}
4242+
4243+static inline struct dentry *unionfs_lock_parent(struct dentry *d,
4244+ unsigned int subclass)
4245+{
4246+ struct dentry *p;
4247+
4248+ BUG_ON(!d);
4249+ p = dget_parent(d);
4250+ if (p != d)
4251+ mutex_lock_nested(&UNIONFS_D(p)->lock, subclass);
4252+ return p;
4253+}
4254+
4255+static inline void unionfs_unlock_parent(struct dentry *d, struct dentry *p)
4256+{
4257+ BUG_ON(!d);
4258+ BUG_ON(!p);
4259+ if (p != d) {
4260+ BUG_ON(!mutex_is_locked(&UNIONFS_D(p)->lock));
4261+ mutex_unlock(&UNIONFS_D(p)->lock);
4262+ }
4263+ dput(p);
4264+}
4265+
4266+static inline void verify_locked(struct dentry *d)
4267+{
4268+ BUG_ON(!d);
4269+ BUG_ON(!mutex_is_locked(&UNIONFS_D(d)->lock));
4270+}
4271+
4272+/* macros to put lower objects */
4273+
4274+/*
4275+ * iput lower inodes of an unionfs dentry, from bstart to bend. If
4276+ * @free_lower is true, then also kfree the memory used to hold the lower
4277+ * object pointers.
4278+ */
4279+static inline void iput_lowers(struct inode *inode,
4280+ int bstart, int bend, bool free_lower)
4281+{
4282+ struct inode *lower_inode;
4283+ int bindex;
4284+
4285+ BUG_ON(!inode);
4286+ BUG_ON(!UNIONFS_I(inode));
4287+ BUG_ON(bstart < 0);
4288+
4289+ for (bindex = bstart; bindex <= bend; bindex++) {
4290+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
4291+ if (lower_inode) {
4292+ unionfs_set_lower_inode_idx(inode, bindex, NULL);
4293+ /* see Documentation/filesystems/unionfs/issues.txt */
4294+ lockdep_off();
4295+ iput(lower_inode);
4296+ lockdep_on();
4297+ }
4298+ }
4299+
4300+ if (free_lower) {
4301+ kfree(UNIONFS_I(inode)->lower_inodes);
4302+ UNIONFS_I(inode)->lower_inodes = NULL;
4303+ }
4304+}
4305+
4306+/* iput all lower inodes, and reset start/end branch indices to -1 */
4307+static inline void iput_lowers_all(struct inode *inode, bool free_lower)
4308+{
4309+ int bstart, bend;
4310+
4311+ BUG_ON(!inode);
4312+ BUG_ON(!UNIONFS_I(inode));
4313+ bstart = ibstart(inode);
4314+ bend = ibend(inode);
4315+ BUG_ON(bstart < 0);
4316+
4317+ iput_lowers(inode, bstart, bend, free_lower);
4318+ ibstart(inode) = ibend(inode) = -1;
4319+}
4320+
4321+/*
4322+ * dput/mntput all lower dentries and vfsmounts of an unionfs dentry, from
4323+ * bstart to bend. If @free_lower is true, then also kfree the memory used
4324+ * to hold the lower object pointers.
4325+ *
4326+ * XXX: implement using path_put VFS macros
4327+ */
4328+static inline void path_put_lowers(struct dentry *dentry,
4329+ int bstart, int bend, bool free_lower)
4330+{
4331+ struct dentry *lower_dentry;
4332+ struct vfsmount *lower_mnt;
4333+ int bindex;
4334+
4335+ BUG_ON(!dentry);
4336+ BUG_ON(!UNIONFS_D(dentry));
4337+ BUG_ON(bstart < 0);
4338+
4339+ for (bindex = bstart; bindex <= bend; bindex++) {
4340+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
4341+ if (lower_dentry) {
4342+ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
4343+ dput(lower_dentry);
4344+ }
4345+ lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
4346+ if (lower_mnt) {
4347+ unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
4348+ mntput(lower_mnt);
4349+ }
4350+ }
4351+
4352+ if (free_lower) {
4353+ kfree(UNIONFS_D(dentry)->lower_paths);
4354+ UNIONFS_D(dentry)->lower_paths = NULL;
4355+ }
4356+}
4357+
4358+/*
4359+ * dput/mntput all lower dentries and vfsmounts, and reset start/end branch
4360+ * indices to -1.
4361+ */
4362+static inline void path_put_lowers_all(struct dentry *dentry, bool free_lower)
4363+{
4364+ int bstart, bend;
4365+
4366+ BUG_ON(!dentry);
4367+ BUG_ON(!UNIONFS_D(dentry));
4368+ bstart = dbstart(dentry);
4369+ bend = dbend(dentry);
4370+ BUG_ON(bstart < 0);
4371+
4372+ path_put_lowers(dentry, bstart, bend, free_lower);
4373+ dbstart(dentry) = dbend(dentry) = -1;
4374+}
4375+
4376+#endif /* not _FANOUT_H */
4377diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
4378new file mode 100644
4379index 0000000..5a8f4e0
4380--- /dev/null
4381+++ b/fs/unionfs/file.c
4382@@ -0,0 +1,379 @@
4383+/*
4384+ * Copyright (c) 2003-2010 Erez Zadok
4385+ * Copyright (c) 2003-2006 Charles P. Wright
4386+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
4387+ * Copyright (c) 2005-2006 Junjiro Okajima
4388+ * Copyright (c) 2005 Arun M. Krishnakumar
4389+ * Copyright (c) 2004-2006 David P. Quigley
4390+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
4391+ * Copyright (c) 2003 Puja Gupta
4392+ * Copyright (c) 2003 Harikesavan Krishnan
4393+ * Copyright (c) 2003-2010 Stony Brook University
4394+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
4395+ *
4396+ * This program is free software; you can redistribute it and/or modify
4397+ * it under the terms of the GNU General Public License version 2 as
4398+ * published by the Free Software Foundation.
4399+ */
4400+
4401+#include "union.h"
4402+
4403+static ssize_t unionfs_read(struct file *file, char __user *buf,
4404+ size_t count, loff_t *ppos)
4405+{
4406+ int err;
4407+ struct file *lower_file;
4408+ struct dentry *dentry = file->f_path.dentry;
4409+ struct dentry *parent;
4410+
4411+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
4412+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
4413+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
4414+
4415+ err = unionfs_file_revalidate(file, parent, false);
4416+ if (unlikely(err))
4417+ goto out;
4418+
4419+ lower_file = unionfs_lower_file(file);
4420+ err = vfs_read(lower_file, buf, count, ppos);
4421+ /* update our inode atime upon a successful lower read */
4422+ if (err >= 0) {
4423+ fsstack_copy_attr_atime(dentry->d_inode,
4424+ lower_file->f_path.dentry->d_inode);
4425+ unionfs_check_file(file);
4426+ }
4427+
4428+out:
4429+ unionfs_unlock_dentry(dentry);
4430+ unionfs_unlock_parent(dentry, parent);
4431+ unionfs_read_unlock(dentry->d_sb);
4432+ return err;
4433+}
4434+
4435+static ssize_t unionfs_write(struct file *file, const char __user *buf,
4436+ size_t count, loff_t *ppos)
4437+{
4438+ int err = 0;
4439+ struct file *lower_file;
4440+ struct dentry *dentry = file->f_path.dentry;
4441+ struct dentry *parent;
4442+
4443+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
4444+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
4445+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
4446+
4447+ err = unionfs_file_revalidate(file, parent, true);
4448+ if (unlikely(err))
4449+ goto out;
4450+
4451+ lower_file = unionfs_lower_file(file);
4452+ err = vfs_write(lower_file, buf, count, ppos);
4453+ /* update our inode times+sizes upon a successful lower write */
4454+ if (err >= 0) {
4455+ fsstack_copy_inode_size(dentry->d_inode,
4456+ lower_file->f_path.dentry->d_inode);
4457+ fsstack_copy_attr_times(dentry->d_inode,
4458+ lower_file->f_path.dentry->d_inode);
4459+ UNIONFS_F(file)->wrote_to_file = true; /* for delayed copyup */
4460+ unionfs_check_file(file);
4461+ }
4462+
4463+out:
4464+ unionfs_unlock_dentry(dentry);
4465+ unionfs_unlock_parent(dentry, parent);
4466+ unionfs_read_unlock(dentry->d_sb);
4467+ return err;
4468+}
4469+
4470+static int unionfs_file_readdir(struct file *file, void *dirent,
4471+ filldir_t filldir)
4472+{
4473+ return -ENOTDIR;
4474+}
4475+
4476+static int unionfs_mmap(struct file *file, struct vm_area_struct *vma)
4477+{
4478+ int err = 0;
4479+ bool willwrite;
4480+ struct file *lower_file;
4481+ struct dentry *dentry = file->f_path.dentry;
4482+ struct dentry *parent;
4483+ const struct vm_operations_struct *saved_vm_ops = NULL;
4484+
4485+ /*
4486+ * Since mm/memory.c:might_fault() (under PROVE_LOCKING) was
4487+ * modified in 2.6.29-rc1 to call might_lock_read on mmap_sem, this
4488+ * has been causing false positives in file system stacking layers.
4489+ * In particular, our ->mmap is called after sys_mmap2 already holds
4490+ * mmap_sem, then we lock our own mutexes; but earlier, it's
4491+ * possible for lockdep to have locked our mutexes first, and then
4492+ * we call a lower ->readdir which could call might_fault. The
4493+ * different ordering of the locks is what lockdep complains about
4494+ * -- unnecessarily. Therefore, we have no choice but to tell
4495+ * lockdep to temporarily turn off lockdep here. Note: the comments
4496+ * inside might_sleep also suggest that it would have been
4497+ * nicer to only annotate paths that needs that might_lock_read.
4498+ */
4499+ lockdep_off();
4500+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
4501+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
4502+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
4503+
4504+ /* This might be deferred to mmap's writepage */
4505+ willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
4506+ err = unionfs_file_revalidate(file, parent, willwrite);
4507+ if (unlikely(err))
4508+ goto out;
4509+ unionfs_check_file(file);
4510+
4511+ /*
4512+ * File systems which do not implement ->writepage may use
4513+ * generic_file_readonly_mmap as their ->mmap op. If you call
4514+ * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL.
4515+ * But we cannot call the lower ->mmap op, so we can't tell that
4516+ * writeable mappings won't work. Therefore, our only choice is to
4517+ * check if the lower file system supports the ->writepage, and if
4518+ * not, return EINVAL (the same error that
4519+ * generic_file_readonly_mmap returns in that case).
4520+ */
4521+ lower_file = unionfs_lower_file(file);
4522+ if (willwrite && !lower_file->f_mapping->a_ops->writepage) {
4523+ err = -EINVAL;
4524+ printk(KERN_ERR "unionfs: branch %d file system does not "
4525+ "support writeable mmap\n", fbstart(file));
4526+ goto out;
4527+ }
4528+
4529+ /*
4530+ * find and save lower vm_ops.
4531+ *
4532+ * XXX: the VFS should have a cleaner way of finding the lower vm_ops
4533+ */
4534+ if (!UNIONFS_F(file)->lower_vm_ops) {
4535+ err = lower_file->f_op->mmap(lower_file, vma);
4536+ if (err) {
4537+ printk(KERN_ERR "unionfs: lower mmap failed %d\n", err);
4538+ goto out;
4539+ }
4540+ saved_vm_ops = vma->vm_ops;
4541+ err = do_munmap(current->mm, vma->vm_start,
4542+ vma->vm_end - vma->vm_start);
4543+ if (err) {
4544+ printk(KERN_ERR "unionfs: do_munmap failed %d\n", err);
4545+ goto out;
4546+ }
4547+ }
4548+
4549+ file->f_mapping->a_ops = &unionfs_dummy_aops;
4550+ err = generic_file_mmap(file, vma);
4551+ file->f_mapping->a_ops = &unionfs_aops;
4552+ if (err) {
4553+ printk(KERN_ERR "unionfs: generic_file_mmap failed %d\n", err);
4554+ goto out;
4555+ }
4556+ vma->vm_ops = &unionfs_vm_ops;
4557+ if (!UNIONFS_F(file)->lower_vm_ops)
4558+ UNIONFS_F(file)->lower_vm_ops = saved_vm_ops;
4559+
4560+out:
4561+ if (!err) {
4562+ /* copyup could cause parent dir times to change */
4563+ unionfs_copy_attr_times(parent->d_inode);
4564+ unionfs_check_file(file);
4565+ }
4566+ unionfs_unlock_dentry(dentry);
4567+ unionfs_unlock_parent(dentry, parent);
4568+ unionfs_read_unlock(dentry->d_sb);
4569+ lockdep_on();
4570+ return err;
4571+}
4572+
4573+int unionfs_fsync(struct file *file, int datasync)
4574+{
4575+ int bindex, bstart, bend;
4576+ struct file *lower_file;
4577+ struct dentry *dentry = file->f_path.dentry;
4578+ struct dentry *lower_dentry;
4579+ struct dentry *parent;
4580+ struct inode *lower_inode, *inode;
4581+ int err = -EINVAL;
4582+
4583+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
4584+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
4585+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
4586+
4587+ err = unionfs_file_revalidate(file, parent, true);
4588+ if (unlikely(err))
4589+ goto out;
4590+ unionfs_check_file(file);
4591+
4592+ bstart = fbstart(file);
4593+ bend = fbend(file);
4594+ if (bstart < 0 || bend < 0)
4595+ goto out;
4596+
4597+ inode = dentry->d_inode;
4598+ if (unlikely(!inode)) {
4599+ printk(KERN_ERR
4600+ "unionfs: null lower inode in unionfs_fsync\n");
4601+ goto out;
4602+ }
4603+ for (bindex = bstart; bindex <= bend; bindex++) {
4604+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
4605+ if (!lower_inode || !lower_inode->i_fop->fsync)
4606+ continue;
4607+ lower_file = unionfs_lower_file_idx(file, bindex);
4608+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
4609+ mutex_lock(&lower_inode->i_mutex);
4610+ err = lower_inode->i_fop->fsync(lower_file, datasync);
4611+ if (!err && bindex == bstart)
4612+ fsstack_copy_attr_times(inode, lower_inode);
4613+ mutex_unlock(&lower_inode->i_mutex);
4614+ if (err)
4615+ goto out;
4616+ }
4617+
4618+out:
4619+ if (!err)
4620+ unionfs_check_file(file);
4621+ unionfs_unlock_dentry(dentry);
4622+ unionfs_unlock_parent(dentry, parent);
4623+ unionfs_read_unlock(dentry->d_sb);
4624+ return err;
4625+}
4626+
4627+int unionfs_fasync(int fd, struct file *file, int flag)
4628+{
4629+ int bindex, bstart, bend;
4630+ struct file *lower_file;
4631+ struct dentry *dentry = file->f_path.dentry;
4632+ struct dentry *parent;
4633+ struct inode *lower_inode, *inode;
4634+ int err = 0;
4635+
4636+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
4637+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
4638+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
4639+
4640+ err = unionfs_file_revalidate(file, parent, true);
4641+ if (unlikely(err))
4642+ goto out;
4643+ unionfs_check_file(file);
4644+
4645+ bstart = fbstart(file);
4646+ bend = fbend(file);
4647+ if (bstart < 0 || bend < 0)
4648+ goto out;
4649+
4650+ inode = dentry->d_inode;
4651+ if (unlikely(!inode)) {
4652+ printk(KERN_ERR
4653+ "unionfs: null lower inode in unionfs_fasync\n");
4654+ goto out;
4655+ }
4656+ for (bindex = bstart; bindex <= bend; bindex++) {
4657+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
4658+ if (!lower_inode || !lower_inode->i_fop->fasync)
4659+ continue;
4660+ lower_file = unionfs_lower_file_idx(file, bindex);
4661+ mutex_lock(&lower_inode->i_mutex);
4662+ err = lower_inode->i_fop->fasync(fd, lower_file, flag);
4663+ if (!err && bindex == bstart)
4664+ fsstack_copy_attr_times(inode, lower_inode);
4665+ mutex_unlock(&lower_inode->i_mutex);
4666+ if (err)
4667+ goto out;
4668+ }
4669+
4670+out:
4671+ if (!err)
4672+ unionfs_check_file(file);
4673+ unionfs_unlock_dentry(dentry);
4674+ unionfs_unlock_parent(dentry, parent);
4675+ unionfs_read_unlock(dentry->d_sb);
4676+ return err;
4677+}
4678+
4679+static ssize_t unionfs_splice_read(struct file *file, loff_t *ppos,
4680+ struct pipe_inode_info *pipe, size_t len,
4681+ unsigned int flags)
4682+{
4683+ ssize_t err;
4684+ struct file *lower_file;
4685+ struct dentry *dentry = file->f_path.dentry;
4686+ struct dentry *parent;
4687+
4688+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
4689+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
4690+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
4691+
4692+ err = unionfs_file_revalidate(file, parent, false);
4693+ if (unlikely(err))
4694+ goto out;
4695+
4696+ lower_file = unionfs_lower_file(file);
4697+ err = vfs_splice_to(lower_file, ppos, pipe, len, flags);
4698+ /* update our inode atime upon a successful lower splice-read */
4699+ if (err >= 0) {
4700+ fsstack_copy_attr_atime(dentry->d_inode,
4701+ lower_file->f_path.dentry->d_inode);
4702+ unionfs_check_file(file);
4703+ }
4704+
4705+out:
4706+ unionfs_unlock_dentry(dentry);
4707+ unionfs_unlock_parent(dentry, parent);
4708+ unionfs_read_unlock(dentry->d_sb);
4709+ return err;
4710+}
4711+
4712+static ssize_t unionfs_splice_write(struct pipe_inode_info *pipe,
4713+ struct file *file, loff_t *ppos,
4714+ size_t len, unsigned int flags)
4715+{
4716+ ssize_t err = 0;
4717+ struct file *lower_file;
4718+ struct dentry *dentry = file->f_path.dentry;
4719+ struct dentry *parent;
4720+
4721+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
4722+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
4723+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
4724+
4725+ err = unionfs_file_revalidate(file, parent, true);
4726+ if (unlikely(err))
4727+ goto out;
4728+
4729+ lower_file = unionfs_lower_file(file);
4730+ err = vfs_splice_from(pipe, lower_file, ppos, len, flags);
4731+ /* update our inode times+sizes upon a successful lower write */
4732+ if (err >= 0) {
4733+ fsstack_copy_inode_size(dentry->d_inode,
4734+ lower_file->f_path.dentry->d_inode);
4735+ fsstack_copy_attr_times(dentry->d_inode,
4736+ lower_file->f_path.dentry->d_inode);
4737+ unionfs_check_file(file);
4738+ }
4739+
4740+out:
4741+ unionfs_unlock_dentry(dentry);
4742+ unionfs_unlock_parent(dentry, parent);
4743+ unionfs_read_unlock(dentry->d_sb);
4744+ return err;
4745+}
4746+
4747+struct file_operations unionfs_main_fops = {
4748+ .llseek = generic_file_llseek,
4749+ .read = unionfs_read,
4750+ .write = unionfs_write,
4751+ .readdir = unionfs_file_readdir,
4752+ .unlocked_ioctl = unionfs_ioctl,
4753+ .mmap = unionfs_mmap,
4754+ .open = unionfs_open,
4755+ .flush = unionfs_flush,
4756+ .release = unionfs_file_release,
4757+ .fsync = unionfs_fsync,
4758+ .fasync = unionfs_fasync,
4759+ .splice_read = unionfs_splice_read,
4760+ .splice_write = unionfs_splice_write,
4761+};
4762diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
4763new file mode 100644
4764index 0000000..4c36f16
4765--- /dev/null
4766+++ b/fs/unionfs/inode.c
4767@@ -0,0 +1,1061 @@
4768+/*
4769+ * Copyright (c) 2003-2010 Erez Zadok
4770+ * Copyright (c) 2003-2006 Charles P. Wright
4771+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
4772+ * Copyright (c) 2005-2006 Junjiro Okajima
4773+ * Copyright (c) 2005 Arun M. Krishnakumar
4774+ * Copyright (c) 2004-2006 David P. Quigley
4775+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
4776+ * Copyright (c) 2003 Puja Gupta
4777+ * Copyright (c) 2003 Harikesavan Krishnan
4778+ * Copyright (c) 2003-2010 Stony Brook University
4779+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
4780+ *
4781+ * This program is free software; you can redistribute it and/or modify
4782+ * it under the terms of the GNU General Public License version 2 as
4783+ * published by the Free Software Foundation.
4784+ */
4785+
4786+#include "union.h"
4787+
4788+/*
4789+ * Find a writeable branch to create new object in. Checks all writeble
4790+ * branches of the parent inode, from istart to iend order; if none are
4791+ * suitable, also tries branch 0 (which may require a copyup).
4792+ *
4793+ * Return a lower_dentry we can use to create object in, or ERR_PTR.
4794+ */
4795+static struct dentry *find_writeable_branch(struct inode *parent,
4796+ struct dentry *dentry)
4797+{
4798+ int err = -EINVAL;
4799+ int bindex, istart, iend;
4800+ struct dentry *lower_dentry = NULL;
4801+
4802+ istart = ibstart(parent);
4803+ iend = ibend(parent);
4804+ if (istart < 0)
4805+ goto out;
4806+
4807+begin:
4808+ for (bindex = istart; bindex <= iend; bindex++) {
4809+ /* skip non-writeable branches */
4810+ err = is_robranch_super(dentry->d_sb, bindex);
4811+ if (err) {
4812+ err = -EROFS;
4813+ continue;
4814+ }
4815+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
4816+ if (!lower_dentry)
4817+ continue;
4818+ /*
4819+ * check for whiteouts in writeable branch, and remove them
4820+ * if necessary.
4821+ */
4822+ err = check_unlink_whiteout(dentry, lower_dentry, bindex);
4823+ if (err > 0) /* ignore if whiteout found and removed */
4824+ err = 0;
4825+ if (err)
4826+ continue;
4827+ /* if get here, we can write to the branch */
4828+ break;
4829+ }
4830+ /*
4831+ * If istart wasn't already branch 0, and we got any error, then try
4832+ * branch 0 (which may require copyup)
4833+ */
4834+ if (err && istart > 0) {
4835+ istart = iend = 0;
4836+ goto begin;
4837+ }
4838+
4839+ /*
4840+ * If we tried even branch 0, and still got an error, abort. But if
4841+ * the error was an EROFS, then we should try to copyup.
4842+ */
4843+ if (err && err != -EROFS)
4844+ goto out;
4845+
4846+ /*
4847+ * If we get here, then check if copyup needed. If lower_dentry is
4848+ * NULL, create the entire dentry directory structure in branch 0.
4849+ */
4850+ if (!lower_dentry) {
4851+ bindex = 0;
4852+ lower_dentry = create_parents(parent, dentry,
4853+ dentry->d_name.name, bindex);
4854+ if (IS_ERR(lower_dentry)) {
4855+ err = PTR_ERR(lower_dentry);
4856+ goto out;
4857+ }
4858+ }
4859+ err = 0; /* all's well */
4860+out:
4861+ if (err)
4862+ return ERR_PTR(err);
4863+ return lower_dentry;
4864+}
4865+
4866+static int unionfs_create(struct inode *dir, struct dentry *dentry,
4867+ int mode, struct nameidata *nd_unused)
4868+{
4869+ int err = 0;
4870+ struct dentry *lower_dentry = NULL;
4871+ struct dentry *lower_parent_dentry = NULL;
4872+ struct dentry *parent;
4873+ int valid = 0;
4874+ struct nameidata lower_nd;
4875+
4876+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
4877+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
4878+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
4879+
4880+ valid = __unionfs_d_revalidate(dentry, parent, false);
4881+ if (unlikely(!valid)) {
4882+ err = -ESTALE; /* same as what real_lookup does */
4883+ goto out;
4884+ }
4885+
4886+ lower_dentry = find_writeable_branch(dir, dentry);
4887+ if (IS_ERR(lower_dentry)) {
4888+ err = PTR_ERR(lower_dentry);
4889+ goto out;
4890+ }
4891+
4892+ lower_parent_dentry = lock_parent(lower_dentry);
4893+ if (IS_ERR(lower_parent_dentry)) {
4894+ err = PTR_ERR(lower_parent_dentry);
4895+ goto out_unlock;
4896+ }
4897+
4898+ err = init_lower_nd(&lower_nd, LOOKUP_CREATE);
4899+ if (unlikely(err < 0))
4900+ goto out_unlock;
4901+ err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode,
4902+ &lower_nd);
4903+ release_lower_nd(&lower_nd, err);
4904+
4905+ if (!err) {
4906+ err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
4907+ if (!err) {
4908+ unionfs_copy_attr_times(dir);
4909+ fsstack_copy_inode_size(dir,
4910+ lower_parent_dentry->d_inode);
4911+ /* update no. of links on parent directory */
4912+ dir->i_nlink = unionfs_get_nlinks(dir);
4913+ }
4914+ }
4915+
4916+out_unlock:
4917+ unlock_dir(lower_parent_dentry);
4918+out:
4919+ if (!err) {
4920+ unionfs_postcopyup_setmnt(dentry);
4921+ unionfs_check_inode(dir);
4922+ unionfs_check_dentry(dentry);
4923+ }
4924+ unionfs_unlock_dentry(dentry);
4925+ unionfs_unlock_parent(dentry, parent);
4926+ unionfs_read_unlock(dentry->d_sb);
4927+ return err;
4928+}
4929+
4930+/*
4931+ * unionfs_lookup is the only special function which takes a dentry, yet we
4932+ * do NOT want to call __unionfs_d_revalidate_chain because by definition,
4933+ * we don't have a valid dentry here yet.
4934+ */
4935+static struct dentry *unionfs_lookup(struct inode *dir,
4936+ struct dentry *dentry,
4937+ struct nameidata *nd_unused)
4938+{
4939+ struct dentry *ret, *parent;
4940+ int err = 0;
4941+
4942+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
4943+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
4944+
4945+ /*
4946+ * As long as we lock/dget the parent, then can skip validating the
4947+ * parent now; we may have to rebuild this dentry on the next
4948+ * ->d_revalidate, however.
4949+ */
4950+
4951+ /* allocate dentry private data. We free it in ->d_release */
4952+ err = new_dentry_private_data(dentry, UNIONFS_DMUTEX_CHILD);
4953+ if (unlikely(err)) {
4954+ ret = ERR_PTR(err);
4955+ goto out;
4956+ }
4957+
4958+ ret = unionfs_lookup_full(dentry, parent, INTERPOSE_LOOKUP);
4959+
4960+ if (!IS_ERR(ret)) {
4961+ if (ret)
4962+ dentry = ret;
4963+ /* lookup_full can return multiple positive dentries */
4964+ if (dentry->d_inode && !S_ISDIR(dentry->d_inode->i_mode)) {
4965+ BUG_ON(dbstart(dentry) < 0);
4966+ unionfs_postcopyup_release(dentry);
4967+ }
4968+ unionfs_copy_attr_times(dentry->d_inode);
4969+ }
4970+
4971+ unionfs_check_inode(dir);
4972+ if (!IS_ERR(ret))
4973+ unionfs_check_dentry(dentry);
4974+ unionfs_check_dentry(parent);
4975+ unionfs_unlock_dentry(dentry); /* locked in new_dentry_private data */
4976+
4977+out:
4978+ unionfs_unlock_parent(dentry, parent);
4979+ unionfs_read_unlock(dentry->d_sb);
4980+
4981+ return ret;
4982+}
4983+
4984+static int unionfs_link(struct dentry *old_dentry, struct inode *dir,
4985+ struct dentry *new_dentry)
4986+{
4987+ int err = 0;
4988+ struct dentry *lower_old_dentry = NULL;
4989+ struct dentry *lower_new_dentry = NULL;
4990+ struct dentry *lower_dir_dentry = NULL;
4991+ struct dentry *old_parent, *new_parent;
4992+ char *name = NULL;
4993+ bool valid;
4994+
4995+ unionfs_read_lock(old_dentry->d_sb, UNIONFS_SMUTEX_CHILD);
4996+ old_parent = dget_parent(old_dentry);
4997+ new_parent = dget_parent(new_dentry);
4998+ unionfs_double_lock_parents(old_parent, new_parent);
4999+ unionfs_double_lock_dentry(old_dentry, new_dentry);
5000+
5001+ valid = __unionfs_d_revalidate(old_dentry, old_parent, false);
5002+ if (unlikely(!valid)) {
5003+ err = -ESTALE;
5004+ goto out;
5005+ }
5006+ if (new_dentry->d_inode) {
5007+ valid = __unionfs_d_revalidate(new_dentry, new_parent, false);
5008+ if (unlikely(!valid)) {
5009+ err = -ESTALE;
5010+ goto out;
5011+ }
5012+ }
5013+
5014+ lower_new_dentry = unionfs_lower_dentry(new_dentry);
5015+
5016+ /* check for a whiteout in new dentry branch, and delete it */
5017+ err = check_unlink_whiteout(new_dentry, lower_new_dentry,
5018+ dbstart(new_dentry));
5019+ if (err > 0) { /* whiteout found and removed successfully */
5020+ lower_dir_dentry = dget_parent(lower_new_dentry);
5021+ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
5022+ dput(lower_dir_dentry);
5023+ dir->i_nlink = unionfs_get_nlinks(dir);
5024+ err = 0;
5025+ }
5026+ if (err)
5027+ goto out;
5028+
5029+ /* check if parent hierachy is needed, then link in same branch */
5030+ if (dbstart(old_dentry) != dbstart(new_dentry)) {
5031+ lower_new_dentry = create_parents(dir, new_dentry,
5032+ new_dentry->d_name.name,
5033+ dbstart(old_dentry));
5034+ err = PTR_ERR(lower_new_dentry);
5035+ if (IS_COPYUP_ERR(err))
5036+ goto docopyup;
5037+ if (!lower_new_dentry || IS_ERR(lower_new_dentry))
5038+ goto out;
5039+ }
5040+ lower_new_dentry = unionfs_lower_dentry(new_dentry);
5041+ lower_old_dentry = unionfs_lower_dentry(old_dentry);
5042+
5043+ BUG_ON(dbstart(old_dentry) != dbstart(new_dentry));
5044+ lower_dir_dentry = lock_parent(lower_new_dentry);
5045+ err = is_robranch(old_dentry);
5046+ if (!err) {
5047+ /* see Documentation/filesystems/unionfs/issues.txt */
5048+ lockdep_off();
5049+ err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
5050+ lower_new_dentry);
5051+ lockdep_on();
5052+ }
5053+ unlock_dir(lower_dir_dentry);
5054+
5055+docopyup:
5056+ if (IS_COPYUP_ERR(err)) {
5057+ int old_bstart = dbstart(old_dentry);
5058+ int bindex;
5059+
5060+ for (bindex = old_bstart - 1; bindex >= 0; bindex--) {
5061+ err = copyup_dentry(old_parent->d_inode,
5062+ old_dentry, old_bstart,
5063+ bindex, old_dentry->d_name.name,
5064+ old_dentry->d_name.len, NULL,
5065+ i_size_read(old_dentry->d_inode));
5066+ if (err)
5067+ continue;
5068+ lower_new_dentry =
5069+ create_parents(dir, new_dentry,
5070+ new_dentry->d_name.name,
5071+ bindex);
5072+ lower_old_dentry = unionfs_lower_dentry(old_dentry);
5073+ lower_dir_dentry = lock_parent(lower_new_dentry);
5074+ /* see Documentation/filesystems/unionfs/issues.txt */
5075+ lockdep_off();
5076+ /* do vfs_link */
5077+ err = vfs_link(lower_old_dentry,
5078+ lower_dir_dentry->d_inode,
5079+ lower_new_dentry);
5080+ lockdep_on();
5081+ unlock_dir(lower_dir_dentry);
5082+ goto check_link;
5083+ }
5084+ goto out;
5085+ }
5086+
5087+check_link:
5088+ if (err || !lower_new_dentry->d_inode)
5089+ goto out;
5090+
5091+ /* Its a hard link, so use the same inode */
5092+ new_dentry->d_inode = igrab(old_dentry->d_inode);
5093+ d_add(new_dentry, new_dentry->d_inode);
5094+ unionfs_copy_attr_all(dir, lower_new_dentry->d_parent->d_inode);
5095+ fsstack_copy_inode_size(dir, lower_new_dentry->d_parent->d_inode);
5096+
5097+ /* propagate number of hard-links */
5098+ old_dentry->d_inode->i_nlink = unionfs_get_nlinks(old_dentry->d_inode);
5099+ /* new dentry's ctime may have changed due to hard-link counts */
5100+ unionfs_copy_attr_times(new_dentry->d_inode);
5101+
5102+out:
5103+ if (!new_dentry->d_inode)
5104+ d_drop(new_dentry);
5105+
5106+ kfree(name);
5107+ if (!err)
5108+ unionfs_postcopyup_setmnt(new_dentry);
5109+
5110+ unionfs_check_inode(dir);
5111+ unionfs_check_dentry(new_dentry);
5112+ unionfs_check_dentry(old_dentry);
5113+
5114+ unionfs_double_unlock_dentry(old_dentry, new_dentry);
5115+ unionfs_double_unlock_parents(old_parent, new_parent);
5116+ dput(new_parent);
5117+ dput(old_parent);
5118+ unionfs_read_unlock(old_dentry->d_sb);
5119+
5120+ return err;
5121+}
5122+
5123+static int unionfs_symlink(struct inode *dir, struct dentry *dentry,
5124+ const char *symname)
5125+{
5126+ int err = 0;
5127+ struct dentry *lower_dentry = NULL;
5128+ struct dentry *wh_dentry = NULL;
5129+ struct dentry *lower_parent_dentry = NULL;
5130+ struct dentry *parent;
5131+ char *name = NULL;
5132+ int valid = 0;
5133+ umode_t mode;
5134+
5135+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
5136+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
5137+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
5138+
5139+ valid = __unionfs_d_revalidate(dentry, parent, false);
5140+ if (unlikely(!valid)) {
5141+ err = -ESTALE;
5142+ goto out;
5143+ }
5144+
5145+ /*
5146+ * It's only a bug if this dentry was not negative and couldn't be
5147+ * revalidated (shouldn't happen).
5148+ */
5149+ BUG_ON(!valid && dentry->d_inode);
5150+
5151+ lower_dentry = find_writeable_branch(dir, dentry);
5152+ if (IS_ERR(lower_dentry)) {
5153+ err = PTR_ERR(lower_dentry);
5154+ goto out;
5155+ }
5156+
5157+ lower_parent_dentry = lock_parent(lower_dentry);
5158+ if (IS_ERR(lower_parent_dentry)) {
5159+ err = PTR_ERR(lower_parent_dentry);
5160+ goto out_unlock;
5161+ }
5162+
5163+ mode = S_IALLUGO;
5164+ err = vfs_symlink(lower_parent_dentry->d_inode, lower_dentry, symname);
5165+ if (!err) {
5166+ err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
5167+ if (!err) {
5168+ unionfs_copy_attr_times(dir);
5169+ fsstack_copy_inode_size(dir,
5170+ lower_parent_dentry->d_inode);
5171+ /* update no. of links on parent directory */
5172+ dir->i_nlink = unionfs_get_nlinks(dir);
5173+ }
5174+ }
5175+
5176+out_unlock:
5177+ unlock_dir(lower_parent_dentry);
5178+out:
5179+ dput(wh_dentry);
5180+ kfree(name);
5181+
5182+ if (!err) {
5183+ unionfs_postcopyup_setmnt(dentry);
5184+ unionfs_check_inode(dir);
5185+ unionfs_check_dentry(dentry);
5186+ }
5187+ unionfs_unlock_dentry(dentry);
5188+ unionfs_unlock_parent(dentry, parent);
5189+ unionfs_read_unlock(dentry->d_sb);
5190+ return err;
5191+}
5192+
5193+static int unionfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
5194+{
5195+ int err = 0;
5196+ struct dentry *lower_dentry = NULL;
5197+ struct dentry *lower_parent_dentry = NULL;
5198+ struct dentry *parent;
5199+ int bindex = 0, bstart;
5200+ char *name = NULL;
5201+ int valid;
5202+
5203+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
5204+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
5205+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
5206+
5207+ valid = __unionfs_d_revalidate(dentry, parent, false);
5208+ if (unlikely(!valid)) {
5209+ err = -ESTALE; /* same as what real_lookup does */
5210+ goto out;
5211+ }
5212+
5213+ bstart = dbstart(dentry);
5214+
5215+ lower_dentry = unionfs_lower_dentry(dentry);
5216+
5217+ /* check for a whiteout in new dentry branch, and delete it */
5218+ err = check_unlink_whiteout(dentry, lower_dentry, bstart);
5219+ if (err > 0) /* whiteout found and removed successfully */
5220+ err = 0;
5221+ if (err) {
5222+ /* exit if the error returned was NOT -EROFS */
5223+ if (!IS_COPYUP_ERR(err))
5224+ goto out;
5225+ bstart--;
5226+ }
5227+
5228+ /* check if copyup's needed, and mkdir */
5229+ for (bindex = bstart; bindex >= 0; bindex--) {
5230+ int i;
5231+ int bend = dbend(dentry);
5232+
5233+ if (is_robranch_super(dentry->d_sb, bindex))
5234+ continue;
5235+
5236+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
5237+ if (!lower_dentry) {
5238+ lower_dentry = create_parents(dir, dentry,
5239+ dentry->d_name.name,
5240+ bindex);
5241+ if (!lower_dentry || IS_ERR(lower_dentry)) {
5242+ printk(KERN_ERR "unionfs: lower dentry "
5243+ " NULL for bindex = %d\n", bindex);
5244+ continue;
5245+ }
5246+ }
5247+
5248+ lower_parent_dentry = lock_parent(lower_dentry);
5249+
5250+ if (IS_ERR(lower_parent_dentry)) {
5251+ err = PTR_ERR(lower_parent_dentry);
5252+ goto out;
5253+ }
5254+
5255+ err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry,
5256+ mode);
5257+
5258+ unlock_dir(lower_parent_dentry);
5259+
5260+ /* did the mkdir succeed? */
5261+ if (err)
5262+ break;
5263+
5264+ for (i = bindex + 1; i <= bend; i++) {
5265+ /* XXX: use path_put_lowers? */
5266+ if (unionfs_lower_dentry_idx(dentry, i)) {
5267+ dput(unionfs_lower_dentry_idx(dentry, i));
5268+ unionfs_set_lower_dentry_idx(dentry, i, NULL);
5269+ }
5270+ }
5271+ dbend(dentry) = bindex;
5272+
5273+ /*
5274+ * Only INTERPOSE_LOOKUP can return a value other than 0 on
5275+ * err.
5276+ */
5277+ err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
5278+ if (!err) {
5279+ unionfs_copy_attr_times(dir);
5280+ fsstack_copy_inode_size(dir,
5281+ lower_parent_dentry->d_inode);
5282+
5283+ /* update number of links on parent directory */
5284+ dir->i_nlink = unionfs_get_nlinks(dir);
5285+ }
5286+
5287+ err = make_dir_opaque(dentry, dbstart(dentry));
5288+ if (err) {
5289+ printk(KERN_ERR "unionfs: mkdir: error creating "
5290+ ".wh.__dir_opaque: %d\n", err);
5291+ goto out;
5292+ }
5293+
5294+ /* we are done! */
5295+ break;
5296+ }
5297+
5298+out:
5299+ if (!dentry->d_inode)
5300+ d_drop(dentry);
5301+
5302+ kfree(name);
5303+
5304+ if (!err) {
5305+ unionfs_copy_attr_times(dentry->d_inode);
5306+ unionfs_postcopyup_setmnt(dentry);
5307+ }
5308+ unionfs_check_inode(dir);
5309+ unionfs_check_dentry(dentry);
5310+ unionfs_unlock_dentry(dentry);
5311+ unionfs_unlock_parent(dentry, parent);
5312+ unionfs_read_unlock(dentry->d_sb);
5313+
5314+ return err;
5315+}
5316+
5317+static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
5318+ dev_t dev)
5319+{
5320+ int err = 0;
5321+ struct dentry *lower_dentry = NULL;
5322+ struct dentry *wh_dentry = NULL;
5323+ struct dentry *lower_parent_dentry = NULL;
5324+ struct dentry *parent;
5325+ char *name = NULL;
5326+ int valid = 0;
5327+
5328+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
5329+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
5330+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
5331+
5332+ valid = __unionfs_d_revalidate(dentry, parent, false);
5333+ if (unlikely(!valid)) {
5334+ err = -ESTALE;
5335+ goto out;
5336+ }
5337+
5338+ /*
5339+ * It's only a bug if this dentry was not negative and couldn't be
5340+ * revalidated (shouldn't happen).
5341+ */
5342+ BUG_ON(!valid && dentry->d_inode);
5343+
5344+ lower_dentry = find_writeable_branch(dir, dentry);
5345+ if (IS_ERR(lower_dentry)) {
5346+ err = PTR_ERR(lower_dentry);
5347+ goto out;
5348+ }
5349+
5350+ lower_parent_dentry = lock_parent(lower_dentry);
5351+ if (IS_ERR(lower_parent_dentry)) {
5352+ err = PTR_ERR(lower_parent_dentry);
5353+ goto out_unlock;
5354+ }
5355+
5356+ err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
5357+ if (!err) {
5358+ err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
5359+ if (!err) {
5360+ unionfs_copy_attr_times(dir);
5361+ fsstack_copy_inode_size(dir,
5362+ lower_parent_dentry->d_inode);
5363+ /* update no. of links on parent directory */
5364+ dir->i_nlink = unionfs_get_nlinks(dir);
5365+ }
5366+ }
5367+
5368+out_unlock:
5369+ unlock_dir(lower_parent_dentry);
5370+out:
5371+ dput(wh_dentry);
5372+ kfree(name);
5373+
5374+ if (!err) {
5375+ unionfs_postcopyup_setmnt(dentry);
5376+ unionfs_check_inode(dir);
5377+ unionfs_check_dentry(dentry);
5378+ }
5379+ unionfs_unlock_dentry(dentry);
5380+ unionfs_unlock_parent(dentry, parent);
5381+ unionfs_read_unlock(dentry->d_sb);
5382+ return err;
5383+}
5384+
5385+/* requires sb, dentry, and parent to already be locked */
5386+static int __unionfs_readlink(struct dentry *dentry, char __user *buf,
5387+ int bufsiz)
5388+{
5389+ int err;
5390+ struct dentry *lower_dentry;
5391+
5392+ lower_dentry = unionfs_lower_dentry(dentry);
5393+
5394+ if (!lower_dentry->d_inode->i_op ||
5395+ !lower_dentry->d_inode->i_op->readlink) {
5396+ err = -EINVAL;
5397+ goto out;
5398+ }
5399+
5400+ err = lower_dentry->d_inode->i_op->readlink(lower_dentry,
5401+ buf, bufsiz);
5402+ if (err >= 0)
5403+ fsstack_copy_attr_atime(dentry->d_inode,
5404+ lower_dentry->d_inode);
5405+
5406+out:
5407+ return err;
5408+}
5409+
5410+static int unionfs_readlink(struct dentry *dentry, char __user *buf,
5411+ int bufsiz)
5412+{
5413+ int err;
5414+ struct dentry *parent;
5415+
5416+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
5417+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
5418+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
5419+
5420+ if (unlikely(!__unionfs_d_revalidate(dentry, parent, false))) {
5421+ err = -ESTALE;
5422+ goto out;
5423+ }
5424+
5425+ err = __unionfs_readlink(dentry, buf, bufsiz);
5426+
5427+out:
5428+ unionfs_check_dentry(dentry);
5429+ unionfs_unlock_dentry(dentry);
5430+ unionfs_unlock_parent(dentry, parent);
5431+ unionfs_read_unlock(dentry->d_sb);
5432+
5433+ return err;
5434+}
5435+
5436+static void *unionfs_follow_link(struct dentry *dentry, struct nameidata *nd)
5437+{
5438+ char *buf;
5439+ int len = PAGE_SIZE, err;
5440+ mm_segment_t old_fs;
5441+ struct dentry *parent;
5442+
5443+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
5444+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
5445+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
5446+
5447+ /* This is freed by the put_link method assuming a successful call. */
5448+ buf = kmalloc(len, GFP_KERNEL);
5449+ if (unlikely(!buf)) {
5450+ err = -ENOMEM;
5451+ goto out;
5452+ }
5453+
5454+ /* read the symlink, and then we will follow it */
5455+ old_fs = get_fs();
5456+ set_fs(KERNEL_DS);
5457+ err = __unionfs_readlink(dentry, buf, len);
5458+ set_fs(old_fs);
5459+ if (err < 0) {
5460+ kfree(buf);
5461+ buf = NULL;
5462+ goto out;
5463+ }
5464+ buf[err] = 0;
5465+ nd_set_link(nd, buf);
5466+ err = 0;
5467+
5468+out:
5469+ if (err >= 0) {
5470+ unionfs_check_nd(nd);
5471+ unionfs_check_dentry(dentry);
5472+ }
5473+
5474+ unionfs_unlock_dentry(dentry);
5475+ unionfs_unlock_parent(dentry, parent);
5476+ unionfs_read_unlock(dentry->d_sb);
5477+
5478+ return ERR_PTR(err);
5479+}
5480+
5481+/* this @nd *IS* still used */
5482+static void unionfs_put_link(struct dentry *dentry, struct nameidata *nd,
5483+ void *cookie)
5484+{
5485+ struct dentry *parent;
5486+ char *buf;
5487+
5488+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
5489+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
5490+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
5491+
5492+ if (unlikely(!__unionfs_d_revalidate(dentry, parent, false)))
5493+ printk(KERN_ERR
5494+ "unionfs: put_link failed to revalidate dentry\n");
5495+
5496+ unionfs_check_dentry(dentry);
5497+#if 0
5498+ /* XXX: can't run this check b/c this fxn can receive a poisoned 'nd' PTR */
5499+ unionfs_check_nd(nd);
5500+#endif
5501+ buf = nd_get_link(nd);
5502+ if (!IS_ERR(buf))
5503+ kfree(buf);
5504+ unionfs_unlock_dentry(dentry);
5505+ unionfs_unlock_parent(dentry, parent);
5506+ unionfs_read_unlock(dentry->d_sb);
5507+}
5508+
5509+/*
5510+ * This is a variant of fs/namei.c:permission() or inode_permission() which
5511+ * skips over EROFS tests (because we perform copyup on EROFS).
5512+ */
5513+static int __inode_permission(struct inode *inode, int mask)
5514+{
5515+ int retval;
5516+
5517+ /* nobody gets write access to an immutable file */
5518+ if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
5519+ return -EACCES;
5520+
5521+ /* Ordinary permission routines do not understand MAY_APPEND. */
5522+ if (inode->i_op && inode->i_op->permission) {
5523+ retval = inode->i_op->permission(inode, mask);
5524+ if (!retval) {
5525+ /*
5526+ * Exec permission on a regular file is denied if none
5527+ * of the execute bits are set.
5528+ *
5529+ * This check should be done by the ->permission()
5530+ * method.
5531+ */
5532+ if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode) &&
5533+ !(inode->i_mode & S_IXUGO))
5534+ return -EACCES;
5535+ }
5536+ } else {
5537+ retval = generic_permission(inode, mask, NULL);
5538+ }
5539+ if (retval)
5540+ return retval;
5541+
5542+ return security_inode_permission(inode,
5543+ mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
5544+}
5545+
5546+/*
5547+ * Don't grab the superblock read-lock in unionfs_permission, which prevents
5548+ * a deadlock with the branch-management "add branch" code (which grabbed
5549+ * the write lock). It is safe to not grab the read lock here, because even
5550+ * with branch management taking place, there is no chance that
5551+ * unionfs_permission, or anything it calls, will use stale branch
5552+ * information.
5553+ */
5554+static int unionfs_permission(struct inode *inode, int mask)
5555+{
5556+ struct inode *lower_inode = NULL;
5557+ int err = 0;
5558+ int bindex, bstart, bend;
5559+ const int is_file = !S_ISDIR(inode->i_mode);
5560+ const int write_mask = (mask & MAY_WRITE) && !(mask & MAY_READ);
5561+ struct inode *inode_grabbed = igrab(inode);
5562+ struct dentry *dentry = d_find_alias(inode);
5563+
5564+ if (dentry)
5565+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
5566+
5567+ if (!UNIONFS_I(inode)->lower_inodes) {
5568+ if (is_file) /* dirs can be unlinked but chdir'ed to */
5569+ err = -ESTALE; /* force revalidate */
5570+ goto out;
5571+ }
5572+ bstart = ibstart(inode);
5573+ bend = ibend(inode);
5574+ if (unlikely(bstart < 0 || bend < 0)) {
5575+ /*
5576+ * With branch-management, we can get a stale inode here.
5577+ * If so, we return ESTALE back to link_path_walk, which
5578+ * would discard the dcache entry and re-lookup the
5579+ * dentry+inode. This should be equivalent to issuing
5580+ * __unionfs_d_revalidate_chain on nd.dentry here.
5581+ */
5582+ if (is_file) /* dirs can be unlinked but chdir'ed to */
5583+ err = -ESTALE; /* force revalidate */
5584+ goto out;
5585+ }
5586+
5587+ for (bindex = bstart; bindex <= bend; bindex++) {
5588+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
5589+ if (!lower_inode)
5590+ continue;
5591+
5592+ /*
5593+ * check the condition for D-F-D underlying files/directories,
5594+ * we don't have to check for files, if we are checking for
5595+ * directories.
5596+ */
5597+ if (!is_file && !S_ISDIR(lower_inode->i_mode))
5598+ continue;
5599+
5600+ /*
5601+ * We check basic permissions, but we ignore any conditions
5602+ * such as readonly file systems or branches marked as
5603+ * readonly, because those conditions should lead to a
5604+ * copyup taking place later on. However, if user never had
5605+ * access to the file, then no copyup could ever take place.
5606+ */
5607+ err = __inode_permission(lower_inode, mask);
5608+ if (err && err != -EACCES && err != EPERM && bindex > 0) {
5609+ umode_t mode = lower_inode->i_mode;
5610+ if ((is_robranch_super(inode->i_sb, bindex) ||
5611+ __is_rdonly(lower_inode)) &&
5612+ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
5613+ err = 0;
5614+ if (IS_COPYUP_ERR(err))
5615+ err = 0;
5616+ }
5617+
5618+ /*
5619+ * NFS HACK: NFSv2/3 return EACCES on readonly-exported,
5620+ * locally readonly-mounted file systems, instead of EROFS
5621+ * like other file systems do. So we have no choice here
5622+ * but to intercept this and ignore it for NFS branches
5623+ * marked readonly. Specifically, we avoid using NFS's own
5624+ * "broken" ->permission method, and rely on
5625+ * generic_permission() to do basic checking for us.
5626+ */
5627+ if (err && err == -EACCES &&
5628+ is_robranch_super(inode->i_sb, bindex) &&
5629+ lower_inode->i_sb->s_magic == NFS_SUPER_MAGIC)
5630+ err = generic_permission(lower_inode, mask, NULL);
5631+
5632+ /*
5633+ * The permissions are an intersection of the overall directory
5634+ * permissions, so we fail if one fails.
5635+ */
5636+ if (err)
5637+ goto out;
5638+
5639+ /* only the leftmost file matters. */
5640+ if (is_file || write_mask) {
5641+ if (is_file && write_mask) {
5642+ err = get_write_access(lower_inode);
5643+ if (!err)
5644+ put_write_access(lower_inode);
5645+ }
5646+ break;
5647+ }
5648+ }
5649+ /* sync times which may have changed (asynchronously) below */
5650+ unionfs_copy_attr_times(inode);
5651+
5652+out:
5653+ unionfs_check_inode(inode);
5654+ if (dentry) {
5655+ unionfs_unlock_dentry(dentry);
5656+ dput(dentry);
5657+ }
5658+ iput(inode_grabbed);
5659+ return err;
5660+}
5661+
5662+static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
5663+{
5664+ int err = 0;
5665+ struct dentry *lower_dentry;
5666+ struct dentry *parent;
5667+ struct inode *inode;
5668+ struct inode *lower_inode;
5669+ int bstart, bend, bindex;
5670+ loff_t size;
5671+
5672+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
5673+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
5674+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
5675+
5676+ if (unlikely(!__unionfs_d_revalidate(dentry, parent, false))) {
5677+ err = -ESTALE;
5678+ goto out;
5679+ }
5680+
5681+ bstart = dbstart(dentry);
5682+ bend = dbend(dentry);
5683+ inode = dentry->d_inode;
5684+
5685+ /*
5686+ * mode change is for clearing setuid/setgid. Allow lower filesystem
5687+ * to reinterpret it in its own way.
5688+ */
5689+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
5690+ ia->ia_valid &= ~ATTR_MODE;
5691+
5692+ lower_dentry = unionfs_lower_dentry(dentry);
5693+ if (!lower_dentry) { /* should never happen after above revalidate */
5694+ err = -EINVAL;
5695+ goto out;
5696+ }
5697+ lower_inode = unionfs_lower_inode(inode);
5698+
5699+ /* check if user has permission to change lower inode */
5700+ err = inode_change_ok(lower_inode, ia);
5701+ if (err)
5702+ goto out;
5703+
5704+ /* copyup if the file is on a read only branch */
5705+ if (is_robranch_super(dentry->d_sb, bstart)
5706+ || __is_rdonly(lower_inode)) {
5707+ /* check if we have a branch to copy up to */
5708+ if (bstart <= 0) {
5709+ err = -EACCES;
5710+ goto out;
5711+ }
5712+
5713+ if (ia->ia_valid & ATTR_SIZE)
5714+ size = ia->ia_size;
5715+ else
5716+ size = i_size_read(inode);
5717+ /* copyup to next available branch */
5718+ for (bindex = bstart - 1; bindex >= 0; bindex--) {
5719+ err = copyup_dentry(parent->d_inode,
5720+ dentry, bstart, bindex,
5721+ dentry->d_name.name,
5722+ dentry->d_name.len,
5723+ NULL, size);
5724+ if (!err)
5725+ break;
5726+ }
5727+ if (err)
5728+ goto out;
5729+ /* get updated lower_dentry/inode after copyup */
5730+ lower_dentry = unionfs_lower_dentry(dentry);
5731+ lower_inode = unionfs_lower_inode(inode);
5732+ }
5733+
5734+ /*
5735+ * If shrinking, first truncate upper level to cancel writing dirty
5736+ * pages beyond the new eof; and also if its' maxbytes is more
5737+ * limiting (fail with -EFBIG before making any change to the lower
5738+ * level). There is no need to vmtruncate the upper level
5739+ * afterwards in the other cases: we fsstack_copy_inode_size from
5740+ * the lower level.
5741+ */
5742+ if (ia->ia_valid & ATTR_SIZE) {
5743+ size = i_size_read(inode);
5744+ if (ia->ia_size < size || (ia->ia_size > size &&
5745+ inode->i_sb->s_maxbytes < lower_inode->i_sb->s_maxbytes)) {
5746+ err = vmtruncate(inode, ia->ia_size);
5747+ if (err)
5748+ goto out;
5749+ }
5750+ }
5751+
5752+ /* notify the (possibly copied-up) lower inode */
5753+ /*
5754+ * Note: we use lower_dentry->d_inode, because lower_inode may be
5755+ * unlinked (no inode->i_sb and i_ino==0. This happens if someone
5756+ * tries to open(), unlink(), then ftruncate() a file.
5757+ */
5758+ mutex_lock(&lower_dentry->d_inode->i_mutex);
5759+ err = notify_change(lower_dentry, ia);
5760+ mutex_unlock(&lower_dentry->d_inode->i_mutex);
5761+ if (err)
5762+ goto out;
5763+
5764+ /* get attributes from the first lower inode */
5765+ if (ibstart(inode) >= 0)
5766+ unionfs_copy_attr_all(inode, lower_inode);
5767+ /*
5768+ * unionfs_copy_attr_all will copy the lower times to our inode if
5769+ * the lower ones are newer (useful for cache coherency). However,
5770+ * ->setattr is the only place in which we may have to copy the
5771+ * lower inode times absolutely, to support utimes(2).
5772+ */
5773+ if (ia->ia_valid & ATTR_MTIME_SET)
5774+ inode->i_mtime = lower_inode->i_mtime;
5775+ if (ia->ia_valid & ATTR_CTIME)
5776+ inode->i_ctime = lower_inode->i_ctime;
5777+ if (ia->ia_valid & ATTR_ATIME_SET)
5778+ inode->i_atime = lower_inode->i_atime;
5779+ fsstack_copy_inode_size(inode, lower_inode);
5780+
5781+out:
5782+ if (!err)
5783+ unionfs_check_dentry(dentry);
5784+ unionfs_unlock_dentry(dentry);
5785+ unionfs_unlock_parent(dentry, parent);
5786+ unionfs_read_unlock(dentry->d_sb);
5787+
5788+ return err;
5789+}
5790+
5791+struct inode_operations unionfs_symlink_iops = {
5792+ .readlink = unionfs_readlink,
5793+ .permission = unionfs_permission,
5794+ .follow_link = unionfs_follow_link,
5795+ .setattr = unionfs_setattr,
5796+ .put_link = unionfs_put_link,
5797+};
5798+
5799+struct inode_operations unionfs_dir_iops = {
5800+ .create = unionfs_create,
5801+ .lookup = unionfs_lookup,
5802+ .link = unionfs_link,
5803+ .unlink = unionfs_unlink,
5804+ .symlink = unionfs_symlink,
5805+ .mkdir = unionfs_mkdir,
5806+ .rmdir = unionfs_rmdir,
5807+ .mknod = unionfs_mknod,
5808+ .rename = unionfs_rename,
5809+ .permission = unionfs_permission,
5810+ .setattr = unionfs_setattr,
5811+#ifdef CONFIG_UNION_FS_XATTR
5812+ .setxattr = unionfs_setxattr,
5813+ .getxattr = unionfs_getxattr,
5814+ .removexattr = unionfs_removexattr,
5815+ .listxattr = unionfs_listxattr,
5816+#endif /* CONFIG_UNION_FS_XATTR */
5817+};
5818+
5819+struct inode_operations unionfs_main_iops = {
5820+ .permission = unionfs_permission,
5821+ .setattr = unionfs_setattr,
5822+#ifdef CONFIG_UNION_FS_XATTR
5823+ .setxattr = unionfs_setxattr,
5824+ .getxattr = unionfs_getxattr,
5825+ .removexattr = unionfs_removexattr,
5826+ .listxattr = unionfs_listxattr,
5827+#endif /* CONFIG_UNION_FS_XATTR */
5828+};
5829diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
5830new file mode 100644
5831index 0000000..b63c17e
5832--- /dev/null
5833+++ b/fs/unionfs/lookup.c
5834@@ -0,0 +1,569 @@
5835+/*
5836+ * Copyright (c) 2003-2010 Erez Zadok
5837+ * Copyright (c) 2003-2006 Charles P. Wright
5838+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
5839+ * Copyright (c) 2005-2006 Junjiro Okajima
5840+ * Copyright (c) 2005 Arun M. Krishnakumar
5841+ * Copyright (c) 2004-2006 David P. Quigley
5842+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
5843+ * Copyright (c) 2003 Puja Gupta
5844+ * Copyright (c) 2003 Harikesavan Krishnan
5845+ * Copyright (c) 2003-2010 Stony Brook University
5846+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
5847+ *
5848+ * This program is free software; you can redistribute it and/or modify
5849+ * it under the terms of the GNU General Public License version 2 as
5850+ * published by the Free Software Foundation.
5851+ */
5852+
5853+#include "union.h"
5854+
5855+/*
5856+ * Lookup one path component @name relative to a <base,mnt> path pair.
5857+ * Behaves nearly the same as lookup_one_len (i.e., return negative dentry
5858+ * on ENOENT), but uses the @mnt passed, so it can cross bind mounts and
5859+ * other lower mounts properly. If @new_mnt is non-null, will fill in the
5860+ * new mnt there. Caller is responsible to dput/mntput/path_put returned
5861+ * @dentry and @new_mnt.
5862+ */
5863+struct dentry *__lookup_one(struct dentry *base, struct vfsmount *mnt,
5864+ const char *name, struct vfsmount **new_mnt)
5865+{
5866+ struct dentry *dentry = NULL;
5867+ struct nameidata lower_nd;
5868+ int err;
5869+
5870+ /* we use flags=0 to get basic lookup */
5871+ err = vfs_path_lookup(base, mnt, name, 0, &lower_nd);
5872+
5873+ switch (err) {
5874+ case 0: /* no error */
5875+ dentry = lower_nd.path.dentry;
5876+ if (new_mnt)
5877+ *new_mnt = lower_nd.path.mnt; /* rc already inc'ed */
5878+ break;
5879+ case -ENOENT:
5880+ /*
5881+ * We don't consider ENOENT an error, and we want to return
5882+ * a negative dentry (ala lookup_one_len). As we know
5883+ * there was no inode for this name before (-ENOENT), then
5884+ * it's safe to call lookup_one_len (which doesn't take a
5885+ * vfsmount).
5886+ */
5887+ dentry = lookup_lck_len(name, base, strlen(name));
5888+ if (new_mnt)
5889+ *new_mnt = mntget(lower_nd.path.mnt);
5890+ break;
5891+ default: /* all other real errors */
5892+ dentry = ERR_PTR(err);
5893+ break;
5894+ }
5895+
5896+ return dentry;
5897+}
5898+
5899+/*
5900+ * This is a utility function that fills in a unionfs dentry.
5901+ * Caller must lock this dentry with unionfs_lock_dentry.
5902+ *
5903+ * Returns: 0 (ok), or -ERRNO if an error occurred.
5904+ * XXX: get rid of _partial_lookup and make callers call _lookup_full directly
5905+ */
5906+int unionfs_partial_lookup(struct dentry *dentry, struct dentry *parent)
5907+{
5908+ struct dentry *tmp;
5909+ int err = -ENOSYS;
5910+
5911+ tmp = unionfs_lookup_full(dentry, parent, INTERPOSE_PARTIAL);
5912+
5913+ if (!tmp) {
5914+ err = 0;
5915+ goto out;
5916+ }
5917+ if (IS_ERR(tmp)) {
5918+ err = PTR_ERR(tmp);
5919+ goto out;
5920+ }
5921+ /* XXX: need to change the interface */
5922+ BUG_ON(tmp != dentry);
5923+out:
5924+ return err;
5925+}
5926+
5927+/* The dentry cache is just so we have properly sized dentries. */
5928+static struct kmem_cache *unionfs_dentry_cachep;
5929+int unionfs_init_dentry_cache(void)
5930+{
5931+ unionfs_dentry_cachep =
5932+ kmem_cache_create("unionfs_dentry",
5933+ sizeof(struct unionfs_dentry_info),
5934+ 0, SLAB_RECLAIM_ACCOUNT, NULL);
5935+
5936+ return (unionfs_dentry_cachep ? 0 : -ENOMEM);
5937+}
5938+
5939+void unionfs_destroy_dentry_cache(void)
5940+{
5941+ if (unionfs_dentry_cachep)
5942+ kmem_cache_destroy(unionfs_dentry_cachep);
5943+}
5944+
5945+void free_dentry_private_data(struct dentry *dentry)
5946+{
5947+ if (!dentry || !dentry->d_fsdata)
5948+ return;
5949+ kfree(UNIONFS_D(dentry)->lower_paths);
5950+ UNIONFS_D(dentry)->lower_paths = NULL;
5951+ kmem_cache_free(unionfs_dentry_cachep, dentry->d_fsdata);
5952+ dentry->d_fsdata = NULL;
5953+}
5954+
5955+static inline int __realloc_dentry_private_data(struct dentry *dentry)
5956+{
5957+ struct unionfs_dentry_info *info = UNIONFS_D(dentry);
5958+ void *p;
5959+ int size;
5960+
5961+ BUG_ON(!info);
5962+
5963+ size = sizeof(struct path) * sbmax(dentry->d_sb);
5964+ p = krealloc(info->lower_paths, size, GFP_ATOMIC);
5965+ if (unlikely(!p))
5966+ return -ENOMEM;
5967+
5968+ info->lower_paths = p;
5969+
5970+ info->bstart = -1;
5971+ info->bend = -1;
5972+ info->bopaque = -1;
5973+ info->bcount = sbmax(dentry->d_sb);
5974+ atomic_set(&info->generation,
5975+ atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
5976+
5977+ memset(info->lower_paths, 0, size);
5978+
5979+ return 0;
5980+}
5981+
5982+/* UNIONFS_D(dentry)->lock must be locked */
5983+int realloc_dentry_private_data(struct dentry *dentry)
5984+{
5985+ if (!__realloc_dentry_private_data(dentry))
5986+ return 0;
5987+
5988+ kfree(UNIONFS_D(dentry)->lower_paths);
5989+ free_dentry_private_data(dentry);
5990+ return -ENOMEM;
5991+}
5992+
5993+/* allocate new dentry private data */
5994+int new_dentry_private_data(struct dentry *dentry, int subclass)
5995+{
5996+ struct unionfs_dentry_info *info = UNIONFS_D(dentry);
5997+
5998+ BUG_ON(info);
5999+
6000+ info = kmem_cache_alloc(unionfs_dentry_cachep, GFP_ATOMIC);
6001+ if (unlikely(!info))
6002+ return -ENOMEM;
6003+
6004+ mutex_init(&info->lock);
6005+ mutex_lock_nested(&info->lock, subclass);
6006+
6007+ info->lower_paths = NULL;
6008+
6009+ dentry->d_fsdata = info;
6010+
6011+ if (!__realloc_dentry_private_data(dentry))
6012+ return 0;
6013+
6014+ mutex_unlock(&info->lock);
6015+ free_dentry_private_data(dentry);
6016+ return -ENOMEM;
6017+}
6018+
6019+/*
6020+ * scan through the lower dentry objects, and set bstart to reflect the
6021+ * starting branch
6022+ */
6023+void update_bstart(struct dentry *dentry)
6024+{
6025+ int bindex;
6026+ int bstart = dbstart(dentry);
6027+ int bend = dbend(dentry);
6028+ struct dentry *lower_dentry;
6029+
6030+ for (bindex = bstart; bindex <= bend; bindex++) {
6031+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
6032+ if (!lower_dentry)
6033+ continue;
6034+ if (lower_dentry->d_inode) {
6035+ dbstart(dentry) = bindex;
6036+ break;
6037+ }
6038+ dput(lower_dentry);
6039+ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
6040+ }
6041+}
6042+
6043+
6044+/*
6045+ * Initialize a nameidata structure (the intent part) we can pass to a lower
6046+ * file system. Returns 0 on success or -error (only -ENOMEM possible).
6047+ * Inside that nd structure, this function may also return an allocated
6048+ * struct file (for open intents). The caller, when done with this nd, must
6049+ * kfree the intent file (using release_lower_nd).
6050+ *
6051+ * XXX: this code, and the callers of this code, should be redone using
6052+ * vfs_path_lookup() when (1) the nameidata structure is refactored into a
6053+ * separate intent-structure, and (2) open_namei() is broken into a VFS-only
6054+ * function and a method that other file systems can call.
6055+ */
6056+int init_lower_nd(struct nameidata *nd, unsigned int flags)
6057+{
6058+ int err = 0;
6059+#ifdef ALLOC_LOWER_ND_FILE
6060+ /*
6061+ * XXX: one day we may need to have the lower return an open file
6062+ * for us. It is not needed in 2.6.23-rc1 for nfs2/nfs3, but may
6063+ * very well be needed for nfs4.
6064+ */
6065+ struct file *file;
6066+#endif /* ALLOC_LOWER_ND_FILE */
6067+
6068+ memset(nd, 0, sizeof(struct nameidata));
6069+ if (!flags)
6070+ return err;
6071+
6072+ switch (flags) {
6073+ case LOOKUP_CREATE:
6074+ nd->intent.open.flags |= O_CREAT;
6075+ /* fall through: shared code for create/open cases */
6076+ case LOOKUP_OPEN:
6077+ nd->flags = flags;
6078+ nd->intent.open.flags |= (FMODE_READ | FMODE_WRITE);
6079+#ifdef ALLOC_LOWER_ND_FILE
6080+ file = kzalloc(sizeof(struct file), GFP_KERNEL);
6081+ if (unlikely(!file)) {
6082+ err = -ENOMEM;
6083+ break; /* exit switch statement and thus return */
6084+ }
6085+ nd->intent.open.file = file;
6086+#endif /* ALLOC_LOWER_ND_FILE */
6087+ break;
6088+ default:
6089+ /*
6090+ * We should never get here, for now.
6091+ * We can add new cases here later on.
6092+ */
6093+ pr_debug("unionfs: unknown nameidata flag 0x%x\n", flags);
6094+ BUG();
6095+ break;
6096+ }
6097+
6098+ return err;
6099+}
6100+
6101+void release_lower_nd(struct nameidata *nd, int err)
6102+{
6103+ if (!nd->intent.open.file)
6104+ return;
6105+ else if (!err)
6106+ release_open_intent(nd);
6107+#ifdef ALLOC_LOWER_ND_FILE
6108+ kfree(nd->intent.open.file);
6109+#endif /* ALLOC_LOWER_ND_FILE */
6110+}
6111+
6112+/*
6113+ * Main (and complex) driver function for Unionfs's lookup
6114+ *
6115+ * Returns: NULL (ok), ERR_PTR if an error occurred, or a non-null non-error
6116+ * PTR if d_splice returned a different dentry.
6117+ *
6118+ * If lookupmode is INTERPOSE_PARTIAL/REVAL/REVAL_NEG, the passed dentry's
6119+ * inode info must be locked. If lookupmode is INTERPOSE_LOOKUP (i.e., a
6120+ * newly looked-up dentry), then unionfs_lookup_backend will return a locked
6121+ * dentry's info, which the caller must unlock.
6122+ */
6123+struct dentry *unionfs_lookup_full(struct dentry *dentry,
6124+ struct dentry *parent, int lookupmode)
6125+{
6126+ int err = 0;
6127+ struct dentry *lower_dentry = NULL;
6128+ struct vfsmount *lower_mnt;
6129+ struct vfsmount *lower_dir_mnt;
6130+ struct dentry *wh_lower_dentry = NULL;
6131+ struct dentry *lower_dir_dentry = NULL;
6132+ struct dentry *d_interposed = NULL;
6133+ int bindex, bstart, bend, bopaque;
6134+ int opaque, num_positive = 0;
6135+ const char *name;
6136+ int namelen;
6137+ int pos_start, pos_end;
6138+
6139+ /*
6140+ * We should already have a lock on this dentry in the case of a
6141+ * partial lookup, or a revalidation. Otherwise it is returned from
6142+ * new_dentry_private_data already locked.
6143+ */
6144+ verify_locked(dentry);
6145+ verify_locked(parent);
6146+
6147+ /* must initialize dentry operations */
6148+ dentry->d_op = &unionfs_dops;
6149+
6150+ /* We never partial lookup the root directory. */
6151+ if (IS_ROOT(dentry))
6152+ goto out;
6153+
6154+ name = dentry->d_name.name;
6155+ namelen = dentry->d_name.len;
6156+
6157+ /* No dentries should get created for possible whiteout names. */
6158+ if (!is_validname(name)) {
6159+ err = -EPERM;
6160+ goto out_free;
6161+ }
6162+
6163+ /* Now start the actual lookup procedure. */
6164+ bstart = dbstart(parent);
6165+ bend = dbend(parent);
6166+ bopaque = dbopaque(parent);
6167+ BUG_ON(bstart < 0);
6168+
6169+ /* adjust bend to bopaque if needed */
6170+ if ((bopaque >= 0) && (bopaque < bend))
6171+ bend = bopaque;
6172+
6173+ /* lookup all possible dentries */
6174+ for (bindex = bstart; bindex <= bend; bindex++) {
6175+
6176+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
6177+ lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
6178+
6179+ /* skip if we already have a positive lower dentry */
6180+ if (lower_dentry) {
6181+ if (dbstart(dentry) < 0)
6182+ dbstart(dentry) = bindex;
6183+ if (bindex > dbend(dentry))
6184+ dbend(dentry) = bindex;
6185+ if (lower_dentry->d_inode)
6186+ num_positive++;
6187+ continue;
6188+ }
6189+
6190+ lower_dir_dentry =
6191+ unionfs_lower_dentry_idx(parent, bindex);
6192+ /* if the lower dentry's parent does not exist, skip this */
6193+ if (!lower_dir_dentry || !lower_dir_dentry->d_inode)
6194+ continue;
6195+
6196+ /* also skip it if the parent isn't a directory. */
6197+ if (!S_ISDIR(lower_dir_dentry->d_inode->i_mode))
6198+ continue; /* XXX: should be BUG_ON */
6199+
6200+ /* check for whiteouts: stop lookup if found */
6201+ wh_lower_dentry = lookup_whiteout(name, lower_dir_dentry);
6202+ if (IS_ERR(wh_lower_dentry)) {
6203+ err = PTR_ERR(wh_lower_dentry);
6204+ goto out_free;
6205+ }
6206+ if (wh_lower_dentry->d_inode) {
6207+ dbend(dentry) = dbopaque(dentry) = bindex;
6208+ if (dbstart(dentry) < 0)
6209+ dbstart(dentry) = bindex;
6210+ dput(wh_lower_dentry);
6211+ break;
6212+ }
6213+ dput(wh_lower_dentry);
6214+
6215+ /* Now do regular lookup; lookup @name */
6216+ lower_dir_mnt = unionfs_lower_mnt_idx(parent, bindex);
6217+ lower_mnt = NULL; /* XXX: needed? */
6218+
6219+ lower_dentry = __lookup_one(lower_dir_dentry, lower_dir_mnt,
6220+ name, &lower_mnt);
6221+
6222+ if (IS_ERR(lower_dentry)) {
6223+ err = PTR_ERR(lower_dentry);
6224+ goto out_free;
6225+ }
6226+ unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry);
6227+ if (!lower_mnt)
6228+ lower_mnt = unionfs_mntget(dentry->d_sb->s_root,
6229+ bindex);
6230+ unionfs_set_lower_mnt_idx(dentry, bindex, lower_mnt);
6231+
6232+ /* adjust dbstart/end */
6233+ if (dbstart(dentry) < 0)
6234+ dbstart(dentry) = bindex;
6235+ if (bindex > dbend(dentry))
6236+ dbend(dentry) = bindex;
6237+ /*
6238+ * We always store the lower dentries above, and update
6239+ * dbstart/dbend, even if the whole unionfs dentry is
6240+ * negative (i.e., no lower inodes).
6241+ */
6242+ if (!lower_dentry->d_inode)
6243+ continue;
6244+ num_positive++;
6245+
6246+ /*
6247+ * check if we just found an opaque directory, if so, stop
6248+ * lookups here.
6249+ */
6250+ if (!S_ISDIR(lower_dentry->d_inode->i_mode))
6251+ continue;
6252+ opaque = is_opaque_dir(dentry, bindex);
6253+ if (opaque < 0) {
6254+ err = opaque;
6255+ goto out_free;
6256+ } else if (opaque) {
6257+ dbend(dentry) = dbopaque(dentry) = bindex;
6258+ break;
6259+ }
6260+ dbend(dentry) = bindex;
6261+
6262+ /* update parent directory's atime with the bindex */
6263+ fsstack_copy_attr_atime(parent->d_inode,
6264+ lower_dir_dentry->d_inode);
6265+ }
6266+
6267+ /* sanity checks, then decide if to process a negative dentry */
6268+ BUG_ON(dbstart(dentry) < 0 && dbend(dentry) >= 0);
6269+ BUG_ON(dbstart(dentry) >= 0 && dbend(dentry) < 0);
6270+
6271+ if (num_positive > 0)
6272+ goto out_positive;
6273+
6274+ /*** handle NEGATIVE dentries ***/
6275+
6276+ /*
6277+ * If negative, keep only first lower negative dentry, to save on
6278+ * memory.
6279+ */
6280+ if (dbstart(dentry) < dbend(dentry)) {
6281+ path_put_lowers(dentry, dbstart(dentry) + 1,
6282+ dbend(dentry), false);
6283+ dbend(dentry) = dbstart(dentry);
6284+ }
6285+ if (lookupmode == INTERPOSE_PARTIAL)
6286+ goto out;
6287+ if (lookupmode == INTERPOSE_LOOKUP) {
6288+ /*
6289+ * If all we found was a whiteout in the first available
6290+ * branch, then create a negative dentry for a possibly new
6291+ * file to be created.
6292+ */
6293+ if (dbopaque(dentry) < 0)
6294+ goto out;
6295+ /* XXX: need to get mnt here */
6296+ bindex = dbstart(dentry);
6297+ if (unionfs_lower_dentry_idx(dentry, bindex))
6298+ goto out;
6299+ lower_dir_dentry =
6300+ unionfs_lower_dentry_idx(parent, bindex);
6301+ if (!lower_dir_dentry || !lower_dir_dentry->d_inode)
6302+ goto out;
6303+ if (!S_ISDIR(lower_dir_dentry->d_inode->i_mode))
6304+ goto out; /* XXX: should be BUG_ON */
6305+ /* XXX: do we need to cross bind mounts here? */
6306+ lower_dentry = lookup_lck_len(name, lower_dir_dentry, namelen);
6307+ if (IS_ERR(lower_dentry)) {
6308+ err = PTR_ERR(lower_dentry);
6309+ goto out;
6310+ }
6311+ /* XXX: need to mntget/mntput as needed too! */
6312+ unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry);
6313+ /* XXX: wrong mnt for crossing bind mounts! */
6314+ lower_mnt = unionfs_mntget(dentry->d_sb->s_root, bindex);
6315+ unionfs_set_lower_mnt_idx(dentry, bindex, lower_mnt);
6316+
6317+ goto out;
6318+ }
6319+
6320+ /* if we're revalidating a positive dentry, don't make it negative */
6321+ if (lookupmode != INTERPOSE_REVAL)
6322+ d_add(dentry, NULL);
6323+
6324+ goto out;
6325+
6326+out_positive:
6327+ /*** handle POSITIVE dentries ***/
6328+
6329+ /*
6330+ * This unionfs dentry is positive (at least one lower inode
6331+ * exists), so scan entire dentry from beginning to end, and remove
6332+ * any negative lower dentries, if any. Then, update dbstart/dbend
6333+ * to reflect the start/end of positive dentries.
6334+ */
6335+ pos_start = pos_end = -1;
6336+ for (bindex = bstart; bindex <= bend; bindex++) {
6337+ lower_dentry = unionfs_lower_dentry_idx(dentry,
6338+ bindex);
6339+ if (lower_dentry && lower_dentry->d_inode) {
6340+ if (pos_start < 0)
6341+ pos_start = bindex;
6342+ if (bindex > pos_end)
6343+ pos_end = bindex;
6344+ continue;
6345+ }
6346+ path_put_lowers(dentry, bindex, bindex, false);
6347+ }
6348+ if (pos_start >= 0)
6349+ dbstart(dentry) = pos_start;
6350+ if (pos_end >= 0)
6351+ dbend(dentry) = pos_end;
6352+
6353+ /* Partial lookups need to re-interpose, or throw away older negs. */
6354+ if (lookupmode == INTERPOSE_PARTIAL) {
6355+ if (dentry->d_inode) {
6356+ unionfs_reinterpose(dentry);
6357+ goto out;
6358+ }
6359+
6360+ /*
6361+ * This dentry was positive, so it is as if we had a
6362+ * negative revalidation.
6363+ */
6364+ lookupmode = INTERPOSE_REVAL_NEG;
6365+ update_bstart(dentry);
6366+ }
6367+
6368+ /*
6369+ * Interpose can return a dentry if d_splice returned a different
6370+ * dentry.
6371+ */
6372+ d_interposed = unionfs_interpose(dentry, dentry->d_sb, lookupmode);
6373+ if (IS_ERR(d_interposed))
6374+ err = PTR_ERR(d_interposed);
6375+ else if (d_interposed)
6376+ dentry = d_interposed;
6377+
6378+ if (!err)
6379+ goto out;
6380+ d_drop(dentry);
6381+
6382+out_free:
6383+ /* should dput/mntput all the underlying dentries on error condition */
6384+ if (dbstart(dentry) >= 0)
6385+ path_put_lowers_all(dentry, false);
6386+ /* free lower_paths unconditionally */
6387+ kfree(UNIONFS_D(dentry)->lower_paths);
6388+ UNIONFS_D(dentry)->lower_paths = NULL;
6389+
6390+out:
6391+ if (dentry && UNIONFS_D(dentry)) {
6392+ BUG_ON(dbstart(dentry) < 0 && dbend(dentry) >= 0);
6393+ BUG_ON(dbstart(dentry) >= 0 && dbend(dentry) < 0);
6394+ }
6395+ if (d_interposed && UNIONFS_D(d_interposed)) {
6396+ BUG_ON(dbstart(d_interposed) < 0 && dbend(d_interposed) >= 0);
6397+ BUG_ON(dbstart(d_interposed) >= 0 && dbend(d_interposed) < 0);
6398+ }
6399+
6400+ if (!err && d_interposed)
6401+ return d_interposed;
6402+ return ERR_PTR(err);
6403+}
6404diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
6405new file mode 100644
6406index 0000000..258386e
6407--- /dev/null
6408+++ b/fs/unionfs/main.c
6409@@ -0,0 +1,758 @@
6410+/*
6411+ * Copyright (c) 2003-2010 Erez Zadok
6412+ * Copyright (c) 2003-2006 Charles P. Wright
6413+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
6414+ * Copyright (c) 2005-2006 Junjiro Okajima
6415+ * Copyright (c) 2005 Arun M. Krishnakumar
6416+ * Copyright (c) 2004-2006 David P. Quigley
6417+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
6418+ * Copyright (c) 2003 Puja Gupta
6419+ * Copyright (c) 2003 Harikesavan Krishnan
6420+ * Copyright (c) 2003-2010 Stony Brook University
6421+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
6422+ *
6423+ * This program is free software; you can redistribute it and/or modify
6424+ * it under the terms of the GNU General Public License version 2 as
6425+ * published by the Free Software Foundation.
6426+ */
6427+
6428+#include "union.h"
6429+#include <linux/module.h>
6430+#include <linux/moduleparam.h>
6431+
6432+static void unionfs_fill_inode(struct dentry *dentry,
6433+ struct inode *inode)
6434+{
6435+ struct inode *lower_inode;
6436+ struct dentry *lower_dentry;
6437+ int bindex, bstart, bend;
6438+
6439+ bstart = dbstart(dentry);
6440+ bend = dbend(dentry);
6441+
6442+ for (bindex = bstart; bindex <= bend; bindex++) {
6443+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
6444+ if (!lower_dentry) {
6445+ unionfs_set_lower_inode_idx(inode, bindex, NULL);
6446+ continue;
6447+ }
6448+
6449+ /* Initialize the lower inode to the new lower inode. */
6450+ if (!lower_dentry->d_inode)
6451+ continue;
6452+
6453+ unionfs_set_lower_inode_idx(inode, bindex,
6454+ igrab(lower_dentry->d_inode));
6455+ }
6456+
6457+ ibstart(inode) = dbstart(dentry);
6458+ ibend(inode) = dbend(dentry);
6459+
6460+ /* Use attributes from the first branch. */
6461+ lower_inode = unionfs_lower_inode(inode);
6462+
6463+ /* Use different set of inode ops for symlinks & directories */
6464+ if (S_ISLNK(lower_inode->i_mode))
6465+ inode->i_op = &unionfs_symlink_iops;
6466+ else if (S_ISDIR(lower_inode->i_mode))
6467+ inode->i_op = &unionfs_dir_iops;
6468+
6469+ /* Use different set of file ops for directories */
6470+ if (S_ISDIR(lower_inode->i_mode))
6471+ inode->i_fop = &unionfs_dir_fops;
6472+
6473+ /* properly initialize special inodes */
6474+ if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) ||
6475+ S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode))
6476+ init_special_inode(inode, lower_inode->i_mode,
6477+ lower_inode->i_rdev);
6478+
6479+ /* all well, copy inode attributes */
6480+ unionfs_copy_attr_all(inode, lower_inode);
6481+ fsstack_copy_inode_size(inode, lower_inode);
6482+}
6483+
6484+/*
6485+ * Connect a unionfs inode dentry/inode with several lower ones. This is
6486+ * the classic stackable file system "vnode interposition" action.
6487+ *
6488+ * @sb: unionfs's super_block
6489+ */
6490+struct dentry *unionfs_interpose(struct dentry *dentry, struct super_block *sb,
6491+ int flag)
6492+{
6493+ int err = 0;
6494+ struct inode *inode;
6495+ int need_fill_inode = 1;
6496+ struct dentry *spliced = NULL;
6497+
6498+ verify_locked(dentry);
6499+
6500+ /*
6501+ * We allocate our new inode below by calling unionfs_iget,
6502+ * which will initialize some of the new inode's fields
6503+ */
6504+
6505+ /*
6506+ * On revalidate we've already got our own inode and just need
6507+ * to fix it up.
6508+ */
6509+ if (flag == INTERPOSE_REVAL) {
6510+ inode = dentry->d_inode;
6511+ UNIONFS_I(inode)->bstart = -1;
6512+ UNIONFS_I(inode)->bend = -1;
6513+ atomic_set(&UNIONFS_I(inode)->generation,
6514+ atomic_read(&UNIONFS_SB(sb)->generation));
6515+
6516+ UNIONFS_I(inode)->lower_inodes =
6517+ kcalloc(sbmax(sb), sizeof(struct inode *), GFP_KERNEL);
6518+ if (unlikely(!UNIONFS_I(inode)->lower_inodes)) {
6519+ err = -ENOMEM;
6520+ goto out;
6521+ }
6522+ } else {
6523+ /* get unique inode number for unionfs */
6524+ inode = unionfs_iget(sb, iunique(sb, UNIONFS_ROOT_INO));
6525+ if (IS_ERR(inode)) {
6526+ err = PTR_ERR(inode);
6527+ goto out;
6528+ }
6529+ if (atomic_read(&inode->i_count) > 1)
6530+ goto skip;
6531+ }
6532+
6533+ need_fill_inode = 0;
6534+ unionfs_fill_inode(dentry, inode);
6535+
6536+skip:
6537+ /* only (our) lookup wants to do a d_add */
6538+ switch (flag) {
6539+ case INTERPOSE_DEFAULT:
6540+ /* for operations which create new inodes */
6541+ d_add(dentry, inode);
6542+ break;
6543+ case INTERPOSE_REVAL_NEG:
6544+ d_instantiate(dentry, inode);
6545+ break;
6546+ case INTERPOSE_LOOKUP:
6547+ spliced = d_splice_alias(inode, dentry);
6548+ if (spliced && spliced != dentry) {
6549+ /*
6550+ * d_splice can return a dentry if it was
6551+ * disconnected and had to be moved. We must ensure
6552+ * that the private data of the new dentry is
6553+ * correct and that the inode info was filled
6554+ * properly. Finally we must return this new
6555+ * dentry.
6556+ */
6557+ spliced->d_op = &unionfs_dops;
6558+ spliced->d_fsdata = dentry->d_fsdata;
6559+ dentry->d_fsdata = NULL;
6560+ dentry = spliced;
6561+ if (need_fill_inode) {
6562+ need_fill_inode = 0;
6563+ unionfs_fill_inode(dentry, inode);
6564+ }
6565+ goto out_spliced;
6566+ } else if (!spliced) {
6567+ if (need_fill_inode) {
6568+ need_fill_inode = 0;
6569+ unionfs_fill_inode(dentry, inode);
6570+ goto out_spliced;
6571+ }
6572+ }
6573+ break;
6574+ case INTERPOSE_REVAL:
6575+ /* Do nothing. */
6576+ break;
6577+ default:
6578+ printk(KERN_CRIT "unionfs: invalid interpose flag passed!\n");
6579+ BUG();
6580+ }
6581+ goto out;
6582+
6583+out_spliced:
6584+ if (!err)
6585+ return spliced;
6586+out:
6587+ return ERR_PTR(err);
6588+}
6589+
6590+/* like interpose above, but for an already existing dentry */
6591+void unionfs_reinterpose(struct dentry *dentry)
6592+{
6593+ struct dentry *lower_dentry;
6594+ struct inode *inode;
6595+ int bindex, bstart, bend;
6596+
6597+ verify_locked(dentry);
6598+
6599+ /* This is pre-allocated inode */
6600+ inode = dentry->d_inode;
6601+
6602+ bstart = dbstart(dentry);
6603+ bend = dbend(dentry);
6604+ for (bindex = bstart; bindex <= bend; bindex++) {
6605+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
6606+ if (!lower_dentry)
6607+ continue;
6608+
6609+ if (!lower_dentry->d_inode)
6610+ continue;
6611+ if (unionfs_lower_inode_idx(inode, bindex))
6612+ continue;
6613+ unionfs_set_lower_inode_idx(inode, bindex,
6614+ igrab(lower_dentry->d_inode));
6615+ }
6616+ ibstart(inode) = dbstart(dentry);
6617+ ibend(inode) = dbend(dentry);
6618+}
6619+
6620+/*
6621+ * make sure the branch we just looked up (nd) makes sense:
6622+ *
6623+ * 1) we're not trying to stack unionfs on top of unionfs
6624+ * 2) it exists
6625+ * 3) is a directory
6626+ */
6627+int check_branch(struct nameidata *nd)
6628+{
6629+ /* XXX: remove in ODF code -- stacking unions allowed there */
6630+ if (!strcmp(nd->path.dentry->d_sb->s_type->name, UNIONFS_NAME))
6631+ return -EINVAL;
6632+ if (!nd->path.dentry->d_inode)
6633+ return -ENOENT;
6634+ if (!S_ISDIR(nd->path.dentry->d_inode->i_mode))
6635+ return -ENOTDIR;
6636+ return 0;
6637+}
6638+
6639+/* checks if two lower_dentries have overlapping branches */
6640+static int is_branch_overlap(struct dentry *dent1, struct dentry *dent2)
6641+{
6642+ struct dentry *dent = NULL;
6643+
6644+ dent = dent1;
6645+ while ((dent != dent2) && (dent->d_parent != dent))
6646+ dent = dent->d_parent;
6647+
6648+ if (dent == dent2)
6649+ return 1;
6650+
6651+ dent = dent2;
6652+ while ((dent != dent1) && (dent->d_parent != dent))
6653+ dent = dent->d_parent;
6654+
6655+ return (dent == dent1);
6656+}
6657+
6658+/*
6659+ * Parse "ro" or "rw" options, but default to "rw" if no mode options was
6660+ * specified. Fill the mode bits in @perms. If encounter an unknown
6661+ * string, return -EINVAL. Otherwise return 0.
6662+ */
6663+int parse_branch_mode(const char *name, int *perms)
6664+{
6665+ if (!name || !strcmp(name, "rw")) {
6666+ *perms = MAY_READ | MAY_WRITE;
6667+ return 0;
6668+ }
6669+ if (!strcmp(name, "ro")) {
6670+ *perms = MAY_READ;
6671+ return 0;
6672+ }
6673+ return -EINVAL;
6674+}
6675+
6676+/*
6677+ * parse the dirs= mount argument
6678+ *
6679+ * We don't need to lock the superblock private data's rwsem, as we get
6680+ * called only by unionfs_read_super - it is still a long time before anyone
6681+ * can even get a reference to us.
6682+ */
6683+static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info
6684+ *lower_root_info, char *options)
6685+{
6686+ struct nameidata nd;
6687+ char *name;
6688+ int err = 0;
6689+ int branches = 1;
6690+ int bindex = 0;
6691+ int i = 0;
6692+ int j = 0;
6693+ struct dentry *dent1;
6694+ struct dentry *dent2;
6695+
6696+ if (options[0] == '\0') {
6697+ printk(KERN_ERR "unionfs: no branches specified\n");
6698+ err = -EINVAL;
6699+ goto out;
6700+ }
6701+
6702+ /*
6703+ * Each colon means we have a separator, this is really just a rough
6704+ * guess, since strsep will handle empty fields for us.
6705+ */
6706+ for (i = 0; options[i]; i++)
6707+ if (options[i] == ':')
6708+ branches++;
6709+
6710+ /* allocate space for underlying pointers to lower dentry */
6711+ UNIONFS_SB(sb)->data =
6712+ kcalloc(branches, sizeof(struct unionfs_data), GFP_KERNEL);
6713+ if (unlikely(!UNIONFS_SB(sb)->data)) {
6714+ err = -ENOMEM;
6715+ goto out;
6716+ }
6717+
6718+ lower_root_info->lower_paths =
6719+ kcalloc(branches, sizeof(struct path), GFP_KERNEL);
6720+ if (unlikely(!lower_root_info->lower_paths)) {
6721+ err = -ENOMEM;
6722+ goto out;
6723+ }
6724+
6725+ /* now parsing a string such as "b1:b2=rw:b3=ro:b4" */
6726+ branches = 0;
6727+ while ((name = strsep(&options, ":")) != NULL) {
6728+ int perms;
6729+ char *mode = strchr(name, '=');
6730+
6731+ if (!name)
6732+ continue;
6733+ if (!*name) { /* bad use of ':' (extra colons) */
6734+ err = -EINVAL;
6735+ goto out;
6736+ }
6737+
6738+ branches++;
6739+
6740+ /* strip off '=' if any */
6741+ if (mode)
6742+ *mode++ = '\0';
6743+
6744+ err = parse_branch_mode(mode, &perms);
6745+ if (err) {
6746+ printk(KERN_ERR "unionfs: invalid mode \"%s\" for "
6747+ "branch %d\n", mode, bindex);
6748+ goto out;
6749+ }
6750+ /* ensure that leftmost branch is writeable */
6751+ if (!bindex && !(perms & MAY_WRITE)) {
6752+ printk(KERN_ERR "unionfs: leftmost branch cannot be "
6753+ "read-only (use \"-o ro\" to create a "
6754+ "read-only union)\n");
6755+ err = -EINVAL;
6756+ goto out;
6757+ }
6758+
6759+ err = path_lookup(name, LOOKUP_FOLLOW, &nd);
6760+ if (err) {
6761+ printk(KERN_ERR "unionfs: error accessing "
6762+ "lower directory '%s' (error %d)\n",
6763+ name, err);
6764+ goto out;
6765+ }
6766+
6767+ err = check_branch(&nd);
6768+ if (err) {
6769+ printk(KERN_ERR "unionfs: lower directory "
6770+ "'%s' is not a valid branch\n", name);
6771+ path_put(&nd.path);
6772+ goto out;
6773+ }
6774+
6775+ lower_root_info->lower_paths[bindex].dentry = nd.path.dentry;
6776+ lower_root_info->lower_paths[bindex].mnt = nd.path.mnt;
6777+
6778+ set_branchperms(sb, bindex, perms);
6779+ set_branch_count(sb, bindex, 0);
6780+ new_branch_id(sb, bindex);
6781+
6782+ if (lower_root_info->bstart < 0)
6783+ lower_root_info->bstart = bindex;
6784+ lower_root_info->bend = bindex;
6785+ bindex++;
6786+ }
6787+
6788+ if (branches == 0) {
6789+ printk(KERN_ERR "unionfs: no branches specified\n");
6790+ err = -EINVAL;
6791+ goto out;
6792+ }
6793+
6794+ BUG_ON(branches != (lower_root_info->bend + 1));
6795+
6796+ /*
6797+ * Ensure that no overlaps exist in the branches.
6798+ *
6799+ * This test is required because the Linux kernel has no support
6800+ * currently for ensuring coherency between stackable layers and
6801+ * branches. If we were to allow overlapping branches, it would be
6802+ * possible, for example, to delete a file via one branch, which
6803+ * would not be reflected in another branch. Such incoherency could
6804+ * lead to inconsistencies and even kernel oopses. Rather than
6805+ * implement hacks to work around some of these cache-coherency
6806+ * problems, we prevent branch overlapping, for now. A complete
6807+ * solution will involve proper kernel/VFS support for cache
6808+ * coherency, at which time we could safely remove this
6809+ * branch-overlapping test.
6810+ */
6811+ for (i = 0; i < branches; i++) {
6812+ dent1 = lower_root_info->lower_paths[i].dentry;
6813+ for (j = i + 1; j < branches; j++) {
6814+ dent2 = lower_root_info->lower_paths[j].dentry;
6815+ if (is_branch_overlap(dent1, dent2)) {
6816+ printk(KERN_ERR "unionfs: branches %d and "
6817+ "%d overlap\n", i, j);
6818+ err = -EINVAL;
6819+ goto out;
6820+ }
6821+ }
6822+ }
6823+
6824+out:
6825+ if (err) {
6826+ for (i = 0; i < branches; i++)
6827+ path_put(&lower_root_info->lower_paths[i]);
6828+
6829+ kfree(lower_root_info->lower_paths);
6830+ kfree(UNIONFS_SB(sb)->data);
6831+
6832+ /*
6833+ * MUST clear the pointers to prevent potential double free if
6834+ * the caller dies later on
6835+ */
6836+ lower_root_info->lower_paths = NULL;
6837+ UNIONFS_SB(sb)->data = NULL;
6838+ }
6839+ return err;
6840+}
6841+
6842+/*
6843+ * Parse mount options. See the manual page for usage instructions.
6844+ *
6845+ * Returns the dentry object of the lower-level (lower) directory;
6846+ * We want to mount our stackable file system on top of that lower directory.
6847+ */
6848+static struct unionfs_dentry_info *unionfs_parse_options(
6849+ struct super_block *sb,
6850+ char *options)
6851+{
6852+ struct unionfs_dentry_info *lower_root_info;
6853+ char *optname;
6854+ int err = 0;
6855+ int bindex;
6856+ int dirsfound = 0;
6857+
6858+ /* allocate private data area */
6859+ err = -ENOMEM;
6860+ lower_root_info =
6861+ kzalloc(sizeof(struct unionfs_dentry_info), GFP_KERNEL);
6862+ if (unlikely(!lower_root_info))
6863+ goto out_error;
6864+ lower_root_info->bstart = -1;
6865+ lower_root_info->bend = -1;
6866+ lower_root_info->bopaque = -1;
6867+
6868+ while ((optname = strsep(&options, ",")) != NULL) {
6869+ char *optarg;
6870+
6871+ if (!optname || !*optname)
6872+ continue;
6873+
6874+ optarg = strchr(optname, '=');
6875+ if (optarg)
6876+ *optarg++ = '\0';
6877+
6878+ /*
6879+ * All of our options take an argument now. Insert ones that
6880+ * don't, above this check.
6881+ */
6882+ if (!optarg) {
6883+ printk(KERN_ERR "unionfs: %s requires an argument\n",
6884+ optname);
6885+ err = -EINVAL;
6886+ goto out_error;
6887+ }
6888+
6889+ if (!strcmp("dirs", optname)) {
6890+ if (++dirsfound > 1) {
6891+ printk(KERN_ERR
6892+ "unionfs: multiple dirs specified\n");
6893+ err = -EINVAL;
6894+ goto out_error;
6895+ }
6896+ err = parse_dirs_option(sb, lower_root_info, optarg);
6897+ if (err)
6898+ goto out_error;
6899+ continue;
6900+ }
6901+
6902+ err = -EINVAL;
6903+ printk(KERN_ERR
6904+ "unionfs: unrecognized option '%s'\n", optname);
6905+ goto out_error;
6906+ }
6907+ if (dirsfound != 1) {
6908+ printk(KERN_ERR "unionfs: dirs option required\n");
6909+ err = -EINVAL;
6910+ goto out_error;
6911+ }
6912+ goto out;
6913+
6914+out_error:
6915+ if (lower_root_info && lower_root_info->lower_paths) {
6916+ for (bindex = lower_root_info->bstart;
6917+ bindex >= 0 && bindex <= lower_root_info->bend;
6918+ bindex++)
6919+ path_put(&lower_root_info->lower_paths[bindex]);
6920+ }
6921+
6922+ kfree(lower_root_info->lower_paths);
6923+ kfree(lower_root_info);
6924+
6925+ kfree(UNIONFS_SB(sb)->data);
6926+ UNIONFS_SB(sb)->data = NULL;
6927+
6928+ lower_root_info = ERR_PTR(err);
6929+out:
6930+ return lower_root_info;
6931+}
6932+
6933+/*
6934+ * our custom d_alloc_root work-alike
6935+ *
6936+ * we can't use d_alloc_root if we want to use our own interpose function
6937+ * unchanged, so we simply call our own "fake" d_alloc_root
6938+ */
6939+static struct dentry *unionfs_d_alloc_root(struct super_block *sb)
6940+{
6941+ struct dentry *ret = NULL;
6942+
6943+ if (sb) {
6944+ static const struct qstr name = {
6945+ .name = "/",
6946+ .len = 1
6947+ };
6948+
6949+ ret = d_alloc(NULL, &name);
6950+ if (likely(ret)) {
6951+ ret->d_op = &unionfs_dops;
6952+ ret->d_sb = sb;
6953+ ret->d_parent = ret;
6954+ }
6955+ }
6956+ return ret;
6957+}
6958+
6959+/*
6960+ * There is no need to lock the unionfs_super_info's rwsem as there is no
6961+ * way anyone can have a reference to the superblock at this point in time.
6962+ */
6963+static int unionfs_read_super(struct super_block *sb, void *raw_data,
6964+ int silent)
6965+{
6966+ int err = 0;
6967+ struct unionfs_dentry_info *lower_root_info = NULL;
6968+ int bindex, bstart, bend;
6969+
6970+ if (!raw_data) {
6971+ printk(KERN_ERR
6972+ "unionfs: read_super: missing data argument\n");
6973+ err = -EINVAL;
6974+ goto out;
6975+ }
6976+
6977+ /* Allocate superblock private data */
6978+ sb->s_fs_info = kzalloc(sizeof(struct unionfs_sb_info), GFP_KERNEL);
6979+ if (unlikely(!UNIONFS_SB(sb))) {
6980+ printk(KERN_CRIT "unionfs: read_super: out of memory\n");
6981+ err = -ENOMEM;
6982+ goto out;
6983+ }
6984+
6985+ UNIONFS_SB(sb)->bend = -1;
6986+ atomic_set(&UNIONFS_SB(sb)->generation, 1);
6987+ init_rwsem(&UNIONFS_SB(sb)->rwsem);
6988+ UNIONFS_SB(sb)->high_branch_id = -1; /* -1 == invalid branch ID */
6989+
6990+ lower_root_info = unionfs_parse_options(sb, raw_data);
6991+ if (IS_ERR(lower_root_info)) {
6992+ printk(KERN_ERR
6993+ "unionfs: read_super: error while parsing options "
6994+ "(err = %ld)\n", PTR_ERR(lower_root_info));
6995+ err = PTR_ERR(lower_root_info);
6996+ lower_root_info = NULL;
6997+ goto out_free;
6998+ }
6999+ if (lower_root_info->bstart == -1) {
7000+ err = -ENOENT;
7001+ goto out_free;
7002+ }
7003+
7004+ /* set the lower superblock field of upper superblock */
7005+ bstart = lower_root_info->bstart;
7006+ BUG_ON(bstart != 0);
7007+ sbend(sb) = bend = lower_root_info->bend;
7008+ for (bindex = bstart; bindex <= bend; bindex++) {
7009+ struct dentry *d = lower_root_info->lower_paths[bindex].dentry;
7010+ atomic_inc(&d->d_sb->s_active);
7011+ unionfs_set_lower_super_idx(sb, bindex, d->d_sb);
7012+ }
7013+
7014+ /* max Bytes is the maximum bytes from highest priority branch */
7015+ sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
7016+
7017+ /*
7018+ * Our c/m/atime granularity is 1 ns because we may stack on file
7019+ * systems whose granularity is as good. This is important for our
7020+ * time-based cache coherency.
7021+ */
7022+ sb->s_time_gran = 1;
7023+
7024+ sb->s_op = &unionfs_sops;
7025+
7026+ /* See comment next to the definition of unionfs_d_alloc_root */
7027+ sb->s_root = unionfs_d_alloc_root(sb);
7028+ if (unlikely(!sb->s_root)) {
7029+ err = -ENOMEM;
7030+ goto out_dput;
7031+ }
7032+
7033+ /* link the upper and lower dentries */
7034+ sb->s_root->d_fsdata = NULL;
7035+ err = new_dentry_private_data(sb->s_root, UNIONFS_DMUTEX_ROOT);
7036+ if (unlikely(err))
7037+ goto out_freedpd;
7038+
7039+ /* Set the lower dentries for s_root */
7040+ for (bindex = bstart; bindex <= bend; bindex++) {
7041+ struct dentry *d;
7042+ struct vfsmount *m;
7043+
7044+ d = lower_root_info->lower_paths[bindex].dentry;
7045+ m = lower_root_info->lower_paths[bindex].mnt;
7046+
7047+ unionfs_set_lower_dentry_idx(sb->s_root, bindex, d);
7048+ unionfs_set_lower_mnt_idx(sb->s_root, bindex, m);
7049+ }
7050+ dbstart(sb->s_root) = bstart;
7051+ dbend(sb->s_root) = bend;
7052+
7053+ /* Set the generation number to one, since this is for the mount. */
7054+ atomic_set(&UNIONFS_D(sb->s_root)->generation, 1);
7055+
7056+ /*
7057+ * Call interpose to create the upper level inode. Only
7058+ * INTERPOSE_LOOKUP can return a value other than 0 on err.
7059+ */
7060+ err = PTR_ERR(unionfs_interpose(sb->s_root, sb, 0));
7061+ unionfs_unlock_dentry(sb->s_root);
7062+ if (!err)
7063+ goto out;
7064+ /* else fall through */
7065+
7066+out_freedpd:
7067+ if (UNIONFS_D(sb->s_root)) {
7068+ kfree(UNIONFS_D(sb->s_root)->lower_paths);
7069+ free_dentry_private_data(sb->s_root);
7070+ }
7071+ dput(sb->s_root);
7072+
7073+out_dput:
7074+ if (lower_root_info && !IS_ERR(lower_root_info)) {
7075+ for (bindex = lower_root_info->bstart;
7076+ bindex <= lower_root_info->bend; bindex++) {
7077+ struct dentry *d;
7078+ d = lower_root_info->lower_paths[bindex].dentry;
7079+ /* drop refs we took earlier */
7080+ atomic_dec(&d->d_sb->s_active);
7081+ path_put(&lower_root_info->lower_paths[bindex]);
7082+ }
7083+ kfree(lower_root_info->lower_paths);
7084+ kfree(lower_root_info);
7085+ lower_root_info = NULL;
7086+ }
7087+
7088+out_free:
7089+ kfree(UNIONFS_SB(sb)->data);
7090+ kfree(UNIONFS_SB(sb));
7091+ sb->s_fs_info = NULL;
7092+
7093+out:
7094+ if (lower_root_info && !IS_ERR(lower_root_info)) {
7095+ kfree(lower_root_info->lower_paths);
7096+ kfree(lower_root_info);
7097+ }
7098+ return err;
7099+}
7100+
7101+static int unionfs_get_sb(struct file_system_type *fs_type,
7102+ int flags, const char *dev_name,
7103+ void *raw_data, struct vfsmount *mnt)
7104+{
7105+ int err;
7106+ err = get_sb_nodev(fs_type, flags, raw_data, unionfs_read_super, mnt);
7107+ if (!err)
7108+ UNIONFS_SB(mnt->mnt_sb)->dev_name =
7109+ kstrdup(dev_name, GFP_KERNEL);
7110+ return err;
7111+}
7112+
7113+static struct file_system_type unionfs_fs_type = {
7114+ .owner = THIS_MODULE,
7115+ .name = UNIONFS_NAME,
7116+ .get_sb = unionfs_get_sb,
7117+ .kill_sb = generic_shutdown_super,
7118+ .fs_flags = FS_REVAL_DOT,
7119+};
7120+
7121+static int __init init_unionfs_fs(void)
7122+{
7123+ int err;
7124+
7125+ pr_info("Registering unionfs " UNIONFS_VERSION "\n");
7126+
7127+ err = unionfs_init_filldir_cache();
7128+ if (unlikely(err))
7129+ goto out;
7130+ err = unionfs_init_inode_cache();
7131+ if (unlikely(err))
7132+ goto out;
7133+ err = unionfs_init_dentry_cache();
7134+ if (unlikely(err))
7135+ goto out;
7136+ err = init_sioq();
7137+ if (unlikely(err))
7138+ goto out;
7139+ err = register_filesystem(&unionfs_fs_type);
7140+out:
7141+ if (unlikely(err)) {
7142+ stop_sioq();
7143+ unionfs_destroy_filldir_cache();
7144+ unionfs_destroy_inode_cache();
7145+ unionfs_destroy_dentry_cache();
7146+ }
7147+ return err;
7148+}
7149+
7150+static void __exit exit_unionfs_fs(void)
7151+{
7152+ stop_sioq();
7153+ unionfs_destroy_filldir_cache();
7154+ unionfs_destroy_inode_cache();
7155+ unionfs_destroy_dentry_cache();
7156+ unregister_filesystem(&unionfs_fs_type);
7157+ pr_info("Completed unionfs module unload\n");
7158+}
7159+
7160+MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
7161+ " (http://www.fsl.cs.sunysb.edu)");
7162+MODULE_DESCRIPTION("Unionfs " UNIONFS_VERSION
7163+ " (http://unionfs.filesystems.org)");
7164+MODULE_LICENSE("GPL");
7165+
7166+module_init(init_unionfs_fs);
7167+module_exit(exit_unionfs_fs);
7168diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c
7169new file mode 100644
7170index 0000000..1f70535
7171--- /dev/null
7172+++ b/fs/unionfs/mmap.c
7173@@ -0,0 +1,89 @@
7174+/*
7175+ * Copyright (c) 2003-2010 Erez Zadok
7176+ * Copyright (c) 2003-2006 Charles P. Wright
7177+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
7178+ * Copyright (c) 2005-2006 Junjiro Okajima
7179+ * Copyright (c) 2006 Shaya Potter
7180+ * Copyright (c) 2005 Arun M. Krishnakumar
7181+ * Copyright (c) 2004-2006 David P. Quigley
7182+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
7183+ * Copyright (c) 2003 Puja Gupta
7184+ * Copyright (c) 2003 Harikesavan Krishnan
7185+ * Copyright (c) 2003-2010 Stony Brook University
7186+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
7187+ *
7188+ * This program is free software; you can redistribute it and/or modify
7189+ * it under the terms of the GNU General Public License version 2 as
7190+ * published by the Free Software Foundation.
7191+ */
7192+
7193+#include "union.h"
7194+
7195+
7196+/*
7197+ * XXX: we need a dummy readpage handler because generic_file_mmap (which we
7198+ * use in unionfs_mmap) checks for the existence of
7199+ * mapping->a_ops->readpage, else it returns -ENOEXEC. The VFS will need to
7200+ * be fixed to allow a file system to define vm_ops->fault without any
7201+ * address_space_ops whatsoever.
7202+ *
7203+ * Otherwise, we don't want to use our readpage method at all.
7204+ */
7205+static int unionfs_readpage(struct file *file, struct page *page)
7206+{
7207+ BUG();
7208+ return -EINVAL;
7209+}
7210+
7211+static int unionfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
7212+{
7213+ int err;
7214+ struct file *file, *lower_file;
7215+ const struct vm_operations_struct *lower_vm_ops;
7216+ struct vm_area_struct lower_vma;
7217+
7218+ BUG_ON(!vma);
7219+ memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
7220+ file = lower_vma.vm_file;
7221+ lower_vm_ops = UNIONFS_F(file)->lower_vm_ops;
7222+ BUG_ON(!lower_vm_ops);
7223+
7224+ lower_file = unionfs_lower_file(file);
7225+ BUG_ON(!lower_file);
7226+ /*
7227+ * XXX: vm_ops->fault may be called in parallel. Because we have to
7228+ * resort to temporarily changing the vma->vm_file to point to the
7229+ * lower file, a concurrent invocation of unionfs_fault could see a
7230+ * different value. In this workaround, we keep a different copy of
7231+ * the vma structure in our stack, so we never expose a different
7232+ * value of the vma->vm_file called to us, even temporarily. A
7233+ * better fix would be to change the calling semantics of ->fault to
7234+ * take an explicit file pointer.
7235+ */
7236+ lower_vma.vm_file = lower_file;
7237+ err = lower_vm_ops->fault(&lower_vma, vmf);
7238+ return err;
7239+}
7240+
7241+/*
7242+ * XXX: the default address_space_ops for unionfs is empty. We cannot set
7243+ * our inode->i_mapping->a_ops to NULL because too many code paths expect
7244+ * the a_ops vector to be non-NULL.
7245+ */
7246+struct address_space_operations unionfs_aops = {
7247+ /* empty on purpose */
7248+};
7249+
7250+/*
7251+ * XXX: we need a second, dummy address_space_ops vector, to be used
7252+ * temporarily during unionfs_mmap, because the latter calls
7253+ * generic_file_mmap, which checks if ->readpage exists, else returns
7254+ * -ENOEXEC.
7255+ */
7256+struct address_space_operations unionfs_dummy_aops = {
7257+ .readpage = unionfs_readpage,
7258+};
7259+
7260+struct vm_operations_struct unionfs_vm_ops = {
7261+ .fault = unionfs_fault,
7262+};
7263diff --git a/fs/unionfs/rdstate.c b/fs/unionfs/rdstate.c
7264new file mode 100644
7265index 0000000..f745fbc
7266--- /dev/null
7267+++ b/fs/unionfs/rdstate.c
7268@@ -0,0 +1,285 @@
7269+/*
7270+ * Copyright (c) 2003-2010 Erez Zadok
7271+ * Copyright (c) 2003-2006 Charles P. Wright
7272+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
7273+ * Copyright (c) 2005-2006 Junjiro Okajima
7274+ * Copyright (c) 2005 Arun M. Krishnakumar
7275+ * Copyright (c) 2004-2006 David P. Quigley
7276+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
7277+ * Copyright (c) 2003 Puja Gupta
7278+ * Copyright (c) 2003 Harikesavan Krishnan
7279+ * Copyright (c) 2003-2010 Stony Brook University
7280+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
7281+ *
7282+ * This program is free software; you can redistribute it and/or modify
7283+ * it under the terms of the GNU General Public License version 2 as
7284+ * published by the Free Software Foundation.
7285+ */
7286+
7287+#include "union.h"
7288+
7289+/* This file contains the routines for maintaining readdir state. */
7290+
7291+/*
7292+ * There are two structures here, rdstate which is a hash table
7293+ * of the second structure which is a filldir_node.
7294+ */
7295+
7296+/*
7297+ * This is a struct kmem_cache for filldir nodes, because we allocate a lot
7298+ * of them and they shouldn't waste memory. If the node has a small name
7299+ * (as defined by the dentry structure), then we use an inline name to
7300+ * preserve kmalloc space.
7301+ */
7302+static struct kmem_cache *unionfs_filldir_cachep;
7303+
7304+int unionfs_init_filldir_cache(void)
7305+{
7306+ unionfs_filldir_cachep =
7307+ kmem_cache_create("unionfs_filldir",
7308+ sizeof(struct filldir_node), 0,
7309+ SLAB_RECLAIM_ACCOUNT, NULL);
7310+
7311+ return (unionfs_filldir_cachep ? 0 : -ENOMEM);
7312+}
7313+
7314+void unionfs_destroy_filldir_cache(void)
7315+{
7316+ if (unionfs_filldir_cachep)
7317+ kmem_cache_destroy(unionfs_filldir_cachep);
7318+}
7319+
7320+/*
7321+ * This is a tuning parameter that tells us roughly how big to make the
7322+ * hash table in directory entries per page. This isn't perfect, but
7323+ * at least we get a hash table size that shouldn't be too overloaded.
7324+ * The following averages are based on my home directory.
7325+ * 14.44693 Overall
7326+ * 12.29 Single Page Directories
7327+ * 117.93 Multi-page directories
7328+ */
7329+#define DENTPAGE 4096
7330+#define DENTPERONEPAGE 12
7331+#define DENTPERPAGE 118
7332+#define MINHASHSIZE 1
7333+static int guesstimate_hash_size(struct inode *inode)
7334+{
7335+ struct inode *lower_inode;
7336+ int bindex;
7337+ int hashsize = MINHASHSIZE;
7338+
7339+ if (UNIONFS_I(inode)->hashsize > 0)
7340+ return UNIONFS_I(inode)->hashsize;
7341+
7342+ for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
7343+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
7344+ if (!lower_inode)
7345+ continue;
7346+
7347+ if (i_size_read(lower_inode) == DENTPAGE)
7348+ hashsize += DENTPERONEPAGE;
7349+ else
7350+ hashsize += (i_size_read(lower_inode) / DENTPAGE) *
7351+ DENTPERPAGE;
7352+ }
7353+
7354+ return hashsize;
7355+}
7356+
7357+int init_rdstate(struct file *file)
7358+{
7359+ BUG_ON(sizeof(loff_t) !=
7360+ (sizeof(unsigned int) + sizeof(unsigned int)));
7361+ BUG_ON(UNIONFS_F(file)->rdstate != NULL);
7362+
7363+ UNIONFS_F(file)->rdstate = alloc_rdstate(file->f_path.dentry->d_inode,
7364+ fbstart(file));
7365+
7366+ return (UNIONFS_F(file)->rdstate ? 0 : -ENOMEM);
7367+}
7368+
7369+struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos)
7370+{
7371+ struct unionfs_dir_state *rdstate = NULL;
7372+ struct list_head *pos;
7373+
7374+ spin_lock(&UNIONFS_I(inode)->rdlock);
7375+ list_for_each(pos, &UNIONFS_I(inode)->readdircache) {
7376+ struct unionfs_dir_state *r =
7377+ list_entry(pos, struct unionfs_dir_state, cache);
7378+ if (fpos == rdstate2offset(r)) {
7379+ UNIONFS_I(inode)->rdcount--;
7380+ list_del(&r->cache);
7381+ rdstate = r;
7382+ break;
7383+ }
7384+ }
7385+ spin_unlock(&UNIONFS_I(inode)->rdlock);
7386+ return rdstate;
7387+}
7388+
7389+struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex)
7390+{
7391+ int i = 0;
7392+ int hashsize;
7393+ unsigned long mallocsize = sizeof(struct unionfs_dir_state);
7394+ struct unionfs_dir_state *rdstate;
7395+
7396+ hashsize = guesstimate_hash_size(inode);
7397+ mallocsize += hashsize * sizeof(struct list_head);
7398+ mallocsize = __roundup_pow_of_two(mallocsize);
7399+
7400+ /* This should give us about 500 entries anyway. */
7401+ if (mallocsize > PAGE_SIZE)
7402+ mallocsize = PAGE_SIZE;
7403+
7404+ hashsize = (mallocsize - sizeof(struct unionfs_dir_state)) /
7405+ sizeof(struct list_head);
7406+
7407+ rdstate = kmalloc(mallocsize, GFP_KERNEL);
7408+ if (unlikely(!rdstate))
7409+ return NULL;
7410+
7411+ spin_lock(&UNIONFS_I(inode)->rdlock);
7412+ if (UNIONFS_I(inode)->cookie >= (MAXRDCOOKIE - 1))
7413+ UNIONFS_I(inode)->cookie = 1;
7414+ else
7415+ UNIONFS_I(inode)->cookie++;
7416+
7417+ rdstate->cookie = UNIONFS_I(inode)->cookie;
7418+ spin_unlock(&UNIONFS_I(inode)->rdlock);
7419+ rdstate->offset = 1;
7420+ rdstate->access = jiffies;
7421+ rdstate->bindex = bindex;
7422+ rdstate->dirpos = 0;
7423+ rdstate->hashentries = 0;
7424+ rdstate->size = hashsize;
7425+ for (i = 0; i < rdstate->size; i++)
7426+ INIT_LIST_HEAD(&rdstate->list[i]);
7427+
7428+ return rdstate;
7429+}
7430+
7431+static void free_filldir_node(struct filldir_node *node)
7432+{
7433+ if (node->namelen >= DNAME_INLINE_LEN_MIN)
7434+ kfree(node->name);
7435+ kmem_cache_free(unionfs_filldir_cachep, node);
7436+}
7437+
7438+void free_rdstate(struct unionfs_dir_state *state)
7439+{
7440+ struct filldir_node *tmp;
7441+ int i;
7442+
7443+ for (i = 0; i < state->size; i++) {
7444+ struct list_head *head = &(state->list[i]);
7445+ struct list_head *pos, *n;
7446+
7447+ /* traverse the list and deallocate space */
7448+ list_for_each_safe(pos, n, head) {
7449+ tmp = list_entry(pos, struct filldir_node, file_list);
7450+ list_del(&tmp->file_list);
7451+ free_filldir_node(tmp);
7452+ }
7453+ }
7454+
7455+ kfree(state);
7456+}
7457+
7458+struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
7459+ const char *name, int namelen,
7460+ int is_whiteout)
7461+{
7462+ int index;
7463+ unsigned int hash;
7464+ struct list_head *head;
7465+ struct list_head *pos;
7466+ struct filldir_node *cursor = NULL;
7467+ int found = 0;
7468+
7469+ BUG_ON(namelen <= 0);
7470+
7471+ hash = full_name_hash(name, namelen);
7472+ index = hash % rdstate->size;
7473+
7474+ head = &(rdstate->list[index]);
7475+ list_for_each(pos, head) {
7476+ cursor = list_entry(pos, struct filldir_node, file_list);
7477+
7478+ if (cursor->namelen == namelen && cursor->hash == hash &&
7479+ !strncmp(cursor->name, name, namelen)) {
7480+ /*
7481+ * a duplicate exists, and hence no need to create
7482+ * entry to the list
7483+ */
7484+ found = 1;
7485+
7486+ /*
7487+ * if a duplicate is found in this branch, and is
7488+ * not due to the caller looking for an entry to
7489+ * whiteout, then the file system may be corrupted.
7490+ */
7491+ if (unlikely(!is_whiteout &&
7492+ cursor->bindex == rdstate->bindex))
7493+ printk(KERN_ERR "unionfs: filldir: possible "
7494+ "I/O error: a file is duplicated "
7495+ "in the same branch %d: %s\n",
7496+ rdstate->bindex, cursor->name);
7497+ break;
7498+ }
7499+ }
7500+
7501+ if (!found)
7502+ cursor = NULL;
7503+
7504+ return cursor;
7505+}
7506+
7507+int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name,
7508+ int namelen, int bindex, int whiteout)
7509+{
7510+ struct filldir_node *new;
7511+ unsigned int hash;
7512+ int index;
7513+ int err = 0;
7514+ struct list_head *head;
7515+
7516+ BUG_ON(namelen <= 0);
7517+
7518+ hash = full_name_hash(name, namelen);
7519+ index = hash % rdstate->size;
7520+ head = &(rdstate->list[index]);
7521+
7522+ new = kmem_cache_alloc(unionfs_filldir_cachep, GFP_KERNEL);
7523+ if (unlikely(!new)) {
7524+ err = -ENOMEM;
7525+ goto out;
7526+ }
7527+
7528+ INIT_LIST_HEAD(&new->file_list);
7529+ new->namelen = namelen;
7530+ new->hash = hash;
7531+ new->bindex = bindex;
7532+ new->whiteout = whiteout;
7533+
7534+ if (namelen < DNAME_INLINE_LEN_MIN) {
7535+ new->name = new->iname;
7536+ } else {
7537+ new->name = kmalloc(namelen + 1, GFP_KERNEL);
7538+ if (unlikely(!new->name)) {
7539+ kmem_cache_free(unionfs_filldir_cachep, new);
7540+ new = NULL;
7541+ goto out;
7542+ }
7543+ }
7544+
7545+ memcpy(new->name, name, namelen);
7546+ new->name[namelen] = '\0';
7547+
7548+ rdstate->hashentries++;
7549+
7550+ list_add(&(new->file_list), head);
7551+out:
7552+ return err;
7553+}
7554diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
7555new file mode 100644
7556index 0000000..936700e
7557--- /dev/null
7558+++ b/fs/unionfs/rename.c
7559@@ -0,0 +1,517 @@
7560+/*
7561+ * Copyright (c) 2003-2010 Erez Zadok
7562+ * Copyright (c) 2003-2006 Charles P. Wright
7563+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
7564+ * Copyright (c) 2005-2006 Junjiro Okajima
7565+ * Copyright (c) 2005 Arun M. Krishnakumar
7566+ * Copyright (c) 2004-2006 David P. Quigley
7567+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
7568+ * Copyright (c) 2003 Puja Gupta
7569+ * Copyright (c) 2003 Harikesavan Krishnan
7570+ * Copyright (c) 2003-2010 Stony Brook University
7571+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
7572+ *
7573+ * This program is free software; you can redistribute it and/or modify
7574+ * it under the terms of the GNU General Public License version 2 as
7575+ * published by the Free Software Foundation.
7576+ */
7577+
7578+#include "union.h"
7579+
7580+/*
7581+ * This is a helper function for rename, used when rename ends up with hosed
7582+ * over dentries and we need to revert.
7583+ */
7584+static int unionfs_refresh_lower_dentry(struct dentry *dentry,
7585+ struct dentry *parent, int bindex)
7586+{
7587+ struct dentry *lower_dentry;
7588+ struct dentry *lower_parent;
7589+ int err = 0;
7590+
7591+ verify_locked(dentry);
7592+
7593+ lower_parent = unionfs_lower_dentry_idx(parent, bindex);
7594+
7595+ BUG_ON(!S_ISDIR(lower_parent->d_inode->i_mode));
7596+
7597+ lower_dentry = lookup_one_len(dentry->d_name.name, lower_parent,
7598+ dentry->d_name.len);
7599+ if (IS_ERR(lower_dentry)) {
7600+ err = PTR_ERR(lower_dentry);
7601+ goto out;
7602+ }
7603+
7604+ dput(unionfs_lower_dentry_idx(dentry, bindex));
7605+ iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
7606+ unionfs_set_lower_inode_idx(dentry->d_inode, bindex, NULL);
7607+
7608+ if (!lower_dentry->d_inode) {
7609+ dput(lower_dentry);
7610+ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
7611+ } else {
7612+ unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry);
7613+ unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
7614+ igrab(lower_dentry->d_inode));
7615+ }
7616+
7617+out:
7618+ return err;
7619+}
7620+
7621+static int __unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
7622+ struct dentry *old_parent,
7623+ struct inode *new_dir, struct dentry *new_dentry,
7624+ struct dentry *new_parent,
7625+ int bindex)
7626+{
7627+ int err = 0;
7628+ struct dentry *lower_old_dentry;
7629+ struct dentry *lower_new_dentry;
7630+ struct dentry *lower_old_dir_dentry;
7631+ struct dentry *lower_new_dir_dentry;
7632+ struct dentry *trap;
7633+
7634+ lower_new_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
7635+ lower_old_dentry = unionfs_lower_dentry_idx(old_dentry, bindex);
7636+
7637+ if (!lower_new_dentry) {
7638+ lower_new_dentry =
7639+ create_parents(new_parent->d_inode,
7640+ new_dentry, new_dentry->d_name.name,
7641+ bindex);
7642+ if (IS_ERR(lower_new_dentry)) {
7643+ err = PTR_ERR(lower_new_dentry);
7644+ if (IS_COPYUP_ERR(err))
7645+ goto out;
7646+ printk(KERN_ERR "unionfs: error creating directory "
7647+ "tree for rename, bindex=%d err=%d\n",
7648+ bindex, err);
7649+ goto out;
7650+ }
7651+ }
7652+
7653+ /* check for and remove whiteout, if any */
7654+ err = check_unlink_whiteout(new_dentry, lower_new_dentry, bindex);
7655+ if (err > 0) /* ignore if whiteout found and successfully removed */
7656+ err = 0;
7657+ if (err)
7658+ goto out;
7659+
7660+ /* check of old_dentry branch is writable */
7661+ err = is_robranch_super(old_dentry->d_sb, bindex);
7662+ if (err)
7663+ goto out;
7664+
7665+ dget(lower_old_dentry);
7666+ dget(lower_new_dentry);
7667+ lower_old_dir_dentry = dget_parent(lower_old_dentry);
7668+ lower_new_dir_dentry = dget_parent(lower_new_dentry);
7669+
7670+ trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
7671+ /* source should not be ancenstor of target */
7672+ if (trap == lower_old_dentry) {
7673+ err = -EINVAL;
7674+ goto out_err_unlock;
7675+ }
7676+ /* target should not be ancenstor of source */
7677+ if (trap == lower_new_dentry) {
7678+ err = -ENOTEMPTY;
7679+ goto out_err_unlock;
7680+ }
7681+ err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
7682+ lower_new_dir_dentry->d_inode, lower_new_dentry);
7683+out_err_unlock:
7684+ if (!err) {
7685+ /* update parent dir times */
7686+ fsstack_copy_attr_times(old_dir, lower_old_dir_dentry->d_inode);
7687+ fsstack_copy_attr_times(new_dir, lower_new_dir_dentry->d_inode);
7688+ }
7689+ unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
7690+
7691+ dput(lower_old_dir_dentry);
7692+ dput(lower_new_dir_dentry);
7693+ dput(lower_old_dentry);
7694+ dput(lower_new_dentry);
7695+
7696+out:
7697+ if (!err) {
7698+ /* Fixup the new_dentry. */
7699+ if (bindex < dbstart(new_dentry))
7700+ dbstart(new_dentry) = bindex;
7701+ else if (bindex > dbend(new_dentry))
7702+ dbend(new_dentry) = bindex;
7703+ }
7704+
7705+ return err;
7706+}
7707+
7708+/*
7709+ * Main rename code. This is sufficiently complex, that it's documented in
7710+ * Documentation/filesystems/unionfs/rename.txt. This routine calls
7711+ * __unionfs_rename() above to perform some of the work.
7712+ */
7713+static int do_unionfs_rename(struct inode *old_dir,
7714+ struct dentry *old_dentry,
7715+ struct dentry *old_parent,
7716+ struct inode *new_dir,
7717+ struct dentry *new_dentry,
7718+ struct dentry *new_parent)
7719+{
7720+ int err = 0;
7721+ int bindex;
7722+ int old_bstart, old_bend;
7723+ int new_bstart, new_bend;
7724+ int do_copyup = -1;
7725+ int local_err = 0;
7726+ int eio = 0;
7727+ int revert = 0;
7728+
7729+ old_bstart = dbstart(old_dentry);
7730+ old_bend = dbend(old_dentry);
7731+
7732+ new_bstart = dbstart(new_dentry);
7733+ new_bend = dbend(new_dentry);
7734+
7735+ /* Rename source to destination. */
7736+ err = __unionfs_rename(old_dir, old_dentry, old_parent,
7737+ new_dir, new_dentry, new_parent,
7738+ old_bstart);
7739+ if (err) {
7740+ if (!IS_COPYUP_ERR(err))
7741+ goto out;
7742+ do_copyup = old_bstart - 1;
7743+ } else {
7744+ revert = 1;
7745+ }
7746+
7747+ /*
7748+ * Unlink all instances of destination that exist to the left of
7749+ * bstart of source. On error, revert back, goto out.
7750+ */
7751+ for (bindex = old_bstart - 1; bindex >= new_bstart; bindex--) {
7752+ struct dentry *unlink_dentry;
7753+ struct dentry *unlink_dir_dentry;
7754+
7755+ BUG_ON(bindex < 0);
7756+ unlink_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
7757+ if (!unlink_dentry)
7758+ continue;
7759+
7760+ unlink_dir_dentry = lock_parent(unlink_dentry);
7761+ err = is_robranch_super(old_dir->i_sb, bindex);
7762+ if (!err)
7763+ err = vfs_unlink(unlink_dir_dentry->d_inode,
7764+ unlink_dentry);
7765+
7766+ fsstack_copy_attr_times(new_parent->d_inode,
7767+ unlink_dir_dentry->d_inode);
7768+ /* propagate number of hard-links */
7769+ new_parent->d_inode->i_nlink =
7770+ unionfs_get_nlinks(new_parent->d_inode);
7771+
7772+ unlock_dir(unlink_dir_dentry);
7773+ if (!err) {
7774+ if (bindex != new_bstart) {
7775+ dput(unlink_dentry);
7776+ unionfs_set_lower_dentry_idx(new_dentry,
7777+ bindex, NULL);
7778+ }
7779+ } else if (IS_COPYUP_ERR(err)) {
7780+ do_copyup = bindex - 1;
7781+ } else if (revert) {
7782+ goto revert;
7783+ }
7784+ }
7785+
7786+ if (do_copyup != -1) {
7787+ for (bindex = do_copyup; bindex >= 0; bindex--) {
7788+ /*
7789+ * copyup the file into some left directory, so that
7790+ * you can rename it
7791+ */
7792+ err = copyup_dentry(old_parent->d_inode,
7793+ old_dentry, old_bstart, bindex,
7794+ old_dentry->d_name.name,
7795+ old_dentry->d_name.len, NULL,
7796+ i_size_read(old_dentry->d_inode));
7797+ /* if copyup failed, try next branch to the left */
7798+ if (err)
7799+ continue;
7800+ /*
7801+ * create whiteout before calling __unionfs_rename
7802+ * because the latter will change the old_dentry's
7803+ * lower name and parent dir, resulting in the
7804+ * whiteout getting created in the wrong dir.
7805+ */
7806+ err = create_whiteout(old_dentry, bindex);
7807+ if (err) {
7808+ printk(KERN_ERR "unionfs: can't create a "
7809+ "whiteout for %s in rename (err=%d)\n",
7810+ old_dentry->d_name.name, err);
7811+ continue;
7812+ }
7813+ err = __unionfs_rename(old_dir, old_dentry, old_parent,
7814+ new_dir, new_dentry, new_parent,
7815+ bindex);
7816+ break;
7817+ }
7818+ }
7819+
7820+ /* make it opaque */
7821+ if (S_ISDIR(old_dentry->d_inode->i_mode)) {
7822+ err = make_dir_opaque(old_dentry, dbstart(old_dentry));
7823+ if (err)
7824+ goto revert;
7825+ }
7826+
7827+ /*
7828+ * Create whiteout for source, only if:
7829+ * (1) There is more than one underlying instance of source.
7830+ * (We did a copy_up is taken care of above).
7831+ */
7832+ if ((old_bstart != old_bend) && (do_copyup == -1)) {
7833+ err = create_whiteout(old_dentry, old_bstart);
7834+ if (err) {
7835+ /* can't fix anything now, so we exit with -EIO */
7836+ printk(KERN_ERR "unionfs: can't create a whiteout for "
7837+ "%s in rename!\n", old_dentry->d_name.name);
7838+ err = -EIO;
7839+ }
7840+ }
7841+
7842+out:
7843+ return err;
7844+
7845+revert:
7846+ /* Do revert here. */
7847+ local_err = unionfs_refresh_lower_dentry(new_dentry, new_parent,
7848+ old_bstart);
7849+ if (local_err) {
7850+ printk(KERN_ERR "unionfs: revert failed in rename: "
7851+ "the new refresh failed\n");
7852+ eio = -EIO;
7853+ }
7854+
7855+ local_err = unionfs_refresh_lower_dentry(old_dentry, old_parent,
7856+ old_bstart);
7857+ if (local_err) {
7858+ printk(KERN_ERR "unionfs: revert failed in rename: "
7859+ "the old refresh failed\n");
7860+ eio = -EIO;
7861+ goto revert_out;
7862+ }
7863+
7864+ if (!unionfs_lower_dentry_idx(new_dentry, bindex) ||
7865+ !unionfs_lower_dentry_idx(new_dentry, bindex)->d_inode) {
7866+ printk(KERN_ERR "unionfs: revert failed in rename: "
7867+ "the object disappeared from under us!\n");
7868+ eio = -EIO;
7869+ goto revert_out;
7870+ }
7871+
7872+ if (unionfs_lower_dentry_idx(old_dentry, bindex) &&
7873+ unionfs_lower_dentry_idx(old_dentry, bindex)->d_inode) {
7874+ printk(KERN_ERR "unionfs: revert failed in rename: "
7875+ "the object was created underneath us!\n");
7876+ eio = -EIO;
7877+ goto revert_out;
7878+ }
7879+
7880+ local_err = __unionfs_rename(new_dir, new_dentry, new_parent,
7881+ old_dir, old_dentry, old_parent,
7882+ old_bstart);
7883+
7884+ /* If we can't fix it, then we cop-out with -EIO. */
7885+ if (local_err) {
7886+ printk(KERN_ERR "unionfs: revert failed in rename!\n");
7887+ eio = -EIO;
7888+ }
7889+
7890+ local_err = unionfs_refresh_lower_dentry(new_dentry, new_parent,
7891+ bindex);
7892+ if (local_err)
7893+ eio = -EIO;
7894+ local_err = unionfs_refresh_lower_dentry(old_dentry, old_parent,
7895+ bindex);
7896+ if (local_err)
7897+ eio = -EIO;
7898+
7899+revert_out:
7900+ if (eio)
7901+ err = eio;
7902+ return err;
7903+}
7904+
7905+/*
7906+ * We can't copyup a directory, because it may involve huge numbers of
7907+ * children, etc. Doing that in the kernel would be bad, so instead we
7908+ * return EXDEV to the user-space utility that caused this, and let the
7909+ * user-space recurse and ask us to copy up each file separately.
7910+ */
7911+static int may_rename_dir(struct dentry *dentry, struct dentry *parent)
7912+{
7913+ int err, bstart;
7914+
7915+ err = check_empty(dentry, parent, NULL);
7916+ if (err == -ENOTEMPTY) {
7917+ if (is_robranch(dentry))
7918+ return -EXDEV;
7919+ } else if (err) {
7920+ return err;
7921+ }
7922+
7923+ bstart = dbstart(dentry);
7924+ if (dbend(dentry) == bstart || dbopaque(dentry) == bstart)
7925+ return 0;
7926+
7927+ dbstart(dentry) = bstart + 1;
7928+ err = check_empty(dentry, parent, NULL);
7929+ dbstart(dentry) = bstart;
7930+ if (err == -ENOTEMPTY)
7931+ err = -EXDEV;
7932+ return err;
7933+}
7934+
7935+/*
7936+ * The locking rules in unionfs_rename are complex. We could use a simpler
7937+ * superblock-level name-space lock for renames and copy-ups.
7938+ */
7939+int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
7940+ struct inode *new_dir, struct dentry *new_dentry)
7941+{
7942+ int err = 0;
7943+ struct dentry *wh_dentry;
7944+ struct dentry *old_parent, *new_parent;
7945+ int valid = true;
7946+
7947+ unionfs_read_lock(old_dentry->d_sb, UNIONFS_SMUTEX_CHILD);
7948+ old_parent = dget_parent(old_dentry);
7949+ new_parent = dget_parent(new_dentry);
7950+ /* un/lock parent dentries only if they differ from old/new_dentry */
7951+ if (old_parent != old_dentry &&
7952+ old_parent != new_dentry)
7953+ unionfs_lock_dentry(old_parent, UNIONFS_DMUTEX_REVAL_PARENT);
7954+ if (new_parent != old_dentry &&
7955+ new_parent != new_dentry &&
7956+ new_parent != old_parent)
7957+ unionfs_lock_dentry(new_parent, UNIONFS_DMUTEX_REVAL_CHILD);
7958+ unionfs_double_lock_dentry(old_dentry, new_dentry);
7959+
7960+ valid = __unionfs_d_revalidate(old_dentry, old_parent, false);
7961+ if (!valid) {
7962+ err = -ESTALE;
7963+ goto out;
7964+ }
7965+ if (!d_deleted(new_dentry) && new_dentry->d_inode) {
7966+ valid = __unionfs_d_revalidate(new_dentry, new_parent, false);
7967+ if (!valid) {
7968+ err = -ESTALE;
7969+ goto out;
7970+ }
7971+ }
7972+
7973+ if (!S_ISDIR(old_dentry->d_inode->i_mode))
7974+ err = unionfs_partial_lookup(old_dentry, old_parent);
7975+ else
7976+ err = may_rename_dir(old_dentry, old_parent);
7977+
7978+ if (err)
7979+ goto out;
7980+
7981+ err = unionfs_partial_lookup(new_dentry, new_parent);
7982+ if (err)
7983+ goto out;
7984+
7985+ /*
7986+ * if new_dentry is already lower because of whiteout,
7987+ * simply override it even if the whited-out dir is not empty.
7988+ */
7989+ wh_dentry = find_first_whiteout(new_dentry);
7990+ if (!IS_ERR(wh_dentry)) {
7991+ dput(wh_dentry);
7992+ } else if (new_dentry->d_inode) {
7993+ if (S_ISDIR(old_dentry->d_inode->i_mode) !=
7994+ S_ISDIR(new_dentry->d_inode->i_mode)) {
7995+ err = S_ISDIR(old_dentry->d_inode->i_mode) ?
7996+ -ENOTDIR : -EISDIR;
7997+ goto out;
7998+ }
7999+
8000+ if (S_ISDIR(new_dentry->d_inode->i_mode)) {
8001+ struct unionfs_dir_state *namelist = NULL;
8002+ /* check if this unionfs directory is empty or not */
8003+ err = check_empty(new_dentry, new_parent, &namelist);
8004+ if (err)
8005+ goto out;
8006+
8007+ if (!is_robranch(new_dentry))
8008+ err = delete_whiteouts(new_dentry,
8009+ dbstart(new_dentry),
8010+ namelist);
8011+
8012+ free_rdstate(namelist);
8013+
8014+ if (err)
8015+ goto out;
8016+ }
8017+ }
8018+
8019+ err = do_unionfs_rename(old_dir, old_dentry, old_parent,
8020+ new_dir, new_dentry, new_parent);
8021+ if (err)
8022+ goto out;
8023+
8024+ /*
8025+ * force re-lookup since the dir on ro branch is not renamed, and
8026+ * lower dentries still indicate the un-renamed ones.
8027+ */
8028+ if (S_ISDIR(old_dentry->d_inode->i_mode))
8029+ atomic_dec(&UNIONFS_D(old_dentry)->generation);
8030+ else
8031+ unionfs_postcopyup_release(old_dentry);
8032+ if (new_dentry->d_inode && !S_ISDIR(new_dentry->d_inode->i_mode)) {
8033+ unionfs_postcopyup_release(new_dentry);
8034+ unionfs_postcopyup_setmnt(new_dentry);
8035+ if (!unionfs_lower_inode(new_dentry->d_inode)) {
8036+ /*
8037+ * If we get here, it means that no copyup was
8038+ * needed, and that a file by the old name already
8039+ * existing on the destination branch; that file got
8040+ * renamed earlier in this function, so all we need
8041+ * to do here is set the lower inode.
8042+ */
8043+ struct inode *inode;
8044+ inode = unionfs_lower_inode(old_dentry->d_inode);
8045+ igrab(inode);
8046+ unionfs_set_lower_inode_idx(new_dentry->d_inode,
8047+ dbstart(new_dentry),
8048+ inode);
8049+ }
8050+ }
8051+ /* if all of this renaming succeeded, update our times */
8052+ unionfs_copy_attr_times(old_dentry->d_inode);
8053+ unionfs_copy_attr_times(new_dentry->d_inode);
8054+ unionfs_check_inode(old_dir);
8055+ unionfs_check_inode(new_dir);
8056+ unionfs_check_dentry(old_dentry);
8057+ unionfs_check_dentry(new_dentry);
8058+
8059+out:
8060+ if (err) /* clear the new_dentry stuff created */
8061+ d_drop(new_dentry);
8062+
8063+ unionfs_double_unlock_dentry(old_dentry, new_dentry);
8064+ if (new_parent != old_dentry &&
8065+ new_parent != new_dentry &&
8066+ new_parent != old_parent)
8067+ unionfs_unlock_dentry(new_parent);
8068+ if (old_parent != old_dentry &&
8069+ old_parent != new_dentry)
8070+ unionfs_unlock_dentry(old_parent);
8071+ dput(new_parent);
8072+ dput(old_parent);
8073+ unionfs_read_unlock(old_dentry->d_sb);
8074+
8075+ return err;
8076+}
8077diff --git a/fs/unionfs/sioq.c b/fs/unionfs/sioq.c
8078new file mode 100644
8079index 0000000..760c580
8080--- /dev/null
8081+++ b/fs/unionfs/sioq.c
8082@@ -0,0 +1,101 @@
8083+/*
8084+ * Copyright (c) 2006-2010 Erez Zadok
8085+ * Copyright (c) 2006 Charles P. Wright
8086+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
8087+ * Copyright (c) 2006 Junjiro Okajima
8088+ * Copyright (c) 2006 David P. Quigley
8089+ * Copyright (c) 2006-2010 Stony Brook University
8090+ * Copyright (c) 2006-2010 The Research Foundation of SUNY
8091+ *
8092+ * This program is free software; you can redistribute it and/or modify
8093+ * it under the terms of the GNU General Public License version 2 as
8094+ * published by the Free Software Foundation.
8095+ */
8096+
8097+#include "union.h"
8098+
8099+/*
8100+ * Super-user IO work Queue - sometimes we need to perform actions which
8101+ * would fail due to the unix permissions on the parent directory (e.g.,
8102+ * rmdir a directory which appears empty, but in reality contains
8103+ * whiteouts).
8104+ */
8105+
8106+static struct workqueue_struct *superio_workqueue;
8107+
8108+int __init init_sioq(void)
8109+{
8110+ int err;
8111+
8112+ superio_workqueue = create_workqueue("unionfs_siod");
8113+ if (!IS_ERR(superio_workqueue))
8114+ return 0;
8115+
8116+ err = PTR_ERR(superio_workqueue);
8117+ printk(KERN_ERR "unionfs: create_workqueue failed %d\n", err);
8118+ superio_workqueue = NULL;
8119+ return err;
8120+}
8121+
8122+void stop_sioq(void)
8123+{
8124+ if (superio_workqueue)
8125+ destroy_workqueue(superio_workqueue);
8126+}
8127+
8128+void run_sioq(work_func_t func, struct sioq_args *args)
8129+{
8130+ INIT_WORK(&args->work, func);
8131+
8132+ init_completion(&args->comp);
8133+ while (!queue_work(superio_workqueue, &args->work)) {
8134+ /* TODO: do accounting if needed */
8135+ schedule();
8136+ }
8137+ wait_for_completion(&args->comp);
8138+}
8139+
8140+void __unionfs_create(struct work_struct *work)
8141+{
8142+ struct sioq_args *args = container_of(work, struct sioq_args, work);
8143+ struct create_args *c = &args->create;
8144+
8145+ args->err = vfs_create(c->parent, c->dentry, c->mode, c->nd);
8146+ complete(&args->comp);
8147+}
8148+
8149+void __unionfs_mkdir(struct work_struct *work)
8150+{
8151+ struct sioq_args *args = container_of(work, struct sioq_args, work);
8152+ struct mkdir_args *m = &args->mkdir;
8153+
8154+ args->err = vfs_mkdir(m->parent, m->dentry, m->mode);
8155+ complete(&args->comp);
8156+}
8157+
8158+void __unionfs_mknod(struct work_struct *work)
8159+{
8160+ struct sioq_args *args = container_of(work, struct sioq_args, work);
8161+ struct mknod_args *m = &args->mknod;
8162+
8163+ args->err = vfs_mknod(m->parent, m->dentry, m->mode, m->dev);
8164+ complete(&args->comp);
8165+}
8166+
8167+void __unionfs_symlink(struct work_struct *work)
8168+{
8169+ struct sioq_args *args = container_of(work, struct sioq_args, work);
8170+ struct symlink_args *s = &args->symlink;
8171+
8172+ args->err = vfs_symlink(s->parent, s->dentry, s->symbuf);
8173+ complete(&args->comp);
8174+}
8175+
8176+void __unionfs_unlink(struct work_struct *work)
8177+{
8178+ struct sioq_args *args = container_of(work, struct sioq_args, work);
8179+ struct unlink_args *u = &args->unlink;
8180+
8181+ args->err = vfs_unlink(u->parent, u->dentry);
8182+ complete(&args->comp);
8183+}
8184diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
8185new file mode 100644
8186index 0000000..b26d248
8187--- /dev/null
8188+++ b/fs/unionfs/sioq.h
8189@@ -0,0 +1,91 @@
8190+/*
8191+ * Copyright (c) 2006-2010 Erez Zadok
8192+ * Copyright (c) 2006 Charles P. Wright
8193+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
8194+ * Copyright (c) 2006 Junjiro Okajima
8195+ * Copyright (c) 2006 David P. Quigley
8196+ * Copyright (c) 2006-2010 Stony Brook University
8197+ * Copyright (c) 2006-2010 The Research Foundation of SUNY
8198+ *
8199+ * This program is free software; you can redistribute it and/or modify
8200+ * it under the terms of the GNU General Public License version 2 as
8201+ * published by the Free Software Foundation.
8202+ */
8203+
8204+#ifndef _SIOQ_H
8205+#define _SIOQ_H
8206+
8207+struct deletewh_args {
8208+ struct unionfs_dir_state *namelist;
8209+ struct dentry *dentry;
8210+ int bindex;
8211+};
8212+
8213+struct is_opaque_args {
8214+ struct dentry *dentry;
8215+};
8216+
8217+struct create_args {
8218+ struct inode *parent;
8219+ struct dentry *dentry;
8220+ umode_t mode;
8221+ struct nameidata *nd;
8222+};
8223+
8224+struct mkdir_args {
8225+ struct inode *parent;
8226+ struct dentry *dentry;
8227+ umode_t mode;
8228+};
8229+
8230+struct mknod_args {
8231+ struct inode *parent;
8232+ struct dentry *dentry;
8233+ umode_t mode;
8234+ dev_t dev;
8235+};
8236+
8237+struct symlink_args {
8238+ struct inode *parent;
8239+ struct dentry *dentry;
8240+ char *symbuf;
8241+};
8242+
8243+struct unlink_args {
8244+ struct inode *parent;
8245+ struct dentry *dentry;
8246+};
8247+
8248+
8249+struct sioq_args {
8250+ struct completion comp;
8251+ struct work_struct work;
8252+ int err;
8253+ void *ret;
8254+
8255+ union {
8256+ struct deletewh_args deletewh;
8257+ struct is_opaque_args is_opaque;
8258+ struct create_args create;
8259+ struct mkdir_args mkdir;
8260+ struct mknod_args mknod;
8261+ struct symlink_args symlink;
8262+ struct unlink_args unlink;
8263+ };
8264+};
8265+
8266+/* Extern definitions for SIOQ functions */
8267+extern int __init init_sioq(void);
8268+extern void stop_sioq(void);
8269+extern void run_sioq(work_func_t func, struct sioq_args *args);
8270+
8271+/* Extern definitions for our privilege escalation helpers */
8272+extern void __unionfs_create(struct work_struct *work);
8273+extern void __unionfs_mkdir(struct work_struct *work);
8274+extern void __unionfs_mknod(struct work_struct *work);
8275+extern void __unionfs_symlink(struct work_struct *work);
8276+extern void __unionfs_unlink(struct work_struct *work);
8277+extern void __delete_whiteouts(struct work_struct *work);
8278+extern void __is_opaque_dir(struct work_struct *work);
8279+
8280+#endif /* not _SIOQ_H */
8281diff --git a/fs/unionfs/subr.c b/fs/unionfs/subr.c
8282new file mode 100644
8283index 0000000..570a344
8284--- /dev/null
8285+++ b/fs/unionfs/subr.c
8286@@ -0,0 +1,95 @@
8287+/*
8288+ * Copyright (c) 2003-2010 Erez Zadok
8289+ * Copyright (c) 2003-2006 Charles P. Wright
8290+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
8291+ * Copyright (c) 2005-2006 Junjiro Okajima
8292+ * Copyright (c) 2005 Arun M. Krishnakumar
8293+ * Copyright (c) 2004-2006 David P. Quigley
8294+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
8295+ * Copyright (c) 2003 Puja Gupta
8296+ * Copyright (c) 2003 Harikesavan Krishnan
8297+ * Copyright (c) 2003-2010 Stony Brook University
8298+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
8299+ *
8300+ * This program is free software; you can redistribute it and/or modify
8301+ * it under the terms of the GNU General Public License version 2 as
8302+ * published by the Free Software Foundation.
8303+ */
8304+
8305+#include "union.h"
8306+
8307+/*
8308+ * returns the right n_link value based on the inode type
8309+ */
8310+int unionfs_get_nlinks(const struct inode *inode)
8311+{
8312+ /* don't bother to do all the work since we're unlinked */
8313+ if (inode->i_nlink == 0)
8314+ return 0;
8315+
8316+ if (!S_ISDIR(inode->i_mode))
8317+ return unionfs_lower_inode(inode)->i_nlink;
8318+
8319+ /*
8320+ * For directories, we return 1. The only place that could cares
8321+ * about links is readdir, and there's d_type there so even that
8322+ * doesn't matter.
8323+ */
8324+ return 1;
8325+}
8326+
8327+/* copy a/m/ctime from the lower branch with the newest times */
8328+void unionfs_copy_attr_times(struct inode *upper)
8329+{
8330+ int bindex;
8331+ struct inode *lower;
8332+
8333+ if (!upper)
8334+ return;
8335+ if (ibstart(upper) < 0) {
8336+#ifdef CONFIG_UNION_FS_DEBUG
8337+ WARN_ON(ibstart(upper) < 0);
8338+#endif /* CONFIG_UNION_FS_DEBUG */
8339+ return;
8340+ }
8341+ for (bindex = ibstart(upper); bindex <= ibend(upper); bindex++) {
8342+ lower = unionfs_lower_inode_idx(upper, bindex);
8343+ if (!lower)
8344+ continue; /* not all lower dir objects may exist */
8345+ if (unlikely(timespec_compare(&upper->i_mtime,
8346+ &lower->i_mtime) < 0))
8347+ upper->i_mtime = lower->i_mtime;
8348+ if (unlikely(timespec_compare(&upper->i_ctime,
8349+ &lower->i_ctime) < 0))
8350+ upper->i_ctime = lower->i_ctime;
8351+ if (unlikely(timespec_compare(&upper->i_atime,
8352+ &lower->i_atime) < 0))
8353+ upper->i_atime = lower->i_atime;
8354+ }
8355+}
8356+
8357+/*
8358+ * A unionfs/fanout version of fsstack_copy_attr_all. Uses a
8359+ * unionfs_get_nlinks to properly calcluate the number of links to a file.
8360+ * Also, copies the max() of all a/m/ctimes for all lower inodes (which is
8361+ * important if the lower inode is a directory type)
8362+ */
8363+void unionfs_copy_attr_all(struct inode *dest,
8364+ const struct inode *src)
8365+{
8366+ dest->i_mode = src->i_mode;
8367+ dest->i_uid = src->i_uid;
8368+ dest->i_gid = src->i_gid;
8369+ dest->i_rdev = src->i_rdev;
8370+
8371+ unionfs_copy_attr_times(dest);
8372+
8373+ dest->i_blkbits = src->i_blkbits;
8374+ dest->i_flags = src->i_flags;
8375+
8376+ /*
8377+ * Update the nlinks AFTER updating the above fields, because the
8378+ * get_links callback may depend on them.
8379+ */
8380+ dest->i_nlink = unionfs_get_nlinks(dest);
8381+}
8382diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c
8383new file mode 100644
8384index 0000000..a8f5571
8385--- /dev/null
8386+++ b/fs/unionfs/super.c
8387@@ -0,0 +1,1048 @@
8388+/*
8389+ * Copyright (c) 2003-2010 Erez Zadok
8390+ * Copyright (c) 2003-2006 Charles P. Wright
8391+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
8392+ * Copyright (c) 2005-2006 Junjiro Okajima
8393+ * Copyright (c) 2005 Arun M. Krishnakumar
8394+ * Copyright (c) 2004-2006 David P. Quigley
8395+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
8396+ * Copyright (c) 2003 Puja Gupta
8397+ * Copyright (c) 2003 Harikesavan Krishnan
8398+ * Copyright (c) 2003-2010 Stony Brook University
8399+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
8400+ *
8401+ * This program is free software; you can redistribute it and/or modify
8402+ * it under the terms of the GNU General Public License version 2 as
8403+ * published by the Free Software Foundation.
8404+ */
8405+
8406+#include "union.h"
8407+
8408+/*
8409+ * The inode cache is used with alloc_inode for both our inode info and the
8410+ * vfs inode.
8411+ */
8412+static struct kmem_cache *unionfs_inode_cachep;
8413+
8414+struct inode *unionfs_iget(struct super_block *sb, unsigned long ino)
8415+{
8416+ int size;
8417+ struct unionfs_inode_info *info;
8418+ struct inode *inode;
8419+
8420+ inode = iget_locked(sb, ino);
8421+ if (!inode)
8422+ return ERR_PTR(-ENOMEM);
8423+ if (!(inode->i_state & I_NEW))
8424+ return inode;
8425+
8426+ info = UNIONFS_I(inode);
8427+ memset(info, 0, offsetof(struct unionfs_inode_info, vfs_inode));
8428+ info->bstart = -1;
8429+ info->bend = -1;
8430+ atomic_set(&info->generation,
8431+ atomic_read(&UNIONFS_SB(inode->i_sb)->generation));
8432+ spin_lock_init(&info->rdlock);
8433+ info->rdcount = 1;
8434+ info->hashsize = -1;
8435+ INIT_LIST_HEAD(&info->readdircache);
8436+
8437+ size = sbmax(inode->i_sb) * sizeof(struct inode *);
8438+ info->lower_inodes = kzalloc(size, GFP_KERNEL);
8439+ if (unlikely(!info->lower_inodes)) {
8440+ printk(KERN_CRIT "unionfs: no kernel memory when allocating "
8441+ "lower-pointer array!\n");
8442+ iget_failed(inode);
8443+ return ERR_PTR(-ENOMEM);
8444+ }
8445+
8446+ inode->i_version++;
8447+ inode->i_op = &unionfs_main_iops;
8448+ inode->i_fop = &unionfs_main_fops;
8449+
8450+ inode->i_mapping->a_ops = &unionfs_aops;
8451+
8452+ /*
8453+ * reset times so unionfs_copy_attr_all can keep out time invariants
8454+ * right (upper inode time being the max of all lower ones).
8455+ */
8456+ inode->i_atime.tv_sec = inode->i_atime.tv_nsec = 0;
8457+ inode->i_mtime.tv_sec = inode->i_mtime.tv_nsec = 0;
8458+ inode->i_ctime.tv_sec = inode->i_ctime.tv_nsec = 0;
8459+ unlock_new_inode(inode);
8460+ return inode;
8461+}
8462+
8463+/*
8464+ * we now define delete_inode, because there are two VFS paths that may
8465+ * destroy an inode: one of them calls clear inode before doing everything
8466+ * else that's needed, and the other is fine. This way we truncate the inode
8467+ * size (and its pages) and then clear our own inode, which will do an iput
8468+ * on our and the lower inode.
8469+ *
8470+ * No need to lock sb info's rwsem.
8471+ */
8472+static void unionfs_delete_inode(struct inode *inode)
8473+{
8474+#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
8475+ spin_lock(&inode->i_lock);
8476+#endif
8477+ i_size_write(inode, 0); /* every f/s seems to do that */
8478+#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
8479+ spin_unlock(&inode->i_lock);
8480+#endif
8481+
8482+ if (inode->i_data.nrpages)
8483+ truncate_inode_pages(&inode->i_data, 0);
8484+
8485+ clear_inode(inode);
8486+}
8487+
8488+/*
8489+ * final actions when unmounting a file system
8490+ *
8491+ * No need to lock rwsem.
8492+ */
8493+static void unionfs_put_super(struct super_block *sb)
8494+{
8495+ int bindex, bstart, bend;
8496+ struct unionfs_sb_info *spd;
8497+ int leaks = 0;
8498+
8499+ spd = UNIONFS_SB(sb);
8500+ if (!spd)
8501+ return;
8502+
8503+ bstart = sbstart(sb);
8504+ bend = sbend(sb);
8505+
8506+ /* Make sure we have no leaks of branchget/branchput. */
8507+ for (bindex = bstart; bindex <= bend; bindex++)
8508+ if (unlikely(branch_count(sb, bindex) != 0)) {
8509+ printk(KERN_CRIT
8510+ "unionfs: branch %d has %d references left!\n",
8511+ bindex, branch_count(sb, bindex));
8512+ leaks = 1;
8513+ }
8514+ WARN_ON(leaks != 0);
8515+
8516+ /* decrement lower super references */
8517+ for (bindex = bstart; bindex <= bend; bindex++) {
8518+ struct super_block *s;
8519+ s = unionfs_lower_super_idx(sb, bindex);
8520+ unionfs_set_lower_super_idx(sb, bindex, NULL);
8521+ atomic_dec(&s->s_active);
8522+ }
8523+
8524+ kfree(spd->dev_name);
8525+ kfree(spd->data);
8526+ kfree(spd);
8527+ sb->s_fs_info = NULL;
8528+}
8529+
8530+/*
8531+ * Since people use this to answer the "How big of a file can I write?"
8532+ * question, we report the size of the highest priority branch as the size of
8533+ * the union.
8534+ */
8535+static int unionfs_statfs(struct dentry *dentry, struct kstatfs *buf)
8536+{
8537+ int err = 0;
8538+ struct super_block *sb;
8539+ struct dentry *lower_dentry;
8540+ struct dentry *parent;
8541+ bool valid;
8542+
8543+ sb = dentry->d_sb;
8544+
8545+ unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD);
8546+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
8547+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
8548+
8549+ valid = __unionfs_d_revalidate(dentry, parent, false);
8550+ if (unlikely(!valid)) {
8551+ err = -ESTALE;
8552+ goto out;
8553+ }
8554+ unionfs_check_dentry(dentry);
8555+
8556+ lower_dentry = unionfs_lower_dentry(sb->s_root);
8557+ err = vfs_statfs(lower_dentry, buf);
8558+
8559+ /* set return buf to our f/s to avoid confusing user-level utils */
8560+ buf->f_type = UNIONFS_SUPER_MAGIC;
8561+ /*
8562+ * Our maximum file name can is shorter by a few bytes because every
8563+ * file name could potentially be whited-out.
8564+ *
8565+ * XXX: this restriction goes away with ODF.
8566+ */
8567+ unionfs_set_max_namelen(&buf->f_namelen);
8568+
8569+ /*
8570+ * reset two fields to avoid confusing user-land.
8571+ * XXX: is this still necessary?
8572+ */
8573+ memset(&buf->f_fsid, 0, sizeof(__kernel_fsid_t));
8574+ memset(&buf->f_spare, 0, sizeof(buf->f_spare));
8575+
8576+out:
8577+ unionfs_check_dentry(dentry);
8578+ unionfs_unlock_dentry(dentry);
8579+ unionfs_unlock_parent(dentry, parent);
8580+ unionfs_read_unlock(sb);
8581+ return err;
8582+}
8583+
8584+/* handle mode changing during remount */
8585+static noinline_for_stack int do_remount_mode_option(
8586+ char *optarg,
8587+ int cur_branches,
8588+ struct unionfs_data *new_data,
8589+ struct path *new_lower_paths)
8590+{
8591+ int err = -EINVAL;
8592+ int perms, idx;
8593+ char *modename = strchr(optarg, '=');
8594+ struct nameidata nd;
8595+
8596+ /* by now, optarg contains the branch name */
8597+ if (!*optarg) {
8598+ printk(KERN_ERR
8599+ "unionfs: no branch specified for mode change\n");
8600+ goto out;
8601+ }
8602+ if (!modename) {
8603+ printk(KERN_ERR "unionfs: branch \"%s\" requires a mode\n",
8604+ optarg);
8605+ goto out;
8606+ }
8607+ *modename++ = '\0';
8608+ err = parse_branch_mode(modename, &perms);
8609+ if (err) {
8610+ printk(KERN_ERR "unionfs: invalid mode \"%s\" for \"%s\"\n",
8611+ modename, optarg);
8612+ goto out;
8613+ }
8614+
8615+ /*
8616+ * Find matching branch index. For now, this assumes that nothing
8617+ * has been mounted on top of this Unionfs stack. Once we have /odf
8618+ * and cache-coherency resolved, we'll address the branch-path
8619+ * uniqueness.
8620+ */
8621+ err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
8622+ if (err) {
8623+ printk(KERN_ERR "unionfs: error accessing "
8624+ "lower directory \"%s\" (error %d)\n",
8625+ optarg, err);
8626+ goto out;
8627+ }
8628+ for (idx = 0; idx < cur_branches; idx++)
8629+ if (nd.path.mnt == new_lower_paths[idx].mnt &&
8630+ nd.path.dentry == new_lower_paths[idx].dentry)
8631+ break;
8632+ path_put(&nd.path); /* no longer needed */
8633+ if (idx == cur_branches) {
8634+ err = -ENOENT; /* err may have been reset above */
8635+ printk(KERN_ERR "unionfs: branch \"%s\" "
8636+ "not found\n", optarg);
8637+ goto out;
8638+ }
8639+ /* check/change mode for existing branch */
8640+ /* we don't warn if perms==branchperms */
8641+ new_data[idx].branchperms = perms;
8642+ err = 0;
8643+out:
8644+ return err;
8645+}
8646+
8647+/* handle branch deletion during remount */
8648+static noinline_for_stack int do_remount_del_option(
8649+ char *optarg, int cur_branches,
8650+ struct unionfs_data *new_data,
8651+ struct path *new_lower_paths)
8652+{
8653+ int err = -EINVAL;
8654+ int idx;
8655+ struct nameidata nd;
8656+
8657+ /* optarg contains the branch name to delete */
8658+
8659+ /*
8660+ * Find matching branch index. For now, this assumes that nothing
8661+ * has been mounted on top of this Unionfs stack. Once we have /odf
8662+ * and cache-coherency resolved, we'll address the branch-path
8663+ * uniqueness.
8664+ */
8665+ err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
8666+ if (err) {
8667+ printk(KERN_ERR "unionfs: error accessing "
8668+ "lower directory \"%s\" (error %d)\n",
8669+ optarg, err);
8670+ goto out;
8671+ }
8672+ for (idx = 0; idx < cur_branches; idx++)
8673+ if (nd.path.mnt == new_lower_paths[idx].mnt &&
8674+ nd.path.dentry == new_lower_paths[idx].dentry)
8675+ break;
8676+ path_put(&nd.path); /* no longer needed */
8677+ if (idx == cur_branches) {
8678+ printk(KERN_ERR "unionfs: branch \"%s\" "
8679+ "not found\n", optarg);
8680+ err = -ENOENT;
8681+ goto out;
8682+ }
8683+ /* check if there are any open files on the branch to be deleted */
8684+ if (atomic_read(&new_data[idx].open_files) > 0) {
8685+ err = -EBUSY;
8686+ goto out;
8687+ }
8688+
8689+ /*
8690+ * Now we have to delete the branch. First, release any handles it
8691+ * has. Then, move the remaining array indexes past "idx" in
8692+ * new_data and new_lower_paths one to the left. Finally, adjust
8693+ * cur_branches.
8694+ */
8695+ path_put(&new_lower_paths[idx]);
8696+
8697+ if (idx < cur_branches - 1) {
8698+ /* if idx==cur_branches-1, we delete last branch: easy */
8699+ memmove(&new_data[idx], &new_data[idx+1],
8700+ (cur_branches - 1 - idx) *
8701+ sizeof(struct unionfs_data));
8702+ memmove(&new_lower_paths[idx], &new_lower_paths[idx+1],
8703+ (cur_branches - 1 - idx) * sizeof(struct path));
8704+ }
8705+
8706+ err = 0;
8707+out:
8708+ return err;
8709+}
8710+
8711+/* handle branch insertion during remount */
8712+static noinline_for_stack int do_remount_add_option(
8713+ char *optarg, int cur_branches,
8714+ struct unionfs_data *new_data,
8715+ struct path *new_lower_paths,
8716+ int *high_branch_id)
8717+{
8718+ int err = -EINVAL;
8719+ int perms;
8720+ int idx = 0; /* default: insert at beginning */
8721+ char *new_branch , *modename = NULL;
8722+ struct nameidata nd;
8723+
8724+ /*
8725+ * optarg can be of several forms:
8726+ *
8727+ * /bar:/foo insert /foo before /bar
8728+ * /bar:/foo=ro insert /foo in ro mode before /bar
8729+ * /foo insert /foo in the beginning (prepend)
8730+ * :/foo insert /foo at the end (append)
8731+ */
8732+ if (*optarg == ':') { /* append? */
8733+ new_branch = optarg + 1; /* skip ':' */
8734+ idx = cur_branches;
8735+ goto found_insertion_point;
8736+ }
8737+ new_branch = strchr(optarg, ':');
8738+ if (!new_branch) { /* prepend? */
8739+ new_branch = optarg;
8740+ goto found_insertion_point;
8741+ }
8742+ *new_branch++ = '\0'; /* holds path+mode of new branch */
8743+
8744+ /*
8745+ * Find matching branch index. For now, this assumes that nothing
8746+ * has been mounted on top of this Unionfs stack. Once we have /odf
8747+ * and cache-coherency resolved, we'll address the branch-path
8748+ * uniqueness.
8749+ */
8750+ err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
8751+ if (err) {
8752+ printk(KERN_ERR "unionfs: error accessing "
8753+ "lower directory \"%s\" (error %d)\n",
8754+ optarg, err);
8755+ goto out;
8756+ }
8757+ for (idx = 0; idx < cur_branches; idx++)
8758+ if (nd.path.mnt == new_lower_paths[idx].mnt &&
8759+ nd.path.dentry == new_lower_paths[idx].dentry)
8760+ break;
8761+ path_put(&nd.path); /* no longer needed */
8762+ if (idx == cur_branches) {
8763+ printk(KERN_ERR "unionfs: branch \"%s\" "
8764+ "not found\n", optarg);
8765+ err = -ENOENT;
8766+ goto out;
8767+ }
8768+
8769+ /*
8770+ * At this point idx will hold the index where the new branch should
8771+ * be inserted before.
8772+ */
8773+found_insertion_point:
8774+ /* find the mode for the new branch */
8775+ if (new_branch)
8776+ modename = strchr(new_branch, '=');
8777+ if (modename)
8778+ *modename++ = '\0';
8779+ if (!new_branch || !*new_branch) {
8780+ printk(KERN_ERR "unionfs: null new branch\n");
8781+ err = -EINVAL;
8782+ goto out;
8783+ }
8784+ err = parse_branch_mode(modename, &perms);
8785+ if (err) {
8786+ printk(KERN_ERR "unionfs: invalid mode \"%s\" for "
8787+ "branch \"%s\"\n", modename, new_branch);
8788+ goto out;
8789+ }
8790+ err = path_lookup(new_branch, LOOKUP_FOLLOW, &nd);
8791+ if (err) {
8792+ printk(KERN_ERR "unionfs: error accessing "
8793+ "lower directory \"%s\" (error %d)\n",
8794+ new_branch, err);
8795+ goto out;
8796+ }
8797+ /*
8798+ * It's probably safe to check_mode the new branch to insert. Note:
8799+ * we don't allow inserting branches which are unionfs's by
8800+ * themselves (check_branch returns EINVAL in that case). This is
8801+ * because this code base doesn't support stacking unionfs: the ODF
8802+ * code base supports that correctly.
8803+ */
8804+ err = check_branch(&nd);
8805+ if (err) {
8806+ printk(KERN_ERR "unionfs: lower directory "
8807+ "\"%s\" is not a valid branch\n", optarg);
8808+ path_put(&nd.path);
8809+ goto out;
8810+ }
8811+
8812+ /*
8813+ * Now we have to insert the new branch. But first, move the bits
8814+ * to make space for the new branch, if needed. Finally, adjust
8815+ * cur_branches.
8816+ * We don't release nd here; it's kept until umount/remount.
8817+ */
8818+ if (idx < cur_branches) {
8819+ /* if idx==cur_branches, we append: easy */
8820+ memmove(&new_data[idx+1], &new_data[idx],
8821+ (cur_branches - idx) * sizeof(struct unionfs_data));
8822+ memmove(&new_lower_paths[idx+1], &new_lower_paths[idx],
8823+ (cur_branches - idx) * sizeof(struct path));
8824+ }
8825+ new_lower_paths[idx].dentry = nd.path.dentry;
8826+ new_lower_paths[idx].mnt = nd.path.mnt;
8827+
8828+ new_data[idx].sb = nd.path.dentry->d_sb;
8829+ atomic_set(&new_data[idx].open_files, 0);
8830+ new_data[idx].branchperms = perms;
8831+ new_data[idx].branch_id = ++*high_branch_id; /* assign new branch ID */
8832+
8833+ err = 0;
8834+out:
8835+ return err;
8836+}
8837+
8838+
8839+/*
8840+ * Support branch management options on remount.
8841+ *
8842+ * See Documentation/filesystems/unionfs/ for details.
8843+ *
8844+ * @flags: numeric mount options
8845+ * @options: mount options string
8846+ *
8847+ * This function can rearrange a mounted union dynamically, adding and
8848+ * removing branches, including changing branch modes. Clearly this has to
8849+ * be done safely and atomically. Luckily, the VFS already calls this
8850+ * function with lock_super(sb) and lock_kernel() held, preventing
8851+ * concurrent mixing of new mounts, remounts, and unmounts. Moreover,
8852+ * do_remount_sb(), our caller function, already called shrink_dcache_sb(sb)
8853+ * to purge dentries/inodes from our superblock, and also called
8854+ * fsync_super(sb) to purge any dirty pages. So we're good.
8855+ *
8856+ * XXX: however, our remount code may also need to invalidate mapped pages
8857+ * so as to force them to be re-gotten from the (newly reconfigured) lower
8858+ * branches. This has to wait for proper mmap and cache coherency support
8859+ * in the VFS.
8860+ *
8861+ */
8862+static int unionfs_remount_fs(struct super_block *sb, int *flags,
8863+ char *options)
8864+{
8865+ int err = 0;
8866+ int i;
8867+ char *optionstmp, *tmp_to_free; /* kstrdup'ed of "options" */
8868+ char *optname;
8869+ int cur_branches = 0; /* no. of current branches */
8870+ int new_branches = 0; /* no. of branches actually left in the end */
8871+ int add_branches; /* est. no. of branches to add */
8872+ int del_branches; /* est. no. of branches to del */
8873+ int max_branches; /* max possible no. of branches */
8874+ struct unionfs_data *new_data = NULL, *tmp_data = NULL;
8875+ struct path *new_lower_paths = NULL, *tmp_lower_paths = NULL;
8876+ struct inode **new_lower_inodes = NULL;
8877+ int new_high_branch_id; /* new high branch ID */
8878+ int size; /* memory allocation size, temp var */
8879+ int old_ibstart, old_ibend;
8880+
8881+ unionfs_write_lock(sb);
8882+
8883+ /*
8884+ * The VFS will take care of "ro" and "rw" flags, and we can safely
8885+ * ignore MS_SILENT, but anything else left over is an error. So we
8886+ * need to check if any other flags may have been passed (none are
8887+ * allowed/supported as of now).
8888+ */
8889+ if ((*flags & ~(MS_RDONLY | MS_SILENT)) != 0) {
8890+ printk(KERN_ERR
8891+ "unionfs: remount flags 0x%x unsupported\n", *flags);
8892+ err = -EINVAL;
8893+ goto out_error;
8894+ }
8895+
8896+ /*
8897+ * If 'options' is NULL, it's probably because the user just changed
8898+ * the union to a "ro" or "rw" and the VFS took care of it. So
8899+ * nothing to do and we're done.
8900+ */
8901+ if (!options || options[0] == '\0')
8902+ goto out_error;
8903+
8904+ /*
8905+ * Find out how many branches we will have in the end, counting
8906+ * "add" and "del" commands. Copy the "options" string because
8907+ * strsep modifies the string and we need it later.
8908+ */
8909+ tmp_to_free = kstrdup(options, GFP_KERNEL);
8910+ optionstmp = tmp_to_free;
8911+ if (unlikely(!optionstmp)) {
8912+ err = -ENOMEM;
8913+ goto out_free;
8914+ }
8915+ cur_branches = sbmax(sb); /* current no. branches */
8916+ new_branches = sbmax(sb);
8917+ del_branches = 0;
8918+ add_branches = 0;
8919+ new_high_branch_id = sbhbid(sb); /* save current high_branch_id */
8920+ while ((optname = strsep(&optionstmp, ",")) != NULL) {
8921+ char *optarg;
8922+
8923+ if (!optname || !*optname)
8924+ continue;
8925+
8926+ optarg = strchr(optname, '=');
8927+ if (optarg)
8928+ *optarg++ = '\0';
8929+
8930+ if (!strcmp("add", optname))
8931+ add_branches++;
8932+ else if (!strcmp("del", optname))
8933+ del_branches++;
8934+ }
8935+ kfree(tmp_to_free);
8936+ /* after all changes, will we have at least one branch left? */
8937+ if ((new_branches + add_branches - del_branches) < 1) {
8938+ printk(KERN_ERR
8939+ "unionfs: no branches left after remount\n");
8940+ err = -EINVAL;
8941+ goto out_free;
8942+ }
8943+
8944+ /*
8945+ * Since we haven't actually parsed all the add/del options, nor
8946+ * have we checked them for errors, we don't know for sure how many
8947+ * branches we will have after all changes have taken place. In
8948+ * fact, the total number of branches left could be less than what
8949+ * we have now. So we need to allocate space for a temporary
8950+ * placeholder that is at least as large as the maximum number of
8951+ * branches we *could* have, which is the current number plus all
8952+ * the additions. Once we're done with these temp placeholders, we
8953+ * may have to re-allocate the final size, copy over from the temp,
8954+ * and then free the temps (done near the end of this function).
8955+ */
8956+ max_branches = cur_branches + add_branches;
8957+ /* allocate space for new pointers to lower dentry */
8958+ tmp_data = kcalloc(max_branches,
8959+ sizeof(struct unionfs_data), GFP_KERNEL);
8960+ if (unlikely(!tmp_data)) {
8961+ err = -ENOMEM;
8962+ goto out_free;
8963+ }
8964+ /* allocate space for new pointers to lower paths */
8965+ tmp_lower_paths = kcalloc(max_branches,
8966+ sizeof(struct path), GFP_KERNEL);
8967+ if (unlikely(!tmp_lower_paths)) {
8968+ err = -ENOMEM;
8969+ goto out_free;
8970+ }
8971+ /* copy current info into new placeholders, incrementing refcnts */
8972+ memcpy(tmp_data, UNIONFS_SB(sb)->data,
8973+ cur_branches * sizeof(struct unionfs_data));
8974+ memcpy(tmp_lower_paths, UNIONFS_D(sb->s_root)->lower_paths,
8975+ cur_branches * sizeof(struct path));
8976+ for (i = 0; i < cur_branches; i++)
8977+ path_get(&tmp_lower_paths[i]); /* drop refs at end of fxn */
8978+
8979+ /*******************************************************************
8980+ * For each branch command, do path_lookup on the requested branch,
8981+ * and apply the change to a temp branch list. To handle errors, we
8982+ * already dup'ed the old arrays (above), and increased the refcnts
8983+ * on various f/s objects. So now we can do all the path_lookups
8984+ * and branch-management commands on the new arrays. If it fail mid
8985+ * way, we free the tmp arrays and *put all objects. If we succeed,
8986+ * then we free old arrays and *put its objects, and then replace
8987+ * the arrays with the new tmp list (we may have to re-allocate the
8988+ * memory because the temp lists could have been larger than what we
8989+ * actually needed).
8990+ *******************************************************************/
8991+
8992+ while ((optname = strsep(&options, ",")) != NULL) {
8993+ char *optarg;
8994+
8995+ if (!optname || !*optname)
8996+ continue;
8997+ /*
8998+ * At this stage optname holds a comma-delimited option, but
8999+ * without the commas. Next, we need to break the string on
9000+ * the '=' symbol to separate CMD=ARG, where ARG itself can
9001+ * be KEY=VAL. For example, in mode=/foo=rw, CMD is "mode",
9002+ * KEY is "/foo", and VAL is "rw".
9003+ */
9004+ optarg = strchr(optname, '=');
9005+ if (optarg)
9006+ *optarg++ = '\0';
9007+ /* incgen remount option (instead of old ioctl) */
9008+ if (!strcmp("incgen", optname)) {
9009+ err = 0;
9010+ goto out_no_change;
9011+ }
9012+
9013+ /*
9014+ * All of our options take an argument now. (Insert ones
9015+ * that don't above this check.) So at this stage optname
9016+ * contains the CMD part and optarg contains the ARG part.
9017+ */
9018+ if (!optarg || !*optarg) {
9019+ printk(KERN_ERR "unionfs: all remount options require "
9020+ "an argument (%s)\n", optname);
9021+ err = -EINVAL;
9022+ goto out_release;
9023+ }
9024+
9025+ if (!strcmp("add", optname)) {
9026+ err = do_remount_add_option(optarg, new_branches,
9027+ tmp_data,
9028+ tmp_lower_paths,
9029+ &new_high_branch_id);
9030+ if (err)
9031+ goto out_release;
9032+ new_branches++;
9033+ if (new_branches > UNIONFS_MAX_BRANCHES) {
9034+ printk(KERN_ERR "unionfs: command exceeds "
9035+ "%d branches\n", UNIONFS_MAX_BRANCHES);
9036+ err = -E2BIG;
9037+ goto out_release;
9038+ }
9039+ continue;
9040+ }
9041+ if (!strcmp("del", optname)) {
9042+ err = do_remount_del_option(optarg, new_branches,
9043+ tmp_data,
9044+ tmp_lower_paths);
9045+ if (err)
9046+ goto out_release;
9047+ new_branches--;
9048+ continue;
9049+ }
9050+ if (!strcmp("mode", optname)) {
9051+ err = do_remount_mode_option(optarg, new_branches,
9052+ tmp_data,
9053+ tmp_lower_paths);
9054+ if (err)
9055+ goto out_release;
9056+ continue;
9057+ }
9058+
9059+ /*
9060+ * When you use "mount -o remount,ro", mount(8) will
9061+ * reportedly pass the original dirs= string from
9062+ * /proc/mounts. So for now, we have to ignore dirs= and
9063+ * not consider it an error, unless we want to allow users
9064+ * to pass dirs= in remount. Note that to allow the VFS to
9065+ * actually process the ro/rw remount options, we have to
9066+ * return 0 from this function.
9067+ */
9068+ if (!strcmp("dirs", optname)) {
9069+ printk(KERN_WARNING
9070+ "unionfs: remount ignoring option \"%s\"\n",
9071+ optname);
9072+ continue;
9073+ }
9074+
9075+ err = -EINVAL;
9076+ printk(KERN_ERR
9077+ "unionfs: unrecognized option \"%s\"\n", optname);
9078+ goto out_release;
9079+ }
9080+
9081+out_no_change:
9082+
9083+ /******************************************************************
9084+ * WE'RE ALMOST DONE: check if leftmost branch might be read-only,
9085+ * see if we need to allocate a small-sized new vector, copy the
9086+ * vectors to their correct place, release the refcnt of the older
9087+ * ones, and return. Also handle invalidating any pages that will
9088+ * have to be re-read.
9089+ *******************************************************************/
9090+
9091+ if (!(tmp_data[0].branchperms & MAY_WRITE)) {
9092+ printk(KERN_ERR "unionfs: leftmost branch cannot be read-only "
9093+ "(use \"remount,ro\" to create a read-only union)\n");
9094+ err = -EINVAL;
9095+ goto out_release;
9096+ }
9097+
9098+ /* (re)allocate space for new pointers to lower dentry */
9099+ size = new_branches * sizeof(struct unionfs_data);
9100+ new_data = krealloc(tmp_data, size, GFP_KERNEL);
9101+ if (unlikely(!new_data)) {
9102+ err = -ENOMEM;
9103+ goto out_release;
9104+ }
9105+
9106+ /* allocate space for new pointers to lower paths */
9107+ size = new_branches * sizeof(struct path);
9108+ new_lower_paths = krealloc(tmp_lower_paths, size, GFP_KERNEL);
9109+ if (unlikely(!new_lower_paths)) {
9110+ err = -ENOMEM;
9111+ goto out_release;
9112+ }
9113+
9114+ /* allocate space for new pointers to lower inodes */
9115+ new_lower_inodes = kcalloc(new_branches,
9116+ sizeof(struct inode *), GFP_KERNEL);
9117+ if (unlikely(!new_lower_inodes)) {
9118+ err = -ENOMEM;
9119+ goto out_release;
9120+ }
9121+
9122+ /*
9123+ * OK, just before we actually put the new set of branches in place,
9124+ * we need to ensure that our own f/s has no dirty objects left.
9125+ * Luckily, do_remount_sb() already calls shrink_dcache_sb(sb) and
9126+ * fsync_super(sb), taking care of dentries, inodes, and dirty
9127+ * pages. So all that's left is for us to invalidate any leftover
9128+ * (non-dirty) pages to ensure that they will be re-read from the
9129+ * new lower branches (and to support mmap).
9130+ */
9131+
9132+ /*
9133+ * Once we finish the remounting successfully, our superblock
9134+ * generation number will have increased. This will be detected by
9135+ * our dentry-revalidation code upon subsequent f/s operations
9136+ * through unionfs. The revalidation code will rebuild the union of
9137+ * lower inodes for a given unionfs inode and invalidate any pages
9138+ * of such "stale" inodes (by calling our purge_inode_data
9139+ * function). This revalidation will happen lazily and
9140+ * incrementally, as users perform operations on cached inodes. We
9141+ * would like to encourage this revalidation to happen sooner if
9142+ * possible, so we like to try to invalidate as many other pages in
9143+ * our superblock as we can. We used to call drop_pagecache_sb() or
9144+ * a variant thereof, but either method was racy (drop_caches alone
9145+ * is known to be racy). So now we let the revalidation happen on a
9146+ * per file basis in ->d_revalidate.
9147+ */
9148+
9149+ /* grab new lower super references; release old ones */
9150+ for (i = 0; i < new_branches; i++)
9151+ atomic_inc(&new_data[i].sb->s_active);
9152+ for (i = 0; i < sbmax(sb); i++)
9153+ atomic_dec(&UNIONFS_SB(sb)->data[i].sb->s_active);
9154+
9155+ /* copy new vectors into their correct place */
9156+ tmp_data = UNIONFS_SB(sb)->data;
9157+ UNIONFS_SB(sb)->data = new_data;
9158+ new_data = NULL; /* so don't free good pointers below */
9159+ tmp_lower_paths = UNIONFS_D(sb->s_root)->lower_paths;
9160+ UNIONFS_D(sb->s_root)->lower_paths = new_lower_paths;
9161+ new_lower_paths = NULL; /* so don't free good pointers below */
9162+
9163+ /* update our unionfs_sb_info and root dentry index of last branch */
9164+ i = sbmax(sb); /* save no. of branches to release at end */
9165+ sbend(sb) = new_branches - 1;
9166+ dbend(sb->s_root) = new_branches - 1;
9167+ old_ibstart = ibstart(sb->s_root->d_inode);
9168+ old_ibend = ibend(sb->s_root->d_inode);
9169+ ibend(sb->s_root->d_inode) = new_branches - 1;
9170+ UNIONFS_D(sb->s_root)->bcount = new_branches;
9171+ new_branches = i; /* no. of branches to release below */
9172+
9173+ /*
9174+ * Update lower inodes: 3 steps
9175+ * 1. grab ref on all new lower inodes
9176+ */
9177+ for (i = dbstart(sb->s_root); i <= dbend(sb->s_root); i++) {
9178+ struct dentry *lower_dentry =
9179+ unionfs_lower_dentry_idx(sb->s_root, i);
9180+ igrab(lower_dentry->d_inode);
9181+ new_lower_inodes[i] = lower_dentry->d_inode;
9182+ }
9183+ /* 2. release reference on all older lower inodes */
9184+ iput_lowers(sb->s_root->d_inode, old_ibstart, old_ibend, true);
9185+ /* 3. update root dentry's inode to new lower_inodes array */
9186+ UNIONFS_I(sb->s_root->d_inode)->lower_inodes = new_lower_inodes;
9187+ new_lower_inodes = NULL;
9188+
9189+ /* maxbytes may have changed */
9190+ sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
9191+ /* update high branch ID */
9192+ sbhbid(sb) = new_high_branch_id;
9193+
9194+ /* update our sb->generation for revalidating objects */
9195+ i = atomic_inc_return(&UNIONFS_SB(sb)->generation);
9196+ atomic_set(&UNIONFS_D(sb->s_root)->generation, i);
9197+ atomic_set(&UNIONFS_I(sb->s_root->d_inode)->generation, i);
9198+ if (!(*flags & MS_SILENT))
9199+ pr_info("unionfs: %s: new generation number %d\n",
9200+ UNIONFS_SB(sb)->dev_name, i);
9201+ /* finally, update the root dentry's times */
9202+ unionfs_copy_attr_times(sb->s_root->d_inode);
9203+ err = 0; /* reset to success */
9204+
9205+ /*
9206+ * The code above falls through to the next label, and releases the
9207+ * refcnts of the older ones (stored in tmp_*): if we fell through
9208+ * here, it means success. However, if we jump directly to this
9209+ * label from any error above, then an error occurred after we
9210+ * grabbed various refcnts, and so we have to release the
9211+ * temporarily constructed structures.
9212+ */
9213+out_release:
9214+ /* no need to cleanup/release anything in tmp_data */
9215+ if (tmp_lower_paths)
9216+ for (i = 0; i < new_branches; i++)
9217+ path_put(&tmp_lower_paths[i]);
9218+out_free:
9219+ kfree(tmp_lower_paths);
9220+ kfree(tmp_data);
9221+ kfree(new_lower_paths);
9222+ kfree(new_data);
9223+ kfree(new_lower_inodes);
9224+out_error:
9225+ unionfs_check_dentry(sb->s_root);
9226+ unionfs_write_unlock(sb);
9227+ return err;
9228+}
9229+
9230+/*
9231+ * Called by iput() when the inode reference count reached zero
9232+ * and the inode is not hashed anywhere. Used to clear anything
9233+ * that needs to be, before the inode is completely destroyed and put
9234+ * on the inode free list.
9235+ *
9236+ * No need to lock sb info's rwsem.
9237+ */
9238+static void unionfs_clear_inode(struct inode *inode)
9239+{
9240+ int bindex, bstart, bend;
9241+ struct inode *lower_inode;
9242+ struct list_head *pos, *n;
9243+ struct unionfs_dir_state *rdstate;
9244+
9245+ list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
9246+ rdstate = list_entry(pos, struct unionfs_dir_state, cache);
9247+ list_del(&rdstate->cache);
9248+ free_rdstate(rdstate);
9249+ }
9250+
9251+ /*
9252+ * Decrement a reference to a lower_inode, which was incremented
9253+ * by our read_inode when it was created initially.
9254+ */
9255+ bstart = ibstart(inode);
9256+ bend = ibend(inode);
9257+ if (bstart >= 0) {
9258+ for (bindex = bstart; bindex <= bend; bindex++) {
9259+ lower_inode = unionfs_lower_inode_idx(inode, bindex);
9260+ if (!lower_inode)
9261+ continue;
9262+ unionfs_set_lower_inode_idx(inode, bindex, NULL);
9263+ /* see Documentation/filesystems/unionfs/issues.txt */
9264+ lockdep_off();
9265+ iput(lower_inode);
9266+ lockdep_on();
9267+ }
9268+ }
9269+
9270+ kfree(UNIONFS_I(inode)->lower_inodes);
9271+ UNIONFS_I(inode)->lower_inodes = NULL;
9272+}
9273+
9274+static struct inode *unionfs_alloc_inode(struct super_block *sb)
9275+{
9276+ struct unionfs_inode_info *i;
9277+
9278+ i = kmem_cache_alloc(unionfs_inode_cachep, GFP_KERNEL);
9279+ if (unlikely(!i))
9280+ return NULL;
9281+
9282+ /* memset everything up to the inode to 0 */
9283+ memset(i, 0, offsetof(struct unionfs_inode_info, vfs_inode));
9284+
9285+ i->vfs_inode.i_version = 1;
9286+ return &i->vfs_inode;
9287+}
9288+
9289+static void unionfs_destroy_inode(struct inode *inode)
9290+{
9291+ kmem_cache_free(unionfs_inode_cachep, UNIONFS_I(inode));
9292+}
9293+
9294+/* unionfs inode cache constructor */
9295+static void init_once(void *obj)
9296+{
9297+ struct unionfs_inode_info *i = obj;
9298+
9299+ inode_init_once(&i->vfs_inode);
9300+}
9301+
9302+int unionfs_init_inode_cache(void)
9303+{
9304+ int err = 0;
9305+
9306+ unionfs_inode_cachep =
9307+ kmem_cache_create("unionfs_inode_cache",
9308+ sizeof(struct unionfs_inode_info), 0,
9309+ SLAB_RECLAIM_ACCOUNT, init_once);
9310+ if (unlikely(!unionfs_inode_cachep))
9311+ err = -ENOMEM;
9312+ return err;
9313+}
9314+
9315+/* unionfs inode cache destructor */
9316+void unionfs_destroy_inode_cache(void)
9317+{
9318+ if (unionfs_inode_cachep)
9319+ kmem_cache_destroy(unionfs_inode_cachep);
9320+}
9321+
9322+/*
9323+ * Called when we have a dirty inode, right here we only throw out
9324+ * parts of our readdir list that are too old.
9325+ *
9326+ * No need to grab sb info's rwsem.
9327+ */
9328+static int unionfs_write_inode(struct inode *inode,
9329+ struct writeback_control *wbc)
9330+{
9331+ struct list_head *pos, *n;
9332+ struct unionfs_dir_state *rdstate;
9333+
9334+ spin_lock(&UNIONFS_I(inode)->rdlock);
9335+ list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
9336+ rdstate = list_entry(pos, struct unionfs_dir_state, cache);
9337+ /* We keep this list in LRU order. */
9338+ if ((rdstate->access + RDCACHE_JIFFIES) > jiffies)
9339+ break;
9340+ UNIONFS_I(inode)->rdcount--;
9341+ list_del(&rdstate->cache);
9342+ free_rdstate(rdstate);
9343+ }
9344+ spin_unlock(&UNIONFS_I(inode)->rdlock);
9345+
9346+ return 0;
9347+}
9348+
9349+/*
9350+ * Used only in nfs, to kill any pending RPC tasks, so that subsequent
9351+ * code can actually succeed and won't leave tasks that need handling.
9352+ */
9353+static void unionfs_umount_begin(struct super_block *sb)
9354+{
9355+ struct super_block *lower_sb;
9356+ int bindex, bstart, bend;
9357+
9358+ unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD);
9359+
9360+ bstart = sbstart(sb);
9361+ bend = sbend(sb);
9362+ for (bindex = bstart; bindex <= bend; bindex++) {
9363+ lower_sb = unionfs_lower_super_idx(sb, bindex);
9364+
9365+ if (lower_sb && lower_sb->s_op &&
9366+ lower_sb->s_op->umount_begin)
9367+ lower_sb->s_op->umount_begin(lower_sb);
9368+ }
9369+
9370+ unionfs_read_unlock(sb);
9371+}
9372+
9373+static int unionfs_show_options(struct seq_file *m, struct vfsmount *mnt)
9374+{
9375+ struct super_block *sb = mnt->mnt_sb;
9376+ int ret = 0;
9377+ char *tmp_page;
9378+ char *path;
9379+ int bindex, bstart, bend;
9380+ int perms;
9381+
9382+ unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD);
9383+
9384+ unionfs_lock_dentry(sb->s_root, UNIONFS_DMUTEX_CHILD);
9385+
9386+ tmp_page = (char *) __get_free_page(GFP_KERNEL);
9387+ if (unlikely(!tmp_page)) {
9388+ ret = -ENOMEM;
9389+ goto out;
9390+ }
9391+
9392+ bstart = sbstart(sb);
9393+ bend = sbend(sb);
9394+
9395+ seq_printf(m, ",dirs=");
9396+ for (bindex = bstart; bindex <= bend; bindex++) {
9397+ struct path p;
9398+ p.dentry = unionfs_lower_dentry_idx(sb->s_root, bindex);
9399+ p.mnt = unionfs_lower_mnt_idx(sb->s_root, bindex);
9400+ path = d_path(&p, tmp_page, PAGE_SIZE);
9401+ if (IS_ERR(path)) {
9402+ ret = PTR_ERR(path);
9403+ goto out;
9404+ }
9405+
9406+ perms = branchperms(sb, bindex);
9407+
9408+ seq_printf(m, "%s=%s", path,
9409+ perms & MAY_WRITE ? "rw" : "ro");
9410+ if (bindex != bend)
9411+ seq_printf(m, ":");
9412+ }
9413+
9414+out:
9415+ free_page((unsigned long) tmp_page);
9416+
9417+ unionfs_unlock_dentry(sb->s_root);
9418+
9419+ unionfs_read_unlock(sb);
9420+
9421+ return ret;
9422+}
9423+
9424+struct super_operations unionfs_sops = {
9425+ .delete_inode = unionfs_delete_inode,
9426+ .put_super = unionfs_put_super,
9427+ .statfs = unionfs_statfs,
9428+ .remount_fs = unionfs_remount_fs,
9429+ .clear_inode = unionfs_clear_inode,
9430+ .umount_begin = unionfs_umount_begin,
9431+ .show_options = unionfs_show_options,
9432+ .write_inode = unionfs_write_inode,
9433+ .alloc_inode = unionfs_alloc_inode,
9434+ .destroy_inode = unionfs_destroy_inode,
9435+};
9436diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
9437new file mode 100644
9438index 0000000..d49c834
9439--- /dev/null
9440+++ b/fs/unionfs/union.h
9441@@ -0,0 +1,669 @@
9442+/*
9443+ * Copyright (c) 2003-2010 Erez Zadok
9444+ * Copyright (c) 2003-2006 Charles P. Wright
9445+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
9446+ * Copyright (c) 2005 Arun M. Krishnakumar
9447+ * Copyright (c) 2004-2006 David P. Quigley
9448+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
9449+ * Copyright (c) 2003 Puja Gupta
9450+ * Copyright (c) 2003 Harikesavan Krishnan
9451+ * Copyright (c) 2003-2010 Stony Brook University
9452+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
9453+ *
9454+ * This program is free software; you can redistribute it and/or modify
9455+ * it under the terms of the GNU General Public License version 2 as
9456+ * published by the Free Software Foundation.
9457+ */
9458+
9459+#ifndef _UNION_H_
9460+#define _UNION_H_
9461+
9462+#include <linux/dcache.h>
9463+#include <linux/file.h>
9464+#include <linux/list.h>
9465+#include <linux/fs.h>
9466+#include <linux/mm.h>
9467+#include <linux/module.h>
9468+#include <linux/mount.h>
9469+#include <linux/namei.h>
9470+#include <linux/page-flags.h>
9471+#include <linux/pagemap.h>
9472+#include <linux/poll.h>
9473+#include <linux/security.h>
9474+#include <linux/seq_file.h>
9475+#include <linux/slab.h>
9476+#include <linux/spinlock.h>
9477+#include <linux/smp_lock.h>
9478+#include <linux/statfs.h>
9479+#include <linux/string.h>
9480+#include <linux/vmalloc.h>
9481+#include <linux/writeback.h>
9482+#include <linux/buffer_head.h>
9483+#include <linux/xattr.h>
9484+#include <linux/fs_stack.h>
9485+#include <linux/magic.h>
9486+#include <linux/log2.h>
9487+#include <linux/poison.h>
9488+#include <linux/mman.h>
9489+#include <linux/backing-dev.h>
9490+#include <linux/splice.h>
9491+
9492+#include <asm/system.h>
9493+
9494+#include <linux/union_fs.h>
9495+
9496+/* the file system name */
9497+#define UNIONFS_NAME "unionfs"
9498+
9499+/* unionfs root inode number */
9500+#define UNIONFS_ROOT_INO 1
9501+
9502+/* number of times we try to get a unique temporary file name */
9503+#define GET_TMPNAM_MAX_RETRY 5
9504+
9505+/* maximum number of branches we support, to avoid memory blowup */
9506+#define UNIONFS_MAX_BRANCHES 128
9507+
9508+/* minimum time (seconds) required for time-based cache-coherency */
9509+#define UNIONFS_MIN_CC_TIME 3
9510+
9511+/* Operations vectors defined in specific files. */
9512+extern struct file_operations unionfs_main_fops;
9513+extern struct file_operations unionfs_dir_fops;
9514+extern struct inode_operations unionfs_main_iops;
9515+extern struct inode_operations unionfs_dir_iops;
9516+extern struct inode_operations unionfs_symlink_iops;
9517+extern struct super_operations unionfs_sops;
9518+extern struct dentry_operations unionfs_dops;
9519+extern struct address_space_operations unionfs_aops, unionfs_dummy_aops;
9520+extern struct vm_operations_struct unionfs_vm_ops;
9521+
9522+/* How long should an entry be allowed to persist */
9523+#define RDCACHE_JIFFIES (5*HZ)
9524+
9525+/* compatibility with Real-Time patches */
9526+#ifdef CONFIG_PREEMPT_RT
9527+# define unionfs_rw_semaphore compat_rw_semaphore
9528+#else /* not CONFIG_PREEMPT_RT */
9529+# define unionfs_rw_semaphore rw_semaphore
9530+#endif /* not CONFIG_PREEMPT_RT */
9531+
9532+/* file private data. */
9533+struct unionfs_file_info {
9534+ int bstart;
9535+ int bend;
9536+ atomic_t generation;
9537+
9538+ struct unionfs_dir_state *rdstate;
9539+ struct file **lower_files;
9540+ int *saved_branch_ids; /* IDs of branches when file was opened */
9541+ const struct vm_operations_struct *lower_vm_ops;
9542+ bool wrote_to_file; /* for delayed copyup */
9543+};
9544+
9545+/* unionfs inode data in memory */
9546+struct unionfs_inode_info {
9547+ int bstart;
9548+ int bend;
9549+ atomic_t generation;
9550+ /* Stuff for readdir over NFS. */
9551+ spinlock_t rdlock;
9552+ struct list_head readdircache;
9553+ int rdcount;
9554+ int hashsize;
9555+ int cookie;
9556+
9557+ /* The lower inodes */
9558+ struct inode **lower_inodes;
9559+
9560+ struct inode vfs_inode;
9561+};
9562+
9563+/* unionfs dentry data in memory */
9564+struct unionfs_dentry_info {
9565+ /*
9566+ * The semaphore is used to lock the dentry as soon as we get into a
9567+ * unionfs function from the VFS. Our lock ordering is that children
9568+ * go before their parents.
9569+ */
9570+ struct mutex lock;
9571+ int bstart;
9572+ int bend;
9573+ int bopaque;
9574+ int bcount;
9575+ atomic_t generation;
9576+ struct path *lower_paths;
9577+};
9578+
9579+/* These are the pointers to our various objects. */
9580+struct unionfs_data {
9581+ struct super_block *sb; /* lower super_block */
9582+ atomic_t open_files; /* number of open files on branch */
9583+ int branchperms;
9584+ int branch_id; /* unique branch ID at re/mount time */
9585+};
9586+
9587+/* unionfs super-block data in memory */
9588+struct unionfs_sb_info {
9589+ int bend;
9590+
9591+ atomic_t generation;
9592+
9593+ /*
9594+ * This rwsem is used to make sure that a branch management
9595+ * operation...
9596+ * 1) will not begin before all currently in-flight operations
9597+ * complete.
9598+ * 2) any new operations do not execute until the currently
9599+ * running branch management operation completes.
9600+ *
9601+ * The write_lock_owner records the PID of the task which grabbed
9602+ * the rw_sem for writing. If the same task also tries to grab the
9603+ * read lock, we allow it. This prevents a self-deadlock when
9604+ * branch-management is used on a pivot_root'ed union, because we
9605+ * have to ->lookup paths which belong to the same union.
9606+ */
9607+ struct unionfs_rw_semaphore rwsem;
9608+ pid_t write_lock_owner; /* PID of rw_sem owner (write lock) */
9609+ int high_branch_id; /* last unique branch ID given */
9610+ char *dev_name; /* to identify different unions in pr_debug */
9611+ struct unionfs_data *data;
9612+};
9613+
9614+/*
9615+ * structure for making the linked list of entries by readdir on left branch
9616+ * to compare with entries on right branch
9617+ */
9618+struct filldir_node {
9619+ struct list_head file_list; /* list for directory entries */
9620+ char *name; /* name entry */
9621+ int hash; /* name hash */
9622+ int namelen; /* name len since name is not 0 terminated */
9623+
9624+ /*
9625+ * we can check for duplicate whiteouts and files in the same branch
9626+ * in order to return -EIO.
9627+ */
9628+ int bindex;
9629+
9630+ /* is this a whiteout entry? */
9631+ int whiteout;
9632+
9633+ /* Inline name, so we don't need to separately kmalloc small ones */
9634+ char iname[DNAME_INLINE_LEN_MIN];
9635+};
9636+
9637+/* Directory hash table. */
9638+struct unionfs_dir_state {
9639+ unsigned int cookie; /* the cookie, based off of rdversion */
9640+ unsigned int offset; /* The entry we have returned. */
9641+ int bindex;
9642+ loff_t dirpos; /* offset within the lower level directory */
9643+ int size; /* How big is the hash table? */
9644+ int hashentries; /* How many entries have been inserted? */
9645+ unsigned long access;
9646+
9647+ /* This cache list is used when the inode keeps us around. */
9648+ struct list_head cache;
9649+ struct list_head list[0];
9650+};
9651+
9652+/* externs needed for fanout.h or sioq.h */
9653+extern int unionfs_get_nlinks(const struct inode *inode);
9654+extern void unionfs_copy_attr_times(struct inode *upper);
9655+extern void unionfs_copy_attr_all(struct inode *dest, const struct inode *src);
9656+
9657+/* include miscellaneous macros */
9658+#include "fanout.h"
9659+#include "sioq.h"
9660+
9661+/* externs for cache creation/deletion routines */
9662+extern void unionfs_destroy_filldir_cache(void);
9663+extern int unionfs_init_filldir_cache(void);
9664+extern int unionfs_init_inode_cache(void);
9665+extern void unionfs_destroy_inode_cache(void);
9666+extern int unionfs_init_dentry_cache(void);
9667+extern void unionfs_destroy_dentry_cache(void);
9668+
9669+/* Initialize and free readdir-specific state. */
9670+extern int init_rdstate(struct file *file);
9671+extern struct unionfs_dir_state *alloc_rdstate(struct inode *inode,
9672+ int bindex);
9673+extern struct unionfs_dir_state *find_rdstate(struct inode *inode,
9674+ loff_t fpos);
9675+extern void free_rdstate(struct unionfs_dir_state *state);
9676+extern int add_filldir_node(struct unionfs_dir_state *rdstate,
9677+ const char *name, int namelen, int bindex,
9678+ int whiteout);
9679+extern struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
9680+ const char *name, int namelen,
9681+ int is_whiteout);
9682+
9683+extern struct dentry **alloc_new_dentries(int objs);
9684+extern struct unionfs_data *alloc_new_data(int objs);
9685+
9686+/* We can only use 32-bits of offset for rdstate --- blech! */
9687+#define DIREOF (0xfffff)
9688+#define RDOFFBITS 20 /* This is the number of bits in DIREOF. */
9689+#define MAXRDCOOKIE (0xfff)
9690+/* Turn an rdstate into an offset. */
9691+static inline off_t rdstate2offset(struct unionfs_dir_state *buf)
9692+{
9693+ off_t tmp;
9694+
9695+ tmp = ((buf->cookie & MAXRDCOOKIE) << RDOFFBITS)
9696+ | (buf->offset & DIREOF);
9697+ return tmp;
9698+}
9699+
9700+/* Macros for locking a super_block. */
9701+enum unionfs_super_lock_class {
9702+ UNIONFS_SMUTEX_NORMAL,
9703+ UNIONFS_SMUTEX_PARENT, /* when locking on behalf of file */
9704+ UNIONFS_SMUTEX_CHILD, /* when locking on behalf of dentry */
9705+};
9706+static inline void unionfs_read_lock(struct super_block *sb, int subclass)
9707+{
9708+ if (UNIONFS_SB(sb)->write_lock_owner &&
9709+ UNIONFS_SB(sb)->write_lock_owner == current->pid)
9710+ return;
9711+ down_read_nested(&UNIONFS_SB(sb)->rwsem, subclass);
9712+}
9713+static inline void unionfs_read_unlock(struct super_block *sb)
9714+{
9715+ if (UNIONFS_SB(sb)->write_lock_owner &&
9716+ UNIONFS_SB(sb)->write_lock_owner == current->pid)
9717+ return;
9718+ up_read(&UNIONFS_SB(sb)->rwsem);
9719+}
9720+static inline void unionfs_write_lock(struct super_block *sb)
9721+{
9722+ down_write(&UNIONFS_SB(sb)->rwsem);
9723+ UNIONFS_SB(sb)->write_lock_owner = current->pid;
9724+}
9725+static inline void unionfs_write_unlock(struct super_block *sb)
9726+{
9727+ up_write(&UNIONFS_SB(sb)->rwsem);
9728+ UNIONFS_SB(sb)->write_lock_owner = 0;
9729+}
9730+
9731+static inline void unionfs_double_lock_dentry(struct dentry *d1,
9732+ struct dentry *d2)
9733+{
9734+ BUG_ON(d1 == d2);
9735+ if (d1 < d2) {
9736+ unionfs_lock_dentry(d1, UNIONFS_DMUTEX_PARENT);
9737+ unionfs_lock_dentry(d2, UNIONFS_DMUTEX_CHILD);
9738+ } else {
9739+ unionfs_lock_dentry(d2, UNIONFS_DMUTEX_PARENT);
9740+ unionfs_lock_dentry(d1, UNIONFS_DMUTEX_CHILD);
9741+ }
9742+}
9743+
9744+static inline void unionfs_double_unlock_dentry(struct dentry *d1,
9745+ struct dentry *d2)
9746+{
9747+ BUG_ON(d1 == d2);
9748+ if (d1 < d2) { /* unlock in reverse order than double_lock_dentry */
9749+ unionfs_unlock_dentry(d1);
9750+ unionfs_unlock_dentry(d2);
9751+ } else {
9752+ unionfs_unlock_dentry(d2);
9753+ unionfs_unlock_dentry(d1);
9754+ }
9755+}
9756+
9757+static inline void unionfs_double_lock_parents(struct dentry *p1,
9758+ struct dentry *p2)
9759+{
9760+ if (p1 == p2) {
9761+ unionfs_lock_dentry(p1, UNIONFS_DMUTEX_REVAL_PARENT);
9762+ return;
9763+ }
9764+ if (p1 < p2) {
9765+ unionfs_lock_dentry(p1, UNIONFS_DMUTEX_REVAL_PARENT);
9766+ unionfs_lock_dentry(p2, UNIONFS_DMUTEX_REVAL_CHILD);
9767+ } else {
9768+ unionfs_lock_dentry(p2, UNIONFS_DMUTEX_REVAL_PARENT);
9769+ unionfs_lock_dentry(p1, UNIONFS_DMUTEX_REVAL_CHILD);
9770+ }
9771+}
9772+
9773+static inline void unionfs_double_unlock_parents(struct dentry *p1,
9774+ struct dentry *p2)
9775+{
9776+ if (p1 == p2) {
9777+ unionfs_unlock_dentry(p1);
9778+ return;
9779+ }
9780+ if (p1 < p2) { /* unlock in reverse order of double_lock_parents */
9781+ unionfs_unlock_dentry(p1);
9782+ unionfs_unlock_dentry(p2);
9783+ } else {
9784+ unionfs_unlock_dentry(p2);
9785+ unionfs_unlock_dentry(p1);
9786+ }
9787+}
9788+
9789+extern int new_dentry_private_data(struct dentry *dentry, int subclass);
9790+extern int realloc_dentry_private_data(struct dentry *dentry);
9791+extern void free_dentry_private_data(struct dentry *dentry);
9792+extern void update_bstart(struct dentry *dentry);
9793+extern int init_lower_nd(struct nameidata *nd, unsigned int flags);
9794+extern void release_lower_nd(struct nameidata *nd, int err);
9795+
9796+/*
9797+ * EXTERNALS:
9798+ */
9799+
9800+/* replicates the directory structure up to given dentry in given branch */
9801+extern struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
9802+ const char *name, int bindex);
9803+
9804+/* partial lookup */
9805+extern int unionfs_partial_lookup(struct dentry *dentry,
9806+ struct dentry *parent);
9807+extern struct dentry *unionfs_lookup_full(struct dentry *dentry,
9808+ struct dentry *parent,
9809+ int lookupmode);
9810+
9811+/* copies a file from dbstart to newbindex branch */
9812+extern int copyup_file(struct inode *dir, struct file *file, int bstart,
9813+ int newbindex, loff_t size);
9814+extern int copyup_named_file(struct inode *dir, struct file *file,
9815+ char *name, int bstart, int new_bindex,
9816+ loff_t len);
9817+/* copies a dentry from dbstart to newbindex branch */
9818+extern int copyup_dentry(struct inode *dir, struct dentry *dentry,
9819+ int bstart, int new_bindex, const char *name,
9820+ int namelen, struct file **copyup_file, loff_t len);
9821+/* helper functions for post-copyup actions */
9822+extern void unionfs_postcopyup_setmnt(struct dentry *dentry);
9823+extern void unionfs_postcopyup_release(struct dentry *dentry);
9824+
9825+/* Is this directory empty: 0 if it is empty, -ENOTEMPTY if not. */
9826+extern int check_empty(struct dentry *dentry, struct dentry *parent,
9827+ struct unionfs_dir_state **namelist);
9828+/* whiteout and opaque directory helpers */
9829+extern char *alloc_whname(const char *name, int len);
9830+extern bool is_whiteout_name(char **namep, int *namelenp);
9831+extern bool is_validname(const char *name);
9832+extern struct dentry *lookup_whiteout(const char *name,
9833+ struct dentry *lower_parent);
9834+extern struct dentry *find_first_whiteout(struct dentry *dentry);
9835+extern int unlink_whiteout(struct dentry *wh_dentry);
9836+extern int check_unlink_whiteout(struct dentry *dentry,
9837+ struct dentry *lower_dentry, int bindex);
9838+extern int create_whiteout(struct dentry *dentry, int start);
9839+extern int delete_whiteouts(struct dentry *dentry, int bindex,
9840+ struct unionfs_dir_state *namelist);
9841+extern int is_opaque_dir(struct dentry *dentry, int bindex);
9842+extern int make_dir_opaque(struct dentry *dir, int bindex);
9843+extern void unionfs_set_max_namelen(long *namelen);
9844+
9845+extern void unionfs_reinterpose(struct dentry *this_dentry);
9846+extern struct super_block *unionfs_duplicate_super(struct super_block *sb);
9847+
9848+/* Locking functions. */
9849+extern int unionfs_setlk(struct file *file, int cmd, struct file_lock *fl);
9850+extern int unionfs_getlk(struct file *file, struct file_lock *fl);
9851+
9852+/* Common file operations. */
9853+extern int unionfs_file_revalidate(struct file *file, struct dentry *parent,
9854+ bool willwrite);
9855+extern int unionfs_open(struct inode *inode, struct file *file);
9856+extern int unionfs_file_release(struct inode *inode, struct file *file);
9857+extern int unionfs_flush(struct file *file, fl_owner_t id);
9858+extern long unionfs_ioctl(struct file *file, unsigned int cmd,
9859+ unsigned long arg);
9860+extern int unionfs_fsync(struct file *file, int datasync);
9861+extern int unionfs_fasync(int fd, struct file *file, int flag);
9862+
9863+/* Inode operations */
9864+extern struct inode *unionfs_iget(struct super_block *sb, unsigned long ino);
9865+extern int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
9866+ struct inode *new_dir, struct dentry *new_dentry);
9867+extern int unionfs_unlink(struct inode *dir, struct dentry *dentry);
9868+extern int unionfs_rmdir(struct inode *dir, struct dentry *dentry);
9869+
9870+extern bool __unionfs_d_revalidate(struct dentry *dentry,
9871+ struct dentry *parent, bool willwrite);
9872+extern bool is_negative_lower(const struct dentry *dentry);
9873+extern bool is_newer_lower(const struct dentry *dentry);
9874+extern void purge_sb_data(struct super_block *sb);
9875+
9876+/* The values for unionfs_interpose's flag. */
9877+#define INTERPOSE_DEFAULT 0
9878+#define INTERPOSE_LOOKUP 1
9879+#define INTERPOSE_REVAL 2
9880+#define INTERPOSE_REVAL_NEG 3
9881+#define INTERPOSE_PARTIAL 4
9882+
9883+extern struct dentry *unionfs_interpose(struct dentry *this_dentry,
9884+ struct super_block *sb, int flag);
9885+
9886+#ifdef CONFIG_UNION_FS_XATTR
9887+/* Extended attribute functions. */
9888+extern void *unionfs_xattr_alloc(size_t size, size_t limit);
9889+static inline void unionfs_xattr_kfree(const void *p)
9890+{
9891+ kfree(p);
9892+}
9893+extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name,
9894+ void *value, size_t size);
9895+extern int unionfs_removexattr(struct dentry *dentry, const char *name);
9896+extern ssize_t unionfs_listxattr(struct dentry *dentry, char *list,
9897+ size_t size);
9898+extern int unionfs_setxattr(struct dentry *dentry, const char *name,
9899+ const void *value, size_t size, int flags);
9900+#endif /* CONFIG_UNION_FS_XATTR */
9901+
9902+/* The root directory is unhashed, but isn't deleted. */
9903+static inline int d_deleted(struct dentry *d)
9904+{
9905+ return d_unhashed(d) && (d != d->d_sb->s_root);
9906+}
9907+
9908+/* unionfs_permission, check if we should bypass error to facilitate copyup */
9909+#define IS_COPYUP_ERR(err) ((err) == -EROFS)
9910+
9911+/* unionfs_open, check if we need to copyup the file */
9912+#define OPEN_WRITE_FLAGS (O_WRONLY | O_RDWR | O_APPEND)
9913+#define IS_WRITE_FLAG(flag) ((flag) & OPEN_WRITE_FLAGS)
9914+
9915+static inline int branchperms(const struct super_block *sb, int index)
9916+{
9917+ BUG_ON(index < 0);
9918+ return UNIONFS_SB(sb)->data[index].branchperms;
9919+}
9920+
9921+static inline int set_branchperms(struct super_block *sb, int index, int perms)
9922+{
9923+ BUG_ON(index < 0);
9924+ UNIONFS_SB(sb)->data[index].branchperms = perms;
9925+ return perms;
9926+}
9927+
9928+/* check if readonly lower inode, but possibly unlinked (no inode->i_sb) */
9929+static inline int __is_rdonly(const struct inode *inode)
9930+{
9931+ /* if unlinked, can't be readonly (?) */
9932+ if (!inode->i_sb)
9933+ return 0;
9934+ return IS_RDONLY(inode);
9935+
9936+}
9937+/* Is this file on a read-only branch? */
9938+static inline int is_robranch_super(const struct super_block *sb, int index)
9939+{
9940+ int ret;
9941+
9942+ ret = (!(branchperms(sb, index) & MAY_WRITE)) ? -EROFS : 0;
9943+ return ret;
9944+}
9945+
9946+/* Is this file on a read-only branch? */
9947+static inline int is_robranch_idx(const struct dentry *dentry, int index)
9948+{
9949+ struct super_block *lower_sb;
9950+
9951+ BUG_ON(index < 0);
9952+
9953+ if (!(branchperms(dentry->d_sb, index) & MAY_WRITE))
9954+ return -EROFS;
9955+
9956+ lower_sb = unionfs_lower_super_idx(dentry->d_sb, index);
9957+ BUG_ON(lower_sb == NULL);
9958+ /*
9959+ * test sb flags directly, not IS_RDONLY(lower_inode) because the
9960+ * lower_dentry could be a negative.
9961+ */
9962+ if (lower_sb->s_flags & MS_RDONLY)
9963+ return -EROFS;
9964+
9965+ return 0;
9966+}
9967+
9968+static inline int is_robranch(const struct dentry *dentry)
9969+{
9970+ int index;
9971+
9972+ index = UNIONFS_D(dentry)->bstart;
9973+ BUG_ON(index < 0);
9974+
9975+ return is_robranch_idx(dentry, index);
9976+}
9977+
9978+/*
9979+ * EXTERNALS:
9980+ */
9981+extern int check_branch(struct nameidata *nd);
9982+extern int parse_branch_mode(const char *name, int *perms);
9983+
9984+/* locking helpers */
9985+static inline struct dentry *lock_parent(struct dentry *dentry)
9986+{
9987+ struct dentry *dir = dget_parent(dentry);
9988+ mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
9989+ return dir;
9990+}
9991+static inline struct dentry *lock_parent_wh(struct dentry *dentry)
9992+{
9993+ struct dentry *dir = dget_parent(dentry);
9994+
9995+ mutex_lock_nested(&dir->d_inode->i_mutex, UNIONFS_DMUTEX_WHITEOUT);
9996+ return dir;
9997+}
9998+
9999+static inline void unlock_dir(struct dentry *dir)
10000+{
10001+ mutex_unlock(&dir->d_inode->i_mutex);
10002+ dput(dir);
10003+}
10004+
10005+/* lock base inode mutex before calling lookup_one_len */
10006+static inline struct dentry *lookup_lck_len(const char *name,
10007+ struct dentry *base, int len)
10008+{
10009+ struct dentry *d;
10010+ mutex_lock(&base->d_inode->i_mutex);
10011+ d = lookup_one_len(name, base, len);
10012+ mutex_unlock(&base->d_inode->i_mutex);
10013+ return d;
10014+}
10015+
10016+static inline struct vfsmount *unionfs_mntget(struct dentry *dentry,
10017+ int bindex)
10018+{
10019+ struct vfsmount *mnt;
10020+
10021+ BUG_ON(!dentry || bindex < 0);
10022+
10023+ mnt = mntget(unionfs_lower_mnt_idx(dentry, bindex));
10024+#ifdef CONFIG_UNION_FS_DEBUG
10025+ if (!mnt)
10026+ pr_debug("unionfs: mntget: mnt=%p bindex=%d\n",
10027+ mnt, bindex);
10028+#endif /* CONFIG_UNION_FS_DEBUG */
10029+
10030+ return mnt;
10031+}
10032+
10033+static inline void unionfs_mntput(struct dentry *dentry, int bindex)
10034+{
10035+ struct vfsmount *mnt;
10036+
10037+ if (!dentry && bindex < 0)
10038+ return;
10039+ BUG_ON(!dentry || bindex < 0);
10040+
10041+ mnt = unionfs_lower_mnt_idx(dentry, bindex);
10042+#ifdef CONFIG_UNION_FS_DEBUG
10043+ /*
10044+ * Directories can have NULL lower objects in between start/end, but
10045+ * NOT if at the start/end range. We cannot verify that this dentry
10046+ * is a type=DIR, because it may already be a negative dentry. But
10047+ * if dbstart is greater than dbend, we know that this couldn't have
10048+ * been a regular file: it had to have been a directory.
10049+ */
10050+ if (!mnt && !(bindex > dbstart(dentry) && bindex < dbend(dentry)))
10051+ pr_debug("unionfs: mntput: mnt=%p bindex=%d\n", mnt, bindex);
10052+#endif /* CONFIG_UNION_FS_DEBUG */
10053+ mntput(mnt);
10054+}
10055+
10056+#ifdef CONFIG_UNION_FS_DEBUG
10057+
10058+/* useful for tracking code reachability */
10059+#define UDBG pr_debug("DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__)
10060+
10061+#define unionfs_check_inode(i) __unionfs_check_inode((i), \
10062+ __FILE__, __func__, __LINE__)
10063+#define unionfs_check_dentry(d) __unionfs_check_dentry((d), \
10064+ __FILE__, __func__, __LINE__)
10065+#define unionfs_check_file(f) __unionfs_check_file((f), \
10066+ __FILE__, __func__, __LINE__)
10067+#define unionfs_check_nd(n) __unionfs_check_nd((n), \
10068+ __FILE__, __func__, __LINE__)
10069+#define show_branch_counts(sb) __show_branch_counts((sb), \
10070+ __FILE__, __func__, __LINE__)
10071+#define show_inode_times(i) __show_inode_times((i), \
10072+ __FILE__, __func__, __LINE__)
10073+#define show_dinode_times(d) __show_dinode_times((d), \
10074+ __FILE__, __func__, __LINE__)
10075+#define show_inode_counts(i) __show_inode_counts((i), \
10076+ __FILE__, __func__, __LINE__)
10077+
10078+extern void __unionfs_check_inode(const struct inode *inode, const char *fname,
10079+ const char *fxn, int line);
10080+extern void __unionfs_check_dentry(const struct dentry *dentry,
10081+ const char *fname, const char *fxn,
10082+ int line);
10083+extern void __unionfs_check_file(const struct file *file,
10084+ const char *fname, const char *fxn, int line);
10085+extern void __unionfs_check_nd(const struct nameidata *nd,
10086+ const char *fname, const char *fxn, int line);
10087+extern void __show_branch_counts(const struct super_block *sb,
10088+ const char *file, const char *fxn, int line);
10089+extern void __show_inode_times(const struct inode *inode,
10090+ const char *file, const char *fxn, int line);
10091+extern void __show_dinode_times(const struct dentry *dentry,
10092+ const char *file, const char *fxn, int line);
10093+extern void __show_inode_counts(const struct inode *inode,
10094+ const char *file, const char *fxn, int line);
10095+
10096+#else /* not CONFIG_UNION_FS_DEBUG */
10097+
10098+/* we leave useful hooks for these check functions throughout the code */
10099+#define unionfs_check_inode(i) do { } while (0)
10100+#define unionfs_check_dentry(d) do { } while (0)
10101+#define unionfs_check_file(f) do { } while (0)
10102+#define unionfs_check_nd(n) do { } while (0)
10103+#define show_branch_counts(sb) do { } while (0)
10104+#define show_inode_times(i) do { } while (0)
10105+#define show_dinode_times(d) do { } while (0)
10106+#define show_inode_counts(i) do { } while (0)
10107+
10108+#endif /* not CONFIG_UNION_FS_DEBUG */
10109+
10110+#endif /* not _UNION_H_ */
10111diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
10112new file mode 100644
10113index 0000000..542c513
10114--- /dev/null
10115+++ b/fs/unionfs/unlink.c
10116@@ -0,0 +1,278 @@
10117+/*
10118+ * Copyright (c) 2003-2010 Erez Zadok
10119+ * Copyright (c) 2003-2006 Charles P. Wright
10120+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
10121+ * Copyright (c) 2005-2006 Junjiro Okajima
10122+ * Copyright (c) 2005 Arun M. Krishnakumar
10123+ * Copyright (c) 2004-2006 David P. Quigley
10124+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
10125+ * Copyright (c) 2003 Puja Gupta
10126+ * Copyright (c) 2003 Harikesavan Krishnan
10127+ * Copyright (c) 2003-2010 Stony Brook University
10128+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
10129+ *
10130+ * This program is free software; you can redistribute it and/or modify
10131+ * it under the terms of the GNU General Public License version 2 as
10132+ * published by the Free Software Foundation.
10133+ */
10134+
10135+#include "union.h"
10136+
10137+/*
10138+ * Helper function for Unionfs's unlink operation.
10139+ *
10140+ * The main goal of this function is to optimize the unlinking of non-dir
10141+ * objects in unionfs by deleting all possible lower inode objects from the
10142+ * underlying branches having same dentry name as the non-dir dentry on
10143+ * which this unlink operation is called. This way we delete as many lower
10144+ * inodes as possible, and save space. Whiteouts need to be created in
10145+ * branch0 only if unlinking fails on any of the lower branch other than
10146+ * branch0, or if a lower branch is marked read-only.
10147+ *
10148+ * Also, while unlinking a file, if we encounter any dir type entry in any
10149+ * intermediate branch, then we remove the directory by calling vfs_rmdir.
10150+ * The following special cases are also handled:
10151+
10152+ * (1) If an error occurs in branch0 during vfs_unlink, then we return
10153+ * appropriate error.
10154+ *
10155+ * (2) If we get an error during unlink in any of other lower branch other
10156+ * than branch0, then we create a whiteout in branch0.
10157+ *
10158+ * (3) If a whiteout already exists in any intermediate branch, we delete
10159+ * all possible inodes only up to that branch (this is an "opaqueness"
10160+ * as as per Documentation/filesystems/unionfs/concepts.txt).
10161+ *
10162+ */
10163+static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry,
10164+ struct dentry *parent)
10165+{
10166+ struct dentry *lower_dentry;
10167+ struct dentry *lower_dir_dentry;
10168+ int bindex;
10169+ int err = 0;
10170+
10171+ err = unionfs_partial_lookup(dentry, parent);
10172+ if (err)
10173+ goto out;
10174+
10175+ /* trying to unlink all possible valid instances */
10176+ for (bindex = dbstart(dentry); bindex <= dbend(dentry); bindex++) {
10177+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
10178+ if (!lower_dentry || !lower_dentry->d_inode)
10179+ continue;
10180+
10181+ lower_dir_dentry = lock_parent(lower_dentry);
10182+
10183+ /* avoid destroying the lower inode if the object is in use */
10184+ dget(lower_dentry);
10185+ err = is_robranch_super(dentry->d_sb, bindex);
10186+ if (!err) {
10187+ /* see Documentation/filesystems/unionfs/issues.txt */
10188+ lockdep_off();
10189+ if (!S_ISDIR(lower_dentry->d_inode->i_mode))
10190+ err = vfs_unlink(lower_dir_dentry->d_inode,
10191+ lower_dentry);
10192+ else
10193+ err = vfs_rmdir(lower_dir_dentry->d_inode,
10194+ lower_dentry);
10195+ lockdep_on();
10196+ }
10197+
10198+ /* if lower object deletion succeeds, update inode's times */
10199+ if (!err)
10200+ unionfs_copy_attr_times(dentry->d_inode);
10201+ dput(lower_dentry);
10202+ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
10203+ unlock_dir(lower_dir_dentry);
10204+
10205+ if (err)
10206+ break;
10207+ }
10208+
10209+ /*
10210+ * Create the whiteout in branch 0 (highest priority) only if (a)
10211+ * there was an error in any intermediate branch other than branch 0
10212+ * due to failure of vfs_unlink/vfs_rmdir or (b) a branch marked or
10213+ * mounted read-only.
10214+ */
10215+ if (err) {
10216+ if ((bindex == 0) ||
10217+ ((bindex == dbstart(dentry)) &&
10218+ (!IS_COPYUP_ERR(err))))
10219+ goto out;
10220+ else {
10221+ if (!IS_COPYUP_ERR(err))
10222+ pr_debug("unionfs: lower object deletion "
10223+ "failed in branch:%d\n", bindex);
10224+ err = create_whiteout(dentry, sbstart(dentry->d_sb));
10225+ }
10226+ }
10227+
10228+out:
10229+ if (!err)
10230+ inode_dec_link_count(dentry->d_inode);
10231+
10232+ /* We don't want to leave negative leftover dentries for revalidate. */
10233+ if (!err && (dbopaque(dentry) != -1))
10234+ update_bstart(dentry);
10235+
10236+ return err;
10237+}
10238+
10239+int unionfs_unlink(struct inode *dir, struct dentry *dentry)
10240+{
10241+ int err = 0;
10242+ struct inode *inode = dentry->d_inode;
10243+ struct dentry *parent;
10244+ int valid;
10245+
10246+ BUG_ON(S_ISDIR(inode->i_mode));
10247+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
10248+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
10249+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
10250+
10251+ valid = __unionfs_d_revalidate(dentry, parent, false);
10252+ if (unlikely(!valid)) {
10253+ err = -ESTALE;
10254+ goto out;
10255+ }
10256+ unionfs_check_dentry(dentry);
10257+
10258+ err = unionfs_unlink_whiteout(dir, dentry, parent);
10259+ /* call d_drop so the system "forgets" about us */
10260+ if (!err) {
10261+ unionfs_postcopyup_release(dentry);
10262+ unionfs_postcopyup_setmnt(parent);
10263+ if (inode->i_nlink == 0) /* drop lower inodes */
10264+ iput_lowers_all(inode, false);
10265+ d_drop(dentry);
10266+ /*
10267+ * if unlink/whiteout succeeded, parent dir mtime has
10268+ * changed
10269+ */
10270+ unionfs_copy_attr_times(dir);
10271+ }
10272+
10273+out:
10274+ if (!err) {
10275+ unionfs_check_dentry(dentry);
10276+ unionfs_check_inode(dir);
10277+ }
10278+ unionfs_unlock_dentry(dentry);
10279+ unionfs_unlock_parent(dentry, parent);
10280+ unionfs_read_unlock(dentry->d_sb);
10281+ return err;
10282+}
10283+
10284+static int unionfs_rmdir_first(struct inode *dir, struct dentry *dentry,
10285+ struct unionfs_dir_state *namelist)
10286+{
10287+ int err;
10288+ struct dentry *lower_dentry;
10289+ struct dentry *lower_dir_dentry = NULL;
10290+
10291+ /* Here we need to remove whiteout entries. */
10292+ err = delete_whiteouts(dentry, dbstart(dentry), namelist);
10293+ if (err)
10294+ goto out;
10295+
10296+ lower_dentry = unionfs_lower_dentry(dentry);
10297+
10298+ lower_dir_dentry = lock_parent(lower_dentry);
10299+
10300+ /* avoid destroying the lower inode if the file is in use */
10301+ dget(lower_dentry);
10302+ err = is_robranch(dentry);
10303+ if (!err)
10304+ err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
10305+ dput(lower_dentry);
10306+
10307+ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
10308+ /* propagate number of hard-links */
10309+ dentry->d_inode->i_nlink = unionfs_get_nlinks(dentry->d_inode);
10310+
10311+out:
10312+ if (lower_dir_dentry)
10313+ unlock_dir(lower_dir_dentry);
10314+ return err;
10315+}
10316+
10317+int unionfs_rmdir(struct inode *dir, struct dentry *dentry)
10318+{
10319+ int err = 0;
10320+ struct unionfs_dir_state *namelist = NULL;
10321+ struct dentry *parent;
10322+ int dstart, dend;
10323+ bool valid;
10324+
10325+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
10326+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
10327+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
10328+
10329+ valid = __unionfs_d_revalidate(dentry, parent, false);
10330+ if (unlikely(!valid)) {
10331+ err = -ESTALE;
10332+ goto out;
10333+ }
10334+ unionfs_check_dentry(dentry);
10335+
10336+ /* check if this unionfs directory is empty or not */
10337+ err = check_empty(dentry, parent, &namelist);
10338+ if (err)
10339+ goto out;
10340+
10341+ err = unionfs_rmdir_first(dir, dentry, namelist);
10342+ dstart = dbstart(dentry);
10343+ dend = dbend(dentry);
10344+ /*
10345+ * We create a whiteout for the directory if there was an error to
10346+ * rmdir the first directory entry in the union. Otherwise, we
10347+ * create a whiteout only if there is no chance that a lower
10348+ * priority branch might also have the same named directory. IOW,
10349+ * if there is not another same-named directory at a lower priority
10350+ * branch, then we don't need to create a whiteout for it.
10351+ */
10352+ if (!err) {
10353+ if (dstart < dend)
10354+ err = create_whiteout(dentry, dstart);
10355+ } else {
10356+ int new_err;
10357+
10358+ if (dstart == 0)
10359+ goto out;
10360+
10361+ /* exit if the error returned was NOT -EROFS */
10362+ if (!IS_COPYUP_ERR(err))
10363+ goto out;
10364+
10365+ new_err = create_whiteout(dentry, dstart - 1);
10366+ if (new_err != -EEXIST)
10367+ err = new_err;
10368+ }
10369+
10370+out:
10371+ /*
10372+ * Drop references to lower dentry/inode so storage space for them
10373+ * can be reclaimed. Then, call d_drop so the system "forgets"
10374+ * about us.
10375+ */
10376+ if (!err) {
10377+ iput_lowers_all(dentry->d_inode, false);
10378+ dput(unionfs_lower_dentry_idx(dentry, dstart));
10379+ unionfs_set_lower_dentry_idx(dentry, dstart, NULL);
10380+ d_drop(dentry);
10381+ /* update our lower vfsmnts, in case a copyup took place */
10382+ unionfs_postcopyup_setmnt(dentry);
10383+ unionfs_check_dentry(dentry);
10384+ unionfs_check_inode(dir);
10385+ }
10386+
10387+ if (namelist)
10388+ free_rdstate(namelist);
10389+
10390+ unionfs_unlock_dentry(dentry);
10391+ unionfs_unlock_parent(dentry, parent);
10392+ unionfs_read_unlock(dentry->d_sb);
10393+ return err;
10394+}
10395diff --git a/fs/unionfs/whiteout.c b/fs/unionfs/whiteout.c
10396new file mode 100644
10397index 0000000..405073a
10398--- /dev/null
10399+++ b/fs/unionfs/whiteout.c
10400@@ -0,0 +1,584 @@
10401+/*
10402+ * Copyright (c) 2003-2010 Erez Zadok
10403+ * Copyright (c) 2003-2006 Charles P. Wright
10404+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
10405+ * Copyright (c) 2005-2006 Junjiro Okajima
10406+ * Copyright (c) 2005 Arun M. Krishnakumar
10407+ * Copyright (c) 2004-2006 David P. Quigley
10408+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
10409+ * Copyright (c) 2003 Puja Gupta
10410+ * Copyright (c) 2003 Harikesavan Krishnan
10411+ * Copyright (c) 2003-2010 Stony Brook University
10412+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
10413+ *
10414+ * This program is free software; you can redistribute it and/or modify
10415+ * it under the terms of the GNU General Public License version 2 as
10416+ * published by the Free Software Foundation.
10417+ */
10418+
10419+#include "union.h"
10420+
10421+/*
10422+ * whiteout and opaque directory helpers
10423+ */
10424+
10425+/* What do we use for whiteouts. */
10426+#define UNIONFS_WHPFX ".wh."
10427+#define UNIONFS_WHLEN 4
10428+/*
10429+ * If a directory contains this file, then it is opaque. We start with the
10430+ * .wh. flag so that it is blocked by lookup.
10431+ */
10432+#define UNIONFS_DIR_OPAQUE_NAME "__dir_opaque"
10433+#define UNIONFS_DIR_OPAQUE UNIONFS_WHPFX UNIONFS_DIR_OPAQUE_NAME
10434+
10435+/* construct whiteout filename */
10436+char *alloc_whname(const char *name, int len)
10437+{
10438+ char *buf;
10439+
10440+ buf = kmalloc(len + UNIONFS_WHLEN + 1, GFP_KERNEL);
10441+ if (unlikely(!buf))
10442+ return ERR_PTR(-ENOMEM);
10443+
10444+ strcpy(buf, UNIONFS_WHPFX);
10445+ strlcat(buf, name, len + UNIONFS_WHLEN + 1);
10446+
10447+ return buf;
10448+}
10449+
10450+/*
10451+ * XXX: this can be inline or CPP macro, but is here to keep all whiteout
10452+ * code in one place.
10453+ */
10454+void unionfs_set_max_namelen(long *namelen)
10455+{
10456+ *namelen -= UNIONFS_WHLEN;
10457+}
10458+
10459+/* check if @namep is a whiteout, update @namep and @namelenp accordingly */
10460+bool is_whiteout_name(char **namep, int *namelenp)
10461+{
10462+ if (*namelenp > UNIONFS_WHLEN &&
10463+ !strncmp(*namep, UNIONFS_WHPFX, UNIONFS_WHLEN)) {
10464+ *namep += UNIONFS_WHLEN;
10465+ *namelenp -= UNIONFS_WHLEN;
10466+ return true;
10467+ }
10468+ return false;
10469+}
10470+
10471+/* is the filename valid == !(whiteout for a file or opaque dir marker) */
10472+bool is_validname(const char *name)
10473+{
10474+ if (!strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN))
10475+ return false;
10476+ if (!strncmp(name, UNIONFS_DIR_OPAQUE_NAME,
10477+ sizeof(UNIONFS_DIR_OPAQUE_NAME) - 1))
10478+ return false;
10479+ return true;
10480+}
10481+
10482+/*
10483+ * Look for a whiteout @name in @lower_parent directory. If error, return
10484+ * ERR_PTR. Caller must dput() the returned dentry if not an error.
10485+ *
10486+ * XXX: some callers can reuse the whname allocated buffer to avoid repeated
10487+ * free then re-malloc calls. Need to provide a different API for those
10488+ * callers.
10489+ */
10490+struct dentry *lookup_whiteout(const char *name, struct dentry *lower_parent)
10491+{
10492+ char *whname = NULL;
10493+ int err = 0, namelen;
10494+ struct dentry *wh_dentry = NULL;
10495+
10496+ namelen = strlen(name);
10497+ whname = alloc_whname(name, namelen);
10498+ if (unlikely(IS_ERR(whname))) {
10499+ err = PTR_ERR(whname);
10500+ goto out;
10501+ }
10502+
10503+ /* check if whiteout exists in this branch: lookup .wh.foo */
10504+ wh_dentry = lookup_lck_len(whname, lower_parent, strlen(whname));
10505+ if (IS_ERR(wh_dentry)) {
10506+ err = PTR_ERR(wh_dentry);
10507+ goto out;
10508+ }
10509+
10510+ /* check if negative dentry (ENOENT) */
10511+ if (!wh_dentry->d_inode)
10512+ goto out;
10513+
10514+ /* whiteout found: check if valid type */
10515+ if (!S_ISREG(wh_dentry->d_inode->i_mode)) {
10516+ printk(KERN_ERR "unionfs: invalid whiteout %s entry type %d\n",
10517+ whname, wh_dentry->d_inode->i_mode);
10518+ dput(wh_dentry);
10519+ err = -EIO;
10520+ goto out;
10521+ }
10522+
10523+out:
10524+ kfree(whname);
10525+ if (err)
10526+ wh_dentry = ERR_PTR(err);
10527+ return wh_dentry;
10528+}
10529+
10530+/* find and return first whiteout in parent directory, else ENOENT */
10531+struct dentry *find_first_whiteout(struct dentry *dentry)
10532+{
10533+ int bindex, bstart, bend;
10534+ struct dentry *parent, *lower_parent, *wh_dentry;
10535+
10536+ parent = dget_parent(dentry);
10537+
10538+ bstart = dbstart(parent);
10539+ bend = dbend(parent);
10540+ wh_dentry = ERR_PTR(-ENOENT);
10541+
10542+ for (bindex = bstart; bindex <= bend; bindex++) {
10543+ lower_parent = unionfs_lower_dentry_idx(parent, bindex);
10544+ if (!lower_parent)
10545+ continue;
10546+ wh_dentry = lookup_whiteout(dentry->d_name.name, lower_parent);
10547+ if (IS_ERR(wh_dentry))
10548+ continue;
10549+ if (wh_dentry->d_inode)
10550+ break;
10551+ dput(wh_dentry);
10552+ wh_dentry = ERR_PTR(-ENOENT);
10553+ }
10554+
10555+ dput(parent);
10556+
10557+ return wh_dentry;
10558+}
10559+
10560+/*
10561+ * Unlink a whiteout dentry. Returns 0 or -errno. Caller must hold and
10562+ * release dentry reference.
10563+ */
10564+int unlink_whiteout(struct dentry *wh_dentry)
10565+{
10566+ int err;
10567+ struct dentry *lower_dir_dentry;
10568+
10569+ /* dget and lock parent dentry */
10570+ lower_dir_dentry = lock_parent_wh(wh_dentry);
10571+
10572+ /* see Documentation/filesystems/unionfs/issues.txt */
10573+ lockdep_off();
10574+ err = vfs_unlink(lower_dir_dentry->d_inode, wh_dentry);
10575+ lockdep_on();
10576+ unlock_dir(lower_dir_dentry);
10577+
10578+ /*
10579+ * Whiteouts are special files and should be deleted no matter what
10580+ * (as if they never existed), in order to allow this create
10581+ * operation to succeed. This is especially important in sticky
10582+ * directories: a whiteout may have been created by one user, but
10583+ * the newly created file may be created by another user.
10584+ * Therefore, in order to maintain Unix semantics, if the vfs_unlink
10585+ * above failed, then we have to try to directly unlink the
10586+ * whiteout. Note: in the ODF version of unionfs, whiteout are
10587+ * handled much more cleanly.
10588+ */
10589+ if (err == -EPERM) {
10590+ struct inode *inode = lower_dir_dentry->d_inode;
10591+ err = inode->i_op->unlink(inode, wh_dentry);
10592+ }
10593+ if (err)
10594+ printk(KERN_ERR "unionfs: could not unlink whiteout %s, "
10595+ "err = %d\n", wh_dentry->d_name.name, err);
10596+
10597+ return err;
10598+
10599+}
10600+
10601+/*
10602+ * Helper function when creating new objects (create, symlink, mknod, etc.).
10603+ * Checks to see if there's a whiteout in @lower_dentry's parent directory,
10604+ * whose name is taken from @dentry. Then tries to remove that whiteout, if
10605+ * found. If <dentry,bindex> is a branch marked readonly, return -EROFS.
10606+ * If it finds both a regular file and a whiteout, return -EIO (this should
10607+ * never happen).
10608+ *
10609+ * Return 0 if no whiteout was found. Return 1 if one was found and
10610+ * successfully removed. Therefore a value >= 0 tells the caller that
10611+ * @lower_dentry belongs to a good branch to create the new object in).
10612+ * Return -ERRNO if an error occurred during whiteout lookup or in trying to
10613+ * unlink the whiteout.
10614+ */
10615+int check_unlink_whiteout(struct dentry *dentry, struct dentry *lower_dentry,
10616+ int bindex)
10617+{
10618+ int err;
10619+ struct dentry *wh_dentry = NULL;
10620+ struct dentry *lower_dir_dentry = NULL;
10621+
10622+ /* look for whiteout dentry first */
10623+ lower_dir_dentry = dget_parent(lower_dentry);
10624+ wh_dentry = lookup_whiteout(dentry->d_name.name, lower_dir_dentry);
10625+ dput(lower_dir_dentry);
10626+ if (IS_ERR(wh_dentry)) {
10627+ err = PTR_ERR(wh_dentry);
10628+ goto out;
10629+ }
10630+
10631+ if (!wh_dentry->d_inode) { /* no whiteout exists*/
10632+ err = 0;
10633+ goto out_dput;
10634+ }
10635+
10636+ /* check if regular file and whiteout were both found */
10637+ if (unlikely(lower_dentry->d_inode)) {
10638+ err = -EIO;
10639+ printk(KERN_ERR "unionfs: found both whiteout and regular "
10640+ "file in directory %s (branch %d)\n",
10641+ lower_dir_dentry->d_name.name, bindex);
10642+ goto out_dput;
10643+ }
10644+
10645+ /* check if branch is writeable */
10646+ err = is_robranch_super(dentry->d_sb, bindex);
10647+ if (err)
10648+ goto out_dput;
10649+
10650+ /* .wh.foo has been found, so let's unlink it */
10651+ err = unlink_whiteout(wh_dentry);
10652+ if (!err)
10653+ err = 1; /* a whiteout was found and successfully removed */
10654+out_dput:
10655+ dput(wh_dentry);
10656+out:
10657+ return err;
10658+}
10659+
10660+/*
10661+ * Pass an unionfs dentry and an index. It will try to create a whiteout
10662+ * for the filename in dentry, and will try in branch 'index'. On error,
10663+ * it will proceed to a branch to the left.
10664+ */
10665+int create_whiteout(struct dentry *dentry, int start)
10666+{
10667+ int bstart, bend, bindex;
10668+ struct dentry *lower_dir_dentry;
10669+ struct dentry *lower_dentry;
10670+ struct dentry *lower_wh_dentry;
10671+ struct nameidata nd;
10672+ char *name = NULL;
10673+ int err = -EINVAL;
10674+
10675+ verify_locked(dentry);
10676+
10677+ bstart = dbstart(dentry);
10678+ bend = dbend(dentry);
10679+
10680+ /* create dentry's whiteout equivalent */
10681+ name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
10682+ if (unlikely(IS_ERR(name))) {
10683+ err = PTR_ERR(name);
10684+ goto out;
10685+ }
10686+
10687+ for (bindex = start; bindex >= 0; bindex--) {
10688+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
10689+
10690+ if (!lower_dentry) {
10691+ /*
10692+ * if lower dentry is not present, create the
10693+ * entire lower dentry directory structure and go
10694+ * ahead. Since we want to just create whiteout, we
10695+ * only want the parent dentry, and hence get rid of
10696+ * this dentry.
10697+ */
10698+ lower_dentry = create_parents(dentry->d_inode,
10699+ dentry,
10700+ dentry->d_name.name,
10701+ bindex);
10702+ if (!lower_dentry || IS_ERR(lower_dentry)) {
10703+ int ret = PTR_ERR(lower_dentry);
10704+ if (!IS_COPYUP_ERR(ret))
10705+ printk(KERN_ERR
10706+ "unionfs: create_parents for "
10707+ "whiteout failed: bindex=%d "
10708+ "err=%d\n", bindex, ret);
10709+ continue;
10710+ }
10711+ }
10712+
10713+ lower_wh_dentry =
10714+ lookup_lck_len(name, lower_dentry->d_parent,
10715+ dentry->d_name.len + UNIONFS_WHLEN);
10716+ if (IS_ERR(lower_wh_dentry))
10717+ continue;
10718+
10719+ /*
10720+ * The whiteout already exists. This used to be impossible,
10721+ * but now is possible because of opaqueness.
10722+ */
10723+ if (lower_wh_dentry->d_inode) {
10724+ dput(lower_wh_dentry);
10725+ err = 0;
10726+ goto out;
10727+ }
10728+
10729+ err = init_lower_nd(&nd, LOOKUP_CREATE);
10730+ if (unlikely(err < 0))
10731+ goto out;
10732+ lower_dir_dentry = lock_parent_wh(lower_wh_dentry);
10733+ err = is_robranch_super(dentry->d_sb, bindex);
10734+ if (!err)
10735+ err = vfs_create(lower_dir_dentry->d_inode,
10736+ lower_wh_dentry,
10737+ current_umask() & S_IRUGO,
10738+ &nd);
10739+ unlock_dir(lower_dir_dentry);
10740+ dput(lower_wh_dentry);
10741+ release_lower_nd(&nd, err);
10742+
10743+ if (!err || !IS_COPYUP_ERR(err))
10744+ break;
10745+ }
10746+
10747+ /* set dbopaque so that lookup will not proceed after this branch */
10748+ if (!err)
10749+ dbopaque(dentry) = bindex;
10750+
10751+out:
10752+ kfree(name);
10753+ return err;
10754+}
10755+
10756+/*
10757+ * Delete all of the whiteouts in a given directory for rmdir.
10758+ *
10759+ * lower directory inode should be locked
10760+ */
10761+static int do_delete_whiteouts(struct dentry *dentry, int bindex,
10762+ struct unionfs_dir_state *namelist)
10763+{
10764+ int err = 0;
10765+ struct dentry *lower_dir_dentry = NULL;
10766+ struct dentry *lower_dentry;
10767+ char *name = NULL, *p;
10768+ struct inode *lower_dir;
10769+ int i;
10770+ struct list_head *pos;
10771+ struct filldir_node *cursor;
10772+
10773+ /* Find out lower parent dentry */
10774+ lower_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
10775+ BUG_ON(!S_ISDIR(lower_dir_dentry->d_inode->i_mode));
10776+ lower_dir = lower_dir_dentry->d_inode;
10777+ BUG_ON(!S_ISDIR(lower_dir->i_mode));
10778+
10779+ err = -ENOMEM;
10780+ name = __getname();
10781+ if (unlikely(!name))
10782+ goto out;
10783+ strcpy(name, UNIONFS_WHPFX);
10784+ p = name + UNIONFS_WHLEN;
10785+
10786+ err = 0;
10787+ for (i = 0; !err && i < namelist->size; i++) {
10788+ list_for_each(pos, &namelist->list[i]) {
10789+ cursor =
10790+ list_entry(pos, struct filldir_node,
10791+ file_list);
10792+ /* Only operate on whiteouts in this branch. */
10793+ if (cursor->bindex != bindex)
10794+ continue;
10795+ if (!cursor->whiteout)
10796+ continue;
10797+
10798+ strlcpy(p, cursor->name, PATH_MAX - UNIONFS_WHLEN);
10799+ lower_dentry =
10800+ lookup_lck_len(name, lower_dir_dentry,
10801+ cursor->namelen +
10802+ UNIONFS_WHLEN);
10803+ if (IS_ERR(lower_dentry)) {
10804+ err = PTR_ERR(lower_dentry);
10805+ break;
10806+ }
10807+ if (lower_dentry->d_inode)
10808+ err = vfs_unlink(lower_dir, lower_dentry);
10809+ dput(lower_dentry);
10810+ if (err)
10811+ break;
10812+ }
10813+ }
10814+
10815+ __putname(name);
10816+
10817+ /* After all of the removals, we should copy the attributes once. */
10818+ fsstack_copy_attr_times(dentry->d_inode, lower_dir_dentry->d_inode);
10819+
10820+out:
10821+ return err;
10822+}
10823+
10824+
10825+void __delete_whiteouts(struct work_struct *work)
10826+{
10827+ struct sioq_args *args = container_of(work, struct sioq_args, work);
10828+ struct deletewh_args *d = &args->deletewh;
10829+
10830+ args->err = do_delete_whiteouts(d->dentry, d->bindex, d->namelist);
10831+ complete(&args->comp);
10832+}
10833+
10834+/* delete whiteouts in a dir (for rmdir operation) using sioq if necessary */
10835+int delete_whiteouts(struct dentry *dentry, int bindex,
10836+ struct unionfs_dir_state *namelist)
10837+{
10838+ int err;
10839+ struct super_block *sb;
10840+ struct dentry *lower_dir_dentry;
10841+ struct inode *lower_dir;
10842+ struct sioq_args args;
10843+
10844+ sb = dentry->d_sb;
10845+
10846+ BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
10847+ BUG_ON(bindex < dbstart(dentry));
10848+ BUG_ON(bindex > dbend(dentry));
10849+ err = is_robranch_super(sb, bindex);
10850+ if (err)
10851+ goto out;
10852+
10853+ lower_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
10854+ BUG_ON(!S_ISDIR(lower_dir_dentry->d_inode->i_mode));
10855+ lower_dir = lower_dir_dentry->d_inode;
10856+ BUG_ON(!S_ISDIR(lower_dir->i_mode));
10857+
10858+ if (!inode_permission(lower_dir, MAY_WRITE | MAY_EXEC)) {
10859+ err = do_delete_whiteouts(dentry, bindex, namelist);
10860+ } else {
10861+ args.deletewh.namelist = namelist;
10862+ args.deletewh.dentry = dentry;
10863+ args.deletewh.bindex = bindex;
10864+ run_sioq(__delete_whiteouts, &args);
10865+ err = args.err;
10866+ }
10867+
10868+out:
10869+ return err;
10870+}
10871+
10872+/****************************************************************************
10873+ * Opaque directory helpers *
10874+ ****************************************************************************/
10875+
10876+/*
10877+ * is_opaque_dir: returns 0 if it is NOT an opaque dir, 1 if it is, and
10878+ * -errno if an error occurred trying to figure this out.
10879+ */
10880+int is_opaque_dir(struct dentry *dentry, int bindex)
10881+{
10882+ int err = 0;
10883+ struct dentry *lower_dentry;
10884+ struct dentry *wh_lower_dentry;
10885+ struct inode *lower_inode;
10886+ struct sioq_args args;
10887+
10888+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
10889+ lower_inode = lower_dentry->d_inode;
10890+
10891+ BUG_ON(!S_ISDIR(lower_inode->i_mode));
10892+
10893+ mutex_lock(&lower_inode->i_mutex);
10894+
10895+ if (!inode_permission(lower_inode, MAY_EXEC)) {
10896+ wh_lower_dentry =
10897+ lookup_one_len(UNIONFS_DIR_OPAQUE, lower_dentry,
10898+ sizeof(UNIONFS_DIR_OPAQUE) - 1);
10899+ } else {
10900+ args.is_opaque.dentry = lower_dentry;
10901+ run_sioq(__is_opaque_dir, &args);
10902+ wh_lower_dentry = args.ret;
10903+ }
10904+
10905+ mutex_unlock(&lower_inode->i_mutex);
10906+
10907+ if (IS_ERR(wh_lower_dentry)) {
10908+ err = PTR_ERR(wh_lower_dentry);
10909+ goto out;
10910+ }
10911+
10912+ /* This is an opaque dir iff wh_lower_dentry is positive */
10913+ err = !!wh_lower_dentry->d_inode;
10914+
10915+ dput(wh_lower_dentry);
10916+out:
10917+ return err;
10918+}
10919+
10920+void __is_opaque_dir(struct work_struct *work)
10921+{
10922+ struct sioq_args *args = container_of(work, struct sioq_args, work);
10923+
10924+ args->ret = lookup_one_len(UNIONFS_DIR_OPAQUE, args->is_opaque.dentry,
10925+ sizeof(UNIONFS_DIR_OPAQUE) - 1);
10926+ complete(&args->comp);
10927+}
10928+
10929+int make_dir_opaque(struct dentry *dentry, int bindex)
10930+{
10931+ int err = 0;
10932+ struct dentry *lower_dentry, *diropq;
10933+ struct inode *lower_dir;
10934+ struct nameidata nd;
10935+ const struct cred *old_creds;
10936+ struct cred *new_creds;
10937+
10938+ /*
10939+ * Opaque directory whiteout markers are special files (like regular
10940+ * whiteouts), and should appear to the users as if they don't
10941+ * exist. They should be created/deleted regardless of directory
10942+ * search/create permissions, but only for the duration of this
10943+ * creation of the .wh.__dir_opaque: file. Note, this does not
10944+ * circumvent normal ->permission).
10945+ */
10946+ new_creds = prepare_creds();
10947+ if (unlikely(!new_creds)) {
10948+ err = -ENOMEM;
10949+ goto out_err;
10950+ }
10951+ cap_raise(new_creds->cap_effective, CAP_DAC_READ_SEARCH);
10952+ cap_raise(new_creds->cap_effective, CAP_DAC_OVERRIDE);
10953+ old_creds = override_creds(new_creds);
10954+
10955+ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
10956+ lower_dir = lower_dentry->d_inode;
10957+ BUG_ON(!S_ISDIR(dentry->d_inode->i_mode) ||
10958+ !S_ISDIR(lower_dir->i_mode));
10959+
10960+ mutex_lock(&lower_dir->i_mutex);
10961+ diropq = lookup_one_len(UNIONFS_DIR_OPAQUE, lower_dentry,
10962+ sizeof(UNIONFS_DIR_OPAQUE) - 1);
10963+ if (IS_ERR(diropq)) {
10964+ err = PTR_ERR(diropq);
10965+ goto out;
10966+ }
10967+
10968+ err = init_lower_nd(&nd, LOOKUP_CREATE);
10969+ if (unlikely(err < 0))
10970+ goto out;
10971+ if (!diropq->d_inode)
10972+ err = vfs_create(lower_dir, diropq, S_IRUGO, &nd);
10973+ if (!err)
10974+ dbopaque(dentry) = bindex;
10975+ release_lower_nd(&nd, err);
10976+
10977+ dput(diropq);
10978+
10979+out:
10980+ mutex_unlock(&lower_dir->i_mutex);
10981+ revert_creds(old_creds);
10982+out_err:
10983+ return err;
10984+}
10985diff --git a/fs/unionfs/xattr.c b/fs/unionfs/xattr.c
10986new file mode 100644
10987index 0000000..9002e06
10988--- /dev/null
10989+++ b/fs/unionfs/xattr.c
10990@@ -0,0 +1,173 @@
10991+/*
10992+ * Copyright (c) 2003-2010 Erez Zadok
10993+ * Copyright (c) 2003-2006 Charles P. Wright
10994+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
10995+ * Copyright (c) 2005-2006 Junjiro Okajima
10996+ * Copyright (c) 2005 Arun M. Krishnakumar
10997+ * Copyright (c) 2004-2006 David P. Quigley
10998+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
10999+ * Copyright (c) 2003 Puja Gupta
11000+ * Copyright (c) 2003 Harikesavan Krishnan
11001+ * Copyright (c) 2003-2010 Stony Brook University
11002+ * Copyright (c) 2003-2010 The Research Foundation of SUNY
11003+ *
11004+ * This program is free software; you can redistribute it and/or modify
11005+ * it under the terms of the GNU General Public License version 2 as
11006+ * published by the Free Software Foundation.
11007+ */
11008+
11009+#include "union.h"
11010+
11011+/* This is lifted from fs/xattr.c */
11012+void *unionfs_xattr_alloc(size_t size, size_t limit)
11013+{
11014+ void *ptr;
11015+
11016+ if (size > limit)
11017+ return ERR_PTR(-E2BIG);
11018+
11019+ if (!size) /* size request, no buffer is needed */
11020+ return NULL;
11021+
11022+ ptr = kmalloc(size, GFP_KERNEL);
11023+ if (unlikely(!ptr))
11024+ return ERR_PTR(-ENOMEM);
11025+ return ptr;
11026+}
11027+
11028+/*
11029+ * BKL held by caller.
11030+ * dentry->d_inode->i_mutex locked
11031+ */
11032+ssize_t unionfs_getxattr(struct dentry *dentry, const char *name, void *value,
11033+ size_t size)
11034+{
11035+ struct dentry *lower_dentry = NULL;
11036+ struct dentry *parent;
11037+ int err = -EOPNOTSUPP;
11038+ bool valid;
11039+
11040+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
11041+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
11042+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
11043+
11044+ valid = __unionfs_d_revalidate(dentry, parent, false);
11045+ if (unlikely(!valid)) {
11046+ err = -ESTALE;
11047+ goto out;
11048+ }
11049+
11050+ lower_dentry = unionfs_lower_dentry(dentry);
11051+
11052+ err = vfs_getxattr(lower_dentry, (char *) name, value, size);
11053+
11054+out:
11055+ unionfs_check_dentry(dentry);
11056+ unionfs_unlock_dentry(dentry);
11057+ unionfs_unlock_parent(dentry, parent);
11058+ unionfs_read_unlock(dentry->d_sb);
11059+ return err;
11060+}
11061+
11062+/*
11063+ * BKL held by caller.
11064+ * dentry->d_inode->i_mutex locked
11065+ */
11066+int unionfs_setxattr(struct dentry *dentry, const char *name,
11067+ const void *value, size_t size, int flags)
11068+{
11069+ struct dentry *lower_dentry = NULL;
11070+ struct dentry *parent;
11071+ int err = -EOPNOTSUPP;
11072+ bool valid;
11073+
11074+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
11075+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
11076+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
11077+
11078+ valid = __unionfs_d_revalidate(dentry, parent, false);
11079+ if (unlikely(!valid)) {
11080+ err = -ESTALE;
11081+ goto out;
11082+ }
11083+
11084+ lower_dentry = unionfs_lower_dentry(dentry);
11085+
11086+ err = vfs_setxattr(lower_dentry, (char *) name, (void *) value,
11087+ size, flags);
11088+
11089+out:
11090+ unionfs_check_dentry(dentry);
11091+ unionfs_unlock_dentry(dentry);
11092+ unionfs_unlock_parent(dentry, parent);
11093+ unionfs_read_unlock(dentry->d_sb);
11094+ return err;
11095+}
11096+
11097+/*
11098+ * BKL held by caller.
11099+ * dentry->d_inode->i_mutex locked
11100+ */
11101+int unionfs_removexattr(struct dentry *dentry, const char *name)
11102+{
11103+ struct dentry *lower_dentry = NULL;
11104+ struct dentry *parent;
11105+ int err = -EOPNOTSUPP;
11106+ bool valid;
11107+
11108+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
11109+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
11110+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
11111+
11112+ valid = __unionfs_d_revalidate(dentry, parent, false);
11113+ if (unlikely(!valid)) {
11114+ err = -ESTALE;
11115+ goto out;
11116+ }
11117+
11118+ lower_dentry = unionfs_lower_dentry(dentry);
11119+
11120+ err = vfs_removexattr(lower_dentry, (char *) name);
11121+
11122+out:
11123+ unionfs_check_dentry(dentry);
11124+ unionfs_unlock_dentry(dentry);
11125+ unionfs_unlock_parent(dentry, parent);
11126+ unionfs_read_unlock(dentry->d_sb);
11127+ return err;
11128+}
11129+
11130+/*
11131+ * BKL held by caller.
11132+ * dentry->d_inode->i_mutex locked
11133+ */
11134+ssize_t unionfs_listxattr(struct dentry *dentry, char *list, size_t size)
11135+{
11136+ struct dentry *lower_dentry = NULL;
11137+ struct dentry *parent;
11138+ int err = -EOPNOTSUPP;
11139+ char *encoded_list = NULL;
11140+ bool valid;
11141+
11142+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
11143+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
11144+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
11145+
11146+ valid = __unionfs_d_revalidate(dentry, parent, false);
11147+ if (unlikely(!valid)) {
11148+ err = -ESTALE;
11149+ goto out;
11150+ }
11151+
11152+ lower_dentry = unionfs_lower_dentry(dentry);
11153+
11154+ encoded_list = list;
11155+ err = vfs_listxattr(lower_dentry, encoded_list, size);
11156+
11157+out:
11158+ unionfs_check_dentry(dentry);
11159+ unionfs_unlock_dentry(dentry);
11160+ unionfs_unlock_parent(dentry, parent);
11161+ unionfs_read_unlock(dentry->d_sb);
11162+ return err;
11163+}
11164diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
11165index da317c7..64f1ced 100644
11166--- a/include/linux/fs_stack.h
11167+++ b/include/linux/fs_stack.h
11168@@ -1,7 +1,19 @@
11169+/*
11170+ * Copyright (c) 2006-2009 Erez Zadok
11171+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
11172+ * Copyright (c) 2006-2009 Stony Brook University
11173+ * Copyright (c) 2006-2009 The Research Foundation of SUNY
11174+ *
11175+ * This program is free software; you can redistribute it and/or modify
11176+ * it under the terms of the GNU General Public License version 2 as
11177+ * published by the Free Software Foundation.
11178+ */
11179+
11180 #ifndef _LINUX_FS_STACK_H
11181 #define _LINUX_FS_STACK_H
11182
11183-/* This file defines generic functions used primarily by stackable
11184+/*
11185+ * This file defines generic functions used primarily by stackable
11186 * filesystems; none of these functions require i_mutex to be held.
11187 */
11188
11189diff --git a/include/linux/magic.h b/include/linux/magic.h
11190index eb9800f..9770154 100644
11191--- a/include/linux/magic.h
11192+++ b/include/linux/magic.h
11193@@ -47,6 +47,8 @@
11194 #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
11195 #define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs"
11196
11197+#define UNIONFS_SUPER_MAGIC 0xf15f083d
11198+
11199 #define SMB_SUPER_MAGIC 0x517B
11200 #define USBDEVICE_SUPER_MAGIC 0x9fa2
11201 #define CGROUP_SUPER_MAGIC 0x27e0eb
11202diff --git a/include/linux/namei.h b/include/linux/namei.h
11203index 05b441d..dca6f9a 100644
11204--- a/include/linux/namei.h
11205+++ b/include/linux/namei.h
11206@@ -72,6 +72,7 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
11207
11208 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
11209 int (*open)(struct inode *, struct file *));
11210+extern void release_open_intent(struct nameidata *);
11211
11212 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
11213
11214diff --git a/include/linux/splice.h b/include/linux/splice.h
11215index 997c3b4..54f5501 100644
11216--- a/include/linux/splice.h
11217+++ b/include/linux/splice.h
11218@@ -81,6 +81,11 @@ extern ssize_t splice_to_pipe(struct pipe_inode_info *,
11219 struct splice_pipe_desc *);
11220 extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
11221 splice_direct_actor *);
11222+extern long vfs_splice_from(struct pipe_inode_info *pipe, struct file *out,
11223+ loff_t *ppos, size_t len, unsigned int flags);
11224+extern long vfs_splice_to(struct file *in, loff_t *ppos,
11225+ struct pipe_inode_info *pipe, size_t len,
11226+ unsigned int flags);
11227
11228 /*
11229 * for dynamic pipe sizing
11230diff --git a/include/linux/union_fs.h b/include/linux/union_fs.h
11231new file mode 100644
11232index 0000000..c84d97e
11233--- /dev/null
11234+++ b/include/linux/union_fs.h
11235@@ -0,0 +1,22 @@
11236+/*
11237+ * Copyright (c) 2003-2009 Erez Zadok
11238+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
11239+ * Copyright (c) 2003-2009 Stony Brook University
11240+ * Copyright (c) 2003-2009 The Research Foundation of SUNY
11241+ *
11242+ * This program is free software; you can redistribute it and/or modify
11243+ * it under the terms of the GNU General Public License version 2 as
11244+ * published by the Free Software Foundation.
11245+ */
11246+
11247+#ifndef _LINUX_UNION_FS_H
11248+#define _LINUX_UNION_FS_H
11249+
11250+/*
11251+ * DEFINITIONS FOR USER AND KERNEL CODE:
11252+ */
11253+# define UNIONFS_IOCTL_INCGEN _IOR(0x15, 11, int)
11254+# define UNIONFS_IOCTL_QUERYFILE _IOR(0x15, 15, int)
11255+
11256+#endif /* _LINUX_UNIONFS_H */
11257+
11258diff --git a/security/security.c b/security/security.c
11259index 351942a..69505f7 100644
11260--- a/security/security.c
11261+++ b/security/security.c
11262@@ -529,6 +529,7 @@ int security_inode_permission(struct inode *inode, int mask)
11263 return 0;
11264 return security_ops->inode_permission(inode, mask);
11265 }
11266+EXPORT_SYMBOL(security_inode_permission);
11267
11268 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
11269 {
diff --git a/testing/scst-grsec/APKBUILD b/testing/scst-grsec/APKBUILD
deleted file mode 100644
index 6cec16d728..0000000000
--- a/testing/scst-grsec/APKBUILD
+++ /dev/null
@@ -1,65 +0,0 @@
1# Contributor: Carlo Landmeter
2# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
3
4_flavor=${FLAVOR:-grsec}
5_realname=scst
6# source the kernel version
7if [ -f ../../main/linux-$_flavor/APKBUILD ]; then
8 . ../../main/linux-$_flavor/APKBUILD
9fi
10_kver=$pkgver
11_kernelver=$pkgver-r$pkgrel
12_abi_release=$pkgver-${_flavor}
13_kpkgrel=$pkgrel
14
15_realver=1.0.1.1
16pkgname=${_realname}-${_flavor}
17pkgver=$_kver
18_mypkgrel=0
19pkgrel=$(($_kpkgrel + $_mypkgrel))
20pkgdesc="$_flavor kernel modules for SCST $_realver"
21url="http://scst.sourceforge.net/"
22arch="x86 x86_64"
23license="GPL-2"
24depends="linux-${_flavor}=${_kernelver}"
25install=
26makedepends="linux-${_flavor}-dev=${_kernelver}"
27subpackages="$pkgname-dev"
28source="http://downloads.sourceforge.net/$_realname/$_realname-$_realver.tar.gz
29 scst-kernel-2.6.32.patch
30 "
31_ksrc=/usr/src/linux-headers-${_abi_release}
32
33_builddir="$srcdir"/$_realname-$_realver
34prepare() {
35 cd "$_builddir"
36 for i in "$srcdir"/*.patch; do
37 [ -f "$i" ] || continue
38 msg "Applying $i"
39 patch -p1 -i $i || return 1
40 done
41 sed -e 's:linux/autoconf.h:generated/autoconf.h:' \
42 -i include/scst_debug.h
43}
44
45build() {
46 cd "$_builddir"
47 unset ARCH
48 make KDIR="$_ksrc" || return 1
49}
50
51package() {
52 cd "$_builddir"
53 make KDIR="$_ksrc" \
54 INSTALL_MOD_PATH="$pkgdir" \
55 INSTALL_DIR_H="$pkgdir"/usr/include/scst \
56 install || return 1
57}
58
59# we sourced kernel apkbuild above so we need to override the dev() func
60dev() {
61 default_dev
62}
63
64md5sums="38abb5f10325911ff1374535a30a02ad scst-1.0.1.1.tar.gz
65a87b844b57f997c15c8e0099a313a98e scst-kernel-2.6.32.patch"
diff --git a/testing/scst-grsec/scst-kernel-2.6.32.patch b/testing/scst-grsec/scst-kernel-2.6.32.patch
deleted file mode 100644
index 80fc8610aa..0000000000
--- a/testing/scst-grsec/scst-kernel-2.6.32.patch
+++ /dev/null
@@ -1,17 +0,0 @@
1--- scst-1.0.1.1/src/dev_handlers/scst_vdisk.c.orig
2+++ scst-1.0.1.1/src/dev_handlers/scst_vdisk.c
3@@ -2071,9 +2071,13 @@
4 inode = file->f_dentry->d_inode;
5 mapping = file->f_mapping;
6
7+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
8 res = sync_page_range(inode, mapping, loff, len);
9+#else
10+ res = filemap_write_and_wait_range(file->f_mapping, loff, len);
11+#endif
12 if (unlikely(res != 0)) {
13- PRINT_ERROR("sync_page_range() failed (%d)", res);
14+ PRINT_ERROR("sync range failed (%d)", res);
15 if (cmd != NULL) {
16 scst_set_cmd_error(cmd,
17 SCST_LOAD_SENSE(scst_sense_write_error));
diff --git a/testing/scst-svn-scst/APKBUILD b/testing/scst-svn-scst/APKBUILD
deleted file mode 100644
index 8cbff4ccba..0000000000
--- a/testing/scst-svn-scst/APKBUILD
+++ /dev/null
@@ -1,83 +0,0 @@
1# Contributor: Carlo Landmeter
2# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
3
4_flavor=${FLAVOR:-scst}
5_realname=scst-svn
6# source the kernel version
7if [ -f ../../testing/linux-$_flavor/APKBUILD ]; then
8 . ../../testing/linux-$_flavor/APKBUILD
9fi
10_kver=$pkgver
11_kernelver=$pkgver-r$pkgrel
12_abi_release=$pkgver-${_flavor}
13_kpkgrel=$pkgrel
14
15# We need to build iscsi together with scst because it needs some files from its builddir
16_iscsiname=iscsi-scst-svn
17_iscsidir="$srcdir"/iscsi-scst
18
19_realver=1713
20pkgname=${_realname}-${_flavor}
21pkgver=$_kver
22_mypkgrel=0
23pkgrel=$(($_kpkgrel + $_mypkgrel))
24pkgdesc="$_flavor kernel modules for SCST $_realver"
25url="http://scst.sourceforge.net/"
26arch="x86 x86_64"
27license="GPL-2"
28depends="linux-${_flavor}=${_kernelver}"
29install=
30makedepends="linux-${_flavor}-dev=${_kernelver} sed bash"
31subpackages="$pkgname-dev $_iscsiname-scst:iscsi"
32source="http://alpine.nethq.org/clandmeter/src/$_realname-$_realver.tar.gz
33 http://alpine.nethq.org/clandmeter/src/$_iscsiname-$_realver.tar.gz"
34
35_ksrc=/usr/src/linux-headers-${_abi_release}
36
37_builddir="$srcdir"/scst
38
39prepare() {
40 # we are disabling proc and enabling sysfs control and disabling debug.
41 cd "$_builddir"
42 make disable_proc
43 make debug2release
44
45 cd "$_iscsidir"
46 make disable_proc
47 make debug2release
48 sed -i -e 's/^\(mods: .*\)/\1 include\/iscsi_scst_itf_ver.h/' Makefile
49}
50
51build() {
52 unset ARCH
53
54 cd "$_builddir"
55 make KDIR="$_ksrc" || return 1
56
57 cd "$_iscsidir"
58 make mods KDIR="$_ksrc" || return 1
59}
60
61package() {
62 cd "$_builddir"
63 make KDIR="$_ksrc" \
64 INSTALL_MOD_PATH="$pkgdir" \
65 INSTALL_DIR_H="$pkgdir"/usr/include/scst \
66 install || return 1
67}
68
69# we sourced kernel apkbuild above so we need to override the dev() func
70dev() {
71 default_dev
72}
73
74iscsi() {
75 pkgdesc="SCST iscsi kernel module"
76 cd "$_iscsidir"
77 install -D -m 644 kernel/iscsi-scst.ko \
78 "$subpkgdir"/lib/modules/$_abi_release/extra/iscsi-scst.ko
79
80}
81
82md5sums="38424f48c9fd65624e316195186fb6a7 scst-svn-1713.tar.gz
83cf046db4f7cd9cf969b054dc055922d6 iscsi-scst-svn-1713.tar.gz"
diff --git a/testing/scstadmin-svn/APKBUILD b/testing/scstadmin-svn/APKBUILD
deleted file mode 100644
index e92ae2ccd2..0000000000
--- a/testing/scstadmin-svn/APKBUILD
+++ /dev/null
@@ -1,31 +0,0 @@
1# Contributor:
2# Maintainer:
3pkgname=scstadmin-svn
4pkgver=1713
5pkgrel=0
6pkgdesc="SCST administration tool written in perl"
7url="http://scst.sourceforge.net"
8arch="x86 x86_64"
9license="GPL-2"
10depends="perl"
11makedepends="perl-dev"
12install=
13subpackages="$pkgname-doc"
14source="http://alpine.nethq.org/clandmeter/src/$pkgname-$pkgver.tar.gz"
15
16_builddir="$srcdir"/scstadmin
17
18prepare() {
19 cd "$_builddir"/scst-0.9.00
20 PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
21}
22
23package() {
24 cd "$_builddir"/scst-0.9.00
25 make DESTDIR="$pkgdir" install || return 1
26 cd "$_builddir"
27 install -Dm755 scstadmin.sysfs "$pkgdir"/usr/sbin/scstadmin || return 1
28 install -Dm755 init.d/scst.gentoo "$pkgdir"/etc/init.d/scstadmin
29}
30
31md5sums="5c78c6d4d4079a8d2c2b55f3e3119105 scstadmin-svn-1713.tar.gz"
diff --git a/testing/scstadmin/APKBUILD b/testing/scstadmin/APKBUILD
new file mode 100644
index 0000000000..85350e0675
--- /dev/null
+++ b/testing/scstadmin/APKBUILD
@@ -0,0 +1,39 @@
1# Contributor: Carlo Landmeter
2# Maintainer:
3pkgname=scstadmin
4pkgver=2.0.0
5pkgrel=0
6pkgdesc="SCST administration tool written in perl"
7url="http://scst.sourceforge.net"
8arch="x86_64"
9license="GPL-2"
10depends="perl"
11makedepends="perl-dev"
12install=
13subpackages="$pkgname-doc"
14# increase pkgrel when updating svn rev
15_svn="3161"
16source="http://alpine.nethq.org/distfiles/$pkgname-$pkgver-svn-$_svn.tar.gz
17 scst-init-ash-comapt.patch
18 "
19
20_builddir="$srcdir"/$pkgname
21
22prepare() {
23 cd "$_builddir"/scstadmin.sysfs/scst-0.9.00
24 PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
25 cd "$_builddir"
26 patch -p1 < "$srcdir"/scst-init-ash-comapt.patch
27}
28
29package() {
30 cd "$_builddir"/scstadmin.sysfs/scst-0.9.00
31 make DESTDIR="$pkgdir" install || return 1
32
33 cd "$_builddir"
34 install -Dm755 scstadmin.sysfs/scstadmin "$pkgdir"/usr/sbin/scstadmin || return 1
35 install -Dm755 init.d/scst.gentoo "$pkgdir"/etc/init.d/scstadmin || return 1
36}
37
38md5sums="8f60857b6545dd60d7d26342aba038f1 scstadmin-2.0.0-svn-3161.tar.gz
39061580b8ec84b5f7da0b1332601f505a scst-init-ash-comapt.patch"
diff --git a/testing/scstadmin/scst-init-ash-comapt.patch b/testing/scstadmin/scst-init-ash-comapt.patch
new file mode 100644
index 0000000000..67cd7adf17
--- /dev/null
+++ b/testing/scstadmin/scst-init-ash-comapt.patch
@@ -0,0 +1,35 @@
1--- scstadmin/init.d/scst.gentoo
2+++ scstadmin/init.d/scst.gentoo
3@@ -12,13 +12,11 @@
4 # Note: on most Linux distributions /bin/sh is a soft link to /bin/bash, while
5 # on a default Ubuntu setup /bin/sh is a soft link to /bin/dash !
6
7-opts="${opts} try-restart reload force-reload"
8+opts="${opts} try_restart reload force_reload"
9 depend() {
10 use logger
11 }
12
13-PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin
14-
15 DEFAULTFILE="/etc/conf.d/scst"
16 SCST_CFG=/etc/scst.conf
17 MODPROBE="/sbin/modprobe"
18@@ -121,7 +119,7 @@
19 start
20 }
21
22-try-restart() {
23+try_restart() {
24 ## Restart the service if the service is already running.
25 status >/dev/null 2>&1 && restart
26 }
27@@ -140,7 +138,7 @@
28 fi
29 }
30
31-force-reload() {
32+force_reload() {
33 ## Cause the configuration to be reloaded if the service supports this,
34 ## otherwise restart the service if it is running.
35 einfo "Reloading SCST configuration"