Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F175180750
D60477.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D60477.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Fri, Oct 9, 10:14 PM (3 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40503762
Default Alt Text
D60477.diff (5 KB)
Attached To
Mode
D60477: nvmft: Handle transport errors on unaccepted qpairs
Attached
Detach File
Event Timeline
Log In to Comment