Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 409e1456 authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 9e9cb622 2892505e
Loading
Loading
Loading
Loading
+2 −7
Original line number Diff line number Diff line
@@ -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,
		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");

		kfree_skb(rep_buf);
	}
}
+0 −1
Original line number Diff line number Diff line
@@ -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;
	}
+34 −3
Original line number Diff line number Diff line
@@ -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;
+7 −7
Original line number Diff line number Diff line
@@ -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;
}

+2 −2
Original line number Diff line number Diff line
@@ -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);
Loading