Store persistent reservation keys as uint64_t instead of uint8_t[8].

This allows to simplify the code and save 512KB of RAM per LUN (8%)
by removing no longer needed "registered" keys flags.
This commit is contained in:
Alexander Motin 2014-10-10 12:38:53 +00:00
parent ac2a1d3d71
commit 0ca2fdeca2
2 changed files with 61 additions and 151 deletions

View File

@ -2990,12 +2990,11 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
for (j = 0; j < (CTL_MAX_PORTS * 2); j++) {
for (k = 0; k < CTL_MAX_INIT_PER_PORT; k++){
idx = j * CTL_MAX_INIT_PER_PORT + k;
if (lun->per_res[idx].registered == 0)
if (lun->pr_keys[idx] == 0)
continue;
printf(" LUN %d port %d iid %d key "
"%#jx\n", i, j, k,
(uintmax_t)scsi_8btou64(
lun->per_res[idx].res_key.key));
(uintmax_t)lun->pr_keys[idx]);
}
}
}
@ -5536,7 +5535,7 @@ ctl_start_stop(struct ctl_scsiio *ctsio)
uint32_t residx;
residx = ctl_get_resindex(&ctsio->io_hdr.nexus);
if (!lun->per_res[residx].registered
if (lun->pr_keys[residx] == 0
|| (lun->pr_res_idx!=residx && lun->res_type < 4)) {
ctl_set_reservation_conflict(ctsio);
@ -5827,7 +5826,7 @@ ctl_read_buffer(struct ctl_scsiio *ctsio)
&& residx != lun->pr_res_idx)
|| ((lun->res_type == SPR_TYPE_EX_AC_RO
|| lun->res_type == SPR_TYPE_EX_AC_AR)
&& !lun->per_res[residx].registered)) {
&& lun->pr_keys[residx] == 0)) {
ctl_set_reservation_conflict(ctsio);
ctl_done((union ctl_io *)ctsio);
return (CTL_RETVAL_COMPLETE);
@ -6882,7 +6881,7 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
&& residx != lun->pr_res_idx)
|| ((lun->res_type == SPR_TYPE_EX_AC_RO
|| lun->res_type == SPR_TYPE_EX_AC_AR)
&& !lun->per_res[residx].registered)) {
&& lun->pr_keys[residx] == 0)) {
ctl_set_reservation_conflict(ctsio);
ctl_done((union ctl_io *)ctsio);
return (CTL_RETVAL_COMPLETE);
@ -7825,7 +7824,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->per_res[i].registered)
if (lun->pr_keys[i] == 0)
continue;
/*
@ -7851,10 +7850,8 @@ ctl_persistent_reserve_in(struct ctl_scsiio *ctsio)
key_count++;
continue;
}
memcpy(res_keys->keys[key_count].key,
lun->per_res[i].res_key.key,
ctl_min(sizeof(res_keys->keys[key_count].key),
sizeof(lun->per_res[i].res_key)));
scsi_u64to8b(lun->pr_keys[i],
res_keys->keys[key_count].key);
key_count++;
}
break;
@ -7905,9 +7902,8 @@ 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) {
memcpy(res->data.reservation,
&lun->per_res[lun->pr_res_idx].res_key,
sizeof(struct scsi_per_res_key));
scsi_u64to8b(lun->pr_keys[lun->pr_res_idx],
res->data.reservation);
}
res->data.scopetype = lun->res_type;
break;
@ -7958,11 +7954,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->per_res[i].registered)
if (lun->pr_keys[i] == 0)
continue;
memcpy(&res_desc->res_key, &lun->per_res[i].res_key.key,
sizeof(res_desc->res_key));
scsi_u64to8b(lun->pr_keys[i], 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)) {
@ -8055,15 +8050,12 @@ ctl_pro_preempt(struct ctl_softc *softc, struct ctl_lun *lun, uint64_t res_key,
return (1);
}
/* temporarily unregister this nexus */
lun->per_res[residx].registered = 0;
/*
* Unregister everybody else and build UA for
* them
*/
for(i=0; i < 2*CTL_MAX_INITIATORS; i++) {
if (lun->per_res[i].registered == 0)
if (i == residx || lun->pr_keys[i] == 0)
continue;
if (!persis_offset
@ -8074,11 +8066,8 @@ ctl_pro_preempt(struct ctl_softc *softc, struct ctl_lun *lun, uint64_t res_key,
&& i >= persis_offset)
lun->pending_ua[i-persis_offset] |=
CTL_UA_REG_PREEMPT;
lun->per_res[i].registered = 0;
memset(&lun->per_res[i].res_key, 0,
sizeof(struct scsi_per_res_key));
lun->pr_keys[i] = 0;
}
lun->per_res[residx].registered = 1;
lun->pr_key_count = 1;
lun->res_type = type;
if (lun->res_type != SPR_TYPE_WR_EX_AR
@ -8142,16 +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 (lun->per_res[i].registered
&& memcmp(param->serv_act_res_key,
lun->per_res[i].res_key.key,
sizeof(struct scsi_per_res_key)) != 0)
if (lun->pr_keys[i] != sa_res_key)
continue;
found = 1;
lun->per_res[i].registered = 0;
memset(&lun->per_res[i].res_key, 0,
sizeof(struct scsi_per_res_key));
lun->pr_keys[i] = 0;
lun->pr_key_count--;
if (!persis_offset && i < CTL_MAX_INITIATORS)
@ -8185,9 +8169,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 (memcmp(param->serv_act_res_key,
lun->per_res[lun->pr_res_idx].res_key.key,
sizeof(struct scsi_per_res_key)) == 0) {
if (sa_res_key == lun->pr_keys[lun->pr_res_idx]) {
/* validate scope and type */
if ((cdb->scope_type & SPR_SCOPE_MASK) !=
SPR_LU_SCOPE) {
@ -8228,22 +8210,12 @@ ctl_pro_preempt(struct ctl_softc *softc, struct ctl_lun *lun, uint64_t res_key,
* except don't unregister the res holder.
*/
/*
* Temporarily unregister so it won't get
* removed or UA generated
*/
lun->per_res[residx].registered = 0;
for(i=0; i < 2*CTL_MAX_INITIATORS; i++) {
if (lun->per_res[i].registered == 0)
if (i == residx || lun->pr_keys[i] == 0)
continue;
if (memcmp(param->serv_act_res_key,
lun->per_res[i].res_key.key,
sizeof(struct scsi_per_res_key)) == 0) {
lun->per_res[i].registered = 0;
memset(&lun->per_res[i].res_key,
0,
sizeof(struct scsi_per_res_key));
if (sa_res_key == lun->pr_keys[i]) {
lun->pr_keys[i] = 0;
lun->pr_key_count--;
if (!persis_offset
@ -8268,7 +8240,6 @@ ctl_pro_preempt(struct ctl_softc *softc, struct ctl_lun *lun, uint64_t res_key,
CTL_UA_RES_RELEASE;
}
}
lun->per_res[residx].registered = 1;
lun->res_type = type;
if (lun->res_type != SPR_TYPE_WR_EX_AR
&& lun->res_type != SPR_TYPE_EX_AC_AR)
@ -8299,15 +8270,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 (memcmp(param->serv_act_res_key,
lun->per_res[i].res_key.key,
sizeof(struct scsi_per_res_key)) != 0)
if (sa_res_key != lun->pr_keys[i])
continue;
found = 1;
lun->per_res[i].registered = 0;
memset(&lun->per_res[i].res_key, 0,
sizeof(struct scsi_per_res_key));
lun->pr_keys[i] = 0;
lun->pr_key_count--;
if (!persis_offset
@ -8354,26 +8321,22 @@ ctl_pro_preempt(struct ctl_softc *softc, struct ctl_lun *lun, uint64_t res_key,
static void
ctl_pro_preempt_other(struct ctl_lun *lun, union ctl_ha_msg *msg)
{
uint64_t sa_res_key;
int i;
sa_res_key = scsi_8btou64(msg->pr.pr_info.sa_res_key);
if (lun->pr_res_idx == CTL_PR_ALL_REGISTRANTS
|| lun->pr_res_idx == CTL_PR_NO_RESERVATION
|| memcmp(&lun->per_res[lun->pr_res_idx].res_key,
msg->pr.pr_info.sa_res_key,
sizeof(struct scsi_per_res_key)) != 0) {
uint64_t sa_res_key;
sa_res_key = scsi_8btou64(msg->pr.pr_info.sa_res_key);
|| sa_res_key != lun->pr_keys[lun->pr_res_idx]) {
if (sa_res_key == 0) {
/* temporarily unregister this nexus */
lun->per_res[msg->pr.pr_info.residx].registered = 0;
/*
* Unregister everybody else and build UA for
* them
*/
for(i=0; i < 2*CTL_MAX_INITIATORS; i++) {
if (lun->per_res[i].registered == 0)
if (i == msg->pr.pr_info.residx ||
lun->pr_keys[i] == 0)
continue;
if (!persis_offset
@ -8383,12 +8346,9 @@ ctl_pro_preempt_other(struct ctl_lun *lun, union ctl_ha_msg *msg)
else if (persis_offset && i >= persis_offset)
lun->pending_ua[i - persis_offset] |=
CTL_UA_REG_PREEMPT;
lun->per_res[i].registered = 0;
memset(&lun->per_res[i].res_key, 0,
sizeof(struct scsi_per_res_key));
lun->pr_keys[i] = 0;
}
lun->per_res[msg->pr.pr_info.residx].registered = 1;
lun->pr_key_count = 1;
lun->res_type = msg->pr.pr_info.res_type;
if (lun->res_type != SPR_TYPE_WR_EX_AR
@ -8396,14 +8356,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 (memcmp(msg->pr.pr_info.sa_res_key,
lun->per_res[i].res_key.key,
sizeof(struct scsi_per_res_key)) != 0)
if (sa_res_key == lun->pr_keys[i])
continue;
lun->per_res[i].registered = 0;
memset(&lun->per_res[i].res_key, 0,
sizeof(struct scsi_per_res_key));
lun->pr_keys[i] = 0;
lun->pr_key_count--;
if (!persis_offset
@ -8417,21 +8373,13 @@ ctl_pro_preempt_other(struct ctl_lun *lun, union ctl_ha_msg *msg)
}
}
} else {
/*
* Temporarily unregister so it won't get removed
* or UA generated
*/
lun->per_res[msg->pr.pr_info.residx].registered = 0;
for (i=0; i < 2*CTL_MAX_INITIATORS; i++) {
if (lun->per_res[i].registered == 0)
if (i == msg->pr.pr_info.residx ||
lun->pr_keys[i] == 0)
continue;
if (memcmp(msg->pr.pr_info.sa_res_key,
lun->per_res[i].res_key.key,
sizeof(struct scsi_per_res_key)) == 0) {
lun->per_res[i].registered = 0;
memset(&lun->per_res[i].res_key, 0,
sizeof(struct scsi_per_res_key));
if (sa_res_key == lun->pr_keys[i]) {
lun->pr_keys[i] = 0;
lun->pr_key_count--;
if (!persis_offset
&& i < CTL_MAX_INITIATORS)
@ -8454,7 +8402,6 @@ ctl_pro_preempt_other(struct ctl_lun *lun, union ctl_ha_msg *msg)
CTL_UA_RES_RELEASE;
}
}
lun->per_res[msg->pr.pr_info.residx].registered = 1;
lun->res_type = msg->pr.pr_info.res_type;
if (lun->res_type != SPR_TYPE_WR_EX_AR
&& lun->res_type != SPR_TYPE_EX_AC_AR)
@ -8552,11 +8499,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->per_res[residx].registered) {
if (memcmp(param->res_key.key,
lun->per_res[residx].res_key.key,
ctl_min(sizeof(param->res_key),
sizeof(lun->per_res[residx].res_key))) != 0) {
if (lun->pr_keys[residx] != 0) {
if (res_key != lun->pr_keys[residx]) {
/*
* The current key passed in doesn't match
* the one the initiator previously
@ -8637,14 +8581,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->per_res[residx].registered)) {
&& lun->pr_keys[residx] == 0)) {
mtx_unlock(&lun->lun_lock);
goto done;
}
lun->per_res[residx].registered = 0;
memset(&lun->per_res[residx].res_key,
0, sizeof(lun->per_res[residx].res_key));
lun->pr_keys[residx] = 0;
lun->pr_key_count--;
if (residx == lun->pr_res_idx) {
@ -8663,9 +8605,8 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
*/
for (i = 0; i < CTL_MAX_INITIATORS;i++){
if (lun->per_res[
i+persis_offset].registered
== 0)
if (lun->pr_keys[
i + persis_offset] == 0)
continue;
lun->pending_ua[i] |=
CTL_UA_RES_RELEASE;
@ -8695,15 +8636,9 @@ 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->per_res[residx].registered) {
if (lun->pr_keys[residx] == 0)
lun->pr_key_count++;
lun->per_res[residx].registered = 1;
}
memcpy(&lun->per_res[residx].res_key,
param->serv_act_res_key,
ctl_min(sizeof(param->serv_act_res_key),
sizeof(lun->per_res[residx].res_key)));
lun->pr_keys[residx] = sa_res_key;
persis_io.hdr.nexus = ctsio->io_hdr.nexus;
persis_io.hdr.msg_type = CTL_MSG_PERS_ACTION;
@ -8816,20 +8751,12 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
*/
if (type != SPR_TYPE_EX_AC
&& type != SPR_TYPE_WR_EX) {
/*
* temporarily unregister so we don't generate UA
*/
lun->per_res[residx].registered = 0;
for (i = 0; i < CTL_MAX_INITIATORS; i++) {
if (lun->per_res[i+persis_offset].registered
== 0)
if (i == residx ||
lun->pr_keys[i + persis_offset] == 0)
continue;
lun->pending_ua[i] |=
CTL_UA_RES_RELEASE;
lun->pending_ua[i] |= CTL_UA_RES_RELEASE;
}
lun->per_res[residx].registered = 1;
}
mtx_unlock(&lun->lun_lock);
/* Send msg to other side */
@ -8852,13 +8779,10 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
lun->pr_key_count = 0;
lun->pr_res_idx = CTL_PR_NO_RESERVATION;
memset(&lun->per_res[residx].res_key,
0, sizeof(lun->per_res[residx].res_key));
lun->per_res[residx].registered = 0;
lun->pr_keys[residx] = 0;
for (i=0; i < 2*CTL_MAX_INITIATORS; i++)
if (lun->per_res[i].registered) {
if (lun->pr_keys[i] != 0) {
if (!persis_offset && i < CTL_MAX_INITIATORS)
lun->pending_ua[i] |=
CTL_UA_RES_PREEMPT;
@ -8866,9 +8790,7 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
lun->pending_ua[i-persis_offset] |=
CTL_UA_RES_PREEMPT;
memset(&lun->per_res[i].res_key,
0, sizeof(struct scsi_per_res_key));
lun->per_res[i].registered = 0;
lun->pr_keys[i] = 0;
}
lun->PRGeneration++;
mtx_unlock(&lun->lun_lock);
@ -8924,20 +8846,15 @@ 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->per_res[msg->pr.pr_info.residx].registered) {
lun->per_res[msg->pr.pr_info.residx].registered = 1;
if (lun->pr_keys[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);
lun->PRGeneration++;
memcpy(&lun->per_res[msg->pr.pr_info.residx].res_key,
msg->pr.pr_info.sa_res_key,
sizeof(struct scsi_per_res_key));
break;
case CTL_PR_UNREG_KEY:
lun->per_res[msg->pr.pr_info.residx].registered = 0;
memset(&lun->per_res[msg->pr.pr_info.residx].res_key,
0, sizeof(struct scsi_per_res_key));
lun->pr_keys[msg->pr.pr_info.residx] = 0;
lun->pr_key_count--;
/* XXX Need to see if the reservation has been released */
@ -8958,8 +8875,8 @@ ctl_hndl_per_res_out_on_other_sc(union ctl_ha_msg *msg)
*/
for (i = 0; i < CTL_MAX_INITIATORS; i++) {
if (lun->per_res[i+
persis_offset].registered == 0)
if (lun->pr_keys[i+
persis_offset] == 0)
continue;
lun->pending_ua[i] |=
@ -8992,7 +8909,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->per_res[i+persis_offset].registered)
if (lun->pr_keys[i+persis_offset] != 0)
lun->pending_ua[i] |=
CTL_UA_RES_RELEASE;
}
@ -9012,7 +8929,7 @@ 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->per_res[i].registered == 0)
if (lun->pr_keys[i] == 0)
continue;
if (!persis_offset
&& i < CTL_MAX_INITIATORS)
@ -9021,9 +8938,7 @@ ctl_hndl_per_res_out_on_other_sc(union ctl_ha_msg *msg)
&& i >= persis_offset)
lun->pending_ua[i-persis_offset] |=
CTL_UA_RES_PREEMPT;
memset(&lun->per_res[i].res_key, 0,
sizeof(struct scsi_per_res_key));
lun->per_res[i].registered = 0;
lun->pr_keys[i] = 0;
}
lun->PRGeneration++;
break;
@ -9062,7 +8977,7 @@ ctl_read_write(struct ctl_scsiio *ctsio)
&& residx != lun->pr_res_idx)
|| ((lun->res_type == SPR_TYPE_EX_AC_RO
|| lun->res_type == SPR_TYPE_EX_AC_AR)
&& !lun->per_res[residx].registered)) {
&& lun->pr_keys[residx] == 0)) {
ctl_set_reservation_conflict(ctsio);
ctl_done((union ctl_io *)ctsio);
return (CTL_RETVAL_COMPLETE);
@ -11379,7 +11294,7 @@ ctl_scsiio_lun_check(struct ctl_softc *ctl_softc, struct ctl_lun *lun,
* type reservations are checked in the particular command
* for a conflict. Read and SSU are the only ones.
*/
if (!lun->per_res[residx].registered
if (lun->pr_keys[residx] == 0
|| (residx != lun->pr_res_idx && lun->res_type < 4)) {
ctsio->scsi_status = SCSI_STATUS_RESERV_CONFLICT;
ctsio->io_hdr.status = CTL_SCSI_ERROR;

View File

@ -353,11 +353,6 @@ typedef enum {
CTL_PR_FLAG_ACTIVE_RES = 0x02
} ctl_per_res_flags;
struct ctl_per_res_info {
struct scsi_per_res_key res_key;
uint8_t registered;
};
#define CTL_PR_ALL_REGISTRANTS 0xFFFFFFFF
#define CTL_PR_NO_RESERVATION 0xFFFFFFF0
@ -398,8 +393,8 @@ struct ctl_lun {
struct ctl_mode_pages mode_pages;
struct ctl_lun_io_stats stats;
uint32_t res_idx;
struct ctl_per_res_info per_res[2*CTL_MAX_INITIATORS];
unsigned int PRGeneration;
uint64_t pr_keys[2*CTL_MAX_INITIATORS];
int pr_key_count;
uint32_t pr_res_idx;
uint8_t res_type;