Thu Jul 23 04:32:13 2009 UTC ()
Fix from Bert Kiers, also noted by jak - be consistent in naming the
key for the target hostname variable - it's "target hostname", not
"target host".


(agc)
diff -r1.2 -r1.3 src/external/bsd/iscsi/dist/src/initiator/iscsi-initiator.c

cvs diff -r1.2 -r1.3 src/external/bsd/iscsi/dist/src/initiator/iscsi-initiator.c (switch to unified diff)

--- src/external/bsd/iscsi/dist/src/initiator/iscsi-initiator.c 2009/06/30 02:44:52 1.2
+++ src/external/bsd/iscsi/dist/src/initiator/iscsi-initiator.c 2009/07/23 04:32:13 1.3
@@ -1,757 +1,757 @@ @@ -1,757 +1,757 @@
1/*- 1/*-
2 * Copyright (c) 2007,2009 The NetBSD Foundation, Inc. 2 * Copyright (c) 2007,2009 The NetBSD Foundation, Inc.
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * This code is derived from software contributed to The NetBSD Foundation 5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Alistair Crooks (agc@netbsd.org) 6 * by Alistair Crooks (agc@netbsd.org)
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE. 27 * POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29#include <sys/types.h> 29#include <sys/types.h>
30 30
31#define FUSE_USE_VERSION 26 31#define FUSE_USE_VERSION 26
32 32
33#include <err.h> 33#include <err.h>
34#include <errno.h> 34#include <errno.h>
35#include <fcntl.h> 35#include <fcntl.h>
36#include <fuse.h> 36#include <fuse.h>
37#include <stdio.h> 37#include <stdio.h>
38#include <stdlib.h> 38#include <stdlib.h>
39#include <string.h> 39#include <string.h>
40#include <unistd.h> 40#include <unistd.h>
41 41
42#include "scsi_cmd_codes.h" 42#include "scsi_cmd_codes.h"
43#include "iscsi.h" 43#include "iscsi.h"
44#include "initiator.h" 44#include "initiator.h"
45#include "tests.h" 45#include "tests.h"
46 46
47#include "virtdir.h" 47#include "virtdir.h"
48 48
49#if defined(__NetBSD__) && defined(USE_LIBKMOD) 49#if defined(__NetBSD__) && defined(USE_LIBKMOD)
50#include "libkmod.h" 50#include "libkmod.h"
51#endif 51#endif
52 52
53#include "defs.h" 53#include "defs.h"
54 54
55static int verbose; /* how chatty are we? */ 55static int verbose; /* how chatty are we? */
56 56
57static virtdir_t iscsi; 57static virtdir_t iscsi;
58 58
59enum { 59enum {
60 VendorLen = 8, 60 VendorLen = 8,
61 ProductLen = 16, 61 ProductLen = 16,
62 VersionLen = 4, 62 VersionLen = 4,
63 63
64 SGsize = 131072 64 SGsize = 131072
65}; 65};
66 66
67 67
68/* this struct keeps information on the target */ 68/* this struct keeps information on the target */
69typedef struct targetinfo_t { 69typedef struct targetinfo_t {
70 char *host; /* resolvable host name */ 70 char *host; /* resolvable host name */
71 char *ip; /* textual IP address */ 71 char *ip; /* textual IP address */
72 char *targetname; /* name of iSCSI target prog */ 72 char *targetname; /* name of iSCSI target prog */
73 char *stargetname; /* short name of the target */  73 char *stargetname; /* short name of the target */
74 uint64_t target; /* target number */ 74 uint64_t target; /* target number */
75 uint32_t lun; /* LUN number */ 75 uint32_t lun; /* LUN number */
76 uint32_t lbac; /* number of LBAs */ 76 uint32_t lbac; /* number of LBAs */
77 uint32_t blocksize; /* size of device blocks */ 77 uint32_t blocksize; /* size of device blocks */
78 uint32_t devicetype; /* SCSI device type */ 78 uint32_t devicetype; /* SCSI device type */
79 char vendor[VendorLen + 1]; 79 char vendor[VendorLen + 1];
80 /* device vendor information */ 80 /* device vendor information */
81 char product[ProductLen + 1]; 81 char product[ProductLen + 1];
82 /* device product information */ 82 /* device product information */
83 char version[VersionLen + 1]; 83 char version[VersionLen + 1];
84 /* device version information */ 84 /* device version information */
85 char *serial; /* unit serial number */ 85 char *serial; /* unit serial number */
86} targetinfo_t; 86} targetinfo_t;
87 87
88DEFINE_ARRAY(targetv_t, targetinfo_t); 88DEFINE_ARRAY(targetv_t, targetinfo_t);
89 89
90static targetv_t tv; /* target vector of targetinfo_t structs */ 90static targetv_t tv; /* target vector of targetinfo_t structs */
91 91
92/* iqns and target addresses are returned as pairs in this dynamic array */ 92/* iqns and target addresses are returned as pairs in this dynamic array */
93static strv_t all_targets; 93static strv_t all_targets;
94 94
95/* Small Target Info... */ 95/* Small Target Info... */
96typedef struct sti_t { 96typedef struct sti_t {
97 struct stat st; /* normal stat info */ 97 struct stat st; /* normal stat info */
98 uint64_t target; /* cached target number, so we don't have an expensive pathname-based lookup */ 98 uint64_t target; /* cached target number, so we don't have an expensive pathname-based lookup */
99} sti_t; 99} sti_t;
100 100
101#ifndef __UNCONST 101#ifndef __UNCONST
102#define __UNCONST(x) (x) 102#define __UNCONST(x) (x)
103#endif 103#endif
104 104
105static void 105static void
106lba2cdb(uint8_t *cdb, uint32_t *lba, uint16_t *len) 106lba2cdb(uint8_t *cdb, uint32_t *lba, uint16_t *len)
107{ 107{
108 /* Some platforms (like strongarm) aligns on */ 108 /* Some platforms (like strongarm) aligns on */
109 /* word boundaries. So HTONL and NTOHL won't */ 109 /* word boundaries. So HTONL and NTOHL won't */
110 /* work here. */ 110 /* work here. */
111 int little_endian = 1; 111 int little_endian = 1;
112 112
113 if (*(char *) (void *) &little_endian) { 113 if (*(char *) (void *) &little_endian) {
114 /* little endian */ 114 /* little endian */
115 cdb[2] = ((uint8_t *) (void *)lba)[3]; 115 cdb[2] = ((uint8_t *) (void *)lba)[3];
116 cdb[3] = ((uint8_t *) (void *)lba)[2]; 116 cdb[3] = ((uint8_t *) (void *)lba)[2];
117 cdb[4] = ((uint8_t *) (void *)lba)[1]; 117 cdb[4] = ((uint8_t *) (void *)lba)[1];
118 cdb[5] = ((uint8_t *) (void *)lba)[0]; 118 cdb[5] = ((uint8_t *) (void *)lba)[0];
119 cdb[7] = ((uint8_t *) (void *)len)[1]; 119 cdb[7] = ((uint8_t *) (void *)len)[1];
120 cdb[8] = ((uint8_t *) (void *)len)[0]; 120 cdb[8] = ((uint8_t *) (void *)len)[0];
121 } else { 121 } else {
122 /* big endian */ 122 /* big endian */
123 cdb[2] = ((uint8_t *) (void *)lba)[2]; 123 cdb[2] = ((uint8_t *) (void *)lba)[2];
124 cdb[3] = ((uint8_t *) (void *)lba)[3]; 124 cdb[3] = ((uint8_t *) (void *)lba)[3];
125 cdb[4] = ((uint8_t *) (void *)lba)[0]; 125 cdb[4] = ((uint8_t *) (void *)lba)[0];
126 cdb[5] = ((uint8_t *) (void *)lba)[1]; 126 cdb[5] = ((uint8_t *) (void *)lba)[1];
127 cdb[7] = ((uint8_t *) (void *)len)[0]; 127 cdb[7] = ((uint8_t *) (void *)len)[0];
128 cdb[8] = ((uint8_t *) (void *)len)[1]; 128 cdb[8] = ((uint8_t *) (void *)len)[1];
129 } 129 }
130} 130}
131 131
132/* read the capacity (maximum LBA and blocksize) from the target */ 132/* read the capacity (maximum LBA and blocksize) from the target */
133int  133int
134read_capacity(uint64_t target, uint32_t lun, uint32_t *maxlba, uint32_t *blocklen) 134read_capacity(uint64_t target, uint32_t lun, uint32_t *maxlba, uint32_t *blocklen)
135{ 135{
136 iscsi_scsi_cmd_args_t args; 136 iscsi_scsi_cmd_args_t args;
137 initiator_cmd_t cmd; 137 initiator_cmd_t cmd;
138 uint8_t data[8]; 138 uint8_t data[8];
139 uint8_t cdb[16]; 139 uint8_t cdb[16];
140 140
141 (void) memset(cdb, 0x0, sizeof(cdb)); 141 (void) memset(cdb, 0x0, sizeof(cdb));
142 cdb[0] = READ_CAPACITY; 142 cdb[0] = READ_CAPACITY;
143 cdb[1] = lun << 5; 143 cdb[1] = lun << 5;
144 144
145 (void) memset(&args, 0x0, sizeof(args)); 145 (void) memset(&args, 0x0, sizeof(args));
146 args.recv_data = data; 146 args.recv_data = data;
147 args.input = 1; 147 args.input = 1;
148 args.lun = lun; 148 args.lun = lun;
149 args.trans_len = 8; 149 args.trans_len = 8;
150 args.cdb = cdb; 150 args.cdb = cdb;
151 151
152 (void) memset(&cmd, 0, sizeof(initiator_cmd_t)); 152 (void) memset(&cmd, 0, sizeof(initiator_cmd_t));
153 153
154 cmd.isid = target; 154 cmd.isid = target;
155 cmd.type = ISCSI_SCSI_CMD; 155 cmd.type = ISCSI_SCSI_CMD;
156 cmd.ptr = &args; 156 cmd.ptr = &args;
157 157
158 if (initiator_command(&cmd) != 0) { 158 if (initiator_command(&cmd) != 0) {
159 iscsi_err(__FILE__, __LINE__, "initiator_command() failed\n"); 159 iscsi_err(__FILE__, __LINE__, "initiator_command() failed\n");
160 return -1; 160 return -1;
161 } 161 }
162 if (args.status) { 162 if (args.status) {
163 iscsi_err(__FILE__, __LINE__, "READ_CAPACITY failed (status %#x)\n", args.status); 163 iscsi_err(__FILE__, __LINE__, "READ_CAPACITY failed (status %#x)\n", args.status);
164 return -1; 164 return -1;
165 } 165 }
166 *maxlba = ISCSI_NTOHL(*((uint32_t *) (data))); 166 *maxlba = ISCSI_NTOHL(*((uint32_t *) (data)));
167 *blocklen = ISCSI_NTOHL(*((uint32_t *) (data + 4))); 167 *blocklen = ISCSI_NTOHL(*((uint32_t *) (data + 4)));
168 if (*maxlba == 0) { 168 if (*maxlba == 0) {
169 iscsi_err(__FILE__, __LINE__, "Device returned Maximum LBA of zero\n"); 169 iscsi_err(__FILE__, __LINE__, "Device returned Maximum LBA of zero\n");
170 return -1; 170 return -1;
171 } 171 }
172 if (*blocklen % 2) { 172 if (*blocklen % 2) {
173 iscsi_err(__FILE__, __LINE__, "Device returned strange block len: %u\n", *blocklen); 173 iscsi_err(__FILE__, __LINE__, "Device returned strange block len: %u\n", *blocklen);
174 return -1; 174 return -1;
175 } 175 }
176 return 0; 176 return 0;
177} 177}
178 178
179/* send inquiry command to the target, to get it to identify itself */ 179/* send inquiry command to the target, to get it to identify itself */
180static int  180static int
181inquiry(uint64_t target, uint32_t lun, uint8_t type, uint8_t inquire, uint8_t *data) 181inquiry(uint64_t target, uint32_t lun, uint8_t type, uint8_t inquire, uint8_t *data)
182{ 182{
183 iscsi_scsi_cmd_args_t args; 183 iscsi_scsi_cmd_args_t args;
184 initiator_cmd_t cmd; 184 initiator_cmd_t cmd;
185 uint8_t cdb[16]; 185 uint8_t cdb[16];
186 186
187 (void) memset(cdb, 0x0, sizeof(cdb)); 187 (void) memset(cdb, 0x0, sizeof(cdb));
188 cdb[0] = INQUIRY; 188 cdb[0] = INQUIRY;
189 cdb[1] = type | (lun << 5); 189 cdb[1] = type | (lun << 5);
190 cdb[2] = inquire; 190 cdb[2] = inquire;
191 cdb[4] = 256 - 1; 191 cdb[4] = 256 - 1;
192 192
193 (void) memset(&args, 0x0, sizeof(args)); 193 (void) memset(&args, 0x0, sizeof(args));
194 args.input = 1; 194 args.input = 1;
195 args.trans_len = 256; 195 args.trans_len = 256;
196 args.cdb = cdb; 196 args.cdb = cdb;
197 args.lun = lun; 197 args.lun = lun;
198 args.recv_data = data; 198 args.recv_data = data;
199 (void) memset(&cmd, 0x0, sizeof(cmd)); 199 (void) memset(&cmd, 0x0, sizeof(cmd));
200 cmd.isid = target; 200 cmd.isid = target;
201 cmd.type = ISCSI_SCSI_CMD; 201 cmd.type = ISCSI_SCSI_CMD;
202 cmd.ptr = &args; 202 cmd.ptr = &args;
203 203
204 if (initiator_command(&cmd) != 0) { 204 if (initiator_command(&cmd) != 0) {
205 iscsi_err(__FILE__, __LINE__, "initiator_command() failed\n"); 205 iscsi_err(__FILE__, __LINE__, "initiator_command() failed\n");
206 return -1; 206 return -1;
207 } 207 }
208 if (args.status) { 208 if (args.status) {
209 iscsi_err(__FILE__, __LINE__, "INQUIRY failed (status %#x)\n", args.status); 209 iscsi_err(__FILE__, __LINE__, "INQUIRY failed (status %#x)\n", args.status);
210 return -1; 210 return -1;
211 } 211 }
212 212
213 return 0; 213 return 0;
214} 214}
215 215
216/* read or write a single block of information */ 216/* read or write a single block of information */
217static int  217static int
218blockop(uint64_t target, uint32_t lun, uint32_t lba, uint32_t len, 218blockop(uint64_t target, uint32_t lun, uint32_t lba, uint32_t len,
219 uint32_t blocklen, uint8_t *data, int writing) 219 uint32_t blocklen, uint8_t *data, int writing)
220{ 220{
221 iscsi_scsi_cmd_args_t args; 221 iscsi_scsi_cmd_args_t args;
222 initiator_cmd_t cmd; 222 initiator_cmd_t cmd;
223 uint16_t readlen; 223 uint16_t readlen;
224 uint8_t cdb[16]; 224 uint8_t cdb[16];
225 225
226 /* Build CDB */ 226 /* Build CDB */
227 (void) memset(cdb, 0, 16); 227 (void) memset(cdb, 0, 16);
228 cdb[0] = (writing) ? WRITE_10 : READ_10; 228 cdb[0] = (writing) ? WRITE_10 : READ_10;
229 cdb[1] = lun << 5; 229 cdb[1] = lun << 5;
230 readlen = (uint16_t) len; 230 readlen = (uint16_t) len;
231 lba2cdb(cdb, &lba, &readlen); 231 lba2cdb(cdb, &lba, &readlen);
232 232
233 /* Build SCSI command */ 233 /* Build SCSI command */
234 (void) memset(&args, 0x0, sizeof(args)); 234 (void) memset(&args, 0x0, sizeof(args));
235 if (writing) { 235 if (writing) {
236 args.send_data = data; 236 args.send_data = data;
237 args.output = 1; 237 args.output = 1;
238 } else { 238 } else {
239 args.recv_data = data; 239 args.recv_data = data;
240 args.input = 1; 240 args.input = 1;
241 } 241 }
242 args.lun = lun; 242 args.lun = lun;
243 args.trans_len = len*blocklen; 243 args.trans_len = len*blocklen;
244 args.length = len*blocklen; 244 args.length = len*blocklen;
245 args.cdb = cdb; 245 args.cdb = cdb;
246 (void) memset(&cmd, 0, sizeof(initiator_cmd_t)); 246 (void) memset(&cmd, 0, sizeof(initiator_cmd_t));
247 cmd.isid = target; 247 cmd.isid = target;
248 cmd.type = ISCSI_SCSI_CMD; 248 cmd.type = ISCSI_SCSI_CMD;
249 cmd.ptr = &args; 249 cmd.ptr = &args;
250 /* Execute iSCSI command */ 250 /* Execute iSCSI command */
251 if (initiator_command(&cmd) != 0) { 251 if (initiator_command(&cmd) != 0) {
252 iscsi_err(__FILE__, __LINE__, "initiator_command() failed\n"); 252 iscsi_err(__FILE__, __LINE__, "initiator_command() failed\n");
253 return -1; 253 return -1;
254 } 254 }
255 255
256 if (args.status) { 256 if (args.status) {
257 iscsi_err(__FILE__, __LINE__, "scsi_command() failed (status %#x)\n", args.status); 257 iscsi_err(__FILE__, __LINE__, "scsi_command() failed (status %#x)\n", args.status);
258 return -1; 258 return -1;
259 } 259 }
260 return 0; 260 return 0;
261} 261}
262 262
263/* perform a scatter/gather block operation */ 263/* perform a scatter/gather block operation */
264static int  264static int
265sgblockop(uint64_t target, uint32_t lun, uint32_t lba, uint32_t len, 265sgblockop(uint64_t target, uint32_t lun, uint32_t lba, uint32_t len,
266 uint32_t blocklen, uint8_t *data, int sglen, int writing) 266 uint32_t blocklen, uint8_t *data, int sglen, int writing)
267{ 267{
268 iscsi_scsi_cmd_args_t args; 268 iscsi_scsi_cmd_args_t args;
269 initiator_cmd_t cmd; 269 initiator_cmd_t cmd;
270 uint16_t readlen; 270 uint16_t readlen;
271 uint8_t cdb[16]; 271 uint8_t cdb[16];
272 272
273 /* Build CDB */ 273 /* Build CDB */
274 274
275 (void) memset(cdb, 0, 16); 275 (void) memset(cdb, 0, 16);
276 cdb[0] = (writing) ? WRITE_10 : READ_10; 276 cdb[0] = (writing) ? WRITE_10 : READ_10;
277 cdb[1] = lun << 5; 277 cdb[1] = lun << 5;
278 readlen = (uint16_t) len; 278 readlen = (uint16_t) len;
279 lba2cdb(cdb, &lba, &readlen); 279 lba2cdb(cdb, &lba, &readlen);
280 280
281 /* Build iSCSI command */ 281 /* Build iSCSI command */
282 (void) memset(&args, 0x0, sizeof(args)); 282 (void) memset(&args, 0x0, sizeof(args));
283 args.lun = lun; 283 args.lun = lun;
284 args.output = (writing) ? 1 : 0; 284 args.output = (writing) ? 1 : 0;
285 args.input = (writing) ? 0 : 1; 285 args.input = (writing) ? 0 : 1;
286 args.trans_len = len * blocklen; 286 args.trans_len = len * blocklen;
287 args.length = len * blocklen; 287 args.length = len * blocklen;
288 args.send_data = (writing) ? data : NULL; 288 args.send_data = (writing) ? data : NULL;
289 args.send_sg_len = (writing) ? sglen : 0; 289 args.send_sg_len = (writing) ? sglen : 0;
290 args.recv_data = (writing) ? NULL : data; 290 args.recv_data = (writing) ? NULL : data;
291 args.recv_sg_len = (writing) ? 0 : sglen; 291 args.recv_sg_len = (writing) ? 0 : sglen;
292 args.cdb = cdb; 292 args.cdb = cdb;
293 memset(&cmd, 0, sizeof(initiator_cmd_t)); 293 memset(&cmd, 0, sizeof(initiator_cmd_t));
294 cmd.isid = target; 294 cmd.isid = target;
295 cmd.ptr = &args; 295 cmd.ptr = &args;
296 cmd.type = ISCSI_SCSI_CMD; 296 cmd.type = ISCSI_SCSI_CMD;
297 297
298 /* Execute iSCSI command */ 298 /* Execute iSCSI command */
299 299
300 if (initiator_command(&cmd) != 0) { 300 if (initiator_command(&cmd) != 0) {
301 iscsi_err(__FILE__, __LINE__, "initiator_command() failed\n"); 301 iscsi_err(__FILE__, __LINE__, "initiator_command() failed\n");
302 return -1; 302 return -1;
303 } 303 }
304 if (args.status) { 304 if (args.status) {
305 iscsi_err(__FILE__, __LINE__, "scsi_command() failed (status %#x)\n", args.status); 305 iscsi_err(__FILE__, __LINE__, "scsi_command() failed (status %#x)\n", args.status);
306 return -1; 306 return -1;
307 } 307 }
308 return 0; 308 return 0;
309} 309}
310 310
311/* read info from the target - method depends on size of data being read */ 311/* read info from the target - method depends on size of data being read */
312static int  312static int
313targetop(uint32_t t, uint64_t offset, uint32_t length, uint32_t request, char *buf, int writing) 313targetop(uint32_t t, uint64_t offset, uint32_t length, uint32_t request, char *buf, int writing)
314{ 314{
315 struct iovec *iov; 315 struct iovec *iov;
316 uint32_t ioc; 316 uint32_t ioc;
317 uint32_t i; 317 uint32_t i;
318 int req_len; 318 int req_len;
319 319
320 if (request > SGsize) { 320 if (request > SGsize) {
321 /* split up request into blocksize chunks */ 321 /* split up request into blocksize chunks */
322 ioc = request / SGsize; 322 ioc = request / SGsize;
323 if ((ioc * SGsize) < request) 323 if ((ioc * SGsize) < request)
324 ioc++; 324 ioc++;
325 if ((iov = iscsi_malloc(ioc * sizeof(*iov))) == NULL) { 325 if ((iov = iscsi_malloc(ioc * sizeof(*iov))) == NULL) {
326 iscsi_err(__FILE__, __LINE__, "out of memory\n"); 326 iscsi_err(__FILE__, __LINE__, "out of memory\n");
327 return -1; 327 return -1;
328 } 328 }
329 329
330 for (i = 0 ; i < ioc ; i++) { 330 for (i = 0 ; i < ioc ; i++) {
331 iov[i].iov_base = &buf[i * SGsize]; 331 iov[i].iov_base = &buf[i * SGsize];
332 if (i == (ioc - 1)) { /* last one */ 332 if (i == (ioc - 1)) { /* last one */
333 iov[i].iov_len = request - (i * SGsize); 333 iov[i].iov_len = request - (i * SGsize);
334 } else { 334 } else {
335 iov[i].iov_len = SGsize; 335 iov[i].iov_len = SGsize;
336 } 336 }
337 } 337 }
338 338
339 if (sgblockop(tv.v[t].target, tv.v[t].lun, offset / tv.v[t].blocksize, (length / tv.v[t].blocksize), tv.v[t].blocksize, (uint8_t *) iov, ioc, writing) != 0) { 339 if (sgblockop(tv.v[t].target, tv.v[t].lun, offset / tv.v[t].blocksize, (length / tv.v[t].blocksize), tv.v[t].blocksize, (uint8_t *) iov, ioc, writing) != 0) {
340 iscsi_free(iov); 340 iscsi_free(iov);
341 iscsi_err(__FILE__, __LINE__, "read_10() failed\n"); 341 iscsi_err(__FILE__, __LINE__, "read_10() failed\n");
342 return -1; 342 return -1;
343 } 343 }
344 iscsi_free(iov); 344 iscsi_free(iov);
345 } else { 345 } else {
346 req_len = length / tv.v[t].blocksize; 346 req_len = length / tv.v[t].blocksize;
347 if ((req_len * tv.v[t].blocksize) < length) 347 if ((req_len * tv.v[t].blocksize) < length)
348 req_len++; 348 req_len++;
349 if (blockop(tv.v[t].target, tv.v[t].lun, offset / tv.v[t].blocksize,  349 if (blockop(tv.v[t].target, tv.v[t].lun, offset / tv.v[t].blocksize,
350 req_len, tv.v[t].blocksize, (uint8_t *) buf, writing) != 0) { 350 req_len, tv.v[t].blocksize, (uint8_t *) buf, writing) != 0) {
351 iscsi_err(__FILE__, __LINE__, "read_10() failed\n"); 351 iscsi_err(__FILE__, __LINE__, "read_10() failed\n");
352 return -1; 352 return -1;
353 } 353 }
354 } 354 }
355 return 0; 355 return 0;
356} 356}
357 357
358 358
359/****************************************************************************/ 359/****************************************************************************/
360 360
361/* perform the stat operation */ 361/* perform the stat operation */
362/* if this is the root, then just synthesise the data */ 362/* if this is the root, then just synthesise the data */
363/* otherwise, retrieve the data, and be sure to fill in the size */ 363/* otherwise, retrieve the data, and be sure to fill in the size */
364static int  364static int
365iscsifs_getattr(const char *path, struct stat *st) 365iscsifs_getattr(const char *path, struct stat *st)
366{ 366{
367 virt_dirent_t *ep; 367 virt_dirent_t *ep;
368 sti_t *p; 368 sti_t *p;
369 369
370 if (strcmp(path, "/") == 0) { 370 if (strcmp(path, "/") == 0) {
371 (void) memset(st, 0x0, sizeof(*st)); 371 (void) memset(st, 0x0, sizeof(*st));
372 st->st_mode = S_IFDIR | 0755; 372 st->st_mode = S_IFDIR | 0755;
373 st->st_nlink = 2; 373 st->st_nlink = 2;
374 return 0; 374 return 0;
375 } 375 }
376 if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) { 376 if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) {
377 return -ENOENT; 377 return -ENOENT;
378 } 378 }
379 switch(ep->type) { 379 switch(ep->type) {
380 case 'b': 380 case 'b':
381 (void) memcpy(st, &iscsi.file, sizeof(*st)); 381 (void) memcpy(st, &iscsi.file, sizeof(*st));
382 st->st_mode = (S_IFBLK | 0644); 382 st->st_mode = (S_IFBLK | 0644);
383 break; 383 break;
384 case 'c': 384 case 'c':
385 (void) memcpy(st, &iscsi.file, sizeof(*st)); 385 (void) memcpy(st, &iscsi.file, sizeof(*st));
386 st->st_mode = (S_IFCHR | 0644); 386 st->st_mode = (S_IFCHR | 0644);
387 break; 387 break;
388 case 'd': 388 case 'd':
389 (void) memcpy(st, &iscsi.dir, sizeof(*st)); 389 (void) memcpy(st, &iscsi.dir, sizeof(*st));
390 break; 390 break;
391 case 'f': 391 case 'f':
392 (void) memcpy(st, &iscsi.file, sizeof(*st)); 392 (void) memcpy(st, &iscsi.file, sizeof(*st));
393 p = (sti_t *) ep->tgt; 393 p = (sti_t *) ep->tgt;
394 st->st_size = p->st.st_size; 394 st->st_size = p->st.st_size;
395 break; 395 break;
396 case 'l': 396 case 'l':
397 (void) memcpy(st, &iscsi.lnk, sizeof(*st)); 397 (void) memcpy(st, &iscsi.lnk, sizeof(*st));
398 st->st_size = ep->tgtlen; 398 st->st_size = ep->tgtlen;
399 break; 399 break;
400 default: 400 default:
401 warn("unknown directory type `%c'", ep->type); 401 warn("unknown directory type `%c'", ep->type);
402 return -ENOENT; 402 return -ENOENT;
403 } 403 }
404 st->st_ino = ep->ino; 404 st->st_ino = ep->ino;
405 return 0; 405 return 0;
406} 406}
407 407
408/* readdir operation */ 408/* readdir operation */
409static int  409static int
410iscsifs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, 410iscsifs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
411 off_t offset, struct fuse_file_info * fi) 411 off_t offset, struct fuse_file_info * fi)
412{ 412{
413 virt_dirent_t *dp; 413 virt_dirent_t *dp;
414 VIRTDIR *dirp; 414 VIRTDIR *dirp;
415 415
416 if ((dirp = openvirtdir(&iscsi, path)) == NULL) { 416 if ((dirp = openvirtdir(&iscsi, path)) == NULL) {
417 return 0; 417 return 0;
418 } 418 }
419 filler(buf, ".", NULL, 0); 419 filler(buf, ".", NULL, 0);
420 filler(buf, "..", NULL, 0); 420 filler(buf, "..", NULL, 0);
421 while ((dp = readvirtdir(dirp)) != NULL) { 421 while ((dp = readvirtdir(dirp)) != NULL) {
422 filler(buf, dp->d_name, NULL, 0); 422 filler(buf, dp->d_name, NULL, 0);
423 } 423 }
424 closevirtdir(dirp); 424 closevirtdir(dirp);
425 return 0; 425 return 0;
426} 426}
427 427
428/* open the file in the file system */ 428/* open the file in the file system */
429static int  429static int
430iscsifs_open(const char *path, struct fuse_file_info *fi) 430iscsifs_open(const char *path, struct fuse_file_info *fi)
431{ 431{
432 virt_dirent_t *ep; 432 virt_dirent_t *ep;
433 const char *slash; 433 const char *slash;
434 434
435 if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) { 435 if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) {
436 return -ENOENT; 436 return -ENOENT;
437 } 437 }
438 /* check path is the correct one */ 438 /* check path is the correct one */
439 if ((slash = strrchr(path, '/')) == NULL) { 439 if ((slash = strrchr(path, '/')) == NULL) {
440 slash = path; 440 slash = path;
441 } else { 441 } else {
442 slash += 1; 442 slash += 1;
443 } 443 }
444 if (strcmp(slash, "storage") != 0) { 444 if (strcmp(slash, "storage") != 0) {
445 return -ENOENT; 445 return -ENOENT;
446 } 446 }
447 return 0; 447 return 0;
448} 448}
449 449
450/* read the storage from the iSCSI target */ 450/* read the storage from the iSCSI target */
451static int  451static int
452iscsifs_read(const char *path, char *buf, size_t size, off_t offset, 452iscsifs_read(const char *path, char *buf, size_t size, off_t offset,
453 struct fuse_file_info * fi) 453 struct fuse_file_info * fi)
454{ 454{
455 virt_dirent_t *ep; 455 virt_dirent_t *ep;
456 uint64_t target; 456 uint64_t target;
457 sti_t *p; 457 sti_t *p;
458 458
459 if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) { 459 if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) {
460 return -ENOENT; 460 return -ENOENT;
461 } 461 }
462 462
463 p = (sti_t *)ep->tgt; 463 p = (sti_t *)ep->tgt;
464 target = p->target; 464 target = p->target;
465 465
466 if (targetop(target, offset, size, size, buf, 0) < 0) { 466 if (targetop(target, offset, size, size, buf, 0) < 0) {
467 return -EPERM; 467 return -EPERM;
468 } 468 }
469 return size; 469 return size;
470} 470}
471 471
472/* write the file's contents to the file system */ 472/* write the file's contents to the file system */
473static int  473static int
474iscsifs_write(const char *path, const char *buf, size_t size, off_t offset, 474iscsifs_write(const char *path, const char *buf, size_t size, off_t offset,
475 struct fuse_file_info * fi) 475 struct fuse_file_info * fi)
476{ 476{
477 virt_dirent_t *ep; 477 virt_dirent_t *ep;
478 uint64_t target;  478 uint64_t target;
479 sti_t *p; 479 sti_t *p;
480 480
481 if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) { 481 if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) {
482 return -ENOENT; 482 return -ENOENT;
483 } 483 }
484  484
485 p = (sti_t *)ep->tgt; 485 p = (sti_t *)ep->tgt;
486 target = p->target; 486 target = p->target;
487 487
488 if (targetop(target, offset, size, size, __UNCONST(buf), 1) < 0) { 488 if (targetop(target, offset, size, size, __UNCONST(buf), 1) < 0) {
489 return -EPERM; 489 return -EPERM;
490 } 490 }
491 return size; 491 return size;
492} 492}
493 493
494/* fill in the statvfs struct */ 494/* fill in the statvfs struct */
495static int 495static int
496iscsifs_statfs(const char *path, struct statvfs *st) 496iscsifs_statfs(const char *path, struct statvfs *st)
497{ 497{
498 (void) memset(st, 0x0, sizeof(*st)); 498 (void) memset(st, 0x0, sizeof(*st));
499 return 0; 499 return 0;
500} 500}
501 501
502/* read the symbolic link */ 502/* read the symbolic link */
503static int 503static int
504iscsifs_readlink(const char *path, char *buf, size_t size) 504iscsifs_readlink(const char *path, char *buf, size_t size)
505{ 505{
506 virt_dirent_t *ep; 506 virt_dirent_t *ep;
507 507
508 if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) { 508 if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) {
509 return -ENOENT; 509 return -ENOENT;
510 } 510 }
511 if (ep->tgt == NULL) { 511 if (ep->tgt == NULL) {
512 return -ENOENT; 512 return -ENOENT;
513 } 513 }
514 (void) strlcpy(buf, ep->tgt, size); 514 (void) strlcpy(buf, ep->tgt, size);
515 return 0; 515 return 0;
516} 516}
517 517
518/* operations struct */ 518/* operations struct */
519static struct fuse_operations iscsiops = { 519static struct fuse_operations iscsiops = {
520 .getattr = iscsifs_getattr, 520 .getattr = iscsifs_getattr,
521 .readlink = iscsifs_readlink, 521 .readlink = iscsifs_readlink,
522 .readdir = iscsifs_readdir, 522 .readdir = iscsifs_readdir,
523 .open = iscsifs_open, 523 .open = iscsifs_open,
524 .read = iscsifs_read, 524 .read = iscsifs_read,
525 .write = iscsifs_write, 525 .write = iscsifs_write,
526 .statfs = iscsifs_statfs 526 .statfs = iscsifs_statfs
527}; 527};
528 528
529int  529int
530main(int argc, char **argv) 530main(int argc, char **argv)
531{ 531{
532 iscsi_initiator_t ini; 532 iscsi_initiator_t ini;
533 initiator_target_t tinfo; 533 initiator_target_t tinfo;
534 unsigned u; 534 unsigned u;
535 uint32_t lbac; 535 uint32_t lbac;
536 uint32_t blocksize; 536 uint32_t blocksize;
537 uint8_t data[256]; 537 uint8_t data[256];
538 sti_t sti; 538 sti_t sti;
539 char hostname[1024]; 539 char hostname[1024];
540 char name[1024]; 540 char name[1024];
541 char *colon; 541 char *colon;
542 char *host; 542 char *host;
543 char *user; 543 char *user;
544 char buf[32]; 544 char buf[32];
545 char devtype; 545 char devtype;
546 int discover; 546 int discover;
547 int cc; 547 int cc;
548 int i; 548 int i;
549 549
550 (void) memset(&tinfo, 0x0, sizeof(tinfo)); 550 (void) memset(&tinfo, 0x0, sizeof(tinfo));
551 iscsi_initiator_set_defaults(&ini); 551 iscsi_initiator_set_defaults(&ini);
552 user = NULL; 552 user = NULL;
553 (void) gethostname(host = hostname, sizeof(hostname)); 553 (void) gethostname(host = hostname, sizeof(hostname));
554 discover = 0; 554 discover = 0;
555 (void) stat("/etc/hosts", &sti.st); 555 (void) stat("/etc/hosts", &sti.st);
556 devtype = 'f'; 556 devtype = 'f';
557 iscsi_initiator_setvar(&ini, "address family", "4"); 557 iscsi_initiator_setvar(&ini, "address family", "4");
558 while ((i = getopt(argc, argv, "46a:bcd:Dfh:p:t:u:v:V")) != -1) { 558 while ((i = getopt(argc, argv, "46a:bcd:Dfh:p:t:u:v:V")) != -1) {
559 switch(i) { 559 switch(i) {
560 case '4': 560 case '4':
561 case '6': 561 case '6':
562 buf[0] = i; 562 buf[0] = i;
563 buf[1] = 0x0; 563 buf[1] = 0x0;
564 iscsi_initiator_setvar(&ini, "address family", buf); 564 iscsi_initiator_setvar(&ini, "address family", buf);
565 break; 565 break;
566 case 'a': 566 case 'a':
567 iscsi_initiator_setvar(&ini, "auth type", optarg); 567 iscsi_initiator_setvar(&ini, "auth type", optarg);
568 break; 568 break;
569 case 'b': 569 case 'b':
570 devtype = 'b'; 570 devtype = 'b';
571 break; 571 break;
572 case 'c': 572 case 'c':
573 devtype = 'c'; 573 devtype = 'c';
574 break; 574 break;
575 case 'd': 575 case 'd':
576 iscsi_initiator_setvar(&ini, "digest type", optarg); 576 iscsi_initiator_setvar(&ini, "digest type", optarg);
577 break; 577 break;
578 case 'D': 578 case 'D':
579 discover = 1; 579 discover = 1;
580 break; 580 break;
581 case 'f': 581 case 'f':
582 devtype = 'f'; 582 devtype = 'f';
583 break; 583 break;
584 case 'h': 584 case 'h':
585 iscsi_initiator_setvar(&ini, "target host", optarg); 585 iscsi_initiator_setvar(&ini, "target hostname", optarg);
586 break; 586 break;
587 case 'p': 587 case 'p':
588 iscsi_initiator_setvar(&ini, "target port", optarg); 588 iscsi_initiator_setvar(&ini, "target port", optarg);
589 break; 589 break;
590 case 't': 590 case 't':
591 iscsi_initiator_setvar(&ini, "target instance", optarg); 591 iscsi_initiator_setvar(&ini, "target instance", optarg);
592 break; 592 break;
593 case 'u': 593 case 'u':
594 iscsi_initiator_setvar(&ini, "user", optarg); 594 iscsi_initiator_setvar(&ini, "user", optarg);
595 break; 595 break;
596 case 'V': 596 case 'V':
597 (void) printf("\"%s\" %s\nPlease send all bug reports " 597 (void) printf("\"%s\" %s\nPlease send all bug reports "
598 "to %s\n", 598 "to %s\n",
599 PACKAGE_NAME, 599 PACKAGE_NAME,
600 PACKAGE_VERSION, 600 PACKAGE_VERSION,
601 PACKAGE_BUGREPORT); 601 PACKAGE_BUGREPORT);
602 exit(EXIT_SUCCESS); 602 exit(EXIT_SUCCESS);
603 /* NOTREACHED */ 603 /* NOTREACHED */
604 case 'v': 604 case 'v':
605 verbose += 1; 605 verbose += 1;
606 if (strcmp(optarg, "net") == 0) { 606 if (strcmp(optarg, "net") == 0) {
607 iscsi_initiator_setvar(&ini, "debug", "net"); 607 iscsi_initiator_setvar(&ini, "debug", "net");
608 } else if (strcmp(optarg, "iscsi") == 0) { 608 } else if (strcmp(optarg, "iscsi") == 0) {
609 iscsi_initiator_setvar(&ini, "debug", "iscsi"); 609 iscsi_initiator_setvar(&ini, "debug", "iscsi");
610 } else if (strcmp(optarg, "scsi") == 0) { 610 } else if (strcmp(optarg, "scsi") == 0) {
611 iscsi_initiator_setvar(&ini, "debug", "scsi"); 611 iscsi_initiator_setvar(&ini, "debug", "scsi");
612 } else if (strcmp(optarg, "all") == 0) { 612 } else if (strcmp(optarg, "all") == 0) {
613 iscsi_initiator_setvar(&ini, "debug", "all"); 613 iscsi_initiator_setvar(&ini, "debug", "all");
614 } 614 }
615 break; 615 break;
616 default: 616 default:
617 (void) fprintf(stderr, "%s: unknown option `%c'", 617 (void) fprintf(stderr, "%s: unknown option `%c'",
618 *argv, i); 618 *argv, i);
619 } 619 }
620 } 620 }
621 if (iscsi_initiator_getvar(&ini, "user") == NULL) { 621 if (iscsi_initiator_getvar(&ini, "user") == NULL) {
622 iscsi_err(__FILE__, __LINE__, "user must be specified with -u"); 622 iscsi_err(__FILE__, __LINE__, "user must be specified with -u");
623 exit(EXIT_FAILURE); 623 exit(EXIT_FAILURE);
624 } 624 }
625 625
626 if (iscsi_initiator_start(&ini) == -1) { 626 if (iscsi_initiator_start(&ini) == -1) {
627 iscsi_err(__FILE__, __LINE__, "initiator_init() failed\n"); 627 iscsi_err(__FILE__, __LINE__, "initiator_init() failed\n");
628 exit(EXIT_FAILURE); 628 exit(EXIT_FAILURE);
629 } 629 }
630 630
631 if (iscsi_initiator_discover(host, 0, 0) < 0) { 631 if (iscsi_initiator_discover(host, 0, 0) < 0) {
632 printf("initiator_discover() in discover failed\n"); 632 printf("initiator_discover() in discover failed\n");
633 exit(EXIT_FAILURE); 633 exit(EXIT_FAILURE);
634 } 634 }
635 635
636 if (iscsi_initiator_get_targets(0,&all_targets) == -1) { 636 if (iscsi_initiator_get_targets(0,&all_targets) == -1) {
637 iscsi_err(__FILE__, __LINE__, 637 iscsi_err(__FILE__, __LINE__,
638 "initiator_get_targets() failed\n"); 638 "initiator_get_targets() failed\n");
639 exit(EXIT_FAILURE); 639 exit(EXIT_FAILURE);
640 } 640 }
641 641
642 642
643 if (discover) { 643 if (discover) {
644 printf("Targets available from host %s:\n",host); 644 printf("Targets available from host %s:\n",host);
645 for (u = 0; u < all_targets.c ; u += 2) { 645 for (u = 0; u < all_targets.c ; u += 2) {
646 printf("%s at %s\n", all_targets.v[u], 646 printf("%s at %s\n", all_targets.v[u],
647 all_targets.v[u + 1]); 647 all_targets.v[u + 1]);
648 } 648 }
649 649
650 exit(EXIT_SUCCESS); 650 exit(EXIT_SUCCESS);
651 } 651 }
652 652
653 if (all_targets.c/2 > CONFIG_INITIATOR_NUM_TARGETS) { 653 if (all_targets.c/2 > CONFIG_INITIATOR_NUM_TARGETS) {
654 (void) fprintf(stderr, 654 (void) fprintf(stderr,
655 "CONFIG_INITIATOR_NUM_TARGETS in initiator.h " 655 "CONFIG_INITIATOR_NUM_TARGETS in initiator.h "
656 "is too small. %d targets available, " 656 "is too small. %d targets available, "
657 "only %d configurable.\n", 657 "only %d configurable.\n",
658 all_targets.c/2, CONFIG_INITIATOR_NUM_TARGETS); 658 all_targets.c/2, CONFIG_INITIATOR_NUM_TARGETS);
659 (void) fprintf(stderr, 659 (void) fprintf(stderr,
660 "Truncating number of targets to %d.\n", 660 "Truncating number of targets to %d.\n",
661 CONFIG_INITIATOR_NUM_TARGETS); 661 CONFIG_INITIATOR_NUM_TARGETS);
662 all_targets.c = CONFIG_INITIATOR_NUM_TARGETS; 662 all_targets.c = CONFIG_INITIATOR_NUM_TARGETS;
663 } 663 }
664 664
665 sti.st.st_ino = 0x15c51; 665 sti.st.st_ino = 0x15c51;
666 666
667#if defined(__NetBSD__) && defined(USE_LIBKMOD) 667#if defined(__NetBSD__) && defined(USE_LIBKMOD)
668 /* check that the puffs module is loaded on NetBSD */ 668 /* check that the puffs module is loaded on NetBSD */
669 if (kmodstat("puffs", NULL) == 0 && !kmodload("puffs")) { 669 if (kmodstat("puffs", NULL) == 0 && !kmodload("puffs")) {
670 (void) fprintf(stderr, "initiator: can't load puffs module\n"); 670 (void) fprintf(stderr, "initiator: can't load puffs module\n");
671 } 671 }
672#endif 672#endif
673 673
674 for (u = 0 ; u < all_targets.c / 2 ; u++) { 674 for (u = 0 ; u < all_targets.c / 2 ; u++) {
675 ALLOC(targetinfo_t, tv.v, tv.size, tv.c, 10, 10, "iscsifs", 675 ALLOC(targetinfo_t, tv.v, tv.size, tv.c, 10, 10, "iscsifs",
676 exit(EXIT_FAILURE)); 676 exit(EXIT_FAILURE));
677 677
678 initiator_set_target_name(u, all_targets.v[u * 2]); 678 initiator_set_target_name(u, all_targets.v[u * 2]);
679 679
680 if (iscsi_initiator_discover(host, u, 0) < 0) { 680 if (iscsi_initiator_discover(host, u, 0) < 0) {
681 printf("iscsi_initiator_discover() failed\n"); 681 printf("iscsi_initiator_discover() failed\n");
682 break; 682 break;
683 } 683 }
684 684
685 get_target_info(u, &tinfo); 685 get_target_info(u, &tinfo);
686 if ((colon = strrchr(tinfo.TargetName, ':')) == NULL) { 686 if ((colon = strrchr(tinfo.TargetName, ':')) == NULL) {
687 colon = tinfo.TargetName; 687 colon = tinfo.TargetName;
688 } else { 688 } else {
689 colon += 1; 689 colon += 1;
690 } 690 }
691 691
692 /* stuff size into st.st_size */ 692 /* stuff size into st.st_size */
693 (void) read_capacity(u, 0, &lbac, &blocksize); 693 (void) read_capacity(u, 0, &lbac, &blocksize);
694 sti.st.st_size = ((uint64_t)lbac + 1) * blocksize; 694 sti.st.st_size = ((uint64_t)lbac + 1) * blocksize;
695 sti.target = u; 695 sti.target = u;
696 696
697 tv.v[tv.c].host = strdup(tinfo.name); 697 tv.v[tv.c].host = strdup(tinfo.name);
698 tv.v[tv.c].ip = strdup(tinfo.ip); 698 tv.v[tv.c].ip = strdup(tinfo.ip);
699 tv.v[tv.c].targetname = strdup(tinfo.TargetName); 699 tv.v[tv.c].targetname = strdup(tinfo.TargetName);
700 tv.v[tv.c].stargetname = strdup(colon); 700 tv.v[tv.c].stargetname = strdup(colon);
701 tv.v[tv.c].target = u; 701 tv.v[tv.c].target = u;
702 tv.v[tv.c].lun = 0; 702 tv.v[tv.c].lun = 0;
703 tv.v[tv.c].lbac = lbac; 703 tv.v[tv.c].lbac = lbac;
704 tv.v[tv.c].blocksize = blocksize; 704 tv.v[tv.c].blocksize = blocksize;
705 705
706 /* get iSCSI target information */ 706 /* get iSCSI target information */
707 (void) memset(data, 0x0, sizeof(data)); 707 (void) memset(data, 0x0, sizeof(data));
708 inquiry(u, 0, 0, 0, data); 708 inquiry(u, 0, 0, 0, data);
709 tv.v[tv.c].devicetype = (data[0] & 0x1f); 709 tv.v[tv.c].devicetype = (data[0] & 0x1f);
710 (void) memcpy(tv.v[tv.c].vendor, &data[8], VendorLen); 710 (void) memcpy(tv.v[tv.c].vendor, &data[8], VendorLen);
711 (void) memcpy(tv.v[tv.c].product, &data[8 + VendorLen], 711 (void) memcpy(tv.v[tv.c].product, &data[8 + VendorLen],
712 ProductLen); 712 ProductLen);
713 (void) memcpy(tv.v[tv.c].version, 713 (void) memcpy(tv.v[tv.c].version,
714 &data[8 + VendorLen + ProductLen], VersionLen); 714 &data[8 + VendorLen + ProductLen], VersionLen);
715 (void) memset(data, 0x0, sizeof(data)); 715 (void) memset(data, 0x0, sizeof(data));
716 inquiry(u, 0, INQUIRY_EVPD_BIT, INQUIRY_UNIT_SERIAL_NUMBER_VPD, 716 inquiry(u, 0, INQUIRY_EVPD_BIT, INQUIRY_UNIT_SERIAL_NUMBER_VPD,
717 data); 717 data);
718 tv.v[tv.c].serial = strdup((char *)&data[4]); 718 tv.v[tv.c].serial = strdup((char *)&data[4]);
719 719
720 /* create the tree using virtdir routines */ 720 /* create the tree using virtdir routines */
721 cc = snprintf(name, sizeof(name), "/%s/%s", host, colon); 721 cc = snprintf(name, sizeof(name), "/%s/%s", host, colon);
722 virtdir_add(&iscsi, name, cc, 'd', name, cc); 722 virtdir_add(&iscsi, name, cc, 'd', name, cc);
723 cc = snprintf(name, sizeof(name), "/%s/%s/storage", host, 723 cc = snprintf(name, sizeof(name), "/%s/%s/storage", host,
724 colon); 724 colon);
725 virtdir_add(&iscsi, name, cc, devtype, (void *)&sti, 725 virtdir_add(&iscsi, name, cc, devtype, (void *)&sti,
726 sizeof(sti)); 726 sizeof(sti));
727 cc = snprintf(name, sizeof(name), "/%s/%s/hostname", host, 727 cc = snprintf(name, sizeof(name), "/%s/%s/hostname", host,
728 colon); 728 colon);
729 virtdir_add(&iscsi, name, cc, 'l', tinfo.name, 729 virtdir_add(&iscsi, name, cc, 'l', tinfo.name,
730 strlen(tinfo.name)); 730 strlen(tinfo.name));
731 cc = snprintf(name, sizeof(name), "/%s/%s/ip", host, colon); 731 cc = snprintf(name, sizeof(name), "/%s/%s/ip", host, colon);
732 virtdir_add(&iscsi, name, cc, 'l', tinfo.ip, strlen(tinfo.ip)); 732 virtdir_add(&iscsi, name, cc, 'l', tinfo.ip, strlen(tinfo.ip));
733 cc = snprintf(name, sizeof(name), "/%s/%s/targetname", host, 733 cc = snprintf(name, sizeof(name), "/%s/%s/targetname", host,
734 colon); 734 colon);
735 virtdir_add(&iscsi, name, cc, 'l', tinfo.TargetName, 735 virtdir_add(&iscsi, name, cc, 'l', tinfo.TargetName,
736 strlen(tinfo.TargetName)); 736 strlen(tinfo.TargetName));
737 cc = snprintf(name, sizeof(name), "/%s/%s/vendor", host, colon); 737 cc = snprintf(name, sizeof(name), "/%s/%s/vendor", host, colon);
738 virtdir_add(&iscsi, name, cc, 'l', tv.v[tv.c].vendor, 738 virtdir_add(&iscsi, name, cc, 'l', tv.v[tv.c].vendor,
739 strlen(tv.v[tv.c].vendor)); 739 strlen(tv.v[tv.c].vendor));
740 cc = snprintf(name, sizeof(name), "/%s/%s/product", host, 740 cc = snprintf(name, sizeof(name), "/%s/%s/product", host,
741 colon); 741 colon);
742 virtdir_add(&iscsi, name, cc, 'l', tv.v[tv.c].product, 742 virtdir_add(&iscsi, name, cc, 'l', tv.v[tv.c].product,
743 strlen(tv.v[tv.c].product)); 743 strlen(tv.v[tv.c].product));
744 cc = snprintf(name, sizeof(name), "/%s/%s/version", host, 744 cc = snprintf(name, sizeof(name), "/%s/%s/version", host,
745 colon); 745 colon);
746 virtdir_add(&iscsi, name, cc, 'l', tv.v[tv.c].version, 746 virtdir_add(&iscsi, name, cc, 'l', tv.v[tv.c].version,
747 strlen(tv.v[tv.c].version)); 747 strlen(tv.v[tv.c].version));
748 if (tv.v[tv.c].serial[0] && tv.v[tv.c].serial[0] != ' ') { 748 if (tv.v[tv.c].serial[0] && tv.v[tv.c].serial[0] != ' ') {
749 cc = snprintf(name, sizeof(name), "/%s/%s/serial", 749 cc = snprintf(name, sizeof(name), "/%s/%s/serial",
750 host, colon); 750 host, colon);
751 virtdir_add(&iscsi, name, cc, 'l', tv.v[tv.c].serial, 751 virtdir_add(&iscsi, name, cc, 'l', tv.v[tv.c].serial,
752 strlen(tv.v[tv.c].serial)); 752 strlen(tv.v[tv.c].serial));
753 } 753 }
754 tv.c += 1; 754 tv.c += 1;
755 } 755 }
756 return fuse_main(argc - optind, argv + optind, &iscsiops, NULL); 756 return fuse_main(argc - optind, argv + optind, &iscsiops, NULL);
757} 757}