Deleted Added
full compact
ctl.c (268690) ctl.c (268692)
1/*-
2 * Copyright (c) 2003-2009 Silicon Graphics International Corp.
3 * Copyright (c) 2012 The FreeBSD Foundation
4 * All rights reserved.
5 *
6 * Portions of this software were developed by Edward Tomasz Napierala
7 * under sponsorship from the FreeBSD Foundation.
8 *

--- 28 unchanged lines hidden (view full) ---

37 * CAM Target Layer, a SCSI device emulation subsystem.
38 *
39 * Author: Ken Merry <ken@FreeBSD.org>
40 */
41
42#define _CTL_C
43
44#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2003-2009 Silicon Graphics International Corp.
3 * Copyright (c) 2012 The FreeBSD Foundation
4 * All rights reserved.
5 *
6 * Portions of this software were developed by Edward Tomasz Napierala
7 * under sponsorship from the FreeBSD Foundation.
8 *

--- 28 unchanged lines hidden (view full) ---

37 * CAM Target Layer, a SCSI device emulation subsystem.
38 *
39 * Author: Ken Merry <ken@FreeBSD.org>
40 */
41
42#define _CTL_C
43
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD: stable/10/sys/cam/ctl/ctl.c 268690 2014-07-15 17:12:37Z mav $");
45__FBSDID("$FreeBSD: stable/10/sys/cam/ctl/ctl.c 268692 2014-07-15 17:14:53Z mav $");
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/kernel.h>
50#include <sys/types.h>
51#include <sys/kthread.h>
52#include <sys/bio.h>
53#include <sys/fcntl.h>

--- 1032 unchanged lines hidden (view full) ---

1086 ctl_pool_free(emergency_pool);
1087 ctl_pool_free(other_pool);
1088 return (error);
1089 }
1090 if (bootverbose)
1091 printf("ctl: CAM Target Layer loaded\n");
1092
1093 /*
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/kernel.h>
50#include <sys/types.h>
51#include <sys/kthread.h>
52#include <sys/bio.h>
53#include <sys/fcntl.h>

--- 1032 unchanged lines hidden (view full) ---

1086 ctl_pool_free(emergency_pool);
1087 ctl_pool_free(other_pool);
1088 return (error);
1089 }
1090 if (bootverbose)
1091 printf("ctl: CAM Target Layer loaded\n");
1092
1093 /*
1094 * Initialize the initiator and portname mappings
1095 */
1096 memset(softc->wwpn_iid, 0, sizeof(softc->wwpn_iid));
1097
1098 /*
1099 * Initialize the ioctl front end.
1100 */
1101 ctl_frontend_register(&ioctl_frontend);
1102 port = &softc->ioctl_info.port;
1103 port->frontend = &ioctl_frontend;
1104 sprintf(softc->ioctl_info.port_name, "ioctl");
1105 port->port_type = CTL_PORT_IOCTL;
1106 port->num_requested_ctl_io = 100;

--- 255 unchanged lines hidden (view full) ---

1362
1363 ioctl_info = (struct ctl_ioctl_info *)arg;
1364
1365 ioctl_info->flags &= ~CTL_IOCTL_FLAG_ENABLED;
1366}
1367
1368/*
1369 * Remove an initiator by port number and initiator ID.
1094 * Initialize the ioctl front end.
1095 */
1096 ctl_frontend_register(&ioctl_frontend);
1097 port = &softc->ioctl_info.port;
1098 port->frontend = &ioctl_frontend;
1099 sprintf(softc->ioctl_info.port_name, "ioctl");
1100 port->port_type = CTL_PORT_IOCTL;
1101 port->num_requested_ctl_io = 100;

--- 255 unchanged lines hidden (view full) ---

1357
1358 ioctl_info = (struct ctl_ioctl_info *)arg;
1359
1360 ioctl_info->flags &= ~CTL_IOCTL_FLAG_ENABLED;
1361}
1362
1363/*
1364 * Remove an initiator by port number and initiator ID.
1370 * Returns 0 for success, 1 for failure.
1365 * Returns 0 for success, -1 for failure.
1371 */
1372int
1366 */
1367int
1373ctl_remove_initiator(int32_t targ_port, uint32_t iid)
1368ctl_remove_initiator(struct ctl_port *port, int iid)
1374{
1369{
1375 struct ctl_softc *softc;
1370 struct ctl_softc *softc = control_softc;
1376
1371
1377 softc = control_softc;
1378
1379 mtx_assert(&softc->ctl_lock, MA_NOTOWNED);
1380
1372 mtx_assert(&softc->ctl_lock, MA_NOTOWNED);
1373
1381 if ((targ_port < 0)
1382 || (targ_port > CTL_MAX_PORTS)) {
1383 printf("%s: invalid port number %d\n", __func__, targ_port);
1384 return (1);
1385 }
1386 if (iid > CTL_MAX_INIT_PER_PORT) {
1387 printf("%s: initiator ID %u > maximun %u!\n",
1388 __func__, iid, CTL_MAX_INIT_PER_PORT);
1374 if (iid > CTL_MAX_INIT_PER_PORT) {
1375 printf("%s: initiator ID %u > maximun %u!\n",
1376 __func__, iid, CTL_MAX_INIT_PER_PORT);
1389 return (1);
1377 return (-1);
1390 }
1391
1392 mtx_lock(&softc->ctl_lock);
1378 }
1379
1380 mtx_lock(&softc->ctl_lock);
1393
1394 softc->wwpn_iid[targ_port][iid].in_use = 0;
1395
1381 port->wwpn_iid[iid].in_use--;
1382 port->wwpn_iid[iid].last_use = time_uptime;
1396 mtx_unlock(&softc->ctl_lock);
1397
1398 return (0);
1399}
1400
1401/*
1402 * Add an initiator to the initiator map.
1383 mtx_unlock(&softc->ctl_lock);
1384
1385 return (0);
1386}
1387
1388/*
1389 * Add an initiator to the initiator map.
1403 * Returns 0 for success, 1 for failure.
1390 * Returns iid for success, < 0 for failure.
1404 */
1405int
1391 */
1392int
1406ctl_add_initiator(uint64_t wwpn, int32_t targ_port, uint32_t iid)
1393ctl_add_initiator(struct ctl_port *port, int iid, uint64_t wwpn, char *name)
1407{
1394{
1408 struct ctl_softc *softc;
1409 int retval;
1395 struct ctl_softc *softc = control_softc;
1396 time_t best_time;
1397 int i, best;
1410
1398
1411 softc = control_softc;
1412
1413 mtx_assert(&softc->ctl_lock, MA_NOTOWNED);
1414
1399 mtx_assert(&softc->ctl_lock, MA_NOTOWNED);
1400
1415 retval = 0;
1416
1417 if ((targ_port < 0)
1418 || (targ_port > CTL_MAX_PORTS)) {
1419 printf("%s: invalid port number %d\n", __func__, targ_port);
1420 return (1);
1421 }
1422 if (iid > CTL_MAX_INIT_PER_PORT) {
1423 printf("%s: WWPN %#jx initiator ID %u > maximun %u!\n",
1401 if (iid >= CTL_MAX_INIT_PER_PORT) {
1402 printf("%s: WWPN %#jx initiator ID %u > maximum %u!\n",
1424 __func__, wwpn, iid, CTL_MAX_INIT_PER_PORT);
1403 __func__, wwpn, iid, CTL_MAX_INIT_PER_PORT);
1425 return (1);
1404 free(name, M_CTL);
1405 return (-1);
1426 }
1427
1428 mtx_lock(&softc->ctl_lock);
1429
1406 }
1407
1408 mtx_lock(&softc->ctl_lock);
1409
1430 if (softc->wwpn_iid[targ_port][iid].in_use != 0) {
1410 if (iid < 0 && (wwpn != 0 || name != NULL)) {
1411 for (i = 0; i < CTL_MAX_INIT_PER_PORT; i++) {
1412 if (wwpn != 0 && wwpn == port->wwpn_iid[i].wwpn) {
1413 iid = i;
1414 break;
1415 }
1416 if (name != NULL && port->wwpn_iid[i].name != NULL &&
1417 strcmp(name, port->wwpn_iid[i].name) == 0) {
1418 iid = i;
1419 break;
1420 }
1421 }
1422 }
1423
1424 if (iid < 0) {
1425 for (i = 0; i < CTL_MAX_INIT_PER_PORT; i++) {
1426 if (port->wwpn_iid[i].in_use == 0 &&
1427 port->wwpn_iid[i].wwpn == 0 &&
1428 port->wwpn_iid[i].name == NULL) {
1429 iid = i;
1430 break;
1431 }
1432 }
1433 }
1434
1435 if (iid < 0) {
1436 best = -1;
1437 best_time = INT32_MAX;
1438 for (i = 0; i < CTL_MAX_INIT_PER_PORT; i++) {
1439 if (port->wwpn_iid[i].in_use == 0) {
1440 if (port->wwpn_iid[i].last_use < best_time) {
1441 best = i;
1442 best_time = port->wwpn_iid[i].last_use;
1443 }
1444 }
1445 }
1446 iid = best;
1447 }
1448
1449 if (iid < 0) {
1450 mtx_unlock(&softc->ctl_lock);
1451 free(name, M_CTL);
1452 return (-2);
1453 }
1454
1455 if (port->wwpn_iid[iid].in_use > 0 && (wwpn != 0 || name != NULL)) {
1431 /*
1456 /*
1432 * We don't treat this as an error.
1457 * This is not an error yet.
1433 */
1458 */
1434 if (softc->wwpn_iid[targ_port][iid].wwpn == wwpn) {
1435 printf("%s: port %d iid %u WWPN %#jx arrived again?\n",
1436 __func__, targ_port, iid, (uintmax_t)wwpn);
1437 goto bailout;
1459 if (wwpn != 0 && wwpn == port->wwpn_iid[iid].wwpn) {
1460#if 0
1461 printf("%s: port %d iid %u WWPN %#jx arrived"
1462 " again\n", __func__, port->targ_port,
1463 iid, (uintmax_t)wwpn);
1464#endif
1465 goto take;
1438 }
1466 }
1467 if (name != NULL && port->wwpn_iid[iid].name != NULL &&
1468 strcmp(name, port->wwpn_iid[iid].name) == 0) {
1469#if 0
1470 printf("%s: port %d iid %u name '%s' arrived"
1471 " again\n", __func__, port->targ_port,
1472 iid, name);
1473#endif
1474 goto take;
1475 }
1439
1440 /*
1441 * This is an error, but what do we do about it? The
1442 * driver is telling us we have a new WWPN for this
1443 * initiator ID, so we pretty much need to use it.
1444 */
1476
1477 /*
1478 * This is an error, but what do we do about it? The
1479 * driver is telling us we have a new WWPN for this
1480 * initiator ID, so we pretty much need to use it.
1481 */
1445 printf("%s: port %d iid %u WWPN %#jx arrived, WWPN %#jx is "
1446 "still at that address\n", __func__, targ_port, iid,
1447 (uintmax_t)wwpn,
1448 (uintmax_t)softc->wwpn_iid[targ_port][iid].wwpn);
1482 printf("%s: port %d iid %u WWPN %#jx '%s' arrived,"
1483 " but WWPN %#jx '%s' is still at that address\n",
1484 __func__, port->targ_port, iid, wwpn, name,
1485 (uintmax_t)port->wwpn_iid[iid].wwpn,
1486 port->wwpn_iid[iid].name);
1449
1450 /*
1451 * XXX KDM clear have_ca and ua_pending on each LUN for
1452 * this initiator.
1453 */
1454 }
1487
1488 /*
1489 * XXX KDM clear have_ca and ua_pending on each LUN for
1490 * this initiator.
1491 */
1492 }
1455 softc->wwpn_iid[targ_port][iid].in_use = 1;
1456 softc->wwpn_iid[targ_port][iid].iid = iid;
1457 softc->wwpn_iid[targ_port][iid].wwpn = wwpn;
1458 softc->wwpn_iid[targ_port][iid].port = targ_port;
1459
1460bailout:
1461
1493take:
1494 free(port->wwpn_iid[iid].name, M_CTL);
1495 port->wwpn_iid[iid].name = name;
1496 port->wwpn_iid[iid].wwpn = wwpn;
1497 port->wwpn_iid[iid].in_use++;
1462 mtx_unlock(&softc->ctl_lock);
1463
1498 mtx_unlock(&softc->ctl_lock);
1499
1464 return (retval);
1500 return (iid);
1465}
1466
1467static int
1468ctl_ioctl_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
1469{
1470 return (0);
1471}
1472

--- 1396 unchanged lines hidden (view full) ---

2869 "error serial %ju on LUN %u\n", __func__,
2870 delete_desc->serial, delete_desc->lun_id);
2871 retval = EINVAL;
2872 break;
2873 }
2874 break;
2875 }
2876 case CTL_DUMP_STRUCTS: {
1501}
1502
1503static int
1504ctl_ioctl_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
1505{
1506 return (0);
1507}
1508

--- 1396 unchanged lines hidden (view full) ---

2905 "error serial %ju on LUN %u\n", __func__,
2906 delete_desc->serial, delete_desc->lun_id);
2907 retval = EINVAL;
2908 break;
2909 }
2910 break;
2911 }
2912 case CTL_DUMP_STRUCTS: {
2877 int i, j, k;
2913 int i, j, k, idx;
2878 struct ctl_port *port;
2879 struct ctl_frontend *fe;
2880
2914 struct ctl_port *port;
2915 struct ctl_frontend *fe;
2916
2881 printf("CTL IID to WWPN map start:\n");
2882 for (i = 0; i < CTL_MAX_PORTS; i++) {
2883 for (j = 0; j < CTL_MAX_INIT_PER_PORT; j++) {
2884 if (softc->wwpn_iid[i][j].in_use == 0)
2885 continue;
2886
2887 printf("port %d iid %u WWPN %#jx\n",
2888 softc->wwpn_iid[i][j].port,
2889 softc->wwpn_iid[i][j].iid,
2890 (uintmax_t)softc->wwpn_iid[i][j].wwpn);
2891 }
2892 }
2893 printf("CTL IID to WWPN map end\n");
2917 mtx_lock(&softc->ctl_lock);
2894 printf("CTL Persistent Reservation information start:\n");
2895 for (i = 0; i < CTL_MAX_LUNS; i++) {
2896 struct ctl_lun *lun;
2897
2898 lun = softc->ctl_luns[i];
2899
2900 if ((lun == NULL)
2901 || ((lun->flags & CTL_LUN_DISABLED) != 0))
2902 continue;
2903
2904 for (j = 0; j < (CTL_MAX_PORTS * 2); j++) {
2905 for (k = 0; k < CTL_MAX_INIT_PER_PORT; k++){
2918 printf("CTL Persistent Reservation information start:\n");
2919 for (i = 0; i < CTL_MAX_LUNS; i++) {
2920 struct ctl_lun *lun;
2921
2922 lun = softc->ctl_luns[i];
2923
2924 if ((lun == NULL)
2925 || ((lun->flags & CTL_LUN_DISABLED) != 0))
2926 continue;
2927
2928 for (j = 0; j < (CTL_MAX_PORTS * 2); j++) {
2929 for (k = 0; k < CTL_MAX_INIT_PER_PORT; k++){
2906 if (lun->per_res[j+k].registered == 0)
2930 idx = j * CTL_MAX_INIT_PER_PORT + k;
2931 if (lun->per_res[idx].registered == 0)
2907 continue;
2932 continue;
2908 printf("LUN %d port %d iid %d key "
2933 printf(" LUN %d port %d iid %d key "
2909 "%#jx\n", i, j, k,
2910 (uintmax_t)scsi_8btou64(
2934 "%#jx\n", i, j, k,
2935 (uintmax_t)scsi_8btou64(
2911 lun->per_res[j+k].res_key.key));
2936 lun->per_res[idx].res_key.key));
2912 }
2913 }
2914 }
2915 printf("CTL Persistent Reservation information end\n");
2916 printf("CTL Ports:\n");
2937 }
2938 }
2939 }
2940 printf("CTL Persistent Reservation information end\n");
2941 printf("CTL Ports:\n");
2917 /*
2918 * XXX KDM calling this without a lock. We'd likely want
2919 * to drop the lock before calling the frontend's dump
2920 * routine anyway.
2921 */
2922 STAILQ_FOREACH(port, &softc->port_list, links) {
2942 STAILQ_FOREACH(port, &softc->port_list, links) {
2923 printf("Port %s Frontend %s Type %u pport %d vport %d WWNN "
2924 "%#jx WWPN %#jx\n", port->port_name,
2943 printf(" Port %d '%s' Frontend '%s' Type %u pp %d vp %d WWNN "
2944 "%#jx WWPN %#jx\n", port->targ_port, port->port_name,
2925 port->frontend->name, port->port_type,
2926 port->physical_port, port->virtual_port,
2927 (uintmax_t)port->wwnn, (uintmax_t)port->wwpn);
2945 port->frontend->name, port->port_type,
2946 port->physical_port, port->virtual_port,
2947 (uintmax_t)port->wwnn, (uintmax_t)port->wwpn);
2948 for (j = 0; j < CTL_MAX_INIT_PER_PORT; j++) {
2949 if (port->wwpn_iid[j].in_use == 0 &&
2950 port->wwpn_iid[j].wwpn == 0 &&
2951 port->wwpn_iid[j].name == NULL)
2952 continue;
2953
2954 printf(" iid %u use %d WWPN %#jx '%s'\n",
2955 j, port->wwpn_iid[j].in_use,
2956 (uintmax_t)port->wwpn_iid[j].wwpn,
2957 port->wwpn_iid[j].name);
2958 }
2928 }
2929 printf("CTL Port information end\n");
2959 }
2960 printf("CTL Port information end\n");
2961 mtx_unlock(&softc->ctl_lock);
2962 /*
2963 * XXX KDM calling this without a lock. We'd likely want
2964 * to drop the lock before calling the frontend's dump
2965 * routine anyway.
2966 */
2930 printf("CTL Frontends:\n");
2931 STAILQ_FOREACH(fe, &softc->fe_list, links) {
2967 printf("CTL Frontends:\n");
2968 STAILQ_FOREACH(fe, &softc->fe_list, links) {
2932 printf("Frontend %s\n", fe->name);
2969 printf(" Frontend '%s'\n", fe->name);
2933 if (fe->fe_dump != NULL)
2934 fe->fe_dump();
2935 }
2936 printf("CTL Frontend information end\n");
2937 break;
2938 }
2939 case CTL_LUN_REQ: {
2940 struct ctl_lun_req *lun_req;

--- 10992 unchanged lines hidden ---
2970 if (fe->fe_dump != NULL)
2971 fe->fe_dump();
2972 }
2973 printf("CTL Frontend information end\n");
2974 break;
2975 }
2976 case CTL_LUN_REQ: {
2977 struct ctl_lun_req *lun_req;

--- 10992 unchanged lines hidden ---