From patchwork Sun Feb 28 17:54:00 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Eckelmann X-Patchwork-Id: 15862 Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [127.0.0.1]) by open-mesh.org (Postfix) with ESMTP id 1589481A61; Sun, 28 Feb 2016 18:54:03 +0100 (CET) Authentication-Results: open-mesh.org; dkim=fail reason="verification failed; unprotected key" header.d=narfation.org header.i=@narfation.org header.b=Es2tnYts; dkim-adsp=fail (unprotected policy); dkim-atps=neutral Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=79.140.41.39; helo=v3-1039.vlinux.de; envelope-from=sven@narfation.org; receiver=b.a.t.m.a.n@lists.open-mesh.org Authentication-Results: open-mesh.org; dmarc=pass header.from=narfation.org Received: from v3-1039.vlinux.de (narfation.org [79.140.41.39]) by open-mesh.org (Postfix) with ESMTPS id 56DD081A4D for ; Sun, 28 Feb 2016 18:54:02 +0100 (CET) Received: from sven-edge.localnet (p200300C593C5AAFD0000000000002E16.dip0.t-ipconnect.de [IPv6:2003:c5:93c5:aafd::2e16]) by v3-1039.vlinux.de (Postfix) with ESMTPSA id B97661100E6; Sun, 28 Feb 2016 18:54:01 +0100 (CET) Authentication-Results: v3-1039.vlinux.de; dmarc=none header.from=narfation.org DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=narfation.org; s=20121; t=1456682042; bh=ISdeLnSdhT0GM4/K+RGGX9nblrTclLZmo/lpoNiCEss=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Es2tnYtsizPhBhl+ylQOoFcYfumftvU3r7dM6P9R0XgLmcK8wCUuyeqDNA0K7x3da vnXoBlv/5c+80B9NlefYQlLtkjw9n7lo0RiQdXvAQqCqDJvxY+ICe+iNwoy3SNjRmw M3khM8yFNXNQ6ImSWGpRuYrnBDX9+miS0BAiXoac= From: Sven Eckelmann To: Philipp Psurek Date: Sun, 28 Feb 2016 18:54 +0100 Message-ID: <10188871.knElSYMs1v@sven-edge> User-Agent: KMail/4.14.10 (Linux/4.4.0-1-amd64; KDE/4.14.14; x86_64; ; ) In-Reply-To: <1456681344.1958.64.camel@gmail.com> References: <1456616348.1958.16.camel@gmail.com> <1456681096.1958.61.camel@gmail.com> <1456681344.1958.64.camel@gmail.com> MIME-Version: 1.0 Cc: b.a.t.m.a.n@lists.open-mesh.org Subject: Re: [B.A.T.M.A.N.] batctl: page allocation failure X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" On Sunday 28 February 2016 18:42:24 Philipp Psurek wrote: > > this is interesting: > > > > batctl o | wc -l > > 9320 Yes, there was a line missing in my last patch The complete version is attached. But I doubt it makes much sense when you don't have the problem anymore. Kind regards, Sven From: Sven Eckelmann Date: Sun, 28 Feb 2016 17:13:12 +0100 Subject: [PATCH] TEST: speedup originator output by using seq_operations --- net/batman-adv/bat_iv_ogm.c | 93 +++++++++++--------------- net/batman-adv/bat_v.c | 91 +++++++++++--------------- net/batman-adv/bridge_loop_avoidance.c | 4 +- net/batman-adv/debugfs.c | 50 +++++++++++++- net/batman-adv/distributed-arp-table.c | 2 +- net/batman-adv/gateway_client.c | 2 +- net/batman-adv/main.c | 5 +- net/batman-adv/main.h | 3 +- net/batman-adv/network-coding.c | 2 +- net/batman-adv/originator.c | 115 +++++++++++++++++++++++++++++---- net/batman-adv/originator.h | 7 +- net/batman-adv/translation-table.c | 4 +- net/batman-adv/types.h | 30 ++++++++- 13 files changed, 268 insertions(+), 140 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 2c65668..cddb3e8 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -1846,74 +1846,54 @@ batadv_iv_ogm_orig_print_neigh(struct batadv_orig_node *orig_node, } } -/** - * batadv_iv_ogm_orig_print - print the originator table - * @bat_priv: the bat priv with all the soft interface information - * @seq: debugfs table seq_file struct - * @if_outgoing: the outgoing interface for which this should be printed - */ -static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv, - struct seq_file *seq, - struct batadv_hard_iface *if_outgoing) +static void batadv_iv_ogm_oriq_seq_header(struct batadv_priv *bat_priv, + struct seq_file *seq) { - struct batadv_neigh_node *neigh_node; - struct batadv_hashtable *hash = bat_priv->orig_hash; - int last_seen_msecs, last_seen_secs; - struct batadv_orig_node *orig_node; - struct batadv_neigh_ifinfo *n_ifinfo; - unsigned long last_seen_jiffies; - struct hlist_head *head; - int batman_count = 0; - u32 i; - seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n", "Originator", "last-seen", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF", "Potential nexthops"); +} - for (i = 0; i < hash->size; i++) { - head = &hash->table[i]; +static void batadv_iv_ogm_orig_seq_show(struct batadv_priv *bat_priv, + struct seq_file *seq, + struct batadv_orig_node *orig_node, + struct batadv_hard_iface *if_outgoing) +{ + struct batadv_neigh_node *neigh_node; + int last_seen_msecs, last_seen_secs; + struct batadv_neigh_ifinfo *n_ifinfo; + unsigned long last_seen_jiffies; - rcu_read_lock(); - hlist_for_each_entry_rcu(orig_node, head, hash_entry) { - neigh_node = batadv_orig_router_get(orig_node, - if_outgoing); - if (!neigh_node) - continue; + neigh_node = batadv_orig_router_get(orig_node, if_outgoing); + if (!neigh_node) + return; - n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, - if_outgoing); - if (!n_ifinfo) - goto next; + n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing); + if (!n_ifinfo) + goto next; - if (n_ifinfo->bat_iv.tq_avg == 0) - goto next; + if (n_ifinfo->bat_iv.tq_avg == 0) + goto next; - last_seen_jiffies = jiffies - orig_node->last_seen; - last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); - last_seen_secs = last_seen_msecs / 1000; - last_seen_msecs = last_seen_msecs % 1000; + last_seen_jiffies = jiffies - orig_node->last_seen; + last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); + last_seen_secs = last_seen_msecs / 1000; + last_seen_msecs = last_seen_msecs % 1000; - seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", - orig_node->orig, last_seen_secs, - last_seen_msecs, n_ifinfo->bat_iv.tq_avg, - neigh_node->addr, - neigh_node->if_incoming->net_dev->name); + seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", + orig_node->orig, last_seen_secs, + last_seen_msecs, n_ifinfo->bat_iv.tq_avg, + neigh_node->addr, + neigh_node->if_incoming->net_dev->name); - batadv_iv_ogm_orig_print_neigh(orig_node, if_outgoing, - seq); - seq_puts(seq, "\n"); - batman_count++; + batadv_iv_ogm_orig_print_neigh(orig_node, if_outgoing, + seq); + seq_puts(seq, "\n"); next: - batadv_neigh_node_put(neigh_node); - if (n_ifinfo) - batadv_neigh_ifinfo_put(n_ifinfo); - } - rcu_read_unlock(); - } - - if (batman_count == 0) - seq_puts(seq, "No batman nodes in range ...\n"); + batadv_neigh_node_put(neigh_node); + if (n_ifinfo) + batadv_neigh_ifinfo_put(n_ifinfo); } /** @@ -2062,7 +2042,8 @@ static struct batadv_algo_ops batadv_batman_iv __read_mostly = { .bat_neigh_cmp = batadv_iv_ogm_neigh_cmp, .bat_neigh_is_similar_or_better = batadv_iv_ogm_neigh_is_sob, .bat_neigh_print = batadv_iv_neigh_print, - .bat_orig_print = batadv_iv_ogm_orig_print, + .bat_orig_seq_header = batadv_iv_ogm_oriq_seq_header, + .bat_orig_seq_show = batadv_iv_ogm_orig_seq_show, .bat_orig_free = batadv_iv_ogm_orig_free, .bat_orig_add_if = batadv_iv_ogm_orig_add_if, .bat_orig_del_if = batadv_iv_ogm_orig_del_if, diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c index 3315b9a..6d3ff2d 100644 --- a/net/batman-adv/bat_v.c +++ b/net/batman-adv/bat_v.c @@ -171,72 +171,52 @@ static void batadv_v_neigh_print(struct batadv_priv *bat_priv, seq_puts(seq, "No batman nodes in range ...\n"); } -/** - * batadv_v_orig_print - print the originator table - * @bat_priv: the bat priv with all the soft interface information - * @seq: debugfs table seq_file struct - * @if_outgoing: the outgoing interface for which this should be printed - */ -static void batadv_v_orig_print(struct batadv_priv *bat_priv, - struct seq_file *seq, - struct batadv_hard_iface *if_outgoing) +static void batadv_v_orig_seq_header(struct batadv_priv *bat_priv, + struct seq_file *seq) { - struct batadv_neigh_node *neigh_node; - struct batadv_hashtable *hash = bat_priv->orig_hash; - int last_seen_msecs, last_seen_secs; - struct batadv_orig_node *orig_node; - struct batadv_neigh_ifinfo *n_ifinfo; - unsigned long last_seen_jiffies; - struct hlist_head *head; - int batman_count = 0; - u32 i; - seq_printf(seq, " %-15s %s (%11s) %17s [%10s]: %20s ...\n", "Originator", "last-seen", "throughput", "Nexthop", "outgoingIF", "Potential nexthops"); +} - for (i = 0; i < hash->size; i++) { - head = &hash->table[i]; +static void batadv_v_orig_seq_show(struct batadv_priv *bat_priv, + struct seq_file *seq, + struct batadv_orig_node *orig_node, + struct batadv_hard_iface *if_outgoing) +{ + struct batadv_neigh_node *neigh_node; + struct batadv_neigh_ifinfo *n_ifinfo; + int last_seen_msecs, last_seen_secs; + unsigned long last_seen_jiffies; - rcu_read_lock(); - hlist_for_each_entry_rcu(orig_node, head, hash_entry) { - neigh_node = batadv_orig_router_get(orig_node, - if_outgoing); - if (!neigh_node) - continue; + neigh_node = batadv_orig_router_get(orig_node, if_outgoing); + if (!neigh_node) + return; - n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, - if_outgoing); - if (!n_ifinfo) - goto next; + n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing); + if (!n_ifinfo) + goto next; - last_seen_jiffies = jiffies - orig_node->last_seen; - last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); - last_seen_secs = last_seen_msecs / 1000; - last_seen_msecs = last_seen_msecs % 1000; + last_seen_jiffies = jiffies - orig_node->last_seen; + last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); + last_seen_secs = last_seen_msecs / 1000; + last_seen_msecs = last_seen_msecs % 1000; - seq_printf(seq, "%pM %4i.%03is (%9u.%1u) %pM [%10s]:", - orig_node->orig, last_seen_secs, - last_seen_msecs, - n_ifinfo->bat_v.throughput / 10, - n_ifinfo->bat_v.throughput % 10, - neigh_node->addr, - neigh_node->if_incoming->net_dev->name); + seq_printf(seq, "%pM %4i.%03is (%9u.%1u) %pM [%10s]:", + orig_node->orig, last_seen_secs, + last_seen_msecs, + n_ifinfo->bat_v.throughput / 10, + n_ifinfo->bat_v.throughput % 10, + neigh_node->addr, + neigh_node->if_incoming->net_dev->name); - batadv_v_orig_print_neigh(orig_node, if_outgoing, seq); - seq_puts(seq, "\n"); - batman_count++; + batadv_v_orig_print_neigh(orig_node, if_outgoing, seq); + seq_puts(seq, "\n"); next: - batadv_neigh_node_put(neigh_node); - if (n_ifinfo) - batadv_neigh_ifinfo_put(n_ifinfo); - } - rcu_read_unlock(); - } - - if (batman_count == 0) - seq_puts(seq, "No batman nodes in range ...\n"); + batadv_neigh_node_put(neigh_node); + if (n_ifinfo) + batadv_neigh_ifinfo_put(n_ifinfo); } static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1, @@ -281,7 +261,8 @@ static struct batadv_algo_ops batadv_batman_v __read_mostly = { .bat_hardif_neigh_init = batadv_v_hardif_neigh_init, .bat_ogm_emit = batadv_v_ogm_emit, .bat_ogm_schedule = batadv_v_ogm_schedule, - .bat_orig_print = batadv_v_orig_print, + .bat_orig_seq_header = batadv_v_orig_seq_header, + .bat_orig_seq_show = batadv_v_orig_seq_show, .bat_neigh_cmp = batadv_v_neigh_cmp, .bat_neigh_is_similar_or_better = batadv_v_neigh_is_sob, .bat_neigh_print = batadv_v_neigh_print, diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 642167f..c00b9b8 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -1807,7 +1807,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) bool is_own; u8 *primary_addr; - primary_if = batadv_seq_print_text_primary_if_get(seq); + primary_if = batadv_seq_print_text_primary_if_get(seq, net_dev); if (!primary_if) goto out; @@ -1865,7 +1865,7 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) bool is_own; u8 *primary_addr; - primary_if = batadv_seq_print_text_primary_if_get(seq); + primary_if = batadv_seq_print_text_primary_if_get(seq, net_dev); if (!primary_if) goto out; diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c index 3dc5208..ddaae44 100644 --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c @@ -269,11 +269,43 @@ static int neighbors_open(struct inode *inode, struct file *file) return single_open(file, batadv_hardif_neigh_seq_print_text, net_dev); } -static int batadv_originators_open(struct inode *inode, struct file *file) +static const struct seq_operations batadv_orig_seq_ops = { + .start = batadv_orig_seq_start, + .next = batadv_orig_seq_next, + .stop = batadv_orig_seq_stop, + .show = batadv_orig_seq_show, +}; + +/** + * batadv_seq_open - TODO + * @inode: TODO + * @f: TODO + * @ops: TODO + * @size: TODO + * + * Return: TODO + */ +static int batadv_seq_open(struct inode *inode, struct file *f, + const struct seq_operations *ops, int size) { + struct batadv_seq_private *p; struct net_device *net_dev = (struct net_device *)inode->i_private; - return single_open(file, batadv_orig_seq_print_text, net_dev); + BUG_ON(size < sizeof(*p)); + + p = __seq_open_private(f, ops, size); + if (p == NULL) + return -ENOMEM; + + p->net_dev = net_dev; + + return 0; +} + +static int batadv_originators_open(struct inode *inode, struct file *file) +{ + return batadv_seq_open(inode, file, &batadv_orig_seq_ops, + sizeof(struct batadv_seq_hash_iter)); } /** @@ -375,6 +407,18 @@ struct batadv_debuginfo batadv_debuginfo_##_name = { \ } \ } +#define BATADV_DEBUGINFO_SEQ(_name, _mode, _open) \ +struct batadv_debuginfo batadv_debuginfo_##_name = { \ + .attr = { .name = __stringify(_name), \ + .mode = _mode, }, \ + .fops = { .owner = THIS_MODULE, \ + .open = _open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = seq_release_private, \ + } \ +} + /* the following attributes are general and therefore they will be directly * placed in the BATADV_DEBUGFS_SUBDIR subdirectory of debugfs */ @@ -387,7 +431,7 @@ static struct batadv_debuginfo *batadv_general_debuginfos[] = { /* The following attributes are per soft interface */ static BATADV_DEBUGINFO(neighbors, S_IRUGO, neighbors_open); -static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open); +static BATADV_DEBUGINFO_SEQ(originators, S_IRUGO, batadv_originators_open); static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open); static BATADV_DEBUGINFO(transtable_global, S_IRUGO, batadv_transtable_global_open); diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 919a8d2..dc553e5 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -809,7 +809,7 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset) int last_seen_msecs, last_seen_secs, last_seen_mins; u32 i; - primary_if = batadv_seq_print_text_primary_if_get(seq); + primary_if = batadv_seq_print_text_primary_if_get(seq, net_dev); if (!primary_if) goto out; diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index c59aff5..1c2360c 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -637,7 +637,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset) struct batadv_gw_node *gw_node; int gw_count = 0; - primary_if = batadv_seq_print_text_primary_if_get(seq); + primary_if = batadv_seq_print_text_primary_if_get(seq, net_dev); if (!primary_if) goto out; diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index d64ddb9..74c81eb 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -269,13 +269,14 @@ bool batadv_is_my_mac(struct batadv_priv *bat_priv, const u8 *addr) * batadv_seq_print_text_primary_if_get - called from debugfs table printing * function that requires the primary interface * @seq: debugfs table seq_file struct + * @net_dev: batman-adv net_device * * Return: primary interface if found or NULL otherwise. */ struct batadv_hard_iface * -batadv_seq_print_text_primary_if_get(struct seq_file *seq) +batadv_seq_print_text_primary_if_get(struct seq_file *seq, + struct net_device *net_dev) { - struct net_device *net_dev = (struct net_device *)seq->private; struct batadv_priv *bat_priv = netdev_priv(net_dev); struct batadv_hard_iface *primary_if; diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index e602408..94e9f57 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -203,7 +203,8 @@ int batadv_mesh_init(struct net_device *soft_iface); void batadv_mesh_free(struct net_device *soft_iface); bool batadv_is_my_mac(struct batadv_priv *bat_priv, const u8 *addr); struct batadv_hard_iface * -batadv_seq_print_text_primary_if_get(struct seq_file *seq); +batadv_seq_print_text_primary_if_get(struct seq_file *seq, + struct net_device *net_dev); int batadv_max_header_len(void); void batadv_skb_set_priority(struct sk_buff *skb, int offset); int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev, diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index 32f9fa1..38fbecc 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -1905,7 +1905,7 @@ int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset) struct batadv_nc_node *nc_node; int i; - primary_if = batadv_seq_print_text_primary_if_get(seq); + primary_if = batadv_seq_print_text_primary_if_get(seq, net_dev); if (!primary_if) goto out; diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index e63d6a5..ed0f626 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -698,7 +698,7 @@ int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset) struct batadv_priv *bat_priv = netdev_priv(net_dev); struct batadv_hard_iface *primary_if; - primary_if = batadv_seq_print_text_primary_if_get(seq); + primary_if = batadv_seq_print_text_primary_if_get(seq, net_dev); if (!primary_if) return 0; @@ -1235,35 +1235,121 @@ void batadv_purge_orig_ref(struct batadv_priv *bat_priv) _batadv_purge_orig(bat_priv); } -int batadv_orig_seq_print_text(struct seq_file *seq, void *offset) +static void batadv_orig_seq_show_header(struct seq_file *seq) { - struct net_device *net_dev = (struct net_device *)seq->private; - struct batadv_priv *bat_priv = netdev_priv(net_dev); + struct batadv_seq_hash_iter *iter = seq->private; + struct batadv_priv *bat_priv = netdev_priv(iter->p.net_dev); struct batadv_hard_iface *primary_if; - primary_if = batadv_seq_print_text_primary_if_get(seq); + primary_if = batadv_seq_print_text_primary_if_get(seq, iter->p.net_dev); if (!primary_if) - return 0; + return; seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s %s)]\n", BATADV_SOURCE_VERSION, primary_if->net_dev->name, - primary_if->net_dev->dev_addr, net_dev->name, + primary_if->net_dev->dev_addr, iter->p.net_dev->name, bat_priv->bat_algo_ops->name); batadv_hardif_put(primary_if); - if (!bat_priv->bat_algo_ops->bat_orig_print) { - seq_puts(seq, - "No printing function for this routing protocol\n"); + if (bat_priv->bat_algo_ops->bat_orig_seq_header) + bat_priv->bat_algo_ops->bat_orig_seq_header(bat_priv, seq); +} + +static void *batadv_orig_seq_get_idx(struct seq_file *seq, loff_t pos) +{ + struct batadv_seq_hash_iter *iter = seq->private; + struct batadv_priv *bat_priv = netdev_priv(iter->p.net_dev); + struct batadv_hashtable *hash = bat_priv->orig_hash; + struct hlist_head *head; + loff_t cur = 0; + + iter->bucket = 0; + iter->entry = NULL; + + for (; iter->bucket < hash->size; iter->bucket++) { + head = &hash->table[iter->bucket]; + iter->entry = rcu_dereference_raw(hlist_first_rcu(head)); + + if (iter->entry) { + cur++; + if (cur == pos) + return iter->entry; + } + } + + return NULL; +} + +void *batadv_orig_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(RCU) +{ + rcu_read_lock(); + + if (*pos == 0) + return SEQ_START_TOKEN; + return batadv_orig_seq_get_idx(seq, *pos); +} + +void *batadv_orig_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct batadv_seq_hash_iter *iter = seq->private; + struct batadv_priv *bat_priv = netdev_priv(iter->p.net_dev); + struct batadv_hashtable *hash = bat_priv->orig_hash; + struct hlist_head *head; + + ++*pos; + if (v == SEQ_START_TOKEN) { + iter->bucket = 0; + iter->entry = NULL; + /* TODO seq_puts(seq, "No batman nodes in range ...\n"); */ + } else { + iter->entry = rcu_dereference_raw(hlist_next_rcu(iter->entry)); + if (!iter->entry) + iter->bucket++; + } + + if (iter->entry) + return iter->entry; + + for (; iter->bucket < hash->size; iter->bucket++) { + head = &hash->table[iter->bucket]; + iter->entry = rcu_dereference_raw(hlist_first_rcu(head)); + + if (iter->entry) + return iter->entry; + } + + return NULL; +} + +int batadv_orig_seq_show(struct seq_file *seq, void *v) +{ + struct batadv_seq_hash_iter *iter = seq->private; + struct batadv_priv *bat_priv = netdev_priv(iter->p.net_dev); + struct batadv_orig_node *orig_node; + + if (v == SEQ_START_TOKEN) { + batadv_orig_seq_show_header(seq); return 0; } - bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq, - BATADV_IF_DEFAULT); + orig_node = hlist_entry(iter->entry, struct batadv_orig_node, hash_entry); + + if (bat_priv->bat_algo_ops->bat_orig_seq_show) + bat_priv->bat_algo_ops->bat_orig_seq_show(bat_priv, seq, + orig_node, + BATADV_IF_DEFAULT); return 0; } +void batadv_orig_seq_stop(struct seq_file *seq, void *v) + __releases(RCU) +{ + rcu_read_unlock(); +} + /** * batadv_orig_hardif_seq_print_text - writes originator infos for a specific * outgoing interface @@ -1276,7 +1362,7 @@ int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct batadv_hard_iface *hard_iface; - struct batadv_priv *bat_priv; + /* TODO struct batadv_priv *bat_priv; */ hard_iface = batadv_hardif_get_by_netdev(net_dev); @@ -1285,6 +1371,8 @@ int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset) goto out; } + /* + TODO bat_priv = netdev_priv(hard_iface->soft_iface); if (!bat_priv->bat_algo_ops->bat_orig_print) { seq_puts(seq, @@ -1303,6 +1391,7 @@ int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset) hard_iface->soft_iface->name, bat_priv->bat_algo_ops->name); bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq, hard_iface); + */ out: if (hard_iface) diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 64a8951..ba5a915 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@ -29,6 +29,7 @@ #include #include +#include "hard-interface.h" #include "hash.h" struct seq_file; @@ -71,7 +72,11 @@ batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node, struct batadv_hard_iface *if_outgoing); void batadv_orig_ifinfo_put(struct batadv_orig_ifinfo *orig_ifinfo); -int batadv_orig_seq_print_text(struct seq_file *seq, void *offset); +void *batadv_orig_seq_start(struct seq_file *seq, loff_t *pos); +void *batadv_orig_seq_next(struct seq_file *seq, void *v, loff_t *pos); +int batadv_orig_seq_show(struct seq_file *seq, void *v); +void batadv_orig_seq_stop(struct seq_file *seq, void *v); + int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset); int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, int max_if_num); diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 2ed55f4..eab36a9 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -1001,7 +1001,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) bool no_purge; u16 np_flag = BATADV_TT_CLIENT_NOPURGE; - primary_if = batadv_seq_print_text_primary_if_get(seq); + primary_if = batadv_seq_print_text_primary_if_get(seq, net_dev); if (!primary_if) goto out; @@ -1699,7 +1699,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset) struct hlist_head *head; u32 i; - primary_if = batadv_seq_print_text_primary_if_get(seq); + primary_if = batadv_seq_print_text_primary_if_get(seq, net_dev); if (!primary_if) goto out; diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 9abfb3e..764332e 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1297,8 +1297,12 @@ struct batadv_algo_ops { void (*bat_neigh_print)(struct batadv_priv *priv, struct seq_file *seq); void (*bat_neigh_free)(struct batadv_neigh_node *neigh); /* orig_node handling API */ - void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq, - struct batadv_hard_iface *hard_iface); + void (*bat_orig_seq_header)(struct batadv_priv *priv, + struct seq_file *seq); + void (*bat_orig_seq_show)(struct batadv_priv *priv, + struct seq_file *seq, + struct batadv_orig_node *orig_node, + struct batadv_hard_iface *if_outgoing); void (*bat_orig_free)(struct batadv_orig_node *orig_node); int (*bat_orig_add_if)(struct batadv_orig_node *orig_node, int max_if_num); @@ -1403,4 +1407,26 @@ enum batadv_tvlv_handler_flags { BATADV_TVLV_HANDLER_OGM_CALLED = BIT(2), }; +/** + * struct batadv_seq_private - private data of seq_open + * @net_dev: network device the seq private data belongs to + */ +struct batadv_seq_private { + struct net_device *net_dev; +}; + +/** + * struct batadv_seq_hash_iter - private data of seq_open for hash iterators + * @p: standard batadv_seq_private data + * @header_shown: whether header was already shown + * @bucket: current hash bucket + * @entry: current hash entry + */ +struct batadv_seq_hash_iter { + struct batadv_seq_private p; + int header_shown; + u32 bucket; + struct hlist_node *entry; +}; + #endif /* _NET_BATMAN_ADV_TYPES_H_ */