Page MenuHomeFreeBSD

D60477.diff
No OneTemporary

D60477.diff

diff --git a/sys/dev/nvmf/controller/nvmft_controller.c b/sys/dev/nvmf/controller/nvmft_controller.c
--- a/sys/dev/nvmf/controller/nvmft_controller.c
+++ b/sys/dev/nvmf/controller/nvmft_controller.c
@@ -162,7 +162,9 @@
ctrlr = nvmft_controller_alloc(np, cntlid, data);
mtx_lock(&np->lock);
- if (!np->online) {
+ mtx_lock(&ctrlr->lock);
+ if (!np->online || !nvmft_qpair_set_ctrlr(qp, ctrlr)) {
+ mtx_unlock(&ctrlr->lock);
mtx_unlock(&np->lock);
nvmft_controller_free(ctrlr);
free_unr(np->ids, cntlid);
@@ -192,9 +194,18 @@
callout_reset_sbt(&ctrlr->ka_timer, ctrlr->ka_sbt, 0,
nvmft_keep_alive_timer, ctrlr, C_HARDCLOCK);
}
+
+ ctrlr->pending_connects++;
+ mtx_unlock(&ctrlr->lock);
mtx_unlock(&np->lock);
- nvmft_finish_accept(qp, cmd, ctrlr);
+ nvmft_finish_accept(qp, cmd, cntlid);
+
+ mtx_lock(&ctrlr->lock);
+ ctrlr->pending_connects--;
+ if (ctrlr->pending_connects == 0)
+ wakeup(&ctrlr->pending_connects);
+ mtx_unlock(&ctrlr->lock);
return (0);
}
@@ -306,11 +317,25 @@
nvmft_qpair_destroy(qp);
return (EINVAL);
}
+ if (!nvmft_qpair_set_ctrlr(qp, ctrlr)) {
+ mtx_unlock(&ctrlr->lock);
+ mtx_unlock(&np->lock);
+ nvmft_qpair_destroy(qp);
+ return (ENOTCONN);
+ }
ctrlr->io_qpairs[qid - 1].qp = qp;
+ ctrlr->pending_connects++;
mtx_unlock(&ctrlr->lock);
mtx_unlock(&np->lock);
- nvmft_finish_accept(qp, cmd, ctrlr);
+
+ nvmft_finish_accept(qp, cmd, cntlid);
+
+ mtx_lock(&ctrlr->lock);
+ ctrlr->pending_connects--;
+ if (ctrlr->pending_connects == 0)
+ wakeup(&ctrlr->pending_connects);
+ mtx_unlock(&ctrlr->lock);
return (0);
}
@@ -324,11 +349,18 @@
CTR(KTR_NVMFT, "%s: %p", __func__, ctrlr);
+ /*
+ * Wait for any pending connects to finish.
+ */
+ mtx_lock(&ctrlr->lock);
+ while (ctrlr->pending_connects != 0)
+ mtx_sleep(&ctrlr->pending_connects, &ctrlr->lock, 0, "nvmftsh",
+ 0);
+
/*
* Shutdown all I/O queues to terminate pending datamoves and
* stop receiving new commands.
*/
- mtx_lock(&ctrlr->lock);
for (u_int i = 0; i < ctrlr->num_io_queues; i++) {
if (ctrlr->io_qpairs[i].qp != NULL) {
ctrlr->io_qpairs[i].shutdown = true;
diff --git a/sys/dev/nvmf/controller/nvmft_qpair.c b/sys/dev/nvmf/controller/nvmft_qpair.c
--- a/sys/dev/nvmf/controller/nvmft_qpair.c
+++ b/sys/dev/nvmf/controller/nvmft_qpair.c
@@ -26,8 +26,9 @@
struct nvmf_qpair *qp;
struct cidset *cids;
- bool admin;
- bool sq_flow_control;
+ bool admin:1;
+ bool sq_flow_control:1;
+ bool early_error:1;
uint16_t qid;
u_int qsize;
uint16_t sqhd;
@@ -51,6 +52,21 @@
struct nvmft_qpair *qp = arg;
struct nvmft_controller *ctrlr = qp->ctrlr;
+ /*
+ * Ignore errors on qpairs which are not yet associated with a
+ * conroller.
+ */
+ if (ctrlr == NULL) {
+ mtx_lock(&qp->lock);
+ ctrlr = qp->ctrlr;
+ if (ctrlr == NULL) {
+ qp->early_error = true;
+ mtx_unlock(&qp->lock);
+ return;
+ }
+ mtx_unlock(&qp->lock);
+ }
+
/*
* XXX: The Linux TCP initiator sends a RST immediately after
* the FIN, so treat ECONNRESET as plain EOF to avoid spurious
@@ -131,6 +147,19 @@
return (qp);
}
+bool
+nvmft_qpair_set_ctrlr(struct nvmft_qpair *qp, struct nvmft_controller *ctrlr)
+{
+ mtx_lock(&qp->lock);
+ if (qp->early_error) {
+ mtx_unlock(&qp->lock);
+ return (false);
+ }
+ qp->ctrlr = ctrlr;
+ mtx_unlock(&qp->lock);
+ return (true);
+}
+
void
nvmft_qpair_shutdown(struct nvmft_qpair *qp)
{
@@ -366,17 +395,16 @@
int
nvmft_finish_accept(struct nvmft_qpair *qp,
- const struct nvmf_fabric_connect_cmd *cmd, struct nvmft_controller *ctrlr)
+ const struct nvmf_fabric_connect_cmd *cmd, uint16_t cntlid)
{
struct nvmf_fabric_connect_rsp rsp;
- qp->ctrlr = ctrlr;
nvmft_init_connect_rsp(&rsp, cmd, 0);
if (qp->sq_flow_control)
rsp.sqhd = htole16(qp->sqhd);
else
rsp.sqhd = htole16(0xffff);
- rsp.status_code_specific.success.cntlid = htole16(ctrlr->cntlid);
+ rsp.status_code_specific.success.cntlid = htole16(cntlid);
return (nvmft_send_connect_response(qp, &rsp));
}
diff --git a/sys/dev/nvmf/controller/nvmft_var.h b/sys/dev/nvmf/controller/nvmft_var.h
--- a/sys/dev/nvmf/controller/nvmft_var.h
+++ b/sys/dev/nvmf/controller/nvmft_var.h
@@ -84,6 +84,8 @@
*/
uint32_t pending_commands;
+ uint16_t pending_connects;
+
volatile int ka_active_traffic;
struct callout ka_timer;
sbintime_t ka_sbt;
@@ -139,6 +141,8 @@
/* nvmft_qpair.c */
struct nvmft_qpair *nvmft_qpair_init(enum nvmf_trtype trtype,
const nvlist_t *params, uint16_t qid, const char *name);
+bool nvmft_qpair_set_ctrlr(struct nvmft_qpair *qp,
+ struct nvmft_controller *ctrlr);
void nvmft_qpair_shutdown(struct nvmft_qpair *qp);
void nvmft_qpair_destroy(struct nvmft_qpair *qp);
struct nvmft_controller *nvmft_qpair_ctrlr(struct nvmft_qpair *qp);
@@ -162,7 +166,7 @@
void nvmft_connect_invalid_parameters(struct nvmft_qpair *qp,
const struct nvmf_fabric_connect_cmd *cmd, bool data, uint16_t offset);
int nvmft_finish_accept(struct nvmft_qpair *qp,
- const struct nvmf_fabric_connect_cmd *cmd, struct nvmft_controller *ctrlr);
+ const struct nvmf_fabric_connect_cmd *cmd, uint16_t ctlid);
static __inline void
nvmft_port_ref(struct nvmft_port *np)

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 10, 12:11 AM (5 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40503762
Default Alt Text
D60477.diff (5 KB)

Event Timeline