mirror of https://github.com/schoebel/mars
net: fix race on mars_shutdown_socket()
This commit is contained in:
parent
d07aaa75c3
commit
dd99340827
47
mars_net.c
47
mars_net.c
|
@ -156,13 +156,14 @@ int mars_create_socket(struct mars_socket *msock, struct sockaddr_storage *addr,
|
|||
int status = -EEXIST;
|
||||
|
||||
if (unlikely(atomic_read(&msock->s_count))) {
|
||||
MARS_WRN("#%d socket already in use\n", msock->s_debug_nr);
|
||||
MARS_ERR("#%d socket already in use\n", msock->s_debug_nr);
|
||||
goto final;
|
||||
}
|
||||
if (unlikely(msock->s_socket)) {
|
||||
MARS_WRN("#%d socket already open\n", msock->s_debug_nr);
|
||||
MARS_ERR("#%d socket already open\n", msock->s_debug_nr);
|
||||
goto final;
|
||||
}
|
||||
|
||||
status = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &msock->s_socket);
|
||||
if (unlikely(status < 0)) {
|
||||
msock->s_socket = NULL;
|
||||
|
@ -240,29 +241,33 @@ EXPORT_SYMBOL_GPL(mars_accept_socket);
|
|||
|
||||
bool mars_get_socket(struct mars_socket *msock)
|
||||
{
|
||||
MARS_LOW("try socket #%d %p s_dead = %d s_count=%d\n", msock->s_debug_nr, msock->s_socket, msock->s_dead, atomic_read(&msock->s_count));
|
||||
if (unlikely(atomic_read(&msock->s_count) <= 0))
|
||||
MARS_LOW("#%d get socket %p s_dead = %d s_count=%d\n", msock->s_debug_nr, msock->s_socket, msock->s_dead, atomic_read(&msock->s_count));
|
||||
if (unlikely(atomic_read(&msock->s_count) <= 0)) {
|
||||
MARS_ERR("#%d bad nesting on msock = %p\n", msock->s_debug_nr, msock);
|
||||
return false;
|
||||
}
|
||||
|
||||
atomic_inc(&msock->s_count);
|
||||
|
||||
if (unlikely(!msock->s_socket || msock->s_dead)) {
|
||||
mars_put_socket(msock);
|
||||
return false;
|
||||
}
|
||||
MARS_LOW("got socket #%d\n", msock->s_debug_nr);
|
||||
MARS_LOW("#%d got socket\n", msock->s_debug_nr);
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mars_get_socket);
|
||||
|
||||
void mars_put_socket(struct mars_socket *msock)
|
||||
{
|
||||
MARS_LOW("try socket #%d %p s_dead = %d s_count=%d\n", msock->s_debug_nr, msock->s_socket, msock->s_dead, atomic_read(&msock->s_count));
|
||||
MARS_LOW("#%d put socket %p s_dead = %d s_count=%d\n", msock->s_debug_nr, msock->s_socket, msock->s_dead, atomic_read(&msock->s_count));
|
||||
if (unlikely(atomic_read(&msock->s_count) <= 0)) {
|
||||
MARS_ERR("bad nesting on msock = %p\n", msock);
|
||||
MARS_ERR("#%d bad nesting on msock = %p sock = %p\n", msock->s_debug_nr, msock, msock->s_socket);
|
||||
} else if (atomic_dec_and_test(&msock->s_count)) {
|
||||
struct socket *sock = msock->s_socket;
|
||||
int i;
|
||||
|
||||
MARS_DBG("closing socket #%d %p\n", msock->s_debug_nr, sock);
|
||||
MARS_DBG("#%d closing socket %p\n", msock->s_debug_nr, sock);
|
||||
if (likely(sock)) {
|
||||
kernel_sock_shutdown(sock, SHUT_WR);
|
||||
sock_release(sock);
|
||||
|
@ -281,17 +286,21 @@ EXPORT_SYMBOL_GPL(mars_put_socket);
|
|||
|
||||
void mars_shutdown_socket(struct mars_socket *msock)
|
||||
{
|
||||
struct socket *sock = msock->s_socket;
|
||||
MARS_IO("try socket #%d %p s_dead = %d s_count=%d\n", msock->s_debug_nr, msock->s_socket, msock->s_dead, atomic_read(&msock->s_count));
|
||||
if (likely(sock)) {
|
||||
if (unlikely(atomic_read(&msock->s_count) <= 0)) {
|
||||
MARS_ERR("bad nesting on msock = %p sock = %p\n", msock, sock);
|
||||
}
|
||||
if (!msock->s_dead) {
|
||||
msock->s_dead = true;
|
||||
MARS_DBG("shutdown socket #%d %p\n", msock->s_debug_nr, sock);
|
||||
kernel_sock_shutdown(sock, SHUT_WR);
|
||||
bool ok;
|
||||
|
||||
MARS_IO("#%d shutdown socket %p s_dead = %d s_count=%d\n", msock->s_debug_nr, msock->s_socket, msock->s_dead, atomic_read(&msock->s_count));
|
||||
|
||||
ok = mars_get_socket(msock);
|
||||
if (likely(ok)) {
|
||||
struct socket *sock = msock->s_socket;
|
||||
if (likely(sock)) {
|
||||
if (!msock->s_dead) {
|
||||
msock->s_dead = true;
|
||||
MARS_DBG("shutdown socket #%d %p\n", msock->s_debug_nr, sock);
|
||||
kernel_sock_shutdown(sock, SHUT_WR);
|
||||
}
|
||||
}
|
||||
mars_put_socket(msock);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mars_shutdown_socket);
|
||||
|
@ -302,7 +311,7 @@ bool mars_socket_is_alive(struct mars_socket *msock)
|
|||
if (!msock->s_socket)
|
||||
goto done;
|
||||
if (unlikely(atomic_read(&msock->s_count) <= 0)) {
|
||||
MARS_ERR("bad nesting on msock = %p\n", msock);
|
||||
MARS_ERR("#%d bad nesting on msock = %p sock = %p\n", msock->s_debug_nr, msock, msock->s_socket);
|
||||
goto done;
|
||||
}
|
||||
if (msock->s_dead)
|
||||
|
|
|
@ -285,28 +285,33 @@ int handler_thread(void *data)
|
|||
struct server_brick *brick = data;
|
||||
struct mars_socket *sock = &brick->handler_socket;
|
||||
struct task_struct *cb_thread = brick->cb_thread;
|
||||
int debug_nr;
|
||||
int status = 0;
|
||||
|
||||
brick->cb_thread = NULL;
|
||||
brick->self_shutdown = true;
|
||||
wake_up_interruptible(&brick->startup_event);
|
||||
|
||||
MARS_DBG("--------------- handler_thread starting on socket %p\n", sock);
|
||||
while (brick->cb_running && !sock->s_dead && !brick_thread_should_stop()) {
|
||||
MARS_DBG("#%d --------------- handler_thread starting on socket %p\n", sock->s_debug_nr, sock);
|
||||
while (brick->cb_running && !brick_thread_should_stop() && mars_socket_is_alive(sock)) {
|
||||
struct mars_cmd cmd = {};
|
||||
|
||||
status = mars_recv_struct(sock, &cmd, mars_cmd_meta);
|
||||
if (unlikely(status < 0 || sock->s_dead)) {
|
||||
MARS_WRN("dead = %d recv cmd status = %d\n", sock->s_dead, status);
|
||||
if (unlikely(status < 0)) {
|
||||
MARS_WRN("#%d recv cmd status = %d\n", sock->s_debug_nr, status);
|
||||
break;
|
||||
}
|
||||
if (unlikely(!mars_socket_is_alive(sock))) {
|
||||
MARS_WRN("#%d is dead\n", sock->s_debug_nr);
|
||||
break;
|
||||
}
|
||||
|
||||
MARS_IO("cmd = %d\n", cmd.cmd_code);
|
||||
MARS_IO("#%d cmd = %d\n", sock->s_debug_nr, cmd.cmd_code);
|
||||
|
||||
status = -EPROTO;
|
||||
switch (cmd.cmd_code & CMD_FLAG_MASK) {
|
||||
case CMD_NOP:
|
||||
MARS_DBG("got NOP operation\n");
|
||||
MARS_DBG("#%d got NOP operation\n", sock->s_debug_nr);
|
||||
status = 0;
|
||||
break;
|
||||
case CMD_NOTIFY:
|
||||
|
@ -341,7 +346,7 @@ int handler_thread(void *data)
|
|||
up(&brick->socket_sem);
|
||||
|
||||
if (status < 0) {
|
||||
MARS_WRN("could not send dentry information, status = %d\n", status);
|
||||
MARS_WRN("#%d could not send dentry information, status = %d\n", sock->s_debug_nr, status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -356,7 +361,7 @@ int handler_thread(void *data)
|
|||
CHECK_PTR_NULL(_bio_brick_type, err);
|
||||
|
||||
if (!mars_global->global_power.button) {
|
||||
MARS_WRN("system is not alive\n");
|
||||
MARS_WRN("#%d system is not alive\n", sock->s_debug_nr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -378,7 +383,7 @@ int handler_thread(void *data)
|
|||
if (likely(prev)) {
|
||||
status = generic_connect((void*)brick->inputs[0], (void*)prev->outputs[0]);
|
||||
} else {
|
||||
MARS_ERR("cannot find brick '%s'\n", path);
|
||||
MARS_ERR("#%d cannot find brick '%s'\n", sock->s_debug_nr, path);
|
||||
}
|
||||
|
||||
err:
|
||||
|
@ -393,7 +398,7 @@ int handler_thread(void *data)
|
|||
#ifdef CONFIG_MARS_LOADAVG_LIMIT // quirk
|
||||
int my_load = (avenrun[0] + FIXED_1/200) >> FSHIFT;
|
||||
if (mars_max_loadavg && my_load >= mars_max_loadavg) {
|
||||
MARS_WRN("loadavg %d too high (%d), aborting data traffic\n", my_load, mars_max_loadavg);
|
||||
MARS_WRN("#%d loadavg %d too high (%d), aborting data traffic\n", sock->s_debug_nr, my_load, mars_max_loadavg);
|
||||
status = -EBUSY;
|
||||
break;
|
||||
}
|
||||
|
@ -402,10 +407,10 @@ int handler_thread(void *data)
|
|||
break;
|
||||
}
|
||||
case CMD_CB:
|
||||
MARS_ERR("oops, as a server I should never get CMD_CB; something is wrong here - attack attempt??\n");
|
||||
MARS_ERR("#%d oops, as a server I should never get CMD_CB; something is wrong here - attack attempt??\n", sock->s_debug_nr);
|
||||
break;
|
||||
default:
|
||||
MARS_ERR("unknown command %d\n", cmd.cmd_code);
|
||||
MARS_ERR("#%d unknown command %d\n", sock->s_debug_nr, cmd.cmd_code);
|
||||
}
|
||||
brick_string_free(cmd.cmd_str1);
|
||||
if (status < 0)
|
||||
|
@ -414,15 +419,17 @@ int handler_thread(void *data)
|
|||
|
||||
mars_shutdown_socket(sock);
|
||||
|
||||
MARS_DBG("handler_thread terminating, status = %d\n", status);
|
||||
MARS_DBG("#%d handler_thread terminating, status = %d\n", sock->s_debug_nr, status);
|
||||
if (cb_thread) {
|
||||
MARS_INF("stopping cb thread...\n");
|
||||
MARS_INF("#%d stopping cb thread...\n", sock->s_debug_nr);
|
||||
brick_thread_stop(cb_thread);
|
||||
}
|
||||
|
||||
_clean_list(brick, &brick->cb_read_list);
|
||||
_clean_list(brick, &brick->cb_write_list);
|
||||
|
||||
debug_nr = sock->s_debug_nr;
|
||||
|
||||
/* Normally, the brick should be shut down from outside.
|
||||
* In case the handler thread stops abnormally (e.g.
|
||||
* shutdown of socket etc), it has to cleanup itself.
|
||||
|
@ -433,21 +440,21 @@ int handler_thread(void *data)
|
|||
*/
|
||||
if (brick->self_shutdown) {
|
||||
struct task_struct *h_thread;
|
||||
MARS_DBG("self-shutdown\n");
|
||||
MARS_DBG("#%d self-shutdown\n", debug_nr);
|
||||
h_thread = _grab_handler(brick);
|
||||
mars_put_socket(sock);
|
||||
if (h_thread) {
|
||||
int status;
|
||||
MARS_DBG("self cleanup...\n");
|
||||
MARS_DBG("#%d self cleanup...\n", debug_nr);
|
||||
status = mars_kill_brick((void*)brick);
|
||||
if (status < 0) {
|
||||
MARS_ERR("kill status = %d, giving up\n", status);
|
||||
MARS_ERR("#%d kill status = %d, giving up\n", debug_nr, status);
|
||||
}
|
||||
put_task_struct(h_thread);
|
||||
}
|
||||
}
|
||||
|
||||
MARS_DBG("done.\n");
|
||||
MARS_DBG("#%d done.\n", debug_nr);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue