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

Commit 39f66a7d authored by Xin Long's avatar Xin Long Committed by David S. Miller
Browse files

sctp: apply rhashtable api to sctp procfs



Traversal the transport rhashtable, get the association only once through
the condition assoc->peer.primary_path != transport.

Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
Signed-off-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4f008781
Loading
Loading
Loading
Loading
+173 −143
Original line number Diff line number Diff line
@@ -281,63 +281,114 @@ void sctp_eps_proc_exit(struct net *net)
	remove_proc_entry("eps", net->sctp.proc_net_sctp);
}

struct sctp_ht_iter {
	struct seq_net_private p;
	struct rhashtable_iter hti;
};

static void *sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
static struct sctp_transport *sctp_transport_get_next(struct seq_file *seq)
{
	if (*pos >= sctp_assoc_hashsize)
		return NULL;
	struct sctp_ht_iter *iter = seq->private;
	struct sctp_transport *t;

	if (*pos < 0)
		*pos = 0;
	t = rhashtable_walk_next(&iter->hti);
	for (; t; t = rhashtable_walk_next(&iter->hti)) {
		if (IS_ERR(t)) {
			if (PTR_ERR(t) == -EAGAIN)
				continue;
			break;
		}

	if (*pos == 0)
		seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT "
				"ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
				"RPORT LADDRS <-> RADDRS "
				"HBINT INS OUTS MAXRT T1X T2X RTXC "
				"wmema wmemq sndbuf rcvbuf\n");
		if (net_eq(sock_net(t->asoc->base.sk), seq_file_net(seq)) &&
		    t->asoc->peer.primary_path == t)
			break;
	}

	return (void *)pos;
	return t;
}

static void sctp_assocs_seq_stop(struct seq_file *seq, void *v)
static struct sctp_transport *sctp_transport_get_idx(struct seq_file *seq,
						     loff_t pos)
{
	void *obj;

	while (pos && (obj = sctp_transport_get_next(seq)) && !IS_ERR(obj))
		pos--;

	return obj;
}

static int sctp_transport_walk_start(struct seq_file *seq)
{
	struct sctp_ht_iter *iter = seq->private;
	int err;

	err = rhashtable_walk_init(&sctp_transport_hashtable, &iter->hti);
	if (err)
		return err;

	err = rhashtable_walk_start(&iter->hti);

	return err == -EAGAIN ? 0 : err;
}

static void sctp_transport_walk_stop(struct seq_file *seq)
{
	struct sctp_ht_iter *iter = seq->private;

	rhashtable_walk_stop(&iter->hti);
	rhashtable_walk_exit(&iter->hti);
}

static void *sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
{
	int err = sctp_transport_walk_start(seq);

	if (err)
		return ERR_PTR(err);

	return *pos ? sctp_transport_get_idx(seq, *pos) : SEQ_START_TOKEN;
}

static void sctp_assocs_seq_stop(struct seq_file *seq, void *v)
{
	sctp_transport_walk_stop(seq);
}

static void *sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	if (++*pos >= sctp_assoc_hashsize)
		return NULL;
	++*pos;

	return pos;
	return sctp_transport_get_next(seq);
}

/* Display sctp associations (/proc/net/sctp/assocs). */
static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
{
	struct sctp_hashbucket *head;
	struct sctp_ep_common *epb;
	struct sctp_transport *transport;
	struct sctp_association *assoc;
	struct sctp_ep_common *epb;
	struct sock *sk;
	int    hash = *(loff_t *)v;

	if (hash >= sctp_assoc_hashsize)
		return -ENOMEM;
	if (v == SEQ_START_TOKEN) {
		seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT "
				"ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
				"RPORT LADDRS <-> RADDRS "
				"HBINT INS OUTS MAXRT T1X T2X RTXC "
				"wmema wmemq sndbuf rcvbuf\n");
		return 0;
	}

	head = &sctp_assoc_hashtable[hash];
	local_bh_disable();
	read_lock(&head->lock);
	sctp_for_each_hentry(epb, &head->chain) {
		assoc = sctp_assoc(epb);
	transport = (struct sctp_transport *)v;
	assoc = transport->asoc;
	epb = &assoc->base;
	sk = epb->sk;
		if (!net_eq(sock_net(sk), seq_file_net(seq)))
			continue;

	seq_printf(seq,
		   "%8pK %8pK %-3d %-3d %-2d %-4d "
		   "%4d %8d %8d %7u %5lu %-5d %5d ",
		   assoc, sk, sctp_sk(sk)->type, sk->sk_state,
			   assoc->state, hash,
		   assoc->state, 0,
		   assoc->assoc_id,
		   assoc->sndbuf_used,
		   atomic_read(&assoc->rmem_alloc),
@@ -360,9 +411,6 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
		sk->sk_sndbuf,
		sk->sk_rcvbuf);
	seq_printf(seq, "\n");
	}
	read_unlock(&head->lock);
	local_bh_enable();

	return 0;
}
@@ -378,7 +426,7 @@ static const struct seq_operations sctp_assoc_ops = {
static int sctp_assocs_seq_open(struct inode *inode, struct file *file)
{
	return seq_open_net(inode, file, &sctp_assoc_ops,
			    sizeof(struct seq_net_private));
			    sizeof(struct sctp_ht_iter));
}

static const struct file_operations sctp_assocs_seq_fops = {
@@ -409,61 +457,49 @@ void sctp_assocs_proc_exit(struct net *net)

static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos)
{
	if (*pos >= sctp_assoc_hashsize)
		return NULL;

	if (*pos < 0)
		*pos = 0;
	int err = sctp_transport_walk_start(seq);

	if (*pos == 0)
		seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX "
				"REM_ADDR_RTX START STATE\n");
	if (err)
		return ERR_PTR(err);

	return (void *)pos;
	return *pos ? sctp_transport_get_idx(seq, *pos) : SEQ_START_TOKEN;
}

static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	if (++*pos >= sctp_assoc_hashsize)
		return NULL;
	++*pos;

	return pos;
	return sctp_transport_get_next(seq);
}

static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v)
{
	sctp_transport_walk_stop(seq);
}

static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
{
	struct sctp_hashbucket *head;
	struct sctp_ep_common *epb;
	struct sctp_association *assoc;
	struct sctp_transport *tsp;
	int    hash = *(loff_t *)v;

	if (hash >= sctp_assoc_hashsize)
		return -ENOMEM;
	if (v == SEQ_START_TOKEN) {
		seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX "
				"REM_ADDR_RTX START STATE\n");
		return 0;
	}

	tsp = (struct sctp_transport *)v;
	assoc = tsp->asoc;

	head = &sctp_assoc_hashtable[hash];
	local_bh_disable();
	read_lock(&head->lock);
	rcu_read_lock();
	sctp_for_each_hentry(epb, &head->chain) {
		if (!net_eq(sock_net(epb->sk), seq_file_net(seq)))
			continue;
		assoc = sctp_assoc(epb);
	list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
				transports) {
		if (tsp->dead)
			continue;

		/*
		 * The remote address (ADDR)
		 */
		tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr);
		seq_printf(seq, " ");

		/*
		 * The association ID (ASSOC_ID)
		 */
@@ -507,14 +543,8 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)

		seq_printf(seq, "\n");
	}
	}

	rcu_read_unlock();
	read_unlock(&head->lock);
	local_bh_enable();

	return 0;

}

static const struct seq_operations sctp_remaddr_ops = {
@@ -533,7 +563,7 @@ void sctp_remaddr_proc_exit(struct net *net)
static int sctp_remaddr_seq_open(struct inode *inode, struct file *file)
{
	return seq_open_net(inode, file, &sctp_remaddr_ops,
			    sizeof(struct seq_net_private));
			    sizeof(struct sctp_ht_iter));
}

static const struct file_operations sctp_remaddr_seq_fops = {