Do not pre-allocate reservation keys memory for every possible initiator.
In configurations with many ports, like iSCSI, each LUN is typically accessed only by limited subset of ports. Allocating that memory on demand allows to reduce CTL memory usage from 5.3MB/LUN to 1.3MB/LUN. MFC after: 1 month
This commit is contained in:
parent
2a72b5936d
commit
411598df7a
@ -3036,7 +3036,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
break;
|
||||
}
|
||||
case CTL_DUMP_STRUCTS: {
|
||||
int i, j, k, idx;
|
||||
int i, j, k;
|
||||
struct ctl_port *port;
|
||||
struct ctl_frontend *fe;
|
||||
|
||||
@ -3052,13 +3052,14 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
continue;
|
||||
|
||||
for (j = 0; j < (CTL_MAX_PORTS * 2); j++) {
|
||||
if (lun->pr_keys[j] == NULL)
|
||||
continue;
|
||||
for (k = 0; k < CTL_MAX_INIT_PER_PORT; k++){
|
||||
idx = j * CTL_MAX_INIT_PER_PORT + k;
|
||||
if (lun->pr_keys[idx] == 0)
|
||||
if (lun->pr_keys[j][k] == 0)
|
||||
continue;
|
||||
printf(" LUN %d port %d iid %d key "
|
||||
"%#jx\n", i, j, k,
|
||||
(uintmax_t)lun->pr_keys[idx]);
|
||||
(uintmax_t)lun->pr_keys[j][k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3647,6 +3648,57 @@ ctl_is_set(uint32_t *mask, uint32_t bit)
|
||||
return (1);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
ctl_get_prkey(struct ctl_lun *lun, uint32_t residx)
|
||||
{
|
||||
uint64_t *t;
|
||||
|
||||
t = lun->pr_keys[residx/CTL_MAX_INIT_PER_PORT];
|
||||
if (t == NULL)
|
||||
return (0);
|
||||
return (t[residx % CTL_MAX_INIT_PER_PORT]);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_clr_prkey(struct ctl_lun *lun, uint32_t residx)
|
||||
{
|
||||
uint64_t *t;
|
||||
|
||||
t = lun->pr_keys[residx/CTL_MAX_INIT_PER_PORT];
|
||||
if (t == NULL)
|
||||
return;
|
||||
t[residx % CTL_MAX_INIT_PER_PORT] = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_alloc_prkey(struct ctl_lun *lun, uint32_t residx)
|
||||
{
|
||||
uint64_t *p;
|
||||
u_int i;
|
||||
|
||||
i = residx/CTL_MAX_INIT_PER_PORT;
|
||||
if (lun->pr_keys[i] != NULL)
|
||||
return;
|
||||
mtx_unlock(&lun->lun_lock);
|
||||
p = malloc(sizeof(uint64_t) * CTL_MAX_INIT_PER_PORT, M_CTL,
|
||||
M_WAITOK | M_ZERO);
|
||||
mtx_lock(&lun->lun_lock);
|
||||
if (lun->pr_keys[i] == NULL)
|
||||
lun->pr_keys[i] = p;
|
||||
else
|
||||
free(p, M_CTL);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_set_prkey(struct ctl_lun *lun, uint32_t residx, uint64_t key)
|
||||
{
|
||||
uint64_t *t;
|
||||
|
||||
t = lun->pr_keys[residx/CTL_MAX_INIT_PER_PORT];
|
||||
KASSERT(t != NULL, ("prkey %d is not allocated", residx));
|
||||
t[residx % CTL_MAX_INIT_PER_PORT] = key;
|
||||
}
|
||||
|
||||
#ifdef unused
|
||||
/*
|
||||
* The bus, target and lun are optional, they can be filled in later.
|
||||
@ -4685,6 +4737,10 @@ ctl_free_lun(struct ctl_lun *lun)
|
||||
ctl_tpc_lun_shutdown(lun);
|
||||
mtx_destroy(&lun->lun_lock);
|
||||
free(lun->lun_devid, M_CTL);
|
||||
for (i = 0; i < 2 * CTL_MAX_PORTS; i++) {
|
||||
if (lun->pr_keys[i] != NULL)
|
||||
free(lun->pr_keys[i], M_CTL);
|
||||
}
|
||||
free(lun->write_buffer, M_CTL);
|
||||
if (lun->flags & CTL_LUN_MALLOCED)
|
||||
free(lun, M_CTL);
|
||||
@ -5345,7 +5401,7 @@ ctl_start_stop(struct ctl_scsiio *ctsio)
|
||||
uint32_t residx;
|
||||
|
||||
residx = ctl_get_resindex(&ctsio->io_hdr.nexus);
|
||||
if (lun->pr_keys[residx] == 0
|
||||
if (ctl_get_prkey(lun, residx) == 0
|
||||
|| (lun->pr_res_idx!=residx && lun->res_type < 4)) {
|
||||
|
||||
ctl_set_reservation_conflict(ctsio);
|
||||
@ -7613,6 +7669,7 @@ ctl_persistent_reserve_in(struct ctl_scsiio *ctsio)
|
||||
/* struct scsi_per_res_in_rsrv in_data; */
|
||||
struct ctl_lun *lun;
|
||||
struct ctl_softc *softc;
|
||||
uint64_t key;
|
||||
|
||||
CTL_DEBUG_PRINT(("ctl_persistent_reserve_in\n"));
|
||||
|
||||
@ -7698,7 +7755,7 @@ ctl_persistent_reserve_in(struct ctl_scsiio *ctsio)
|
||||
lun->pr_key_count, res_keys->header.length);
|
||||
|
||||
for (i = 0, key_count = 0; i < 2*CTL_MAX_INITIATORS; i++) {
|
||||
if (lun->pr_keys[i] == 0)
|
||||
if ((key = ctl_get_prkey(lun, i)) == 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
@ -7724,8 +7781,7 @@ ctl_persistent_reserve_in(struct ctl_scsiio *ctsio)
|
||||
key_count++;
|
||||
continue;
|
||||
}
|
||||
scsi_u64to8b(lun->pr_keys[i],
|
||||
res_keys->keys[key_count].key);
|
||||
scsi_u64to8b(key, res_keys->keys[key_count].key);
|
||||
key_count++;
|
||||
}
|
||||
break;
|
||||
@ -7776,7 +7832,7 @@ ctl_persistent_reserve_in(struct ctl_scsiio *ctsio)
|
||||
* is 0, since it doesn't really matter.
|
||||
*/
|
||||
if (lun->pr_res_idx != CTL_PR_ALL_REGISTRANTS) {
|
||||
scsi_u64to8b(lun->pr_keys[lun->pr_res_idx],
|
||||
scsi_u64to8b(ctl_get_prkey(lun, lun->pr_res_idx),
|
||||
res->data.reservation);
|
||||
}
|
||||
res->data.scopetype = lun->res_type;
|
||||
@ -7828,10 +7884,10 @@ ctl_persistent_reserve_in(struct ctl_scsiio *ctsio)
|
||||
|
||||
res_desc = &res_status->desc[0];
|
||||
for (i = 0; i < 2*CTL_MAX_INITIATORS; i++) {
|
||||
if (lun->pr_keys[i] == 0)
|
||||
if ((key = ctl_get_prkey(lun, i)) == 0)
|
||||
continue;
|
||||
|
||||
scsi_u64to8b(lun->pr_keys[i], res_desc->res_key.key);
|
||||
scsi_u64to8b(key, res_desc->res_key.key);
|
||||
if ((lun->flags & CTL_LUN_PR_RESERVED) &&
|
||||
(lun->pr_res_idx == i ||
|
||||
lun->pr_res_idx == CTL_PR_ALL_REGISTRANTS)) {
|
||||
@ -7931,10 +7987,10 @@ ctl_pro_preempt(struct ctl_softc *softc, struct ctl_lun *lun, uint64_t res_key,
|
||||
* them
|
||||
*/
|
||||
for(i=0; i < 2*CTL_MAX_INITIATORS; i++) {
|
||||
if (i == residx || lun->pr_keys[i] == 0)
|
||||
if (i == residx || ctl_get_prkey(lun, i) == 0)
|
||||
continue;
|
||||
|
||||
lun->pr_keys[i] = 0;
|
||||
ctl_clr_prkey(lun, i);
|
||||
ctl_set_res_ua(lun, i, CTL_UA_REG_PREEMPT);
|
||||
}
|
||||
lun->pr_key_count = 1;
|
||||
@ -8000,11 +8056,11 @@ ctl_pro_preempt(struct ctl_softc *softc, struct ctl_lun *lun, uint64_t res_key,
|
||||
}
|
||||
|
||||
for (i=0; i < 2*CTL_MAX_INITIATORS; i++) {
|
||||
if (lun->pr_keys[i] != sa_res_key)
|
||||
if (ctl_get_prkey(lun, i) != sa_res_key)
|
||||
continue;
|
||||
|
||||
found = 1;
|
||||
lun->pr_keys[i] = 0;
|
||||
ctl_clr_prkey(lun, i);
|
||||
lun->pr_key_count--;
|
||||
ctl_set_res_ua(lun, i, CTL_UA_REG_PREEMPT);
|
||||
}
|
||||
@ -8033,7 +8089,7 @@ ctl_pro_preempt(struct ctl_softc *softc, struct ctl_lun *lun, uint64_t res_key,
|
||||
} else {
|
||||
/* Reserved but not all registrants */
|
||||
/* sa_res_key is res holder */
|
||||
if (sa_res_key == lun->pr_keys[lun->pr_res_idx]) {
|
||||
if (sa_res_key == ctl_get_prkey(lun, lun->pr_res_idx)) {
|
||||
/* validate scope and type */
|
||||
if ((cdb->scope_type & SPR_SCOPE_MASK) !=
|
||||
SPR_LU_SCOPE) {
|
||||
@ -8075,11 +8131,11 @@ ctl_pro_preempt(struct ctl_softc *softc, struct ctl_lun *lun, uint64_t res_key,
|
||||
*/
|
||||
|
||||
for(i=0; i < 2*CTL_MAX_INITIATORS; i++) {
|
||||
if (i == residx || lun->pr_keys[i] == 0)
|
||||
if (i == residx || ctl_get_prkey(lun, i) == 0)
|
||||
continue;
|
||||
|
||||
if (sa_res_key == lun->pr_keys[i]) {
|
||||
lun->pr_keys[i] = 0;
|
||||
if (sa_res_key == ctl_get_prkey(lun, i)) {
|
||||
ctl_clr_prkey(lun, i);
|
||||
lun->pr_key_count--;
|
||||
ctl_set_res_ua(lun, i, CTL_UA_REG_PREEMPT);
|
||||
} else if (type != lun->res_type
|
||||
@ -8118,11 +8174,11 @@ ctl_pro_preempt(struct ctl_softc *softc, struct ctl_lun *lun, uint64_t res_key,
|
||||
int found=0;
|
||||
|
||||
for (i=0; i < 2*CTL_MAX_INITIATORS; i++) {
|
||||
if (sa_res_key != lun->pr_keys[i])
|
||||
if (sa_res_key != ctl_get_prkey(lun, i))
|
||||
continue;
|
||||
|
||||
found = 1;
|
||||
lun->pr_keys[i] = 0;
|
||||
ctl_clr_prkey(lun, i);
|
||||
lun->pr_key_count--;
|
||||
ctl_set_res_ua(lun, i, CTL_UA_REG_PREEMPT);
|
||||
}
|
||||
@ -8168,7 +8224,7 @@ ctl_pro_preempt_other(struct ctl_lun *lun, union ctl_ha_msg *msg)
|
||||
|
||||
if (lun->pr_res_idx == CTL_PR_ALL_REGISTRANTS
|
||||
|| lun->pr_res_idx == CTL_PR_NO_RESERVATION
|
||||
|| sa_res_key != lun->pr_keys[lun->pr_res_idx]) {
|
||||
|| sa_res_key != ctl_get_prkey(lun, lun->pr_res_idx)) {
|
||||
if (sa_res_key == 0) {
|
||||
/*
|
||||
* Unregister everybody else and build UA for
|
||||
@ -8176,10 +8232,10 @@ ctl_pro_preempt_other(struct ctl_lun *lun, union ctl_ha_msg *msg)
|
||||
*/
|
||||
for(i=0; i < 2*CTL_MAX_INITIATORS; i++) {
|
||||
if (i == msg->pr.pr_info.residx ||
|
||||
lun->pr_keys[i] == 0)
|
||||
ctl_get_prkey(lun, i) == 0)
|
||||
continue;
|
||||
|
||||
lun->pr_keys[i] = 0;
|
||||
ctl_clr_prkey(lun, i);
|
||||
ctl_set_res_ua(lun, i, CTL_UA_REG_PREEMPT);
|
||||
}
|
||||
|
||||
@ -8190,10 +8246,10 @@ ctl_pro_preempt_other(struct ctl_lun *lun, union ctl_ha_msg *msg)
|
||||
lun->pr_res_idx = msg->pr.pr_info.residx;
|
||||
} else {
|
||||
for (i=0; i < 2*CTL_MAX_INITIATORS; i++) {
|
||||
if (sa_res_key == lun->pr_keys[i])
|
||||
if (sa_res_key == ctl_get_prkey(lun, i))
|
||||
continue;
|
||||
|
||||
lun->pr_keys[i] = 0;
|
||||
ctl_clr_prkey(lun, i);
|
||||
lun->pr_key_count--;
|
||||
ctl_set_res_ua(lun, i, CTL_UA_REG_PREEMPT);
|
||||
}
|
||||
@ -8201,11 +8257,11 @@ ctl_pro_preempt_other(struct ctl_lun *lun, union ctl_ha_msg *msg)
|
||||
} else {
|
||||
for (i=0; i < 2*CTL_MAX_INITIATORS; i++) {
|
||||
if (i == msg->pr.pr_info.residx ||
|
||||
lun->pr_keys[i] == 0)
|
||||
ctl_get_prkey(lun, i) == 0)
|
||||
continue;
|
||||
|
||||
if (sa_res_key == lun->pr_keys[i]) {
|
||||
lun->pr_keys[i] = 0;
|
||||
if (sa_res_key == ctl_get_prkey(lun, i)) {
|
||||
ctl_clr_prkey(lun, i);
|
||||
lun->pr_key_count--;
|
||||
ctl_set_res_ua(lun, i, CTL_UA_REG_PREEMPT);
|
||||
} else if (msg->pr.pr_info.res_type != lun->res_type
|
||||
@ -8237,7 +8293,7 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
|
||||
struct scsi_per_res_out_parms* param;
|
||||
struct ctl_softc *softc;
|
||||
uint32_t residx;
|
||||
uint64_t res_key, sa_res_key;
|
||||
uint64_t res_key, sa_res_key, key;
|
||||
uint8_t type;
|
||||
union ctl_ha_msg persis_io;
|
||||
int i;
|
||||
@ -8311,8 +8367,8 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
|
||||
*/
|
||||
if ((cdb->action & SPRO_ACTION_MASK) != SPRO_REG_IGNO) {
|
||||
mtx_lock(&lun->lun_lock);
|
||||
if (lun->pr_keys[residx] != 0) {
|
||||
if (res_key != lun->pr_keys[residx]) {
|
||||
if ((key = ctl_get_prkey(lun, residx)) != 0) {
|
||||
if (res_key != key) {
|
||||
/*
|
||||
* The current key passed in doesn't match
|
||||
* the one the initiator previously
|
||||
@ -8393,12 +8449,12 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
|
||||
if ((res_key == 0
|
||||
&& (cdb->action & SPRO_ACTION_MASK) == SPRO_REGISTER)
|
||||
|| ((cdb->action & SPRO_ACTION_MASK) == SPRO_REG_IGNO
|
||||
&& lun->pr_keys[residx] == 0)) {
|
||||
&& ctl_get_prkey(lun, residx) == 0)) {
|
||||
mtx_unlock(&lun->lun_lock);
|
||||
goto done;
|
||||
}
|
||||
|
||||
lun->pr_keys[residx] = 0;
|
||||
ctl_clr_prkey(lun, residx);
|
||||
lun->pr_key_count--;
|
||||
|
||||
if (residx == lun->pr_res_idx) {
|
||||
@ -8417,8 +8473,8 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
|
||||
*/
|
||||
|
||||
for (i = 0; i < CTL_MAX_INITIATORS;i++){
|
||||
if (lun->pr_keys[i +
|
||||
softc->persis_offset] == 0)
|
||||
if (ctl_get_prkey(lun, i +
|
||||
softc->persis_offset) == 0)
|
||||
continue;
|
||||
lun->pending_ua[i] |=
|
||||
CTL_UA_RES_RELEASE;
|
||||
@ -8448,9 +8504,10 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
|
||||
* If we aren't registered currently then increment
|
||||
* the key count and set the registered flag.
|
||||
*/
|
||||
if (lun->pr_keys[residx] == 0)
|
||||
ctl_alloc_prkey(lun, residx);
|
||||
if (ctl_get_prkey(lun, residx) == 0)
|
||||
lun->pr_key_count++;
|
||||
lun->pr_keys[residx] = sa_res_key;
|
||||
ctl_set_prkey(lun, residx, sa_res_key);
|
||||
|
||||
persis_io.hdr.nexus = ctsio->io_hdr.nexus;
|
||||
persis_io.hdr.msg_type = CTL_MSG_PERS_ACTION;
|
||||
@ -8565,7 +8622,8 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
|
||||
&& type != SPR_TYPE_WR_EX) {
|
||||
for (i = 0; i < CTL_MAX_INITIATORS; i++) {
|
||||
if (i == residx ||
|
||||
lun->pr_keys[i + softc->persis_offset] == 0)
|
||||
ctl_get_prkey(lun,
|
||||
i + softc->persis_offset) == 0)
|
||||
continue;
|
||||
lun->pending_ua[i] |= CTL_UA_RES_RELEASE;
|
||||
}
|
||||
@ -8591,11 +8649,10 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
|
||||
lun->pr_key_count = 0;
|
||||
lun->pr_res_idx = CTL_PR_NO_RESERVATION;
|
||||
|
||||
lun->pr_keys[residx] = 0;
|
||||
|
||||
ctl_clr_prkey(lun, residx);
|
||||
for (i=0; i < 2*CTL_MAX_INITIATORS; i++)
|
||||
if (lun->pr_keys[i] != 0) {
|
||||
lun->pr_keys[i] = 0;
|
||||
if (ctl_get_prkey(lun, i) != 0) {
|
||||
ctl_clr_prkey(lun, i);
|
||||
ctl_set_res_ua(lun, i, CTL_UA_REG_PREEMPT);
|
||||
}
|
||||
lun->PRGeneration++;
|
||||
@ -8653,15 +8710,16 @@ ctl_hndl_per_res_out_on_other_sc(union ctl_ha_msg *msg)
|
||||
mtx_lock(&lun->lun_lock);
|
||||
switch(msg->pr.pr_info.action) {
|
||||
case CTL_PR_REG_KEY:
|
||||
if (lun->pr_keys[msg->pr.pr_info.residx] == 0)
|
||||
ctl_alloc_prkey(lun, msg->pr.pr_info.residx);
|
||||
if (ctl_get_prkey(lun, msg->pr.pr_info.residx) == 0)
|
||||
lun->pr_key_count++;
|
||||
lun->pr_keys[msg->pr.pr_info.residx] =
|
||||
scsi_8btou64(msg->pr.pr_info.sa_res_key);
|
||||
ctl_set_prkey(lun, msg->pr.pr_info.residx,
|
||||
scsi_8btou64(msg->pr.pr_info.sa_res_key));
|
||||
lun->PRGeneration++;
|
||||
break;
|
||||
|
||||
case CTL_PR_UNREG_KEY:
|
||||
lun->pr_keys[msg->pr.pr_info.residx] = 0;
|
||||
ctl_clr_prkey(lun, msg->pr.pr_info.residx);
|
||||
lun->pr_key_count--;
|
||||
|
||||
/* XXX Need to see if the reservation has been released */
|
||||
@ -8682,8 +8740,8 @@ ctl_hndl_per_res_out_on_other_sc(union ctl_ha_msg *msg)
|
||||
*/
|
||||
|
||||
for (i = 0; i < CTL_MAX_INITIATORS; i++) {
|
||||
if (lun->pr_keys[i +
|
||||
softc->persis_offset] == 0)
|
||||
if (ctl_get_prkey(lun, i +
|
||||
softc->persis_offset) == 0)
|
||||
continue;
|
||||
|
||||
lun->pending_ua[i] |=
|
||||
@ -8716,7 +8774,7 @@ ctl_hndl_per_res_out_on_other_sc(union ctl_ha_msg *msg)
|
||||
if (lun->res_type != SPR_TYPE_EX_AC
|
||||
&& lun->res_type != SPR_TYPE_WR_EX) {
|
||||
for (i = 0; i < CTL_MAX_INITIATORS; i++)
|
||||
if (lun->pr_keys[i + softc->persis_offset] != 0)
|
||||
if (ctl_get_prkey(lun, i + softc->persis_offset) != 0)
|
||||
lun->pending_ua[i] |=
|
||||
CTL_UA_RES_RELEASE;
|
||||
}
|
||||
@ -8736,9 +8794,9 @@ ctl_hndl_per_res_out_on_other_sc(union ctl_ha_msg *msg)
|
||||
lun->pr_res_idx = CTL_PR_NO_RESERVATION;
|
||||
|
||||
for (i=0; i < 2*CTL_MAX_INITIATORS; i++) {
|
||||
if (lun->pr_keys[i] == 0)
|
||||
if (ctl_get_prkey(lun, i) == 0)
|
||||
continue;
|
||||
lun->pr_keys[i] = 0;
|
||||
ctl_clr_prkey(lun, i);
|
||||
ctl_set_res_ua(lun, i, CTL_UA_REG_PREEMPT);
|
||||
}
|
||||
lun->PRGeneration++;
|
||||
@ -11049,7 +11107,7 @@ ctl_scsiio_lun_check(struct ctl_softc *ctl_softc, struct ctl_lun *lun,
|
||||
* reservation and this isn't the res holder then set a
|
||||
* conflict.
|
||||
*/
|
||||
if (lun->pr_keys[residx] == 0
|
||||
if (ctl_get_prkey(lun, residx) == 0
|
||||
|| (residx != lun->pr_res_idx && lun->res_type < 4)) {
|
||||
ctl_set_reservation_conflict(ctsio);
|
||||
retval = 1;
|
||||
|
@ -410,7 +410,7 @@ struct ctl_lun {
|
||||
struct ctl_lun_io_stats stats;
|
||||
uint32_t res_idx;
|
||||
unsigned int PRGeneration;
|
||||
uint64_t pr_keys[2*CTL_MAX_INITIATORS];
|
||||
uint64_t *pr_keys[2 * CTL_MAX_PORTS];
|
||||
int pr_key_count;
|
||||
uint32_t pr_res_idx;
|
||||
uint8_t res_type;
|
||||
|
Loading…
Reference in New Issue
Block a user