mirror of https://gitee.com/openkylin/linux.git
Merge branch 'tipc'
Eric Hugne says: ==================== tipc: refcount and memory leak fixes v3: Remove error logging from data path completely. Rebased on top of latest net merge. v2: Drop specific -ENOMEM logging in patch #1 (tipc: allow connection shutdown callback to be invoked in advance) And add a general error message if an internal server tries to send a message on a closed/nonexisting connection. In addition to the fix for refcount leak and memory leak during module removal, we also fix a problem where the topology server listening socket where unexpectedly closed. We also eliminate an unnecessary context switch during accept()/recvmsg() for nonblocking sockets. It might be good to include this patchset in stable aswell. After the v3 rebase on latest merge from net all patches apply cleanly on that tree. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
409e145643
|
@ -376,7 +376,6 @@ static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr,
|
|||
struct tipc_cfg_msg_hdr *req_hdr;
|
||||
struct tipc_cfg_msg_hdr *rep_hdr;
|
||||
struct sk_buff *rep_buf;
|
||||
int ret;
|
||||
|
||||
/* Validate configuration message header (ignore invalid message) */
|
||||
req_hdr = (struct tipc_cfg_msg_hdr *)buf;
|
||||
|
@ -398,12 +397,8 @@ static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr,
|
|||
memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr));
|
||||
rep_hdr->tcm_len = htonl(rep_buf->len);
|
||||
rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST);
|
||||
|
||||
ret = tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data,
|
||||
rep_buf->len);
|
||||
if (ret < 0)
|
||||
pr_err("Sending cfg reply message failed, no memory\n");
|
||||
|
||||
tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data,
|
||||
rep_buf->len);
|
||||
kfree_skb(rep_buf);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ unsigned int tipc_k_signal(Handler routine, unsigned long argument)
|
|||
|
||||
spin_lock_bh(&qitem_lock);
|
||||
if (!handler_enabled) {
|
||||
pr_err("Signal request ignored by handler\n");
|
||||
spin_unlock_bh(&qitem_lock);
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
|
|
|
@ -941,17 +941,48 @@ int tipc_nametbl_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_purge_publications - remove all publications for a given type
|
||||
*
|
||||
* tipc_nametbl_lock must be held when calling this function
|
||||
*/
|
||||
static void tipc_purge_publications(struct name_seq *seq)
|
||||
{
|
||||
struct publication *publ, *safe;
|
||||
struct sub_seq *sseq;
|
||||
struct name_info *info;
|
||||
|
||||
if (!seq->sseqs) {
|
||||
nameseq_delete_empty(seq);
|
||||
return;
|
||||
}
|
||||
sseq = seq->sseqs;
|
||||
info = sseq->info;
|
||||
list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) {
|
||||
tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node,
|
||||
publ->ref, publ->key);
|
||||
}
|
||||
}
|
||||
|
||||
void tipc_nametbl_stop(void)
|
||||
{
|
||||
u32 i;
|
||||
struct name_seq *seq;
|
||||
struct hlist_head *seq_head;
|
||||
struct hlist_node *safe;
|
||||
|
||||
/* Verify name table is empty, then release it */
|
||||
/* Verify name table is empty and purge any lingering
|
||||
* publications, then release the name table
|
||||
*/
|
||||
write_lock_bh(&tipc_nametbl_lock);
|
||||
for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {
|
||||
if (hlist_empty(&table.types[i]))
|
||||
continue;
|
||||
pr_err("nametbl_stop(): orphaned hash chain detected\n");
|
||||
break;
|
||||
seq_head = &table.types[i];
|
||||
hlist_for_each_entry_safe(seq, safe, seq_head, ns_list) {
|
||||
tipc_purge_publications(seq);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
kfree(table.types);
|
||||
table.types = NULL;
|
||||
|
|
|
@ -87,7 +87,6 @@ static void tipc_clean_outqueues(struct tipc_conn *con);
|
|||
static void tipc_conn_kref_release(struct kref *kref)
|
||||
{
|
||||
struct tipc_conn *con = container_of(kref, struct tipc_conn, kref);
|
||||
struct tipc_server *s = con->server;
|
||||
|
||||
if (con->sock) {
|
||||
tipc_sock_release_local(con->sock);
|
||||
|
@ -95,10 +94,6 @@ static void tipc_conn_kref_release(struct kref *kref)
|
|||
}
|
||||
|
||||
tipc_clean_outqueues(con);
|
||||
|
||||
if (con->conid)
|
||||
s->tipc_conn_shutdown(con->conid, con->usr_data);
|
||||
|
||||
kfree(con);
|
||||
}
|
||||
|
||||
|
@ -181,6 +176,9 @@ static void tipc_close_conn(struct tipc_conn *con)
|
|||
struct tipc_server *s = con->server;
|
||||
|
||||
if (test_and_clear_bit(CF_CONNECTED, &con->flags)) {
|
||||
if (con->conid)
|
||||
s->tipc_conn_shutdown(con->conid, con->usr_data);
|
||||
|
||||
spin_lock_bh(&s->idr_lock);
|
||||
idr_remove(&s->conn_idr, con->conid);
|
||||
s->idr_in_use--;
|
||||
|
@ -429,10 +427,12 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid,
|
|||
list_add_tail(&e->list, &con->outqueue);
|
||||
spin_unlock_bh(&con->outqueue_lock);
|
||||
|
||||
if (test_bit(CF_CONNECTED, &con->flags))
|
||||
if (test_bit(CF_CONNECTED, &con->flags)) {
|
||||
if (!queue_work(s->send_wq, &con->swork))
|
||||
conn_put(con);
|
||||
|
||||
} else {
|
||||
conn_put(con);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -997,7 +997,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long timeo)
|
|||
|
||||
for (;;) {
|
||||
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
|
||||
if (skb_queue_empty(&sk->sk_receive_queue)) {
|
||||
if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
|
||||
if (sock->state == SS_DISCONNECTING) {
|
||||
err = -ENOTCONN;
|
||||
break;
|
||||
|
@ -1623,7 +1623,7 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo)
|
|||
for (;;) {
|
||||
prepare_to_wait_exclusive(sk_sleep(sk), &wait,
|
||||
TASK_INTERRUPTIBLE);
|
||||
if (skb_queue_empty(&sk->sk_receive_queue)) {
|
||||
if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
|
||||
release_sock(sk);
|
||||
timeo = schedule_timeout(timeo);
|
||||
lock_sock(sk);
|
||||
|
|
|
@ -96,20 +96,16 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower,
|
|||
{
|
||||
struct tipc_subscriber *subscriber = sub->subscriber;
|
||||
struct kvec msg_sect;
|
||||
int ret;
|
||||
|
||||
msg_sect.iov_base = (void *)&sub->evt;
|
||||
msg_sect.iov_len = sizeof(struct tipc_event);
|
||||
|
||||
sub->evt.event = htohl(event, sub->swap);
|
||||
sub->evt.found_lower = htohl(found_lower, sub->swap);
|
||||
sub->evt.found_upper = htohl(found_upper, sub->swap);
|
||||
sub->evt.port.ref = htohl(port_ref, sub->swap);
|
||||
sub->evt.port.node = htohl(node, sub->swap);
|
||||
ret = tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL,
|
||||
msg_sect.iov_base, msg_sect.iov_len);
|
||||
if (ret < 0)
|
||||
pr_err("Sending subscription event failed, no memory\n");
|
||||
tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, msg_sect.iov_base,
|
||||
msg_sect.iov_len);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,14 +149,6 @@ static void subscr_timeout(struct tipc_subscription *sub)
|
|||
/* The spin lock per subscriber is used to protect its members */
|
||||
spin_lock_bh(&subscriber->lock);
|
||||
|
||||
/* Validate if the connection related to the subscriber is
|
||||
* closed (in case subscriber is terminating)
|
||||
*/
|
||||
if (subscriber->conid == 0) {
|
||||
spin_unlock_bh(&subscriber->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Validate timeout (in case subscription is being cancelled) */
|
||||
if (sub->timeout == TIPC_WAIT_FOREVER) {
|
||||
spin_unlock_bh(&subscriber->lock);
|
||||
|
@ -215,9 +203,6 @@ static void subscr_release(struct tipc_subscriber *subscriber)
|
|||
|
||||
spin_lock_bh(&subscriber->lock);
|
||||
|
||||
/* Invalidate subscriber reference */
|
||||
subscriber->conid = 0;
|
||||
|
||||
/* Destroy any existing subscriptions for subscriber */
|
||||
list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
|
||||
subscription_list) {
|
||||
|
|
Loading…
Reference in New Issue