Skip to content

Commit d971d3f

Browse files
committed
MINOR: muxes: adjust takeover with buf_wait interaction
Takeover operation defines an argument <release>. It's a boolean which if set indicate that freed connection resources during the takeover does not have to be reallocated on the new thread. Typically, it is set to false when takever is performed to reuse a connection. However, when used to be able to delete a connection from a different thread, <release> should be set to true. Previously, <release> was only set in conjunction with "del server" handler. This operation was performed under thread isolation, which guarantee that not thread-safe operation such as removal from buf_wait list could be performed on takeover if <release> was true. In the contrary case, takeover operation would fail. Recently, "del server" handler has been adjusted to remove idle connection cleanup with takeover. As such, <release> is never set to true in remaining takeover usage. However, takeover is also used to enforce strict-maxconn on a server. This is performed to delete a connection from any thread, which is the primary reason of <release> to true. But for the moment as takeover implementers considers that thread isolation is active if <release> is set, this is not yet applicable for strict-maxconn usage. Thus, the purpose of this patch is to adjust takeover implementation. Remove assumption between <release> and thread-isolation mode. It's not possible to remove a connection from a buf_wait list, an error will be return in any case.
1 parent 8a45639 commit d971d3f

File tree

4 files changed

+44
-87
lines changed

4 files changed

+44
-87
lines changed

src/mux_fcgi.c

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4435,18 +4435,21 @@ static int fcgi_takeover(struct connection *conn, int orig_tid, int release)
44354435
struct task *new_task = NULL;
44364436
struct tasklet *new_tasklet = NULL;
44374437

4438+
/* If the connection is attached to a buffer_wait (extremely rare),
4439+
* it will be woken up at any instant by its own thread and we can't
4440+
* undo it anyway, so let's give up on this one. It's not interesting
4441+
* at least for reuse anyway since it's not usable right now.
4442+
*
4443+
* TODO if takeover is used to free conn (release == 1), buf_wait may
4444+
* prevent this which is not desirable.
4445+
*/
4446+
if (LIST_INLIST(&fcgi->buf_wait.list))
4447+
goto fail;
4448+
44384449
/* Pre-allocate tasks so that we don't have to roll back after the xprt
44394450
* has been migrated.
44404451
*/
44414452
if (!release) {
4442-
/* If the connection is attached to a buffer_wait (extremely
4443-
* rare), it will be woken up at any instant by its own thread
4444-
* and we can't undo it anyway, so let's give up on this one.
4445-
* It's not interesting anyway since it's not usable right now.
4446-
*/
4447-
if (LIST_INLIST(&fcgi->buf_wait.list))
4448-
goto fail;
4449-
44504453
new_task = task_new_here();
44514454
new_tasklet = tasklet_new();
44524455
if (!new_task || !new_tasklet)
@@ -4503,20 +4506,6 @@ static int fcgi_takeover(struct connection *conn, int orig_tid, int release)
45034506
SUB_RETRY_RECV, &fcgi->wait_event);
45044507
}
45054508

4506-
if (release) {
4507-
/* we're being called for a server deletion and are running
4508-
* under thread isolation. That's the only way we can
4509-
* unregister a possible subscription of the original
4510-
* connection from its owner thread's queue, as this involves
4511-
* manipulating thread-unsafe areas. Note that it is not
4512-
* possible to just call b_dequeue() here as it would update
4513-
* the current thread's bufq_map and not the original one.
4514-
*/
4515-
BUG_ON(!thread_isolated());
4516-
if (LIST_INLIST(&fcgi->buf_wait.list))
4517-
_b_dequeue(&fcgi->buf_wait, orig_tid);
4518-
}
4519-
45204509
if (new_task)
45214510
__task_free(new_task);
45224511
return 0;

src/mux_h1.c

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5596,18 +5596,21 @@ static int h1_takeover(struct connection *conn, int orig_tid, int release)
55965596
struct task *new_task = NULL;
55975597
struct tasklet *new_tasklet = NULL;
55985598

5599+
/* If the connection is attached to a buffer_wait (extremely rare),
5600+
* it will be woken up at any instant by its own thread and we can't
5601+
* undo it anyway, so let's give up on this one. It's not interesting
5602+
* at least for reuse anyway since it's not usable right now.
5603+
*
5604+
* TODO if takeover is used to free conn (release == 1), buf_wait may
5605+
* prevent this which is not desirable.
5606+
*/
5607+
if (LIST_INLIST(&h1c->buf_wait.list))
5608+
goto fail;
5609+
55995610
/* Pre-allocate tasks so that we don't have to roll back after the xprt
56005611
* has been migrated.
56015612
*/
56025613
if (!release) {
5603-
/* If the connection is attached to a buffer_wait (extremely
5604-
* rare), it will be woken up at any instant by its own thread
5605-
* and we can't undo it anyway, so let's give up on this one.
5606-
* It's not interesting anyway since it's not usable right now.
5607-
*/
5608-
if (LIST_INLIST(&h1c->buf_wait.list))
5609-
goto fail;
5610-
56115614
new_task = task_new_here();
56125615
new_tasklet = tasklet_new();
56135616
if (!new_task || !new_tasklet)
@@ -5664,20 +5667,6 @@ static int h1_takeover(struct connection *conn, int orig_tid, int release)
56645667
SUB_RETRY_RECV, &h1c->wait_event);
56655668
}
56665669

5667-
if (release) {
5668-
/* we're being called for a server deletion and are running
5669-
* under thread isolation. That's the only way we can
5670-
* unregister a possible subscription of the original
5671-
* connection from its owner thread's queue, as this involves
5672-
* manipulating thread-unsafe areas. Note that it is not
5673-
* possible to just call b_dequeue() here as it would update
5674-
* the current thread's bufq_map and not the original one.
5675-
*/
5676-
BUG_ON(!thread_isolated());
5677-
if (LIST_INLIST(&h1c->buf_wait.list))
5678-
_b_dequeue(&h1c->buf_wait, orig_tid);
5679-
}
5680-
56815670
if (new_task)
56825671
__task_free(new_task);
56835672
return 0;

src/mux_h2.c

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8375,18 +8375,21 @@ static int h2_takeover(struct connection *conn, int orig_tid, int release)
83758375
struct task *new_task = NULL;
83768376
struct tasklet *new_tasklet = NULL;
83778377

8378+
/* If the connection is attached to a buffer_wait (extremely rare),
8379+
* it will be woken up at any instant by its own thread and we can't
8380+
* undo it anyway, so let's give up on this one. It's not interesting
8381+
* at least for reuse anyway since it's not usable right now.
8382+
*
8383+
* TODO if takeover is used to free conn (release == 1), buf_wait may
8384+
* prevent this which is not desirable.
8385+
*/
8386+
if (LIST_INLIST(&h2c->buf_wait.list))
8387+
goto fail;
8388+
83788389
/* Pre-allocate tasks so that we don't have to roll back after the xprt
83798390
* has been migrated.
83808391
*/
83818392
if (!release) {
8382-
/* If the connection is attached to a buffer_wait (extremely
8383-
* rare), it will be woken up at any instant by its own thread
8384-
* and we can't undo it anyway, so let's give up on this one.
8385-
* It's not interesting anyway since it's not usable right now.
8386-
*/
8387-
if (LIST_INLIST(&h2c->buf_wait.list))
8388-
goto fail;
8389-
83908393
new_task = task_new_here();
83918394
new_tasklet = tasklet_new();
83928395
if (!new_task || !new_tasklet)
@@ -8443,20 +8446,6 @@ static int h2_takeover(struct connection *conn, int orig_tid, int release)
84438446
SUB_RETRY_RECV, &h2c->wait_event);
84448447
}
84458448

8446-
if (release) {
8447-
/* we're being called for a server deletion and are running
8448-
* under thread isolation. That's the only way we can
8449-
* unregister a possible subscription of the original
8450-
* connection from its owner thread's queue, as this involves
8451-
* manipulating thread-unsafe areas. Note that it is not
8452-
* possible to just call b_dequeue() here as it would update
8453-
* the current thread's bufq_map and not the original one.
8454-
*/
8455-
BUG_ON(!thread_isolated());
8456-
if (LIST_INLIST(&h2c->buf_wait.list))
8457-
_b_dequeue(&h2c->buf_wait, orig_tid);
8458-
}
8459-
84608449
if (new_task)
84618450
__task_free(new_task);
84628451
return 0;

src/mux_spop.c

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3633,17 +3633,21 @@ static int spop_takeover(struct connection *conn, int orig_tid, int release)
36333633
struct task *new_task = NULL;
36343634
struct tasklet *new_tasklet = NULL;
36353635

3636+
/* If the connection is attached to a buffer_wait (extremely rare),
3637+
* it will be woken up at any instant by its own thread and we can't
3638+
* undo it anyway, so let's give up on this one. It's not interesting
3639+
* at least for reuse anyway since it's not usable right now.
3640+
*
3641+
* TODO if takeover is used to free conn (release == 1), buf_wait may
3642+
* prevent this which is not desirable.
3643+
*/
3644+
if (LIST_INLIST(&spop_conn->buf_wait.list))
3645+
goto fail;
3646+
36363647
/* Pre-allocate tasks so that we don't have to roll back after the xprt
36373648
* has been migrated.
36383649
*/
36393650
if (!release) {
3640-
/* If the connection is attached to a buffer_wait (extremely
3641-
* rare), it will be woken up at any instant by its own thread
3642-
* and we can't undo it anyway, so let's give up on this one.
3643-
* It's not interesting anyway since it's not usable right now.
3644-
*/
3645-
if (LIST_INLIST(&spop_conn->buf_wait.list))
3646-
goto fail;
36473651

36483652
new_task = task_new_here();
36493653
new_tasklet = tasklet_new();
@@ -3701,20 +3705,6 @@ static int spop_takeover(struct connection *conn, int orig_tid, int release)
37013705
SUB_RETRY_RECV, &spop_conn->wait_event);
37023706
}
37033707

3704-
if (release) {
3705-
/* we're being called for a server deletion and are running
3706-
* under thread isolation. That's the only way we can
3707-
* unregister a possible subscription of the original
3708-
* connection from its owner thread's queue, as this involves
3709-
* manipulating thread-unsafe areas. Note that it is not
3710-
* possible to just call b_dequeue() here as it would update
3711-
* the current thread's bufq_map and not the original one.
3712-
*/
3713-
BUG_ON(!thread_isolated());
3714-
if (LIST_INLIST(&spop_conn->buf_wait.list))
3715-
_b_dequeue(&spop_conn->buf_wait, orig_tid);
3716-
}
3717-
37183708
if (new_task)
37193709
__task_free(new_task);
37203710
return 0;

0 commit comments

Comments
 (0)