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

Merge branch 'strp-kcm-fixes'



Tom Herbert says:

====================
strp: Minor fixes to strparser and kcm

Fix locking issue in kcm and losing events when paused.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3c90a941 1616b38f
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -88,10 +88,7 @@ static inline void strp_pause(struct strparser *strp)
}

/* May be called without holding lock for attached socket */
static inline void strp_unpause(struct strparser *strp)
{
	strp->rx_paused = 0;
}
void strp_unpause(struct strparser *strp);

static inline void save_strp_stats(struct strparser *strp,
				   struct strp_aggr_stats *agg_stats)
+15 −5
Original line number Diff line number Diff line
@@ -173,14 +173,24 @@ static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq,
	if (psock->strp.rx_stopped)
		seq_puts(seq, "RxStop ");

	if (psock->strp.rx_paused)
		seq_puts(seq, "RxPause ");

	if (psock->tx_kcm)
		seq_printf(seq, "Rsvd-%d ", psock->tx_kcm->index);

	if (!psock->strp.rx_paused && !psock->ready_rx_msg) {
		if (psock->sk->sk_receive_queue.qlen) {
			if (psock->strp.rx_need_bytes)
				seq_printf(seq, "RxWait=%u ",
					   psock->strp.rx_need_bytes);
			else
				seq_printf(seq, "RxWait ");
		}
	} else  {
		if (psock->strp.rx_paused)
			seq_puts(seq, "RxPause ");

		if (psock->ready_rx_msg)
			seq_puts(seq, "RdyRx ");
	}

	seq_puts(seq, "\n");
}
+8 −5
Original line number Diff line number Diff line
@@ -1477,12 +1477,13 @@ out:
	return err;
}

/* Lower socket lock held */
static void kcm_unattach(struct kcm_psock *psock)
{
	struct sock *csk = psock->sk;
	struct kcm_mux *mux = psock->mux;

	lock_sock(csk);

	/* Stop getting callbacks from TCP socket. After this there should
	 * be no way to reserve a kcm for this psock.
	 */
@@ -1514,7 +1515,10 @@ static void kcm_unattach(struct kcm_psock *psock)

	write_unlock_bh(&csk->sk_callback_lock);

	/* Call strp_done without sock lock */
	release_sock(csk);
	strp_done(&psock->strp);
	lock_sock(csk);

	bpf_prog_put(psock->bpf_prog);

@@ -1564,6 +1568,8 @@ no_reserved:
		fput(csk->sk_socket->file);
		kmem_cache_free(kcm_psockp, psock);
	}

	release_sock(csk);
}

static int kcm_unattach_ioctl(struct socket *sock, struct kcm_unattach *info)
@@ -1749,11 +1755,8 @@ static void release_mux(struct kcm_mux *mux)
	/* Release psocks */
	list_for_each_entry_safe(psock, tmp_psock,
				 &mux->psocks, psock_list) {
		if (!WARN_ON(psock->unattaching)) {
			lock_sock(psock->strp.sk);
		if (!WARN_ON(psock->unattaching))
			kcm_unattach(psock);
			release_sock(psock->strp.sk);
		}
	}

	if (WARN_ON(mux->psocks_cnt))
+11 −0
Original line number Diff line number Diff line
@@ -445,6 +445,17 @@ int strp_init(struct strparser *strp, struct sock *csk,
}
EXPORT_SYMBOL_GPL(strp_init);

void strp_unpause(struct strparser *strp)
{
	strp->rx_paused = 0;

	/* Sync setting rx_paused with RX work */
	smp_mb();

	queue_work(strp_wq, &strp->rx_work);
}
EXPORT_SYMBOL_GPL(strp_unpause);

/* strp must already be stopped so that strp_tcp_recv will no longer be called.
 * Note that strp_done is not called with the lower socket held.
 */