updated on Thu Jan 26 16:09:46 UTC 2012
[aur-mirror.git] / tgt / 0001-Remove-dummy-RAID-controller-from-LUN-0.patch
blobd226f0c575adc68e17276da5b7d107787e195983
1 From 0d204bda91efaeda3f73c9e7ce932869e63a8545 Mon Sep 17 00:00:00 2001
2 From: Arne Redlich <arne.redlich@googlemail.com>
3 Date: Sun, 20 Mar 2011 20:37:08 +0100
4 Subject: [PATCH] Remove dummy RAID controller from LUN 0
6 The dummy RAID controller serves 2 purposes:
7 (1) commands that are addressed to an inexistent LUN are redirected to it
8 (2) it provides a LUN 0 by default which is required by the SCSI spec
11 (1) is obviously wrong because instead of "wrong lun" "invalid cdb" is returned
12 to the initiator. A "shadow LUN" of type NO_LUN is now used for this purpose.
13 This LU uses bs_null as backingstore, so there are no idle threads spawned for
14 it (in contrast to the previous dummy raid controller at LUN 0).
16 (2) confuses some OSes / users (Windows prompts for drivers,
17 Solaris repeatedly tries to online the LU, but does not succeed).
19 It's now the user's responsibility to attach a LU to LUN 0 to adhere to the
20 SCSI spec (Solaris / WinXP don't insist, Linux does!).
22 Signed-off-by: Arne Redlich <arne.redlich@googlemail.com>
23 ---
24 usr/Makefile | 2 +-
25 usr/list.h | 3 ++
26 usr/nolun.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
27 usr/spc.c | 10 ++++++
28 usr/spc.h | 1 +
29 usr/target.c | 28 +++++++++--------
30 usr/target.h | 2 +
31 7 files changed, 127 insertions(+), 14 deletions(-)
32 create mode 100644 usr/nolun.c
34 diff --git a/usr/Makefile b/usr/Makefile
35 index ea175cd..9ac79c0 100644
36 --- a/usr/Makefile
37 +++ b/usr/Makefile
38 @@ -53,7 +53,7 @@ LIBS += -lpthread
40 PROGRAMS += tgtd tgtadm tgtimg
41 TGTD_OBJS += tgtd.o mgmt.o target.o scsi.o log.o driver.o util.o work.o \
42 - parser.o spc.o sbc.o mmc.o osd.o scc.o smc.o \
43 + parser.o spc.o sbc.o mmc.o nolun.o osd.o scc.o smc.o \
44 ssc.o bs_ssc.o libssc.o \
45 bs_null.o bs_sg.o bs.o libcrc32c.o
47 diff --git a/usr/list.h b/usr/list.h
48 index 2f80a56..698a684 100644
49 --- a/usr/list.h
50 +++ b/usr/list.h
51 @@ -32,6 +32,9 @@ static inline void INIT_LIST_HEAD(struct list_head *list)
52 #define list_first_entry(ptr, type, member) \
53 list_entry((ptr)->next, type, member)
55 +#define list_last_entry(ptr, type, member) \
56 + list_entry((ptr)->prev, type, member)
58 static inline int list_empty(const struct list_head *head)
60 return head->next == head;
61 diff --git a/usr/nolun.c b/usr/nolun.c
62 new file mode 100644
63 index 0000000..0f516a0
64 --- /dev/null
65 +++ b/usr/nolun.c
66 @@ -0,0 +1,95 @@
67 +/*
68 + * Processing of SCSI commands addressed to inexistent LUNs.
69 + *
70 + * Based on scc.c:
71 + *
72 + * Copyright (C) 2007 FUJITA Tomonori <tomof@acm.org>
73 + * Copyright (C) 2007 Mike Christie <michaelc@cs.wisc.edu>
74 + *
75 + * This program is free software; you can redistribute it and/or
76 + * modify it under the terms of the GNU General Public License as
77 + * published by the Free Software Foundation, version 2 of the
78 + * License.
79 + *
80 + * This program is distributed in the hope that it will be useful, but
81 + * WITHOUT ANY WARRANTY; without even the implied warranty of
82 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
83 + * General Public License for more details.
84 + *
85 + * You should have received a copy of the GNU General Public License
86 + * along with this program; if not, write to the Free Software
87 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
88 + * 02110-1301 USA
89 + */
90 +#include <errno.h>
91 +#include <stdio.h>
92 +#include <stdlib.h>
93 +#include <string.h>
94 +#include <stdint.h>
95 +#include <unistd.h>
96 +#include <linux/fs.h>
98 +#include "list.h"
99 +#include "util.h"
100 +#include "tgtd.h"
101 +#include "target.h"
102 +#include "driver.h"
103 +#include "scsi.h"
104 +#include "tgtadm_error.h"
105 +#include "spc.h"
107 +static int nolun_lu_init(struct scsi_lu *lu)
109 + memset(&lu->attrs, 0x0, sizeof(lu->attrs));
110 + /*
111 + * TODO: use PQ 11b (per. dev. supp but not connected) and dev type 0x0
112 + * (SBC-2) instead?
113 + */
114 + lu->attrs.device_type = 0x1f; /* unknown / no device type */
115 + lu->attrs.qualifier = 0x3; /* peripheral dev. not supp. on this LU */
117 + return 0;
120 +static int nolun_lu_config(struct scsi_lu *lu __attribute__((unused)),
121 + char *params __attribute__((unused)))
123 + return TGTADM_NO_LUN;
126 +static int nolun_lu_online(struct scsi_lu *lu __attribute__((unused)))
128 + /* TODO: correct return value? most consumers don't check at all ... */
129 + return -ENOENT;
132 +static int nolun_lu_offline(struct scsi_lu *lu __attribute__((unused)))
134 + return 0;
137 +static void nolun_lu_exit(struct scsi_lu *lu __attribute__((unused)))
139 + return;
142 +static struct device_type_template nolun_template = {
143 + .type = TYPE_NO_LUN,
144 + .lu_init = nolun_lu_init,
145 + .lu_config = nolun_lu_config,
146 + .lu_online = nolun_lu_online,
147 + .lu_offline = nolun_lu_offline,
148 + .lu_exit = nolun_lu_exit,
149 + .ops = {
150 + [0x0 ... 0x11] = {spc_invalid_lun,},
151 + {spc_inquiry,}, /* 0x12 */
152 + [ 0x13 ... 0x9f] = {spc_invalid_lun},
153 + {spc_report_luns,}, /* 0xA0 */
154 + [0xa1 ... 0xff] = {spc_invalid_lun},
158 +__attribute__((constructor)) static void nolun_init(void)
160 + device_type_register(&nolun_template);
162 diff --git a/usr/spc.c b/usr/spc.c
163 index ea901e2..94fa1f9 100644
164 --- a/usr/spc.c
165 +++ b/usr/spc.c
166 @@ -270,6 +270,8 @@ int spc_report_luns(int host_no, struct scsi_cmd *cmd)
167 nr_luns = 0;
169 list_for_each_entry(lu, dev_list, device_siblings) {
170 + if (lu->lun == TGT_SHADOW_LUN)
171 + continue;
172 nr_luns++;
174 if (!alen)
175 @@ -1590,6 +1592,14 @@ int spc_illegal_op(int host_no, struct scsi_cmd *cmd)
176 return SAM_STAT_CHECK_CONDITION;
179 +int spc_invalid_lun(int host_no, struct scsi_cmd *cmd)
181 + dump_cdb(cmd);
182 + scsi_set_in_resid_by_actual(cmd, 0);
183 + sense_data_build(cmd, ILLEGAL_REQUEST, ASC_LUN_NOT_SUPPORTED);
184 + return SAM_STAT_CHECK_CONDITION;
187 enum {
188 Opt_scsi_id, Opt_scsi_sn,
189 Opt_vendor_id, Opt_product_id,
190 diff --git a/usr/spc.h b/usr/spc.h
191 index 430a882..23fab97 100644
192 --- a/usr/spc.h
193 +++ b/usr/spc.h
194 @@ -12,6 +12,7 @@ extern int spc_test_unit(int host_no, struct scsi_cmd *cmd);
195 extern int spc_request_sense(int host_no, struct scsi_cmd *cmd);
196 extern int spc_prevent_allow_media_removal(int host_no, struct scsi_cmd *cmd);
197 extern int spc_illegal_op(int host_no, struct scsi_cmd *cmd);
198 +extern int spc_invalid_lun(int host_no, struct scsi_cmd *cmd);
199 extern int spc_lu_init(struct scsi_lu *lu);
201 typedef int (match_fn_t)(struct scsi_lu *lu, char *params);
202 diff --git a/usr/target.c b/usr/target.c
203 index b8b8715..79319df 100644
204 --- a/usr/target.c
205 +++ b/usr/target.c
206 @@ -510,7 +510,10 @@ int tgt_device_create(int tid, int dev_type, uint64_t lun, char *params,
207 goto out;
210 - bst = target->bst;
211 + bst = (lun == TGT_SHADOW_LUN) ?
212 + get_backingstore_template("null") :
213 + target->bst;
215 if (backing) {
216 if (bstype) {
217 bst = get_backingstore_template(bstype);
218 @@ -675,10 +678,6 @@ int tgt_device_destroy(int tid, uint64_t lun, int force)
220 dprintf("%u %" PRIu64 "\n", tid, lun);
222 - /* lun0 is special */
223 - if (!lun && !force)
224 - return TGTADM_INVALID_REQUEST;
226 lu = __device_lookup(tid, lun, &target);
227 if (!lu) {
228 eprintf("device %" PRIu64 " not found\n", lun);
229 @@ -934,11 +933,11 @@ int target_cmd_queue(int tid, struct scsi_cmd *cmd)
230 cmd->dev_id = dev_id;
231 dprintf("%p %x %" PRIx64 "\n", cmd, cmd->scb[0], dev_id);
232 cmd->dev = device_lookup(target, dev_id);
233 - /* use LUN0 */
234 + /* use TGT_SHADOW_LUN */
235 if (!cmd->dev)
236 - cmd->dev = list_first_entry(&target->device_list,
237 - struct scsi_lu,
238 - device_siblings);
239 + cmd->dev = list_last_entry(&target->device_list,
240 + struct scsi_lu,
241 + device_siblings);
243 cmd->itn_lu_info = it_nexus_lu_info_lookup(itn, cmd->dev->lun);
245 @@ -1767,7 +1766,9 @@ int tgt_target_show_all(char *buf, int rest)
248 shprintf(total, buf, rest, _TAB1 "LUN information:\n");
249 - list_for_each_entry(lu, &target->device_list, device_siblings)
250 + list_for_each_entry(lu, &target->device_list, device_siblings) {
251 + if (lu->lun == TGT_SHADOW_LUN)
252 + continue;
253 shprintf(total, buf, rest,
254 _TAB2 "LUN: %" PRIu64 "\n"
255 _TAB3 "Type: %s\n"
256 @@ -1794,6 +1795,7 @@ int tgt_target_show_all(char *buf, int rest)
257 "None",
258 lu->path ? : "None",
259 open_flags_to_str(strflags, lu->bsoflags));
262 if (!strcmp(tgt_drivers[target->lid]->name, "iscsi") ||
263 !strcmp(tgt_drivers[target->lid]->name, "iser")) {
264 @@ -1911,7 +1913,7 @@ int tgt_target_create(int lld, int tid, char *args)
265 INIT_LIST_HEAD(&target->acl_list);
266 INIT_LIST_HEAD(&target->it_nexus_list);
268 - tgt_device_create(tid, TYPE_RAID, 0, NULL, 0);
269 + tgt_device_create(tid, TYPE_NO_LUN, TGT_SHADOW_LUN, NULL, 0);
271 if (tgt_drivers[lld]->target_create)
272 tgt_drivers[lld]->target_create(target);
273 @@ -1938,8 +1940,8 @@ int tgt_target_destroy(int lld_no, int tid)
276 while (!list_empty(&target->device_list)) {
277 - /* we remove lun0 last */
278 - lu = list_entry(target->device_list.prev, struct scsi_lu,
279 + /* we remove TGT_SHADOW_LUN last */
280 + lu = list_entry(target->device_list.next, struct scsi_lu,
281 device_siblings);
282 ret = tgt_device_destroy(tid, lu->lun, 1);
283 if (ret)
284 diff --git a/usr/target.h b/usr/target.h
285 index 9283431..5cb102f 100644
286 --- a/usr/target.h
287 +++ b/usr/target.h
288 @@ -8,6 +8,8 @@
289 #define HASH_ORDER 4
290 #define hashfn(val) hash_long((unsigned long) (val), HASH_ORDER)
292 +#define TGT_SHADOW_LUN 0xffffffffffffffffULL
294 struct acl_entry {
295 char *address;
296 struct list_head aclent_list;
298 1.7.1