mps(4), mpr(4): Fix lifetime of command buffer for mp?sas_get_sata_identify

In the event that the ID command timed out, mps(4)/mpr(4) did not free the
command until it could be cancelled.  However, it freed the associated
buffer (cm_data).  Fix the lifetime issue by freeing the associated buffer
only after Abort Task or controller reset.

Reviewed by:	scottl
Sponsored by:	Dell EMC Isilon
Differential Revision:	https://reviews.freebsd.org/D18612
This commit is contained in:
Conrad Meyer 2018-12-21 20:29:16 +00:00
parent 8ec22c4d65
commit 8277ce2b78
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=342354
4 changed files with 24 additions and 11 deletions

View File

@ -1169,6 +1169,12 @@ mprsas_complete_all_commands(struct mpr_softc *sc)
cm->cm_reply = NULL;
completed = 0;
if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) {
MPASS(cm->cm_data);
free(cm->cm_data, M_MPR);
cm->cm_data = NULL;
}
if (cm->cm_flags & MPR_CM_FLAGS_POLLED)
cm->cm_flags |= MPR_CM_FLAGS_COMPLETE;

View File

@ -1026,6 +1026,7 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate)
for (i = 1; i < sc->num_reqs; i++) {
cm = &sc->commands[i];
if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) {
free(cm->cm_data, M_MPR);
mpr_free_command(sc, cm);
}
}
@ -1208,15 +1209,14 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle,
out:
/*
* If the SATA_ID_TIMEOUT flag has been set for this command, don't free
* it. The command will be freed after sending a target reset TM. If
* the command did timeout, use EWOULDBLOCK.
* it. The command and buffer will be freed after sending an Abort
* Task TM. If the command did timeout, use EWOULDBLOCK.
*/
if ((cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0)
if ((cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0) {
mpr_free_command(sc, cm);
else if (error == 0)
free(buffer, M_MPR);
} else if (error == 0)
error = EWOULDBLOCK;
cm->cm_data = NULL;
free(buffer, M_MPR);
return (error);
}

View File

@ -1108,6 +1108,12 @@ mpssas_complete_all_commands(struct mps_softc *sc)
cm->cm_reply = NULL;
completed = 0;
if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) {
MPASS(cm->cm_data);
free(cm->cm_data, M_MPT2);
cm->cm_data = NULL;
}
if (cm->cm_flags & MPS_CM_FLAGS_POLLED)
cm->cm_flags |= MPS_CM_FLAGS_COMPLETE;

View File

@ -818,6 +818,7 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
for (i = 1; i < sc->num_reqs; i++) {
cm = &sc->commands[i];
if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) {
free(cm->cm_data, M_MPT2);
mps_free_command(sc, cm);
}
}
@ -1000,15 +1001,15 @@ mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
out:
/*
* If the SATA_ID_TIMEOUT flag has been set for this command, don't free
* it. The command will be freed after sending a target reset TM. If
* the command did timeout, use EWOULDBLOCK.
* it. The command and buffer will be freed after sending an Abort
* Task TM. If the command did timeout, use EWOULDBLOCK.
*/
if ((cm != NULL)
&& (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) == 0)
&& (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) == 0) {
mps_free_command(sc, cm);
else if (error == 0)
free(buffer, M_MPT2);
} else if (error == 0)
error = EWOULDBLOCK;
free(buffer, M_MPT2);
return (error);
}