Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F110675488
D25476.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D25476.diff
View Options
diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c
--- a/sys/dev/mpr/mpr.c
+++ b/sys/dev/mpr/mpr.c
@@ -1141,7 +1141,8 @@
if (++sc->io_cmds_active > sc->io_cmds_highwater)
sc->io_cmds_highwater++;
- KASSERT(cm->cm_state == MPR_CM_STATE_BUSY, ("command not busy\n"));
+ KASSERT(cm->cm_state == MPR_CM_STATE_BUSY,
+ ("command not busy, state = %u\n", cm->cm_state));
cm->cm_state = MPR_CM_STATE_INQUEUE;
if (sc->atomic_desc_capable) {
@@ -1917,6 +1918,11 @@
CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_SKIP | CTLFLAG_NEEDGIANT,
sc, 0, mpr_dump_reqs, "I", "Dump Active Requests");
+ SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "dump_reqs_alltypes", CTLFLAG_RW,
+ &sc->dump_reqs_alltypes, 0,
+ "dump all request types not just inqueue");
+
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "use_phy_num", CTLFLAG_RD, &sc->use_phynum, 0,
"Use the phy number for enumeration");
@@ -2101,7 +2107,7 @@
/* Best effort, no locking */
for (i = smid; i < numreqs; i++) {
cm = &sc->commands[i];
- if (cm->cm_state != state)
+ if ((sc->dump_reqs_alltypes == 0) && (cm->cm_state != state))
continue;
hdr.smid = i;
hdr.state = cm->cm_state;
@@ -2365,6 +2371,8 @@
return;
}
+ KASSERT(cm->cm_state == MPR_CM_STATE_INQUEUE,
+ ("command not inqueue, state = %u\n", cm->cm_state));
cm->cm_state = MPR_CM_STATE_BUSY;
if (cm->cm_flags & MPR_CM_FLAGS_POLLED)
cm->cm_flags |= MPR_CM_FLAGS_COMPLETE;
@@ -2544,9 +2552,6 @@
case MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS:
case MPI26_RPY_DESCRIPT_FLAGS_PCIE_ENCAPSULATED_SUCCESS:
cm = &sc->commands[le16toh(desc->SCSIIOSuccess.SMID)];
- KASSERT(cm->cm_state == MPR_CM_STATE_INQUEUE,
- ("command not inqueue\n"));
- cm->cm_state = MPR_CM_STATE_BUSY;
cm->cm_reply = NULL;
break;
case MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY:
diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c
--- a/sys/dev/mpr/mpr_sas.c
+++ b/sys/dev/mpr/mpr_sas.c
@@ -1194,7 +1194,7 @@
"out\n", tm);
KASSERT(tm->cm_state == MPR_CM_STATE_INQUEUE,
- ("command not inqueue\n"));
+ ("command not inqueue, state = %u\n", tm->cm_state));
tm->cm_state = MPR_CM_STATE_BUSY;
mpr_reinit(sc);
@@ -2437,7 +2437,7 @@
if (cm->cm_flags & MPR_CM_FLAGS_ON_RECOVERY) {
TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery);
KASSERT(cm->cm_state == MPR_CM_STATE_BUSY,
- ("Not busy for CM_FLAGS_TIMEDOUT: %d\n", cm->cm_state));
+ ("Not busy for CM_FLAGS_TIMEDOUT: %u\n", cm->cm_state));
cm->cm_flags &= ~MPR_CM_FLAGS_ON_RECOVERY;
if (cm->cm_reply != NULL)
mprsas_log_command(cm, MPR_RECOVERY,
diff --git a/sys/dev/mpr/mpr_sas_lsi.c b/sys/dev/mpr/mpr_sas_lsi.c
--- a/sys/dev/mpr/mpr_sas_lsi.c
+++ b/sys/dev/mpr/mpr_sas_lsi.c
@@ -125,6 +125,7 @@
static int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle,
Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
u32 devinfo);
+static void mprsas_ata_id_complete(struct mpr_softc *, struct mpr_command *);
static void mprsas_ata_id_timeout(struct mpr_softc *, struct mpr_command *);
int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc,
u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD);
@@ -1005,7 +1006,8 @@
* An Abort Task TM should be used instead of a Target Reset, but that
* would be much more difficult because targets have not been fully
* discovered yet, and LUN's haven't been setup. So, just reset the
- * target instead of the LUN.
+ * target instead of the LUN. The commands should complete once
+ * the target has been reset.
*/
for (i = 1; i < sc->num_reqs; i++) {
cm = &sc->commands[i];
@@ -1033,16 +1035,6 @@
}
}
out:
- /*
- * Free the commands that may not have been freed from the SATA ID call
- */
- 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);
- }
- }
mprsas_startup_decrement(sassc);
return (error);
}
@@ -1218,8 +1210,8 @@
out:
/*
* If the SATA_ID_TIMEOUT flag has been set for this command, don't free
- * it. The command and buffer will be freed after sending an Abort
- * Task TM.
+ * it. The command and buffer will be freed after we send a Target
+ * Reset TM and the command comes back from the controller.
*/
if ((cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0) {
mpr_free_command(sc, cm);
@@ -1228,6 +1220,22 @@
return (error);
}
+/*
+ * This is completion handler to make sure that commands and allocated
+ * buffers get freed when timed out SATA ID commands finally complete after
+ * we've reset the target. In the normal case, we wait for the command to
+ * complete.
+ */
+static void
+mprsas_ata_id_complete(struct mpr_softc *sc, struct mpr_command *cm)
+{
+ mpr_dprint(sc, MPR_INFO, "%s ATA ID completed late cm %p sc %p\n",
+ __func__, cm, sc);
+
+ free(cm->cm_data, M_MPR);
+ mpr_free_command(sc, cm);
+}
+
static void
mprsas_ata_id_timeout(struct mpr_softc *sc, struct mpr_command *cm)
{
@@ -1242,7 +1250,12 @@
* this command has timed out, it's no longer in the queue.
*/
cm->cm_flags |= MPR_CM_FLAGS_SATA_ID_TIMEOUT;
- cm->cm_state = MPR_CM_STATE_BUSY;
+
+ /*
+ * Since we will no longer be waiting for the command to complete,
+ * set a completion handler to make sure we free all resources.
+ */
+ cm->cm_complete = mprsas_ata_id_complete;
}
static int
diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h
--- a/sys/dev/mpr/mprvar.h
+++ b/sys/dev/mpr/mprvar.h
@@ -367,6 +367,7 @@
u_int enable_ssu;
int spinup_wait_time;
int use_phynum;
+ int dump_reqs_alltypes;
uint64_t chain_alloc_fail;
uint64_t prp_page_alloc_fail;
struct sysctl_ctx_list sysctl_ctx;
@@ -617,7 +618,8 @@
struct mpr_chain *chain, *chain_temp;
struct mpr_prp_page *prp_page, *prp_page_temp;
- KASSERT(cm->cm_state == MPR_CM_STATE_BUSY, ("state not busy\n"));
+ KASSERT(cm->cm_state == MPR_CM_STATE_BUSY,
+ ("state not busy, state = %u\n", cm->cm_state));
if (cm->cm_reply != NULL)
mpr_free_reply(sc, cm->cm_reply_data);
@@ -658,7 +660,7 @@
return (NULL);
KASSERT(cm->cm_state == MPR_CM_STATE_FREE,
- ("mpr: Allocating busy command\n"));
+ ("mpr: Allocating busy command, state = %u\n", cm->cm_state));
TAILQ_REMOVE(&sc->req_list, cm, cm_link);
cm->cm_state = MPR_CM_STATE_BUSY;
@@ -671,7 +673,8 @@
{
struct mpr_chain *chain, *chain_temp;
- KASSERT(cm->cm_state == MPR_CM_STATE_BUSY, ("state not busy\n"));
+ KASSERT(cm->cm_state == MPR_CM_STATE_BUSY,
+ ("state not busy, state = %u\n", cm->cm_state));
if (cm->cm_reply != NULL)
mpr_free_reply(sc, cm->cm_reply_data);
@@ -700,7 +703,7 @@
return (NULL);
KASSERT(cm->cm_state == MPR_CM_STATE_FREE,
- ("mpr: Allocating busy command\n"));
+ ("mpr: Allocating busy command, state = %u\n", cm->cm_state));
TAILQ_REMOVE(&sc->high_priority_req_list, cm, cm_link);
cm->cm_state = MPR_CM_STATE_BUSY;
diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c
--- a/sys/dev/mps/mps.c
+++ b/sys/dev/mps/mps.c
@@ -1112,7 +1112,8 @@
rd.u.high = cm->cm_desc.Words.High;
rd.word = htole64(rd.word);
- KASSERT(cm->cm_state == MPS_CM_STATE_BUSY, ("command not busy\n"));
+ KASSERT(cm->cm_state == MPS_CM_STATE_BUSY,
+ ("command not busy, state = %u\n", cm->cm_state));
cm->cm_state = MPS_CM_STATE_INQUEUE;
/* TODO-We may need to make below regwrite atomic */
@@ -1774,6 +1775,11 @@
CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_SKIP | CTLFLAG_NEEDGIANT,
sc, 0, mps_dump_reqs, "I", "Dump Active Requests");
+ SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "dump_reqs_alltypes", CTLFLAG_RW,
+ &sc->dump_reqs_alltypes, 0,
+ "dump all request types not just inqueue");
+
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "use_phy_num", CTLFLAG_RD, &sc->use_phynum, 0,
"Use the phy number for enumeration");
@@ -1947,7 +1953,7 @@
/* Best effort, no locking */
for (i = smid; i < numreqs; i++) {
cm = &sc->commands[i];
- if (cm->cm_state != state)
+ if ((sc->dump_reqs_alltypes == 0) && (cm->cm_state != state))
continue;
hdr.smid = i;
hdr.state = cm->cm_state;
@@ -2206,6 +2212,9 @@
return;
}
+ KASSERT(cm->cm_state == MPS_CM_STATE_INQUEUE,
+ ("command not inqueue, state = %u\n", cm->cm_state));
+ cm->cm_state = MPS_CM_STATE_BUSY;
if (cm->cm_flags & MPS_CM_FLAGS_POLLED)
cm->cm_flags |= MPS_CM_FLAGS_COMPLETE;
@@ -2382,9 +2391,6 @@
switch (flags) {
case MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS:
cm = &sc->commands[le16toh(desc->SCSIIOSuccess.SMID)];
- KASSERT(cm->cm_state == MPS_CM_STATE_INQUEUE,
- ("command not inqueue\n"));
- cm->cm_state = MPS_CM_STATE_BUSY;
cm->cm_reply = NULL;
break;
case MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY:
@@ -2460,7 +2466,6 @@
cm = &sc->commands[
le16toh(desc->AddressReply.SMID)];
if (cm->cm_state == MPS_CM_STATE_INQUEUE) {
- cm->cm_state = MPS_CM_STATE_BUSY;
cm->cm_reply = reply;
cm->cm_reply_data = le32toh(
desc->AddressReply.ReplyFrameAddress);
diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c
--- a/sys/dev/mps/mps_sas.c
+++ b/sys/dev/mps/mps_sas.c
@@ -1170,7 +1170,7 @@
"task mgmt %p timed out\n", tm);
KASSERT(tm->cm_state == MPS_CM_STATE_INQUEUE,
- ("command not inqueue\n"));
+ ("command not inqueue, state = %u\n", tm->cm_state));
tm->cm_state = MPS_CM_STATE_BUSY;
mps_reinit(sc);
@@ -2015,7 +2015,7 @@
if (cm->cm_flags & MPS_CM_FLAGS_ON_RECOVERY) {
TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery);
KASSERT(cm->cm_state == MPS_CM_STATE_BUSY,
- ("Not busy for CM_FLAGS_TIMEDOUT: %d\n", cm->cm_state));
+ ("Not busy for CM_FLAGS_TIMEDOUT: %u\n", cm->cm_state));
cm->cm_flags &= ~MPS_CM_FLAGS_ON_RECOVERY;
if (cm->cm_reply != NULL)
mpssas_log_command(cm, MPS_RECOVERY,
diff --git a/sys/dev/mps/mps_sas_lsi.c b/sys/dev/mps/mps_sas_lsi.c
--- a/sys/dev/mps/mps_sas_lsi.c
+++ b/sys/dev/mps/mps_sas_lsi.c
@@ -123,6 +123,7 @@
static int mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
u32 devinfo);
+static void mpssas_ata_id_complete(struct mps_softc *, struct mps_command *);
static void mpssas_ata_id_timeout(struct mps_softc *, struct mps_command *);
int mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD);
@@ -780,7 +781,8 @@
* An Abort Task TM should be used instead of a Target Reset, but that
* would be much more difficult because targets have not been fully
* discovered yet, and LUN's haven't been setup. So, just reset the
- * target instead of the LUN.
+ * target instead of the LUN. The commands should complete once the
+ * target has been reset.
*/
for (i = 1; i < sc->num_reqs; i++) {
cm = &sc->commands[i];
@@ -808,16 +810,6 @@
}
}
out:
- /*
- * Free the commands that may not have been freed from the SATA ID call
- */
- 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);
- }
- }
mpssas_startup_decrement(sassc);
return (error);
}
@@ -993,8 +985,8 @@
out:
/*
* If the SATA_ID_TIMEOUT flag has been set for this command, don't free
- * it. The command and buffer will be freed after sending an Abort
- * Task TM.
+ * it. The command and buffer will be freed after we send a Target
+ * Reset TM and the command comes back from the controller.
*/
if ((cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) == 0) {
mps_free_command(sc, cm);
@@ -1003,21 +995,41 @@
return (error);
}
+/*
+ * This is completion handler to make sure that commands and allocated
+ * buffers get freed when timed out SATA ID commands finally complete after
+ * we've reset the target. In the normal case, we wait for the command to
+ * complete.
+ */
static void
-mpssas_ata_id_timeout(struct mps_softc *sc, struct mps_command *cm)
+mpssas_ata_id_complete(struct mps_softc *sc, struct mps_command *cm)
{
+ mps_dprint(sc, MPS_INFO, "%s ATA ID completed late cm %p sc %p\n",
+ __func__, cm, sc);
+
+ free(cm->cm_data, M_MPT2);
+ mps_free_command(sc, cm);
+}
+
+static void
+mpssas_ata_id_timeout(struct mps_softc *sc, struct mps_command *cm)
+{
mps_dprint(sc, MPS_INFO, "%s ATA ID command timeout cm %p sc %p\n",
__func__, cm, sc);
/*
* The Abort Task cannot be sent from here because the driver has not
* completed setting up targets. Instead, the command is flagged so
- * that special handling will be used to send the abort. Now that
- * this command has timed out, it's no longer in the queue.
+ * that special handling will be used to send a target reset.
*/
cm->cm_flags |= MPS_CM_FLAGS_SATA_ID_TIMEOUT;
- cm->cm_state = MPS_CM_STATE_BUSY;
+
+ /*
+ * Since we will no longer be waiting for the command to complete,
+ * set a completion handler to make sure we free all resources.
+ */
+ cm->cm_complete = mpssas_ata_id_complete;
}
static int
diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h
--- a/sys/dev/mps/mpsvar.h
+++ b/sys/dev/mps/mpsvar.h
@@ -326,6 +326,7 @@
u_int enable_ssu;
int spinup_wait_time;
int use_phynum;
+ int dump_reqs_alltypes;
uint64_t chain_alloc_fail;
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
@@ -548,7 +549,7 @@
struct mps_chain *chain, *chain_temp;
KASSERT(cm->cm_state == MPS_CM_STATE_BUSY,
- ("state not busy: %d\n", cm->cm_state));
+ ("state not busy: %u\n", cm->cm_state));
if (cm->cm_reply != NULL)
mps_free_reply(sc, cm->cm_reply_data);
@@ -584,7 +585,7 @@
return (NULL);
KASSERT(cm->cm_state == MPS_CM_STATE_FREE,
- ("mps: Allocating busy command: %d\n", cm->cm_state));
+ ("mps: Allocating busy command: %u\n", cm->cm_state));
TAILQ_REMOVE(&sc->req_list, cm, cm_link);
cm->cm_state = MPS_CM_STATE_BUSY;
@@ -598,7 +599,7 @@
struct mps_chain *chain, *chain_temp;
KASSERT(cm->cm_state == MPS_CM_STATE_BUSY,
- ("state not busy: %d\n", cm->cm_state));
+ ("state not busy: %u\n", cm->cm_state));
if (cm->cm_reply != NULL)
mps_free_reply(sc, cm->cm_reply_data);
@@ -627,7 +628,7 @@
return (NULL);
KASSERT(cm->cm_state == MPS_CM_STATE_FREE,
- ("mps: Allocating high priority busy command: %d\n", cm->cm_state));
+ ("mps: Allocating high priority busy command: %u\n", cm->cm_state));
TAILQ_REMOVE(&sc->high_priority_req_list, cm, cm_link);
cm->cm_state = MPS_CM_STATE_BUSY;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Feb 22, 7:02 PM (5 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16777455
Default Alt Text
D25476.diff (14 KB)
Attached To
Mode
D25476: Fix use after free panic and state transitions in mps(4) and mpr(4)
Attached
Detach File
Event Timeline
Log In to Comment