Print this page
NEX-13218 Segfault in sun_fc library
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/sun_fc/common/FCHBAPort.cc
+++ new/usr/src/lib/sun_fc/common/FCHBAPort.cc
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
27 27
28 28 #include <FCHBAPort.h>
29 29 #include <Exceptions.h>
30 30 #include <Trace.h>
31 31 #include <sun_fc.h>
32 32 #include <iostream>
33 33 #include <iomanip>
34 34 #include <sys/types.h>
35 35 #include <sys/mkdev.h>
36 36 #include <sys/stat.h>
37 37 #include <fcntl.h>
38 38 #include <unistd.h>
39 39 #include <stropts.h>
40 40 #include <dirent.h>
41 41 #include <sys/fibre-channel/fc.h>
42 42 #include <sys/fibre-channel/fcio.h>
43 43 #include <sys/fibre-channel/ulp/fcp_util.h>
44 44 #include <sys/fibre-channel/ulp/fcsm.h>
45 45 #include <sys/fibre-channel/impl/fc_error.h>
46 46 #include <sys/fibre-channel/fc_appif.h>
47 47 #include <sys/scsi/generic/commands.h>
48 48 #include <sys/scsi/impl/commands.h>
49 49 #include <sys/scsi/impl/sense.h>
50 50 #include <sys/scsi/generic/inquiry.h>
51 51 #include <sys/scsi/generic/status.h>
52 52 #include <errno.h>
53 53 #include <FCHBANPIVPort.h>
54 54
55 55
56 56 using namespace std;
57 57
58 58 const int FCHBAPort::MAX_FCIO_MSG_LEN = 256;
59 59 const string FCHBAPort::FCSM_DRIVER_PATH = "/devices/pseudo/fcsm@0:fcsm";
60 60 const string FCHBAPort::FCP_DRIVER_PATH = "/devices/pseudo/fcp@0:fcp";
61 61
62 62 /*
63 63 * Interpret the error code in the fcio_t structure
64 64 *
65 65 * message must be at least MAX_FCIO_MSG_LEN in length.
66 66 */
67 67 void
68 68 FCHBAPort::transportError(uint32_t fcio_errno, char *message) {
69 69 Trace log("transportError");
70 70 string fcioErrorString;
71 71 if (message == NULL) {
72 72 log.internalError("NULL routine argument");
73 73 return;
74 74 }
75 75 switch (fcio_errno) {
76 76 case (uint32_t)FC_FAILURE:
77 77 fcioErrorString = "general failure";
78 78 break;
79 79 case (uint32_t)FC_FAILURE_SILENT:
80 80 fcioErrorString = "general failure but fail silently";
81 81 break;
82 82 case FC_SUCCESS:
83 83 fcioErrorString = "successful completion";
84 84 break;
85 85 case FC_CAP_ERROR:
86 86 fcioErrorString = "FCA capability error";
87 87 break;
88 88 case FC_CAP_FOUND:
89 89 fcioErrorString = "FCA capability unsettable";
90 90 break;
91 91 case FC_CAP_SETTABLE:
92 92 fcioErrorString = "FCA capability settable";
93 93 break;
94 94 case FC_UNBOUND:
95 95 fcioErrorString = "unbound stuff";
96 96 break;
97 97 case FC_NOMEM:
98 98 fcioErrorString = "allocation error";
99 99 break;
100 100 case FC_BADPACKET:
101 101 fcioErrorString = "invalid packet specified/supplied";
102 102 break;
103 103 case FC_OFFLINE:
104 104 fcioErrorString = "I/O resource unavailable";
105 105 break;
106 106 case FC_OLDPORT:
107 107 fcioErrorString = "operation on non-loop port";
108 108 break;
109 109 case FC_NO_MAP:
110 110 fcioErrorString = "requested map unavailable";
111 111 break;
112 112 case FC_TRANSPORT_ERROR:
113 113 fcioErrorString = "unable to transport I/O";
114 114 break;
115 115 case FC_ELS_FREJECT:
116 116 fcioErrorString = "ELS rejected by a Fabric";
117 117 break;
118 118 case FC_ELS_PREJECT:
119 119 fcioErrorString = "ELS rejected by an N_port";
120 120 break;
121 121 case FC_ELS_BAD:
122 122 fcioErrorString = "ELS rejected by FCA/fctl";
123 123 break;
124 124 case FC_ELS_MALFORMED:
125 125 fcioErrorString = "poorly formed ELS request";
126 126 break;
127 127 case FC_TOOMANY:
128 128 fcioErrorString = "resource request too large";
129 129 break;
130 130 case FC_UB_BADTOKEN:
131 131 fcioErrorString = "invalid unsolicited buffer token";
132 132 break;
133 133 case FC_UB_ERROR:
134 134 fcioErrorString = "invalid unsol buf request";
135 135 break;
136 136 case FC_UB_BUSY:
137 137 fcioErrorString = "buffer already in use";
138 138 break;
139 139 case FC_BADULP:
140 140 fcioErrorString = "Unknown ulp";
141 141 break;
142 142 case FC_BADTYPE:
143 143 fcioErrorString = "ULP not registered to handle this FC4 type";
144 144 break;
145 145 case FC_UNCLAIMED:
146 146 fcioErrorString = "request or data not claimed";
147 147 break;
148 148 case FC_ULP_SAMEMODULE:
149 149 fcioErrorString = "module already in use";
150 150 break;
151 151 case FC_ULP_SAMETYPE:
152 152 fcioErrorString = "FC4 module already in use";
153 153 break;
154 154 case FC_ABORTED:
155 155 fcioErrorString = "request aborted";
156 156 break;
157 157 case FC_ABORT_FAILED:
158 158 fcioErrorString = "abort request failed";
159 159 break;
160 160 case FC_BADEXCHANGE:
161 161 fcioErrorString = "exchange doesnŐt exist";
162 162 break;
163 163 case FC_BADWWN:
164 164 fcioErrorString = "WWN not recognized";
165 165 break;
166 166 case FC_BADDEV:
167 167 fcioErrorString = "device unrecognized";
168 168 break;
169 169 case FC_BADCMD:
170 170 fcioErrorString = "invalid command issued";
171 171 break;
172 172 case FC_BADOBJECT:
173 173 fcioErrorString = "invalid object requested";
174 174 break;
175 175 case FC_BADPORT:
176 176 fcioErrorString = "invalid port specified";
177 177 break;
178 178 case FC_NOTTHISPORT:
179 179 fcioErrorString = "resource not at this port";
180 180 break;
181 181 case FC_PREJECT:
182 182 fcioErrorString = "reject at remote N_Port";
183 183 break;
184 184 case FC_FREJECT:
185 185 fcioErrorString = "reject at remote Fabric";
186 186 break;
187 187 case FC_PBUSY:
188 188 fcioErrorString = "remote N_Port busy";
189 189 break;
190 190 case FC_FBUSY:
191 191 fcioErrorString = "remote Fabric busy";
192 192 break;
193 193 case FC_ALREADY:
194 194 fcioErrorString = "already logged in";
195 195 break;
196 196 case FC_LOGINREQ:
197 197 fcioErrorString = "login required";
198 198 break;
199 199 case FC_RESETFAIL:
200 200 fcioErrorString = "reset failed";
201 201 break;
202 202 case FC_INVALID_REQUEST:
203 203 fcioErrorString = "request is invalid";
204 204 break;
205 205 case FC_OUTOFBOUNDS:
206 206 fcioErrorString = "port number is out of bounds";
207 207 break;
208 208 case FC_TRAN_BUSY:
209 209 fcioErrorString = "command transport busy";
210 210 break;
211 211 case FC_STATEC_BUSY:
212 212 fcioErrorString = "port driver currently busy";
213 213 break;
214 214 case FC_DEVICE_BUSY:
215 215 fcioErrorString = "transport working on this device";
216 216 break;
217 217 case FC_DEVICE_NOT_TGT:
218 218 fcioErrorString = "device is not a SCSI target";
219 219 break;
220 220 default:
221 221 snprintf(message, MAX_FCIO_MSG_LEN, "Unknown error code 0x%x",
222 222 fcio_errno);
223 223 return;
224 224 }
225 225 snprintf(message, MAX_FCIO_MSG_LEN, "%s", fcioErrorString.c_str());
226 226 }
227 227
228 228 static void
229 229 reportSense(struct scsi_extended_sense *sense, const char *routine) {
230 230 Trace log("reportSense");
231 231 string msg;
232 232 if (!sense) {
233 233 log.internalError("NULL sense argument passed.");
234 234 return;
235 235 }
236 236 if (!routine) {
237 237 log.internalError("NULL routine argument passed.");
238 238 return;
239 239 }
240 240 log.genericIOError("SCSI FAILURE");
241 241 switch (sense->es_key) {
242 242 case KEY_NO_SENSE:
243 243 msg = "No sense";
244 244 break;
245 245 case KEY_RECOVERABLE_ERROR:
246 246 msg = "Recoverable error";
247 247 break;
248 248 case KEY_NOT_READY:
249 249 msg = "Not ready";
250 250 break;
251 251 case KEY_MEDIUM_ERROR:
252 252 msg = "Medium error";
253 253 break;
254 254 case KEY_HARDWARE_ERROR:
255 255 msg = "Hardware error";
256 256 break;
257 257 case KEY_ILLEGAL_REQUEST:
258 258 msg = "Illegal request";
259 259 break;
260 260 case KEY_UNIT_ATTENTION:
261 261 msg = "Unit attention";
262 262 break;
263 263 case KEY_DATA_PROTECT:
264 264 msg = "Data protect";
265 265 break;
266 266 case KEY_BLANK_CHECK:
267 267 msg = "Blank check";
268 268 break;
269 269 case KEY_VENDOR_UNIQUE:
270 270 msg = "Vendor Unique";
271 271 break;
272 272 case KEY_COPY_ABORTED:
273 273 msg = "Copy aborted";
274 274 break;
275 275 case KEY_ABORTED_COMMAND:
276 276 msg = "Aborted command";
277 277 break;
278 278 case KEY_EQUAL:
279 279 msg = "Equal";
280 280 break;
281 281 case KEY_VOLUME_OVERFLOW:
282 282 msg = "Volume overflow";
283 283 break;
284 284 case KEY_MISCOMPARE:
285 285 msg = "Miscompare";
286 286 break;
287 287 case KEY_RESERVED:
288 288 msg = "Reserved";
289 289 break;
290 290 default:
291 291 msg = "unknown sense key";
292 292 }
293 293 log.genericIOError("\tSense key: %s", msg.c_str());
294 294 log.genericIOError("\tASC = 0x%x", sense->es_add_code);
295 295 log.genericIOError("\tASCQ = 0x%x", sense->es_qual_code);
296 296 }
297 297
298 298 /*
299 299 * Issue a SCSI pass thru command.
300 300 * Returns a scsi status value.
301 301 */
302 302 void FCHBAPort::sendSCSIPassThru(struct fcp_scsi_cmd *fscsi,
303 303 HBA_UINT32 *responseSize, HBA_UINT32 *senseSize,
304 304 HBA_UINT8 *scsiStatus) {
305 305 Trace log("FCHBAPort::sendSCSIPassThru");
306 306 int fd;
307 307 HBA_STATUS ret;
308 308 int count;
309 309 char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
310 310 hrtime_t start;
311 311 hrtime_t end;
312 312 int ioctl_errno;
313 313 double duration;
314 314 la_wwn_t wwn;
315 315
316 316 if (fscsi == NULL ||
317 317 responseSize == NULL ||
318 318 senseSize == NULL ||
319 319 scsiStatus == NULL) {
320 320 throw BadArgumentException();
321 321 }
322 322
323 323 memcpy(&wwn, fscsi->scsi_fc_pwwn.raw_wwn, sizeof (la_wwn_t));
324 324 start = gethrtime();
325 325 fscsi->scsi_fc_port_num = instanceNumber;
326 326
327 327 fd = HBA::_open(FCP_DRIVER_PATH, O_RDONLY | O_NDELAY);
328 328 count = 0;
329 329 ioctl_errno = 0;
330 330
331 331 if (ioctl(fd, FCP_TGT_SEND_SCSI, fscsi) != 0) {
332 332 /* save off errno */
333 333 ioctl_errno = errno;
334 334 close(fd);
335 335 /*
336 336 * collect SCSI status first regrardless of the value.
337 337 * 0 is a good status so this should be okay
338 338 */
339 339 *scsiStatus = fscsi->scsi_bufstatus & STATUS_MASK;
340 340 transportError(fscsi->scsi_fc_status, fcioErrorString);
341 341
342 342 /* Did we get a check condition? */
343 343 if ((fscsi->scsi_bufstatus & STATUS_MASK) == STATUS_CHECK) {
344 344 *senseSize = fscsi->scsi_rqlen;
345 345 throw CheckConditionException();
346 346 } else if (fscsi->scsi_fc_status == FC_DEVICE_NOT_TGT) {
347 347 /*
348 348 * fcp driver returns FC_DEVICE_NOT_TGT when the node is not
349 349 * scsi-capable like remote hba nodes.
350 350 */
351 351 throw NotATargetException();
352 352 } else if (fscsi->scsi_fc_status == FC_INVALID_LUN) {
353 353 throw InvalidLUNException();
354 354 } else if (ioctl_errno == EBUSY) {
355 355 throw BusyException();
356 356 } else if (ioctl_errno == EAGAIN) {
357 357 throw TryAgainException();
358 358 } else if (ioctl_errno == ENOTSUP) {
359 359 throw NotSupportedException();
360 360 } else if (ioctl_errno == ENOENT) {
361 361 throw UnavailableException();
362 362 } else {
363 363 throw IOError(this, wwnConversion(wwn.raw_wwn),
364 364 fscsi->scsi_lun);
365 365 }
366 366 } else {
367 367 close(fd);
368 368 /* Just in case, check for a check-condition state */
369 369 if ((fscsi->scsi_bufstatus & STATUS_MASK) == STATUS_CHECK) {
370 370 *scsiStatus = fscsi->scsi_bufstatus & STATUS_MASK;
371 371 *senseSize = fscsi->scsi_rqlen;
372 372 throw CheckConditionException();
373 373 }
374 374 }
375 375
376 376 /* Record the response data */
377 377 *scsiStatus = fscsi->scsi_bufstatus & STATUS_MASK;
378 378 *responseSize = fscsi->scsi_buflen;
379 379 *senseSize = fscsi->scsi_rqlen;
380 380
381 381 /* Do some quick duration calcuations */
382 382 end = gethrtime();
383 383 duration = end - start;
384 384 duration /= HR_SECOND;
385 385 log.debug("Total SCSI IO time for HBA %s "
386 386 "target %016llx was %.4f seconds", getPath().c_str(),
387 387 wwnConversion(wwn.raw_wwn), duration);
388 388
389 389 #ifdef DEBUG
390 390 /* Did we have any failure */
391 391 if (ret != HBA_STATUS_OK) {
392 392 log.genericIOError(
393 393 "Ioctl failed for device \"%s\" target %016llx."
394 394 " Errno: \"%s\"(%d), "
395 395 "Transport: \"%s\", SCSI Status: 0x%x"
396 396 "responseSize = %d, senseSize = %d",
397 397 getPath().c_str(), wwnConversion(fscsi->scsi_fc_pwwn.raw_wwn),
398 398 strerror(ioctl_errno), ioctl_errno, fcioErrorString,
399 399 *scsiStatus, *responseSize, *senseSize);
400 400 /* We may or may not have sense data */
401 401 reportSense((struct scsi_extended_sense *)fscsi->scsi_rqbufaddr,
402 402 ROUTINE);
403 403 }
404 404 #endif
405 405
406 406 }
407 407
408 408 /*
409 409 * constructs the fcp_scsi_cmd struct for SCSI_Inquiry, SendReadCapacity, or
410 410 * SendReportLUNs
411 411 */
412 412 /*#include <fcio.h>
413 413 #include <fcp_util.h>*/
414 414 inline void
415 415 scsi_cmd_init(struct fcp_scsi_cmd *fscsi, const char *portname, void *reqbuf,
416 416 size_t req_len, void *responseBuffer, size_t resp_len,
417 417 void *senseBuffer, size_t sense_len) {
418 418 Trace log("scsi_cmd_init");
419 419 fscsi->scsi_fc_rspcode = 0;
420 420 fscsi->scsi_flags = FCP_SCSI_READ;
421 421 fscsi->scsi_timeout = 10 /* sec */;
422 422 fscsi->scsi_cdbbufaddr = (char *)reqbuf;
423 423 fscsi->scsi_cdblen = (uint32_t) req_len;
424 424 fscsi->scsi_bufaddr = (char *)responseBuffer;
425 425 fscsi->scsi_buflen = (uint32_t) resp_len;
426 426 fscsi->scsi_bufresid = 0;
427 427 fscsi->scsi_bufstatus = 0;
428 428 fscsi->scsi_rqbufaddr = (char *)senseBuffer;
429 429 fscsi->scsi_rqlen = (uint32_t) sense_len;
430 430 fscsi->scsi_rqresid = 0;
431 431 }
432 432
433 433
434 434 FCHBAPort::FCHBAPort(string thePath) : HBAPort() {
435 435 Trace log("FCHBAPort::FCHBAPort");
436 436 log.debug("Initializing HBA port %s", thePath.c_str());
437 437 fcio_t fcio;
438 438 int size = 200;
439 439 fc_hba_npiv_port_list_t *pathList;
440 440 bool retry = false;
441 441 int bufSize;
442 442
443 443 try {
444 444 path = lookupControllerPath(thePath);
445 445 sscanf(path.c_str(), "/dev/cfg/c%d", &controllerNumber);
446 446 } catch (...) {
447 447 log.debug("Unable to lookup controller path and number for %s",
448 448 thePath.c_str());
449 449 path = "/devices";
450 450 path += thePath;
451 451 path += ":fc";
452 452 controllerNumber = -1;
453 453 }
454 454
455 455 // Fetch the minor number for later use
456 456 struct stat sbuf;
457 457 if (stat(path.c_str(), &sbuf) == -1) {
458 458 throw IOError("Unable to stat device path: " + path);
459 459 }
460 460 instanceNumber = minor(sbuf.st_rdev);
461 461
462 462 // This routine is not index based, so we can discard stateChange
463 463 uint64_t tmp;
464 464 HBA_PORTATTRIBUTES attrs = getPortAttributes(tmp);
465 465 memcpy(&tmp, &attrs.PortWWN, 8);
466 466 portWWN = ntohll(tmp);
467 467 memcpy(&tmp, &attrs.NodeWWN, 8);
468 468 nodeWWN = ntohll(tmp);
469 469
470 470 // For reference, here's how to dump WWN's through C++ streams.
471 471 // cout << "\tPort WWN: " << hex << setfill('0') << setw(16) << portWWN
472 472 // << endl;
473 473 // cout << "\tNode WWN: " << hex << setfill('0') << setw(16) << nodeWWN
474 474 // << endl;
475 475
476 476 // we should add code here to build NPIVPORT instance
477 477 // Get Port's NPIV port list ( include nwwn and pwwn and path)
478 478 memset((caddr_t)&fcio, 0, sizeof (fcio));
479 479 fcio.fcio_cmd = FCIO_GET_NPIV_PORT_LIST;
480 480 fcio.fcio_xfer = FCIO_XFER_READ;
481 481 do {
482 482 retry = false;
483 483 bufSize = MAXPATHLEN * (size - 1) + (int) sizeof (fc_hba_npiv_port_list_t);
484 484 pathList = (fc_hba_npiv_port_list_t *) new uchar_t[bufSize];
485 485 pathList->numAdapters = size;
486 486 fcio.fcio_olen = bufSize;
487 487 fcio.fcio_obuf = (char *)pathList;
488 488 fp_ioctl(getPath(), FCIO_CMD, &fcio);
489 489 if (pathList->numAdapters > size) {
490 490 log.debug("Buffer too small for number of NPIV Port.Retry.");
491 491 size = pathList->numAdapters;
492 492 retry = true;
493 493 delete (pathList);
494 494 }
495 495 } while (retry);
496 496 log.debug("Get %d npiv ports", pathList->numAdapters);
497 497 // Make instance for each NPIV Port
498 498 for ( int i = 0; i < pathList->numAdapters; i++) {
499 499 try {
500 500 addPort(new FCHBANPIVPort(pathList->hbaPaths[i]));
501 501 } catch (...) {
502 502 log.debug("Ignoring partial failure");
503 503 }
504 504 }
505 505 delete (pathList);
506 506 }
507 507
508 508 uint32_t FCHBAPort::deleteNPIVPort(uint64_t vportwwn) {
509 509 Trace log("FCHBAPort::deleteNPIVPort");
510 510 fcio_t fcio;
511 511 la_wwn_t lawwn[1];
512 512 int ret = 0;
513 513
514 514 memset(&fcio, 0, sizeof(fcio));
515 515 uint64_t en_wwn = htonll(vportwwn);
516 516 memcpy(&lawwn[0], &en_wwn, sizeof (en_wwn));
517 517
518 518 fcio.fcio_cmd = FCIO_DELETE_NPIV_PORT;
519 519 fcio.fcio_xfer = FCIO_XFER_WRITE;
520 520 fcio.fcio_ilen = sizeof (la_wwn_t) * 2;
521 521 fcio.fcio_ibuf = (caddr_t)&lawwn;
522 522
523 523 fp_ioctl(getPath(), FCIO_CMD, &fcio);
524 524
525 525 return (ret);
526 526 }
527 527
528 528 uint32_t FCHBAPort::createNPIVPort(uint64_t vnodewwn, uint64_t vportwwn, uint32_t vindex) {
529 529 Trace log("FCHBAPort::createNPIVPort");
530 530 fcio_t fcio;
531 531 la_wwn_t lawwn[2];
532 532 uint32_t vportindex = 0;
533 533 HBA_NPIVCREATEENTRY entrybuf;
534 534
535 535 memset(&fcio, 0, sizeof(fcio));
536 536 uint64_t en_wwn = htonll(vnodewwn);
537 537 memcpy(&entrybuf.VNodeWWN, &en_wwn, sizeof (en_wwn));
538 538 en_wwn = htonll(vportwwn);
539 539 memcpy(&entrybuf.VPortWWN, &en_wwn, sizeof (en_wwn));
540 540 entrybuf.vindex = vindex;
541 541
542 542 fcio.fcio_cmd = FCIO_CREATE_NPIV_PORT;
543 543 fcio.fcio_xfer = FCIO_XFER_READ;
544 544 fcio.fcio_olen = sizeof (uint32_t);
545 545 fcio.fcio_obuf = (caddr_t)&vportindex;
546 546 fcio.fcio_ilen = sizeof (HBA_NPIVCREATEENTRY);
547 547 fcio.fcio_ibuf = (caddr_t)&entrybuf;
548 548
549 549 fp_ioctl(getPath(), FCIO_CMD, &fcio);
550 550
551 551 return (vportindex);
552 552 }
553 553
554 554 HBA_PORTNPIVATTRIBUTES FCHBAPort::getPortNPIVAttributes(uint64_t &stateChange) {
555 555 Trace log("FCHBAPort::getPortNPIVAttributes");
556 556
557 557 HBA_PORTNPIVATTRIBUTES attributes;
558 558 fc_hba_port_npiv_attributes_t attrs;
559 559 fcio_t fcio;
560 560
561 561 memset(&fcio, 0, sizeof(fcio));
562 562 memset(&attributes, 0, sizeof(attributes));
563 563
564 564 fcio.fcio_cmd = FCIO_GET_ADAPTER_PORT_NPIV_ATTRIBUTES;
565 565 fcio.fcio_olen = sizeof(attrs);
566 566 fcio.fcio_xfer = FCIO_XFER_READ;
567 567 fcio.fcio_obuf = (caddr_t)&attrs;
568 568
569 569 fp_ioctl(getPath(), FCIO_CMD, &fcio);
570 570
571 571 stateChange = attrs.lastChange;
572 572 attributes.npivflag = attrs.npivflag;
573 573 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
574 574 memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
575 575 attributes.MaxNumberOfNPIVPorts = attrs.MaxNumberOfNPIVPorts;
576 576 attributes.NumberOfNPIVPorts = attrs.NumberOfNPIVPorts;
577 577
578 578 return (attributes);
579 579 }
580 580
581 581 HBA_PORTATTRIBUTES FCHBAPort::getPortAttributes(uint64_t &stateChange) {
582 582 Trace log("FCHBAPort::getPortAttributes");
583 583
584 584 HBA_PORTATTRIBUTES attributes;
585 585 fcio_t fcio;
586 586 fc_hba_port_attributes_t attrs;
587 587
588 588 memset(&fcio, 0, sizeof (fcio));
589 589 memset(&attributes, 0, sizeof (attributes));
590 590
591 591 fcio.fcio_cmd = FCIO_GET_ADAPTER_PORT_ATTRIBUTES;
592 592 fcio.fcio_olen = sizeof (attrs);
593 593 fcio.fcio_xfer = FCIO_XFER_READ;
594 594 fcio.fcio_obuf = (caddr_t)&attrs;
595 595
596 596 fp_ioctl(getPath(), FCIO_CMD, &fcio);
597 597
598 598 stateChange = attrs.lastChange;
599 599
600 600 attributes.PortFcId = attrs.PortFcId;
601 601 attributes.PortType = attrs.PortType;
602 602 attributes.PortState = attrs.PortState;
603 603 attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
604 604 attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
605 605 attributes.PortSpeed = attrs.PortSpeed;
606 606 attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
607 607 attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
608 608 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
609 609 memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
610 610 memcpy(&attributes.FabricName, &attrs.FabricName, 8);
611 611 memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
612 612 memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
613 613 memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
614 614
615 615 strncpy((char *)attributes.OSDeviceName, getPath().c_str(), 256);
616 616 return (attributes);
617 617 }
618 618
619 619 HBA_PORTATTRIBUTES FCHBAPort::getDiscoveredAttributes(
620 620 HBA_UINT32 discoveredport, uint64_t &stateChange) {
621 621 Trace log("FCHBAPort::getDiscoverdAttributes(i)");
622 622
623 623 HBA_PORTATTRIBUTES attributes;
624 624 fcio_t fcio;
625 625 fc_hba_port_attributes_t attrs;
626 626
627 627 memset(&fcio, 0, sizeof (fcio));
628 628 memset(&attributes, 0, sizeof (attributes));
629 629
630 630 fcio.fcio_cmd = FCIO_GET_DISCOVERED_PORT_ATTRIBUTES;
631 631 fcio.fcio_olen = sizeof (attrs);
632 632 fcio.fcio_xfer = FCIO_XFER_READ;
633 633 fcio.fcio_obuf = (caddr_t)&attrs;
634 634 fcio.fcio_ilen = sizeof (discoveredport);
635 635 fcio.fcio_ibuf = (caddr_t)&discoveredport;
636 636
637 637 fp_ioctl(getPath(), FCIO_CMD, &fcio);
638 638
639 639 stateChange = attrs.lastChange;
640 640
641 641 attributes.PortFcId = attrs.PortFcId;
642 642 attributes.PortType = attrs.PortType;
643 643 attributes.PortState = attrs.PortState;
644 644 attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
645 645 attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
646 646 attributes.PortSpeed = attrs.PortSpeed;
647 647 attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
648 648 attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
649 649 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
650 650 memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
651 651 memcpy(&attributes.FabricName, &attrs.FabricName, 8);
652 652 memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
653 653 memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
654 654 memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
655 655
656 656
657 657 return (attributes);
658 658 }
659 659
660 660 HBA_PORTATTRIBUTES FCHBAPort::getDiscoveredAttributes(
661 661 uint64_t wwn, uint64_t &stateChange) {
662 662 Trace log("FCHBAPort::getDiscoverdAttributes(p)");
663 663
664 664 HBA_PORTATTRIBUTES attributes;
665 665 fcio_t fcio;
666 666 fc_hba_port_attributes_t attrs;
667 667 la_wwn_t lawwn;
668 668
669 669 memset(&fcio, 0, sizeof (fcio));
670 670 memset(&attributes, 0, sizeof (attributes));
671 671
672 672 uint64_t en_wwn = htonll(wwn);
673 673 memcpy(&lawwn, &en_wwn, sizeof (en_wwn));
674 674
675 675 fcio.fcio_cmd = FCIO_GET_PORT_ATTRIBUTES;
676 676 fcio.fcio_olen = sizeof (attrs);
677 677 fcio.fcio_xfer = FCIO_XFER_READ;
678 678 fcio.fcio_obuf = (caddr_t)&attrs;
679 679 fcio.fcio_ilen = sizeof (wwn);
680 680 fcio.fcio_ibuf = (caddr_t)&lawwn;
681 681
682 682 fp_ioctl(getPath(), FCIO_CMD, &fcio);
683 683
684 684 stateChange = attrs.lastChange;
685 685
686 686 attributes.PortFcId = attrs.PortFcId;
687 687 attributes.PortType = attrs.PortType;
688 688 attributes.PortState = attrs.PortState;
689 689 attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
690 690 attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
691 691 attributes.PortSpeed = attrs.PortSpeed;
692 692 attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
693 693 attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
694 694 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
695 695 memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
696 696 memcpy(&attributes.FabricName, &attrs.FabricName, 8);
697 697 memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
698 698 memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
699 699 memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
700 700
701 701
702 702 return (attributes);
703 703 }
704 704
705 705
706 706 void FCHBAPort::getTargetMappings(PHBA_FCPTARGETMAPPINGV2 userMappings) {
707 707 Trace log("FCHBAPort::getTargetMappings");
708 708 int i, index;
709 709 uint_t total_entries = 0;
710 710
711 711 struct fcp_ioctl fioctl;
712 712 fc_hba_target_mappings_t *mappings;
713 713 int fd;
714 714 bool zeroLength = false;
715 715
716 716
717 717 if (userMappings == NULL) {
718 718 log.userError("Null mapping argument ");
719 719 throw BadArgumentException();
720 720 }
721 721
722 722 /* It's possible they didn't give any space */
723 723 if (userMappings->NumberOfEntries == 0) {
724 724 zeroLength = true;
725 725 userMappings->NumberOfEntries = 1;
726 726 /* We have to give the driver at least one space */
727 727 }
728 728
729 729 mappings = (fc_hba_target_mappings_t *)new uchar_t[
730 730 (sizeof (fc_hba_mapping_entry_t)) *
731 731 (userMappings->NumberOfEntries - 1) +
732 732 sizeof (fc_hba_target_mappings_t)];
733 733 if (mappings == NULL) {
734 734 log.noMemory();
735 735 throw InternalError();
736 736 }
737 737
738 738
739 739 fioctl.fp_minor = instanceNumber;
740 740 fioctl.listlen = ((uint32_t) (sizeof (fc_hba_mapping_entry_t))) *
741 741 (userMappings->NumberOfEntries - 1) +
742 742 (uint32_t) sizeof (fc_hba_target_mappings_t);
743 743 fioctl.list = (caddr_t)mappings;
744 744
745 745 fd = HBA::_open(FCP_DRIVER_PATH, O_RDONLY | O_NDELAY);
746 746
747 747 log.debug("Performing IOCTL to fetch mappings");
748 748
749 749 if (ioctl(fd, FCP_GET_TARGET_MAPPINGS, &fioctl) != 0) {
750 750 delete (mappings);
751 751 close(fd);
752 752 if (errno == EBUSY) {
753 753 throw BusyException();
754 754 } else if (errno == EAGAIN) {
755 755 throw TryAgainException();
756 756 } else if (errno == ENOTSUP) {
757 757 throw NotSupportedException();
758 758 } else if (errno == ENOENT) {
759 759 throw UnavailableException();
760 760 } else {
761 761 throw IOError("Unable to fetch target mappings");
762 762 }
763 763 }
764 764
765 765 close(fd);
766 766 // Quickly iterate through and copy the data over to the client
767 767 for (i = 0; i < userMappings->NumberOfEntries && !zeroLength &&
768 768 i < mappings->numLuns; i++) {
769 769 string raw = mappings->entries[i].targetDriver;
770 770
771 771
772 772 if (raw.length() <= 0) {
773 773 log.internalError("Bad target mapping without path, truncating.");
774 774 break;
775 775 }
776 776 /*
777 777 * Ideally, we'd like to ask some standard Solaris interface
778 778 * "What is the prefered minor node for this target?"
779 779 * but no such interface exists today. So, for now,
780 780 * we just hard-code ":n" for tapes, ":c,raw" for disks,
781 781 * and ":0" for enclosures.
782 782 * Devices with other generic names will be presented through
783 783 * first matching /dev path.
784 784 */
785 785 if ((raw.find("/st@") != raw.npos) ||
786 786 (raw.find("/tape@") != raw.npos)) {
787 787 raw += ":n";
788 788 } else if ((raw.find("/ssd@") != raw.npos) ||
789 789 (raw.find("/sd@") != raw.npos) ||
790 790 (raw.find("/disk@") != raw.npos)) {
791 791 raw += ":c,raw";
792 792 } else if ((raw.find("/ses@") != raw.npos) ||
793 793 (raw.find("/enclosure@") != raw.npos)) {
794 794 raw += ":0";
795 795 } else {
796 796 log.debug(
797 797 "Unrecognized target driver (%s), using first matching /dev path",
798 798 raw.c_str());
799 799 }
800 800 snprintf(userMappings->entry[i].ScsiId.OSDeviceName,
801 801 sizeof (userMappings->entry[i].ScsiId.OSDeviceName),
802 802 "/devices%s", raw.c_str());
803 803 userMappings->entry[i].ScsiId.ScsiBusNumber =
804 804 controllerNumber;
805 805 userMappings->entry[i].ScsiId.ScsiTargetNumber =
806 806 mappings->entries[i].targetNumber;
807 807 userMappings->entry[i].ScsiId.ScsiOSLun =
808 808 mappings->entries[i].osLUN;
809 809 userMappings->entry[i].FcpId.FcId =
810 810 mappings->entries[i].d_id;
811 811 memcpy(userMappings->entry[i].FcpId.NodeWWN.wwn,
812 812 mappings->entries[i].NodeWWN.raw_wwn,
813 813 sizeof (la_wwn_t));
814 814 memcpy(userMappings->entry[i].FcpId.PortWWN.wwn,
815 815 mappings->entries[i].PortWWN.raw_wwn,
|
↓ open down ↓ |
815 lines elided |
↑ open up ↑ |
816 816 sizeof (la_wwn_t));
817 817
818 818 userMappings->entry[i].FcpId.FcpLun =
819 819 mappings->entries[i].samLUN;
820 820
821 821 memcpy(userMappings->entry[i].LUID.buffer,
822 822 mappings->entries[i].guid,
823 823 sizeof (userMappings->entry[i].LUID.buffer));
824 824 }
825 825
826 + if (!zeroLength) {
827 + i -= 1;
828 + }
826 829 log.debug("Total mappings: %d %08x %08x",
827 830 mappings->numLuns, mappings->entries[i].osLUN, mappings->entries[i].samLUN);
828 831
829 832 // If everything is good, convert paths to sym-links
830 833 if (mappings->numLuns > 0 && !zeroLength) {
831 834 if (userMappings->NumberOfEntries >= mappings->numLuns) {
832 835 // User buffer is larger than needed. (All is good)
833 836 userMappings->NumberOfEntries = mappings->numLuns;
834 837 convertToShortNames(userMappings);
835 838 } else {
836 839 // User buffer is non zero, but too small. Don't bother with links
837 840 userMappings->NumberOfEntries = mappings->numLuns;
838 841 delete (mappings);
839 842 throw MoreDataException();
840 843 }
841 844 } else if (mappings->numLuns > 0) {
842 845 // Zero length buffer, but we've got mappings
843 846 userMappings->NumberOfEntries = mappings->numLuns;
844 847 delete (mappings);
845 848 throw MoreDataException();
846 849 } else {
847 850 // No mappings, no worries
848 851 userMappings->NumberOfEntries = 0;
849 852 delete (mappings);
850 853 return;
851 854 }
852 855 delete (mappings);
853 856 }
854 857
855 858 void FCHBAPort::getRNIDMgmtInfo(PHBA_MGMTINFO info) {
856 859 Trace log("FCHBAPort::getRNIDMgmtInfo");
857 860 HBA_STATUS status = HBA_STATUS_OK;
858 861 fc_rnid_t rnid;
859 862 fcio_t fcio;
860 863
861 864
862 865 if (info == NULL) {
863 866 log.userError("NULL port management info");
864 867 throw BadArgumentException();
865 868 }
866 869
867 870 // Get the RNID information from the first port
868 871 memset(&rnid, 0, sizeof (fc_rnid_t));
869 872 memset((caddr_t)&fcio, 0, sizeof (fcio));
870 873
871 874 fcio.fcio_cmd = FCIO_GET_NODE_ID;
872 875 fcio.fcio_olen = sizeof (fc_rnid_t);
873 876 fcio.fcio_xfer = FCIO_XFER_READ;
874 877 fcio.fcio_obuf = (caddr_t)&rnid;
875 878 fp_ioctl(getPath(), FCIO_CMD, &fcio);
876 879
877 880 // Copy out the struct members of rnid into PHBA_MGMTINFO struct
878 881 memcpy(&info->wwn, &(rnid.global_id), sizeof (info->wwn));
879 882 memcpy(&info->unittype, &(rnid.unit_type), sizeof (info->unittype));
880 883 memcpy(&info->PortId, &(rnid.port_id), sizeof (info->PortId));
881 884 memcpy(&info->NumberOfAttachedNodes, &(rnid.num_attached),
882 885 sizeof (info->NumberOfAttachedNodes));
883 886 memcpy(&info->IPVersion, &(rnid.ip_version), sizeof (info->IPVersion));
884 887 memcpy(&info->UDPPort, &(rnid.udp_port), sizeof (info->UDPPort));
885 888 memcpy(&info->IPAddress, &(rnid.ip_addr), sizeof (info->IPAddress));
886 889 memcpy(&info->TopologyDiscoveryFlags, &(rnid.topo_flags),
887 890 sizeof (info->TopologyDiscoveryFlags));
888 891 }
889 892
890 893 void FCHBAPort::sendCTPassThru(void *requestBuffer, HBA_UINT32 requestSize,
891 894 void *responseBuffer, HBA_UINT32 *responseSize) {
892 895 Trace log("FCHBAPort::sendCTPassThru");
893 896 fcio_t fcio;
894 897 struct stat sbuf;
895 898 minor_t minor_node;
896 899 hrtime_t start, end;
897 900 double duration;
898 901
899 902 // Validate the arguments
900 903 if (requestBuffer == NULL) {
901 904 log.userError("NULL request buffer");
902 905 throw BadArgumentException();
903 906 }
904 907 if (responseBuffer == NULL) {
905 908 log.userError("NULL response buffer");
906 909 throw BadArgumentException();
907 910 }
908 911
909 912 minor_node = instanceNumber;
910 913
911 914 // construct fcio struct
912 915 memset(&fcio, 0, sizeof (fcio_t));
913 916 fcio.fcio_cmd = FCSMIO_CT_CMD;
914 917 fcio.fcio_xfer = FCIO_XFER_RW;
915 918
916 919 fcio.fcio_ilen = requestSize;
917 920 fcio.fcio_ibuf = (char *)requestBuffer;
918 921 fcio.fcio_olen = *responseSize;
919 922 fcio.fcio_obuf = (char *)responseBuffer;
920 923
921 924 fcio.fcio_alen = sizeof (minor_t);
922 925 fcio.fcio_abuf = (char *)&minor_node;
923 926
924 927
925 928 start = gethrtime();
926 929 fcsm_ioctl(FCSMIO_CMD, &fcio);
927 930
928 931 // Do some calculations on the duration of the ioctl.
929 932 end = gethrtime();
930 933 duration = end - start;
931 934 duration /= HR_SECOND;
932 935 log.debug(
933 936 "Total CTPASS ioctl call for HBA %s was %.4f seconds",
934 937 getPath().c_str(), duration);
935 938 }
936 939
937 940 void FCHBAPort::sendRLS(uint64_t destWWN,
938 941 void *pRspBuffer,
939 942 HBA_UINT32 *pRspBufferSize) {
940 943 Trace log("FCHBAPort::sendRLS");
941 944
942 945 fcio_t fcio;
943 946 fc_portid_t rls_req;
944 947
945 948
946 949 // Validate the arguments
947 950 if (pRspBuffer == NULL ||
948 951 pRspBufferSize == NULL) {
949 952 log.userError("NULL hba");
950 953 throw BadArgumentException();
951 954 }
952 955
953 956 // check to see if we are sending RLS to the HBA
954 957 HBA_PORTATTRIBUTES attrs;
955 958 uint64_t tmp;
956 959 if (getPortWWN() == destWWN) {
957 960 attrs = getPortAttributes(tmp);
958 961 } else {
959 962 attrs = getDiscoveredAttributes(destWWN, tmp);
960 963 }
961 964
962 965 memcpy(&rls_req, &attrs.PortFcId,
963 966 sizeof (attrs.PortFcId));
964 967
965 968 memset((caddr_t)&fcio, 0, sizeof (fcio));
966 969 fcio.fcio_cmd = FCIO_LINK_STATUS;
967 970 fcio.fcio_ibuf = (caddr_t)&rls_req;
968 971 fcio.fcio_ilen = sizeof (rls_req);
969 972 fcio.fcio_xfer = FCIO_XFER_RW;
970 973 fcio.fcio_flags = 0;
971 974 fcio.fcio_cmd_flags = FCIO_CFLAGS_RLS_DEST_NPORT;
972 975 fcio.fcio_obuf = (char *)new uchar_t[*pRspBufferSize];
973 976 fcio.fcio_olen = *pRspBufferSize;
974 977
975 978 if (fcio.fcio_obuf == NULL) {
976 979 log.noMemory();
977 980 throw InternalError();
978 981 }
979 982
980 983 fp_ioctl(getPath(), FCIO_CMD, &fcio);
981 984 memcpy(pRspBuffer, fcio.fcio_obuf, *pRspBufferSize);
982 985 if (fcio.fcio_obuf != NULL) {
983 986 delete(fcio.fcio_obuf);
984 987 }
985 988 }
986 989
987 990 void FCHBAPort::sendReportLUNs(uint64_t wwn,
988 991 void *responseBuffer, HBA_UINT32 *responseSize,
989 992 HBA_UINT8 *scsiStatus,
990 993 void *senseBuffer, HBA_UINT32 *senseSize) {
991 994 Trace log("FCHBAPort::sendReportLUNs");
992 995 struct fcp_scsi_cmd fscsi;
993 996 union scsi_cdb scsi_rl_req;
994 997 uint64_t targetWwn = htonll(wwn);
995 998
996 999 // Validate the arguments
997 1000 if (responseBuffer == NULL ||
998 1001 senseBuffer == NULL ||
999 1002 responseSize == NULL ||
1000 1003 senseSize == NULL) {
1001 1004 throw BadArgumentException();
1002 1005 }
1003 1006
1004 1007 memset(&fscsi, 0, sizeof (fscsi));
1005 1008 memset(&scsi_rl_req, 0, sizeof (scsi_rl_req));
1006 1009 memcpy(fscsi.scsi_fc_pwwn.raw_wwn, &targetWwn, sizeof (la_wwn_t));
1007 1010
1008 1011 scsi_cmd_init(&fscsi, getPath().c_str(), &scsi_rl_req,
1009 1012 sizeof (scsi_rl_req), responseBuffer, *responseSize,
1010 1013 senseBuffer, *senseSize);
1011 1014
1012 1015 fscsi.scsi_lun = 0;
1013 1016 scsi_rl_req.scc_cmd = SCMD_REPORT_LUNS;
1014 1017 FORMG5COUNT(&scsi_rl_req, *responseSize);
1015 1018 sendSCSIPassThru(&fscsi, responseSize, senseSize, scsiStatus);
1016 1019 }
1017 1020
1018 1021 /*
1019 1022 * arguments:
1020 1023 * wwn - remote target WWN where the SCSI Inquiry shall be sent
1021 1024 * fcLun - the SCSI LUN to which the SCSI Inquiry shall be sent
1022 1025 * cdb1 - the second byte of the CDB for the SCSI Inquiry
1023 1026 * cdb2 - the third byte of teh CDB for the SCSI Inquiry
1024 1027 * responseBuffer - shall be a pointer to a buffer to receive the SCSI
1025 1028 * Inquiry command response
1026 1029 * responseSize - a pointer to the size of the buffer to receive
1027 1030 * the SCSI Inquiry.
1028 1031 * scsiStatus - a pointer to a buffer to receive SCSI status
1029 1032 * senseBuffer - pointer to a buffer to receive SCSI sense data
1030 1033 * seneseSize - pointer to the size of the buffer to receive SCSI sense
1031 1034 * data
1032 1035 */
1033 1036 void FCHBAPort::sendScsiInquiry(uint64_t wwn, HBA_UINT64 fcLun,
1034 1037 HBA_UINT8 cdb1, HBA_UINT8 cdb2, void *responseBuffer,
1035 1038 HBA_UINT32 *responseSize, HBA_UINT8 *scsiStatus, void *senseBuffer,
1036 1039 HBA_UINT32 *senseSize) {
1037 1040 Trace log("FCHBAPort::sendScsiInquiry");
1038 1041
1039 1042 struct fcp_scsi_cmd fscsi;
1040 1043 union scsi_cdb scsi_inq_req;
1041 1044 uint64_t targetWwn = htonll(wwn);
1042 1045
1043 1046 // Validate the arguments
1044 1047 if (responseBuffer == NULL ||
1045 1048 senseBuffer == NULL ||
1046 1049 responseSize == NULL ||
1047 1050 senseSize == NULL) {
1048 1051 throw BadArgumentException();
1049 1052 }
1050 1053
1051 1054 memset(&fscsi, 0, sizeof (fscsi));
1052 1055 memset(&scsi_inq_req, 0, sizeof (scsi_inq_req));
1053 1056 memcpy(fscsi.scsi_fc_pwwn.raw_wwn, &targetWwn, sizeof (la_wwn_t));
1054 1057
1055 1058
1056 1059 scsi_cmd_init(&fscsi, getPath().c_str(), &scsi_inq_req,
1057 1060 sizeof (scsi_inq_req), responseBuffer, *responseSize,
1058 1061 senseBuffer, *senseSize);
1059 1062 fscsi.scsi_lun = fcLun;
1060 1063
1061 1064 scsi_inq_req.scc_cmd = SCMD_INQUIRY;
1062 1065 scsi_inq_req.g0_addr1 = cdb2;
1063 1066 scsi_inq_req.g0_addr2 = cdb1;
1064 1067 scsi_inq_req.g0_count0 = *responseSize;
1065 1068
1066 1069
1067 1070 sendSCSIPassThru(&fscsi, responseSize, senseSize, scsiStatus);
1068 1071 }
1069 1072
1070 1073
1071 1074 void FCHBAPort::sendReadCapacity(uint64_t pwwn,
1072 1075 HBA_UINT64 fcLun, void *responseBuffer,
1073 1076 HBA_UINT32 *responseSize, HBA_UINT8 *scsiStatus,
1074 1077 void *senseBuffer, HBA_UINT32 *senseSize) {
1075 1078 Trace log("FCHBAPort::sendReadCapacity");
1076 1079
1077 1080 struct fcp_scsi_cmd fscsi;
1078 1081 union scsi_cdb scsi_rc_req;
1079 1082 uint64_t targetWwn = htonll(pwwn);
1080 1083
1081 1084 // Validate the arguments
1082 1085 if (responseBuffer == NULL ||
1083 1086 senseBuffer == NULL ||
1084 1087 responseSize == NULL ||
1085 1088 senseSize == NULL ||
1086 1089 scsiStatus == NULL) {
1087 1090 throw BadArgumentException();
1088 1091 }
1089 1092
1090 1093 memset(&fscsi, 0, sizeof (fscsi));
1091 1094 memset(&scsi_rc_req, 0, sizeof (scsi_rc_req));
1092 1095
1093 1096 scsi_cmd_init(&fscsi, getPath().c_str(), &scsi_rc_req,
1094 1097 sizeof (scsi_rc_req), responseBuffer, *responseSize,
1095 1098 senseBuffer, *senseSize);
1096 1099
1097 1100 memcpy(fscsi.scsi_fc_pwwn.raw_wwn, &targetWwn, sizeof (la_wwn_t));
1098 1101 fscsi.scsi_lun = fcLun;
1099 1102
1100 1103 scsi_rc_req.scc_cmd = SCMD_READ_CAPACITY;
1101 1104 scsi_rc_req.g1_reladdr = 0;
1102 1105
1103 1106 scsi_rc_req.g1_addr3 = 0;
1104 1107 scsi_rc_req.g1_count0 = 0;
1105 1108
1106 1109 sendSCSIPassThru(&fscsi, responseSize, senseSize, scsiStatus);
1107 1110 }
1108 1111
1109 1112 void FCHBAPort::sendRNID(uint64_t destwwn, HBA_UINT32 destfcid,
1110 1113 HBA_UINT32 nodeIdDataFormat, void *pRspBuffer,
1111 1114 HBA_UINT32 *RspBufferSize) {
1112 1115 Trace log("FCHBAPort::sendRNID");
1113 1116 int localportfound, remoteportfound, send;
1114 1117 fcio_t fcio;
1115 1118
1116 1119 // Validate the arguments
1117 1120 if (pRspBuffer == NULL ||
1118 1121 RspBufferSize == NULL) {
1119 1122 throw BadArgumentException();
1120 1123 }
1121 1124 // NodeIdDataFormat must be within the range of 0x00 and 0xff
1122 1125 if (nodeIdDataFormat > 0xff) {
1123 1126 log.userError(
1124 1127 "NodeIdDataFormat must be within the range of 0x00 "
1125 1128 "and 0xFF");
1126 1129 throw BadArgumentException();
1127 1130 }
1128 1131
1129 1132
1130 1133 remoteportfound = 0;
1131 1134 if (destfcid != 0) {
1132 1135 try {
1133 1136 uint64_t tmp;
1134 1137 HBA_PORTATTRIBUTES attrs = getDiscoveredAttributes(destwwn,
1135 1138 tmp);
1136 1139 if (attrs.PortFcId == destfcid) {
1137 1140 send = 1;
1138 1141 remoteportfound = 1;
1139 1142 } else {
1140 1143 send = 0;
1141 1144 remoteportfound = 1;
1142 1145 }
1143 1146 } catch (HBAException &e) {
1144 1147 /*
1145 1148 * Send RNID if destination port not
1146 1149 * present in the discovered ports table
1147 1150 */
1148 1151 }
1149 1152 if (remoteportfound == 0) {
1150 1153 send = 1;
1151 1154 }
1152 1155 } else {
1153 1156 send = 1;
1154 1157 }
1155 1158
1156 1159 if (!send) {
1157 1160 // Can we log something so we can figure out why?
1158 1161 throw BadArgumentException();
1159 1162 }
1160 1163
1161 1164 memset((caddr_t)&fcio, 0, sizeof (fcio));
1162 1165 uint64_t netdestwwn = htonll(destwwn);
1163 1166 fcio.fcio_cmd = FCIO_SEND_NODE_ID;
1164 1167 fcio.fcio_xfer = FCIO_XFER_READ;
1165 1168 fcio.fcio_cmd_flags = nodeIdDataFormat;
1166 1169 fcio.fcio_ilen = sizeof (la_wwn_t);
1167 1170 fcio.fcio_ibuf = (caddr_t)&netdestwwn;
1168 1171 fcio.fcio_olen = *RspBufferSize;
1169 1172 fcio.fcio_obuf = (char *)new uchar_t[*RspBufferSize];
1170 1173
1171 1174
1172 1175 if (fcio.fcio_obuf == NULL) {
1173 1176 log.noMemory();
1174 1177 throw InternalError();
1175 1178 }
1176 1179
1177 1180 fp_ioctl(getPath(), FCIO_CMD, &fcio);
1178 1181
1179 1182 memcpy(pRspBuffer, fcio.fcio_obuf, *RspBufferSize);
1180 1183
1181 1184 if (fcio.fcio_obuf != NULL) {
1182 1185 delete(fcio.fcio_obuf);
1183 1186 }
1184 1187 }
1185 1188
1186 1189 void FCHBAPort::setRNID(HBA_MGMTINFO info) {
1187 1190 Trace log("FCHBAPort::setRNID");
1188 1191 fc_rnid_t rnid;
1189 1192 fcio_t fcio;
1190 1193
1191 1194 memset(&rnid, 0, sizeof (fc_rnid_t));
1192 1195 memset((caddr_t)&fcio, 0, sizeof (fcio));
1193 1196
1194 1197
1195 1198 fcio.fcio_cmd = FCIO_SET_NODE_ID;
1196 1199 fcio.fcio_ilen = sizeof (fc_rnid_t);
1197 1200 fcio.fcio_xfer = FCIO_XFER_WRITE;
1198 1201 fcio.fcio_ibuf = (caddr_t)&rnid;
1199 1202
1200 1203
1201 1204 // Copy the HBA_MGMTINFO into fc_rnid_t struct
1202 1205 memcpy(&(rnid.unit_type), &(info.unittype), sizeof (rnid.unit_type));
1203 1206 memcpy(&(rnid.port_id), &(info.PortId), sizeof (rnid.port_id));
1204 1207 memcpy(&(rnid.global_id), &(info.wwn), sizeof (info.wwn));
1205 1208 memcpy(&(rnid.num_attached), &(info.NumberOfAttachedNodes),
1206 1209 sizeof (rnid.num_attached));
1207 1210 memcpy(&(rnid.ip_version), &(info.IPVersion), sizeof (rnid.ip_version));
1208 1211 memcpy(&(rnid.udp_port), &(info.UDPPort), sizeof (rnid.udp_port));
1209 1212 memcpy(&(rnid.ip_addr), &info.IPAddress, sizeof (rnid.ip_addr));
1210 1213 memcpy(&(rnid.topo_flags), &(info.TopologyDiscoveryFlags),
1211 1214 sizeof (rnid.topo_flags));
1212 1215
1213 1216 fp_ioctl(getPath(), FCIO_CMD, &fcio, O_NDELAY | O_RDONLY | O_EXCL);
1214 1217 }
1215 1218
1216 1219 void FCHBAPort::fp_ioctl(string path, int cmd, fcio_t *fcio, int openflag) {
1217 1220 Trace log("FCHBAPort::fp_ioctl with openflag");
1218 1221 char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
1219 1222 int fd = HBA::_open(path, openflag);
1220 1223 try {
1221 1224 int times = 0;
1222 1225 HBA::_ioctl(fd, cmd, (uchar_t *)fcio);
1223 1226 while (fcio->fcio_errno == FC_STATEC_BUSY) {
1224 1227 sleep(1);
1225 1228 HBA::_ioctl(fd, cmd, (uchar_t *)fcio);
1226 1229 if (times++ > 10) {
1227 1230 break;
1228 1231 }
1229 1232 }
1230 1233 close(fd);
1231 1234 if (fcio->fcio_errno) {
1232 1235 throw IOError("IOCTL transport failure");
1233 1236 }
1234 1237 } catch (...) {
1235 1238 close(fd);
1236 1239 transportError(fcio->fcio_errno, fcioErrorString);
1237 1240 log.genericIOError("ioctl (0x%x) failed. Transport: \"%s\"", cmd,
1238 1241 fcioErrorString);
1239 1242 switch (fcio->fcio_errno) {
1240 1243 case FC_BADWWN:
1241 1244 throw IllegalWWNException();
1242 1245 case FC_BADPORT:
1243 1246 throw IllegalWWNException();
1244 1247 case FC_OUTOFBOUNDS:
1245 1248 throw IllegalIndexException();
1246 1249 case FC_PBUSY:
1247 1250 case FC_FBUSY:
1248 1251 case FC_TRAN_BUSY:
1249 1252 case FC_STATEC_BUSY:
1250 1253 case FC_DEVICE_BUSY:
1251 1254 throw BusyException();
1252 1255 case FC_SUCCESS:
1253 1256 default:
1254 1257 throw;
1255 1258 }
1256 1259 }
1257 1260 }
1258 1261
1259 1262 void FCHBAPort::fp_ioctl(string path, int cmd, fcio_t *fcio) {
1260 1263 Trace log("FCHBAPort::fp_ioctl");
1261 1264 fp_ioctl(path, cmd, fcio, O_NDELAY | O_RDONLY);
1262 1265 }
1263 1266
1264 1267 void FCHBAPort::fcsm_ioctl(int cmd, fcio_t *fcio) {
1265 1268 // We use the same error handling as fp, so just re-use
1266 1269 fp_ioctl(FCSM_DRIVER_PATH, cmd, fcio);
1267 1270 }
|
↓ open down ↓ |
432 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX