From patchwork Tue Jan 27 23:20:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herbert Xu X-Patchwork-Id: 433720 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id BD6CF140283 for ; Wed, 28 Jan 2015 10:21:23 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758180AbbA0XVS (ORCPT ); Tue, 27 Jan 2015 18:21:18 -0500 Received: from helcar.apana.org.au ([209.40.204.226]:47017 "EHLO helcar.apana.org.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754754AbbA0XVN (ORCPT ); Tue, 27 Jan 2015 18:21:13 -0500 Received: from gondolin.me.apana.org.au ([192.168.0.6]) by fornost.hengli.com.au with esmtp (Exim 4.80 #3 (Debian)) id 1YGFRC-0005uq-E8; Wed, 28 Jan 2015 10:20:50 +1100 Received: from herbert by gondolin.me.apana.org.au with local (Exim 4.80) (envelope-from ) id 1YGFRB-0002yg-Ry; Wed, 28 Jan 2015 10:20:49 +1100 Subject: [PATCH 2/2] netlink: Use rhashtable walk iterator References: <20150127231950.GA11374@gondor.apana.org.au> To: Thomas Graf , Ying Xue , davem@davemloft.net, kaber@trash.net, paulmck@linux.vnet.ibm.com, netdev@vger.kernel.org, netfilter-devel@vger.kernel.org Message-Id: From: Herbert Xu Date: Wed, 28 Jan 2015 10:20:49 +1100 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch gets rid of the manual rhashtable walk in netlink which touches rhashtable internals that should not be exposed. It does so by using the rhashtable iterator primitives. In fact the existing code was very buggy. Some sockets weren't shown at all while others were shown more than once. Signed-off-by: Herbert Xu Acked-by: Thomas Graf --- net/netlink/af_netlink.c | 113 +++++++++++++++++------------------------------ 1 file changed, 41 insertions(+), 72 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index d77b346..6f8549e 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -2884,99 +2884,68 @@ EXPORT_SYMBOL(nlmsg_notify); #ifdef CONFIG_PROC_FS struct nl_seq_iter { struct seq_net_private p; + struct rhashtable_iter hti; int link; - int hash_idx; }; -static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos) +static int netlink_walk_start(struct nl_seq_iter *iter) { - struct nl_seq_iter *iter = seq->private; - int i, j; - struct netlink_sock *nlk; - struct sock *s; - loff_t off = 0; - - for (i = 0; i < MAX_LINKS; i++) { - struct rhashtable *ht = &nl_table[i].hash; - const struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht); - - for (j = 0; j < tbl->size; j++) { - struct rhash_head *node; - - rht_for_each_entry_rcu(nlk, node, tbl, j, node) { - s = (struct sock *)nlk; - - if (sock_net(s) != seq_file_net(seq)) - continue; - if (off == pos) { - iter->link = i; - iter->hash_idx = j; - return s; - } - ++off; - } - } - } - return NULL; -} - -static void *netlink_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(RCU) -{ - rcu_read_lock(); - return *pos ? netlink_seq_socket_idx(seq, *pos - 1) : SEQ_START_TOKEN; + rhashtable_walk_init(&nl_table[iter->link].hash, &iter->hti); + return rhashtable_walk_start(&iter->hti); } -static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) +static void *__netlink_seq_next(struct seq_file *seq) { - struct rhashtable *ht; - const struct bucket_table *tbl; - struct rhash_head *node; + struct nl_seq_iter *iter = seq->private; struct netlink_sock *nlk; - struct nl_seq_iter *iter; - struct net *net; - int i, j; - ++*pos; + do { + while (!(nlk = rhashtable_walk_next(&iter->hti))) { + int err; - if (v == SEQ_START_TOKEN) - return netlink_seq_socket_idx(seq, 0); + rhashtable_walk_stop(&iter->hti); + if (++iter->link >= MAX_LINKS) + return NULL; - net = seq_file_net(seq); - iter = seq->private; - nlk = v; + err = netlink_walk_start(iter); + if (err) + return ERR_PTR(err); + } + } while (sock_net(&nlk->sk) != seq_file_net(seq)); - i = iter->link; - ht = &nl_table[i].hash; - tbl = rht_dereference_rcu(ht->tbl, ht); - rht_for_each_entry_rcu_continue(nlk, node, nlk->node.next, tbl, iter->hash_idx, node) - if (net_eq(sock_net((struct sock *)nlk), net)) - return nlk; + return nlk; +} - j = iter->hash_idx + 1; +static void *netlink_seq_start(struct seq_file *seq, loff_t *posp) +{ + struct nl_seq_iter *iter = seq->private; + void *obj = SEQ_START_TOKEN; + loff_t pos; + int err; - do { + iter->link = 0; + err = netlink_walk_start(iter); + if (err) + return ERR_PTR(err); - for (; j < tbl->size; j++) { - rht_for_each_entry_rcu(nlk, node, tbl, j, node) { - if (net_eq(sock_net((struct sock *)nlk), net)) { - iter->link = i; - iter->hash_idx = j; - return nlk; - } - } - } + for (pos = *posp; pos && obj; pos--) + obj = __netlink_seq_next(seq); - j = 0; - } while (++i < MAX_LINKS); + return obj; +} - return NULL; +static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + ++*pos; + return __netlink_seq_next(seq); } static void netlink_seq_stop(struct seq_file *seq, void *v) - __releases(RCU) { - rcu_read_unlock(); + struct nl_seq_iter *iter = seq->private; + + if (iter->link < MAX_LINKS) + rhashtable_walk_stop(&iter->hti); }