* Re: [PATCH net-next 1/4] net: Introduce NETIF_F_GRO_HW
From: David Miller @ 2017-12-04 18:59 UTC (permalink / raw)
To: alexander.duyck; +Cc: michael.chan, netdev, Ariel.Elior, everest-linux-l2
In-Reply-To: <CAKgT0Uc9Nb3jaiz1VRt6bUpjAZGKwUM9xrjvoJUbEAyCKpGXVA@mail.gmail.com>
From: Alexander Duyck <alexander.duyck@gmail.com>
Date: Mon, 4 Dec 2017 10:43:58 -0800
> On Mon, Dec 4, 2017 at 10:23 AM, Michael Chan <michael.chan@broadcom.com> wrote:
>> On Mon, Dec 4, 2017 at 8:47 AM, Alexander Duyck
>> <alexander.duyck@gmail.com> wrote:
>>> On Mon, Dec 4, 2017 at 3:12 AM, Michael Chan <michael.chan@broadcom.com> wrote:
>>>> Introduce NETIF_F_GRO_HW feature flag for NICs that support hardware
>>>> GRO. With this flag, we can now independently turn on or off hardware
>>>> GRO when GRO is on. Hardware GRO guarantees that packets can be
>>>> re-segmented by TSO/GSO to reconstruct the original packet stream.
>>>>
>>>> Cc: Ariel Elior <Ariel.Elior@cavium.com>
>>>> Cc: everest-linux-l2@cavium.com
>>>> Signed-off-by: Michael Chan <michael.chan@broadcom.com>
>>>
>>> Do we really need yet another feature bit for this? We already have
>>> LRO and GRO and now we have to add something that isn't quite either
>>> one?
>>
>> I think so, to be consistent with TSO/GSO on the transmit side. On
>> the receive side, we have LRO/GRO_HW/GRO. There is difference between
>> LRO/GRO_HW that we need to distinguish between the 2.
>
> I don't really see the difference. Your GRO_HW likely doens't do all
> of the stuff GRO can do. Neither does LRO. Both occur in the hardware
> normally. It would make sense to reuse the LRO flag for this instead
> of coming up with a new feature flag that makes things confusing by
> saying you are doing a software offload in hardware.
>
> I view LRO as a subset of what GRO can handle, that is performed in
> hardware. From the stack perspective the only thing that really
> matters is that the frames can be segmented back into what they were
> before they were assembled. That is why I think it would be better to
> add a flag indicating that the LRO is reversible instead of adding yet
> another feature bit that the user has to toggle. That way if at some
> point in the future an issue is found where your "GRO in hardware"
> feature has a bug that isn't reversible it is just a matter of
> clearing the privage flag bit and the mechanisms already in place for
> dealing with assembly and routing can take over.
I don't think they should use the LRO flag.
If their HW GRO stream is fully reversible, which it is, then it's not
LRO.
LRO gets disabled when bridging or routing is enabled, and HW GRO
should not take this penalty.
^ permalink raw reply
* [net-next:master 134/141] net/core/rtnetlink.c:155:15: sparse: incompatible types in comparison expression (different address spaces)
From: kbuild test robot @ 2017-12-04 18:58 UTC (permalink / raw)
To: Florian Westphal; +Cc: kbuild-all, netdev
tree: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git master
head: a3fde2addd5f0218b64102005a237ef727b0dc30
commit: addf9b90de22f7aaad0db39bccb5d51ac47dd4e1 [134/141] net: rtnetlink: use rcu to free rtnl message handlers
reproduce:
# apt-get install sparse
git checkout addf9b90de22f7aaad0db39bccb5d51ac47dd4e1
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
vim +155 net/core/rtnetlink.c
147
148 static struct rtnl_link *rtnl_get_link(int protocol, int msgtype)
149 {
150 struct rtnl_link **tab;
151
152 if (protocol >= ARRAY_SIZE(rtnl_msg_handlers))
153 protocol = PF_UNSPEC;
154
> 155 tab = rcu_dereference_rtnl(rtnl_msg_handlers[protocol]);
156 if (!tab)
157 tab = rcu_dereference_rtnl(rtnl_msg_handlers[PF_UNSPEC]);
158
159 return tab[msgtype];
160 }
161
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply
* Re: [Patch net v2] tipc: fix a null pointer deref on error path
From: David Miller @ 2017-12-04 18:57 UTC (permalink / raw)
To: xiyou.wangcong; +Cc: netdev, tipc-discussion, jon.maloy, ying.xue
In-Reply-To: <20171204183143.7395-1-xiyou.wangcong@gmail.com>
From: Cong Wang <xiyou.wangcong@gmail.com>
Date: Mon, 4 Dec 2017 10:31:43 -0800
> In tipc_topsrv_kern_subscr() when s->tipc_conn_new() fails
> we call tipc_close_conn() to clean up, but in this case
> calling conn_put() is just enough.
>
> This fixes the folllowing crash:
...
> Fixes: 14c04493cb77 ("tipc: add ability to order and receive topology events in driver")
> Reported-by: syzbot <syzkaller@googlegroups.com>
> Cc: Jon Maloy <jon.maloy@ericsson.com>
> Cc: Ying Xue <ying.xue@windriver.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
...
> @@ -511,7 +511,7 @@ bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type,
> s = con->server;
> scbr = s->tipc_conn_new(*conid);
> if (!scbr) {
> - tipc_close_conn(con);
> + conn_put(con);
> return false;
> }
>
> --
> 2.13.0
>
It looks like tipc_accept_from_sock() has a similar problem? The
tipc_close_conn() will get invoked indirectly from the sock_release()
path right?
^ permalink raw reply
* [Patch net-next v2] net_sched: get rid of rcu_barrier() in tcf_block_put_ext()
From: Cong Wang @ 2017-12-04 18:48 UTC (permalink / raw)
To: netdev; +Cc: pabeni, Cong Wang, Eric Dumazet, Jiri Pirko, Jamal Hadi Salim
Both Eric and Paolo noticed the rcu_barrier() we use in
tcf_block_put_ext() could be a performance bottleneck when
we have a lot of tc classes.
Paolo provided the following to demonstrate the issue:
tc qdisc add dev lo root htb
for I in `seq 1 1000`; do
tc class add dev lo parent 1: classid 1:$I htb rate 100kbit
tc qdisc add dev lo parent 1:$I handle $((I + 1)): htb
for J in `seq 1 10`; do
tc filter add dev lo parent $((I + 1)): u32 match ip src 1.1.1.$J
done
done
time tc qdisc del dev root
real 0m54.764s
user 0m0.023s
sys 0m0.000s
The rcu_barrier() there is to ensure we free the block after all chains
are gone, that is, to queue tcf_block_put_final() at the tail of workqueue.
We can achieve this ordering requirement by refcnt'ing tcf block instead,
that is, the tcf block is freed only when the last chain in this block is
gone. This also simplifies the code.
Paolo reported after this patch we get:
real 0m0.017s
user 0m0.000s
sys 0m0.017s
Tested-by: Paolo Abeni <pabeni@redhat.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jiri Pirko <jiri@mellanox.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
include/net/sch_generic.h | 1 -
net/sched/cls_api.c | 30 +++++++++---------------------
2 files changed, 9 insertions(+), 22 deletions(-)
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 65d0d25f2648..02e7ad8b8dad 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -278,7 +278,6 @@ struct tcf_block {
struct net *net;
struct Qdisc *q;
struct list_head cb_list;
- struct work_struct work;
};
static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index ddcf04b4ab43..d51051dd8f7d 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -218,8 +218,12 @@ static void tcf_chain_flush(struct tcf_chain *chain)
static void tcf_chain_destroy(struct tcf_chain *chain)
{
+ struct tcf_block *block = chain->block;
+
list_del(&chain->list);
kfree(chain);
+ if (list_empty(&block->chain_list))
+ kfree(block);
}
static void tcf_chain_hold(struct tcf_chain *chain)
@@ -330,27 +334,13 @@ int tcf_block_get(struct tcf_block **p_block,
}
EXPORT_SYMBOL(tcf_block_get);
-static void tcf_block_put_final(struct work_struct *work)
-{
- struct tcf_block *block = container_of(work, struct tcf_block, work);
- struct tcf_chain *chain, *tmp;
-
- rtnl_lock();
-
- /* At this point, all the chains should have refcnt == 1. */
- list_for_each_entry_safe(chain, tmp, &block->chain_list, list)
- tcf_chain_put(chain);
- rtnl_unlock();
- kfree(block);
-}
-
/* XXX: Standalone actions are not allowed to jump to any chain, and bound
* actions should be all removed after flushing.
*/
void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
struct tcf_block_ext_info *ei)
{
- struct tcf_chain *chain;
+ struct tcf_chain *chain, *tmp;
/* Hold a refcnt for all chains, except 0, so that they don't disappear
* while we are iterating.
@@ -364,13 +354,11 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
tcf_block_offload_unbind(block, q, ei);
- INIT_WORK(&block->work, tcf_block_put_final);
- /* Wait for existing RCU callbacks to cool down, make sure their works
- * have been queued before this. We can not flush pending works here
- * because we are holding the RTNL lock.
+ /* At this point, all the chains should have refcnt >= 1. Block will be
+ * freed after all chains are gone.
*/
- rcu_barrier();
- tcf_queue_work(&block->work);
+ list_for_each_entry_safe(chain, tmp, &block->chain_list, list)
+ tcf_chain_put(chain);
}
EXPORT_SYMBOL(tcf_block_put_ext);
--
2.13.0
^ permalink raw reply related
* Re: [PATCH net-next 1/4] net: Introduce NETIF_F_GRO_HW
From: Alexander Duyck @ 2017-12-04 18:43 UTC (permalink / raw)
To: Michael Chan; +Cc: David Miller, Netdev, Ariel Elior, everest-linux-l2
In-Reply-To: <CACKFLi=rBacDPZJGUY1EBgNQ0Tr8esb+4DGyftfwqpY509UChw@mail.gmail.com>
On Mon, Dec 4, 2017 at 10:23 AM, Michael Chan <michael.chan@broadcom.com> wrote:
> On Mon, Dec 4, 2017 at 8:47 AM, Alexander Duyck
> <alexander.duyck@gmail.com> wrote:
>> On Mon, Dec 4, 2017 at 3:12 AM, Michael Chan <michael.chan@broadcom.com> wrote:
>>> Introduce NETIF_F_GRO_HW feature flag for NICs that support hardware
>>> GRO. With this flag, we can now independently turn on or off hardware
>>> GRO when GRO is on. Hardware GRO guarantees that packets can be
>>> re-segmented by TSO/GSO to reconstruct the original packet stream.
>>>
>>> Cc: Ariel Elior <Ariel.Elior@cavium.com>
>>> Cc: everest-linux-l2@cavium.com
>>> Signed-off-by: Michael Chan <michael.chan@broadcom.com>
>>
>> Do we really need yet another feature bit for this? We already have
>> LRO and GRO and now we have to add something that isn't quite either
>> one?
>
> I think so, to be consistent with TSO/GSO on the transmit side. On
> the receive side, we have LRO/GRO_HW/GRO. There is difference between
> LRO/GRO_HW that we need to distinguish between the 2.
I don't really see the difference. Your GRO_HW likely doens't do all
of the stuff GRO can do. Neither does LRO. Both occur in the hardware
normally. It would make sense to reuse the LRO flag for this instead
of coming up with a new feature flag that makes things confusing by
saying you are doing a software offload in hardware.
I view LRO as a subset of what GRO can handle, that is performed in
hardware. From the stack perspective the only thing that really
matters is that the frames can be segmented back into what they were
before they were assembled. That is why I think it would be better to
add a flag indicating that the LRO is reversible instead of adding yet
another feature bit that the user has to toggle. That way if at some
point in the future an issue is found where your "GRO in hardware"
feature has a bug that isn't reversible it is just a matter of
clearing the privage flag bit and the mechanisms already in place for
dealing with assembly and routing can take over.
>>
>> I think I would rather have something like a netdev private flag that
>> says LRO assembled frames are routable and just have this all run over
>> the LRO flag with a test for the private flag to avoid triggering the
>> LRO disable in the case of the flag being present. Really this is just
>> a clean LRO implementation anyway so maybe we should just go that
>> route where LRO is the hardware offload and GRO is the generic
>> software implementation of that offload. That way when GRO gets some
>> new feature that your hardware doesn't support we don't have to argue
>> about the differences since LRO is meant to be a limited
>> implementation anyway due to the nature of it being in hardware.
>
> Private flag will work. But a standard feature flag is better since
> there are multiple drivers supporting this. A standard way to turn
> this on/off is a better user experience. It's also consistent with
> TSO/GSO on the transmit side.
I agree, and that is why I would prefer to see this use the LRO flag.
It is the flag that is normally used to indicating Rx coalescing in
hardware. Coming up with a custom feature flag for a form of LRO that
your hardware does doesn't make much sense to me. Otherwise I might as
well go modify ixgbe and rename the LRO it does to GRO_HW since I can
make it do most of what you are doing here.
>>
>> To me it just seems like this is an attempt to use the GRO name as a
>> marketing term and I really don't like the feel of it.
>>
>
> I disagree with this. It's more than a marketing term.
Not really. It is a subset of GRO offload in hardware. In my mind that
is just LRO. I say subset since odds are you don't support all of the
same protocols and tunnels that GRO in software does.
^ permalink raw reply
* Re: [PATCH net-next] rtnetlink: ipv6: convert remaining users to rtnl_register_module
From: David Miller @ 2017-12-04 18:35 UTC (permalink / raw)
To: fw; +Cc: netdev
In-Reply-To: <20171204181918.8133-1-fw@strlen.de>
From: Florian Westphal <fw@strlen.de>
Date: Mon, 4 Dec 2017 19:19:18 +0100
> convert remaining users of rtnl_register to rtnl_register_module
> and un-export rtnl_register.
>
> Requested-by: David S. Miller <davem@davemloft.net>
> Signed-off-by: Florian Westphal <fw@strlen.de>
Applied, thanks for following up on this so quickly.
^ permalink raw reply
* Re: net/ipv4: general protection fault in inet_csk_listen_stop
From: Eric Dumazet @ 2017-12-04 18:32 UTC (permalink / raw)
To: idaifish, davem, netdev, syzkaller
In-Reply-To: <CADUsjNminHYSgMt37jcbTNYo0K+6TyPEH0gPqkiKD+Qcw4X--Q@mail.gmail.com>
On Mon, 2017-12-04 at 17:34 +0800, idaifish wrote:
> Hi,
>
> Got the following report while fuzzing the 4.9.66 with syzkaller.
> This bug can be triggered by the attached program on Ubuntu16.04
> (4.4.0-101-generic)
>
Hi
What about current kernels ?
Thanks.
^ permalink raw reply
* [PATCH v2 net-next 5/5] rhashtable: Call library function alloc_bucket_locks
From: Tom Herbert @ 2017-12-04 18:31 UTC (permalink / raw)
To: davem; +Cc: netdev, herbert, rohit, Tom Herbert
In-Reply-To: <20171204183145.3277-1-tom@quantonium.net>
To allocate the array of bucket locks for the hash table we now
call library function alloc_bucket_spinlocks. This function is
based on the old alloc_bucket_locks in rhashtable and should
produce the same effect.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
lib/rhashtable.c | 47 ++++++++---------------------------------------
1 file changed, 8 insertions(+), 39 deletions(-)
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 6fc52d82efe6..3825c30aaa36 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -65,42 +65,6 @@ EXPORT_SYMBOL_GPL(lockdep_rht_bucket_is_held);
#define ASSERT_RHT_MUTEX(HT)
#endif
-
-static int alloc_bucket_locks(struct rhashtable *ht, struct bucket_table *tbl,
- gfp_t gfp)
-{
- unsigned int i, size;
-#if defined(CONFIG_PROVE_LOCKING)
- unsigned int nr_pcpus = 2;
-#else
- unsigned int nr_pcpus = num_possible_cpus();
-#endif
-
- nr_pcpus = min_t(unsigned int, nr_pcpus, 64UL);
- size = roundup_pow_of_two(nr_pcpus * ht->p.locks_mul);
-
- /* Never allocate more than 0.5 locks per bucket */
- size = min_t(unsigned int, size, tbl->size >> 1);
-
- if (tbl->nest)
- size = min(size, 1U << tbl->nest);
-
- if (sizeof(spinlock_t) != 0) {
- if (gfpflags_allow_blocking(gfp))
- tbl->locks = kvmalloc(size * sizeof(spinlock_t), gfp);
- else
- tbl->locks = kmalloc_array(size, sizeof(spinlock_t),
- gfp);
- if (!tbl->locks)
- return -ENOMEM;
- for (i = 0; i < size; i++)
- spin_lock_init(&tbl->locks[i]);
- }
- tbl->locks_mask = size - 1;
-
- return 0;
-}
-
static void nested_table_free(union nested_table *ntbl, unsigned int size)
{
const unsigned int shift = PAGE_SHIFT - ilog2(sizeof(void *));
@@ -140,7 +104,7 @@ static void bucket_table_free(const struct bucket_table *tbl)
if (tbl->nest)
nested_bucket_table_free(tbl);
- kvfree(tbl->locks);
+ free_bucket_spinlocks(tbl->locks);
kvfree(tbl);
}
@@ -207,7 +171,7 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
gfp_t gfp)
{
struct bucket_table *tbl = NULL;
- size_t size;
+ size_t size, max_locks;
int i;
size = sizeof(*tbl) + nbuckets * sizeof(tbl->buckets[0]);
@@ -227,7 +191,12 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
tbl->size = size;
- if (alloc_bucket_locks(ht, tbl, gfp) < 0) {
+ max_locks = size >> 1;
+ if (tbl->nest)
+ max_locks = min_t(size_t, max_locks, 1U << tbl->nest);
+
+ if (alloc_bucket_spinlocks(&tbl->locks, &tbl->locks_mask, max_locks,
+ ht->p.locks_mul, gfp) < 0) {
bucket_table_free(tbl);
return NULL;
}
--
2.11.0
^ permalink raw reply related
* [PATCH v2 net-next 4/5] spinlock: Add library function to allocate spinlock buckets array
From: Tom Herbert @ 2017-12-04 18:31 UTC (permalink / raw)
To: davem; +Cc: netdev, herbert, rohit, Tom Herbert
In-Reply-To: <20171204183145.3277-1-tom@quantonium.net>
Add two new library functions: alloc_bucket_spinlocks and
free_bucket_spinlocks. These are used to allocate and free an array
of spinlocks that are useful as locks for hash buckets. The interface
specifies the maximum number of spinlocks in the array as well
as a CPU multiplier to derive the number of spinlocks to allocate.
The number allocated is rounded up to a power of two to make the
array amenable to hash lookup.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
include/linux/spinlock.h | 6 ++++++
lib/Makefile | 2 +-
lib/bucket_locks.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 61 insertions(+), 1 deletion(-)
create mode 100644 lib/bucket_locks.c
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index a39186194cd6..10fd28b118ee 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -414,4 +414,10 @@ extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
#define atomic_dec_and_lock(atomic, lock) \
__cond_lock(lock, _atomic_dec_and_lock(atomic, lock))
+int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask,
+ size_t max_size, unsigned int cpu_mult,
+ gfp_t gfp);
+
+void free_bucket_spinlocks(spinlock_t *locks);
+
#endif /* __LINUX_SPINLOCK_H */
diff --git a/lib/Makefile b/lib/Makefile
index d11c48ec8ffd..a6c8529dd9b2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -39,7 +39,7 @@ obj-y += bcd.o div64.o sort.o parser.o debug_locks.o random32.o \
gcd.o lcm.o list_sort.o uuid.o flex_array.o iov_iter.o clz_ctz.o \
bsearch.o find_bit.o llist.o memweight.o kfifo.o \
percpu-refcount.o percpu_ida.o rhashtable.o reciprocal_div.o \
- once.o refcount.o usercopy.o errseq.o
+ once.o refcount.o usercopy.o errseq.o bucket_locks.o
obj-$(CONFIG_STRING_SELFTEST) += test_string.o
obj-y += string_helpers.o
obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
diff --git a/lib/bucket_locks.c b/lib/bucket_locks.c
new file mode 100644
index 000000000000..266a97c5708b
--- /dev/null
+++ b/lib/bucket_locks.c
@@ -0,0 +1,54 @@
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+/* Allocate an array of spinlocks to be accessed by a hash. Two arguments
+ * indicate the number of elements to allocate in the array. max_size
+ * gives the maximum number of elements to allocate. cpu_mult gives
+ * the number of locks per CPU to allocate. The size is rounded up
+ * to a power of 2 to be suitable as a hash table.
+ */
+
+int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *locks_mask,
+ size_t max_size, unsigned int cpu_mult, gfp_t gfp)
+{
+ spinlock_t *tlocks = NULL;
+ unsigned int i, size;
+#if defined(CONFIG_PROVE_LOCKING)
+ unsigned int nr_pcpus = 2;
+#else
+ unsigned int nr_pcpus = num_possible_cpus();
+#endif
+
+ if (cpu_mult) {
+ nr_pcpus = min_t(unsigned int, nr_pcpus, 64UL);
+ size = min_t(unsigned int, nr_pcpus * cpu_mult, max_size);
+ } else {
+ size = max_size;
+ }
+
+ if (sizeof(spinlock_t) != 0) {
+ if (gfpflags_allow_blocking(gfp))
+ tlocks = kvmalloc(size * sizeof(spinlock_t), gfp);
+ else
+ tlocks = kmalloc_array(size, sizeof(spinlock_t), gfp);
+ if (!tlocks)
+ return -ENOMEM;
+ for (i = 0; i < size; i++)
+ spin_lock_init(&tlocks[i]);
+ }
+
+ *locks = tlocks;
+ *locks_mask = size - 1;
+
+ return 0;
+}
+EXPORT_SYMBOL(alloc_bucket_spinlocks);
+
+void free_bucket_spinlocks(spinlock_t *locks)
+{
+ kvfree(locks);
+}
+EXPORT_SYMBOL(free_bucket_spinlocks);
--
2.11.0
^ permalink raw reply related
* [PATCH v2 net-next 3/5] rhashtable: abstract out function to get hash
From: Tom Herbert @ 2017-12-04 18:31 UTC (permalink / raw)
To: davem; +Cc: netdev, herbert, rohit, Tom Herbert
In-Reply-To: <20171204183145.3277-1-tom@quantonium.net>
Split out most of rht_key_hashfn which is calculating the hash into
its own function. This way the hash function can be called separately to
get the hash value.
Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
include/linux/rhashtable.h | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 542b1b265ac4..c9df2527e0cd 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -240,34 +240,42 @@ static inline unsigned int rht_bucket_index(const struct bucket_table *tbl,
return (hash >> RHT_HASH_RESERVED_SPACE) & (tbl->size - 1);
}
-static inline unsigned int rht_key_hashfn(
- struct rhashtable *ht, const struct bucket_table *tbl,
- const void *key, const struct rhashtable_params params)
+static inline unsigned int rht_key_get_hash(struct rhashtable *ht,
+ const void *key, const struct rhashtable_params params,
+ unsigned int hash_rnd)
{
unsigned int hash;
/* params must be equal to ht->p if it isn't constant. */
if (!__builtin_constant_p(params.key_len))
- hash = ht->p.hashfn(key, ht->key_len, tbl->hash_rnd);
+ hash = ht->p.hashfn(key, ht->key_len, hash_rnd);
else if (params.key_len) {
unsigned int key_len = params.key_len;
if (params.hashfn)
- hash = params.hashfn(key, key_len, tbl->hash_rnd);
+ hash = params.hashfn(key, key_len, hash_rnd);
else if (key_len & (sizeof(u32) - 1))
- hash = jhash(key, key_len, tbl->hash_rnd);
+ hash = jhash(key, key_len, hash_rnd);
else
- hash = jhash2(key, key_len / sizeof(u32),
- tbl->hash_rnd);
+ hash = jhash2(key, key_len / sizeof(u32), hash_rnd);
} else {
unsigned int key_len = ht->p.key_len;
if (params.hashfn)
- hash = params.hashfn(key, key_len, tbl->hash_rnd);
+ hash = params.hashfn(key, key_len, hash_rnd);
else
- hash = jhash(key, key_len, tbl->hash_rnd);
+ hash = jhash(key, key_len, hash_rnd);
}
+ return hash;
+}
+
+static inline unsigned int rht_key_hashfn(
+ struct rhashtable *ht, const struct bucket_table *tbl,
+ const void *key, const struct rhashtable_params params)
+{
+ unsigned int hash = rht_key_get_hash(ht, key, params, tbl->hash_rnd);
+
return rht_bucket_index(tbl, hash);
}
--
2.11.0
^ permalink raw reply related
* [PATCH v2 net-next 2/5] rhashtable: Add rhastable_walk_peek
From: Tom Herbert @ 2017-12-04 18:31 UTC (permalink / raw)
To: davem; +Cc: netdev, herbert, rohit, Tom Herbert
In-Reply-To: <20171204183145.3277-1-tom@quantonium.net>
This function is like rhashtable_walk_next except that it only returns
the current element in the inter and does not advance the iter.
This patch also creates __rhashtable_walk_find_next. It finds the next
element in the table when the entry cached in iter is NULL or at the end
of a slot. __rhashtable_walk_find_next is called from
rhashtable_walk_next and rhastable_walk_peek.
end_of_table is an added field to the iter structure. This indicates
that the end of table was reached (walker.tbl being NULL is not a
sufficient condition for end of table).
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
include/linux/rhashtable.h | 2 +
lib/rhashtable.c | 103 ++++++++++++++++++++++++++++++++++++++-------
2 files changed, 89 insertions(+), 16 deletions(-)
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 13ccc483738d..542b1b265ac4 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -207,6 +207,7 @@ struct rhashtable_iter {
struct rhashtable_walker walker;
unsigned int slot;
unsigned int skip;
+ bool end_of_table;
};
static inline unsigned long rht_marker(const struct rhashtable *ht, u32 hash)
@@ -386,6 +387,7 @@ static inline void rhashtable_walk_start(struct rhashtable_iter *iter)
}
void *rhashtable_walk_next(struct rhashtable_iter *iter);
+void *rhashtable_walk_peek(struct rhashtable_iter *iter);
void rhashtable_walk_stop(struct rhashtable_iter *iter) __releases(RCU);
void rhashtable_free_and_destroy(struct rhashtable *ht,
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 1935e86ed477..6fc52d82efe6 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -707,6 +707,7 @@ void rhashtable_walk_enter(struct rhashtable *ht, struct rhashtable_iter *iter)
iter->p = NULL;
iter->slot = 0;
iter->skip = 0;
+ iter->end_of_table = 0;
spin_lock(&ht->lock);
iter->walker.tbl =
@@ -761,7 +762,7 @@ int rhashtable_walk_start_check(struct rhashtable_iter *iter)
list_del(&iter->walker.list);
spin_unlock(&ht->lock);
- if (!iter->walker.tbl) {
+ if (!iter->walker.tbl && !iter->end_of_table) {
iter->walker.tbl = rht_dereference_rcu(ht->tbl, ht);
return -EAGAIN;
}
@@ -771,18 +772,16 @@ int rhashtable_walk_start_check(struct rhashtable_iter *iter)
EXPORT_SYMBOL_GPL(rhashtable_walk_start_check);
/**
- * rhashtable_walk_next - Return the next object and advance the iterator
+ * __rhashtable_walk_find_next - Find the next element in a table (or the first
+ * one in case of a new walk).
+ *
* @iter: Hash table iterator
*
- * Note that you must call rhashtable_walk_stop when you are finished
- * with the walk.
+ * Returns the found object or NULL when the end of the table is reached.
*
- * Returns the next object or NULL when the end of the table is reached.
- *
- * Returns -EAGAIN if resize event occured. Note that the iterator
- * will rewind back to the beginning and you may continue to use it.
+ * Returns -EAGAIN if resize event occurred.
*/
-void *rhashtable_walk_next(struct rhashtable_iter *iter)
+static void *__rhashtable_walk_find_next(struct rhashtable_iter *iter)
{
struct bucket_table *tbl = iter->walker.tbl;
struct rhlist_head *list = iter->list;
@@ -790,13 +789,8 @@ void *rhashtable_walk_next(struct rhashtable_iter *iter)
struct rhash_head *p = iter->p;
bool rhlist = ht->rhlist;
- if (p) {
- if (!rhlist || !(list = rcu_dereference(list->next))) {
- p = rcu_dereference(p->next);
- list = container_of(p, struct rhlist_head, rhead);
- }
- goto next;
- }
+ if (!tbl)
+ return NULL;
for (; iter->slot < tbl->size; iter->slot++) {
int skip = iter->skip;
@@ -840,13 +834,90 @@ void *rhashtable_walk_next(struct rhashtable_iter *iter)
iter->slot = 0;
iter->skip = 0;
return ERR_PTR(-EAGAIN);
+ } else {
+ iter->end_of_table = true;
}
return NULL;
}
+
+/**
+ * rhashtable_walk_next - Return the next object and advance the iterator
+ * @iter: Hash table iterator
+ *
+ * Note that you must call rhashtable_walk_stop when you are finished
+ * with the walk.
+ *
+ * Returns the next object or NULL when the end of the table is reached.
+ *
+ * Returns -EAGAIN if resize event occurred. Note that the iterator
+ * will rewind back to the beginning and you may continue to use it.
+ */
+void *rhashtable_walk_next(struct rhashtable_iter *iter)
+{
+ struct rhlist_head *list = iter->list;
+ struct rhashtable *ht = iter->ht;
+ struct rhash_head *p = iter->p;
+ bool rhlist = ht->rhlist;
+
+ if (p) {
+ if (!rhlist || !(list = rcu_dereference(list->next))) {
+ p = rcu_dereference(p->next);
+ list = container_of(p, struct rhlist_head, rhead);
+ }
+ if (!rht_is_a_nulls(p)) {
+ iter->skip++;
+ iter->p = p;
+ iter->list = list;
+ return rht_obj(ht, rhlist ? &list->rhead : p);
+ }
+
+ /* At the end of this slot, switch to next one and then find
+ * next entry from that point.
+ */
+ iter->skip = 0;
+ iter->slot++;
+ }
+
+ return __rhashtable_walk_find_next(iter);
+}
EXPORT_SYMBOL_GPL(rhashtable_walk_next);
/**
+ * rhashtable_walk_peek - Return the next object but don't advance the iterator
+ * @iter: Hash table iterator
+ *
+ * Returns the next object or NULL when the end of the table is reached.
+ *
+ * Returns -EAGAIN if resize event occurred. Note that the iterator
+ * will rewind back to the beginning and you may continue to use it.
+ */
+void *rhashtable_walk_peek(struct rhashtable_iter *iter)
+{
+ struct rhlist_head *list = iter->list;
+ struct rhashtable *ht = iter->ht;
+ struct rhash_head *p = iter->p;
+
+ if (p)
+ return rht_obj(ht, ht->rhlist ? &list->rhead : p);
+
+ /* No object found in current iter, find next one in the table. */
+
+ if (iter->skip) {
+ /* A nonzero skip value points to the next entry in the table
+ * beyond that last one that was found. Decrement skip so
+ * we find the current value. __rhashtable_walk_find_next
+ * will restore the original value of skip assuming that
+ * the table hasn't changed.
+ */
+ iter->skip--;
+ }
+
+ return __rhashtable_walk_find_next(iter);
+}
+EXPORT_SYMBOL_GPL(rhashtable_walk_peek);
+
+/**
* rhashtable_walk_stop - Finish a hash table walk
* @iter: Hash table iterator
*
--
2.11.0
^ permalink raw reply related
* [PATCH v2 net-next 1/5] rhashtable: Change rhashtable_walk_start to return void
From: Tom Herbert @ 2017-12-04 18:31 UTC (permalink / raw)
To: davem; +Cc: netdev, herbert, rohit, Tom Herbert
In-Reply-To: <20171204183145.3277-1-tom@quantonium.net>
Most callers of rhashtable_walk_start don't care about a resize event
which is indicated by a return value of -EAGAIN. So calls to
rhashtable_walk_start are wrapped wih code to ignore -EAGAIN. Something
like this is common:
ret = rhashtable_walk_start(rhiter);
if (ret && ret != -EAGAIN)
goto out;
Since zero and -EAGAIN are the only possible return values from the
function this check is pointless. The condition never evaluates to true.
This patch changes rhashtable_walk_start to return void. This simplifies
code for the callers that ignore -EAGAIN. For the few cases where the
caller cares about the resize event, particularly where the table can be
walked in mulitple parts for netlink or seq file dump, the function
rhashtable_walk_start_check has been added that returns -EAGAIN on a
resize event.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 6 +---
.../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c | 7 ++---
fs/gfs2/glock.c | 7 ++---
include/linux/rhashtable.h | 8 ++++-
include/net/sctp/sctp.h | 2 +-
lib/rhashtable.c | 10 +++++--
lib/test_rhashtable.c | 6 +---
net/ipv6/ila/ila_xlat.c | 4 +--
net/ipv6/seg6.c | 4 +--
net/mac80211/mesh_pathtbl.c | 34 +++++++---------------
net/netfilter/nft_set_hash.c | 10 ++-----
net/netlink/af_netlink.c | 5 ++--
net/netlink/diag.c | 8 ++---
net/sctp/proc.c | 6 +---
net/sctp/socket.c | 19 +++---------
net/tipc/socket.c | 6 ++--
16 files changed, 48 insertions(+), 94 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
index d5031f436f83..df6a57087848 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
@@ -1416,11 +1416,7 @@ bnxt_tc_flow_stats_batch_prep(struct bnxt *bp,
void *flow_node;
int rc, i;
- rc = rhashtable_walk_start(iter);
- if (rc && rc != -EAGAIN) {
- i = 0;
- goto done;
- }
+ rhashtable_walk_start(iter);
rc = 0;
for (i = 0; i < BNXT_FLOW_STATS_BATCH_MAX; i++) {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
index d4a548a6a55c..6d7a10d0c45e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -765,9 +765,7 @@ static void ch_flower_stats_handler(struct work_struct *work)
rhashtable_walk_enter(&adap->flower_tbl, &iter);
do {
- flower_entry = ERR_PTR(rhashtable_walk_start(&iter));
- if (IS_ERR(flower_entry))
- goto walk_stop;
+ rhashtable_walk_start(&iter);
while ((flower_entry = rhashtable_walk_next(&iter)) &&
!IS_ERR(flower_entry)) {
@@ -786,8 +784,9 @@ static void ch_flower_stats_handler(struct work_struct *work)
spin_unlock(&flower_entry->lock);
}
}
-walk_stop:
+
rhashtable_walk_stop(&iter);
+
} while (flower_entry == ERR_PTR(-EAGAIN));
rhashtable_walk_exit(&iter);
mod_timer(&adap->flower_stats_timer, jiffies + STATS_CHECK_PERIOD);
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 11066d8647d2..90af87ff29ba 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -1549,16 +1549,13 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
rhashtable_walk_enter(&gl_hash_table, &iter);
do {
- gl = ERR_PTR(rhashtable_walk_start(&iter));
- if (IS_ERR(gl))
- goto walk_stop;
+ rhashtable_walk_start(&iter);
while ((gl = rhashtable_walk_next(&iter)) && !IS_ERR(gl))
if (gl->gl_name.ln_sbd == sdp &&
lockref_get_not_dead(&gl->gl_lockref))
examiner(gl);
-walk_stop:
rhashtable_walk_stop(&iter);
} while (cond_resched(), gl == ERR_PTR(-EAGAIN));
@@ -1947,7 +1944,7 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
loff_t n = *pos;
rhashtable_walk_enter(&gl_hash_table, &gi->hti);
- if (rhashtable_walk_start(&gi->hti) != 0)
+ if (rhashtable_walk_start_check(&gi->hti) != 0)
return NULL;
do {
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 361c08e35dbc..13ccc483738d 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -378,7 +378,13 @@ void *rhashtable_insert_slow(struct rhashtable *ht, const void *key,
void rhashtable_walk_enter(struct rhashtable *ht,
struct rhashtable_iter *iter);
void rhashtable_walk_exit(struct rhashtable_iter *iter);
-int rhashtable_walk_start(struct rhashtable_iter *iter) __acquires(RCU);
+int rhashtable_walk_start_check(struct rhashtable_iter *iter) __acquires(RCU);
+
+static inline void rhashtable_walk_start(struct rhashtable_iter *iter)
+{
+ (void)rhashtable_walk_start_check(iter);
+}
+
void *rhashtable_walk_next(struct rhashtable_iter *iter);
void rhashtable_walk_stop(struct rhashtable_iter *iter) __releases(RCU);
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 906a9c0efa71..6f79415f6634 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -116,7 +116,7 @@ extern struct percpu_counter sctp_sockets_allocated;
int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *);
struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *);
-int sctp_transport_walk_start(struct rhashtable_iter *iter);
+void sctp_transport_walk_start(struct rhashtable_iter *iter);
void sctp_transport_walk_stop(struct rhashtable_iter *iter);
struct sctp_transport *sctp_transport_get_next(struct net *net,
struct rhashtable_iter *iter);
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index ddd7dde87c3c..1935e86ed477 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -732,7 +732,7 @@ void rhashtable_walk_exit(struct rhashtable_iter *iter)
EXPORT_SYMBOL_GPL(rhashtable_walk_exit);
/**
- * rhashtable_walk_start - Start a hash table walk
+ * rhashtable_walk_start_check - Start a hash table walk
* @iter: Hash table iterator
*
* Start a hash table walk at the current iterator position. Note that we take
@@ -744,8 +744,12 @@ EXPORT_SYMBOL_GPL(rhashtable_walk_exit);
* Returns -EAGAIN if resize event occured. Note that the iterator
* will rewind back to the beginning and you may use it immediately
* by calling rhashtable_walk_next.
+ *
+ * rhashtable_walk_start is defined as an inline variant that returns
+ * void. This is preferred in cases where the caller would ignore
+ * resize events and always continue.
*/
-int rhashtable_walk_start(struct rhashtable_iter *iter)
+int rhashtable_walk_start_check(struct rhashtable_iter *iter)
__acquires(RCU)
{
struct rhashtable *ht = iter->ht;
@@ -764,7 +768,7 @@ int rhashtable_walk_start(struct rhashtable_iter *iter)
return 0;
}
-EXPORT_SYMBOL_GPL(rhashtable_walk_start);
+EXPORT_SYMBOL_GPL(rhashtable_walk_start_check);
/**
* rhashtable_walk_next - Return the next object and advance the iterator
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
index 8e83cbdc049c..76d3667fdea2 100644
--- a/lib/test_rhashtable.c
+++ b/lib/test_rhashtable.c
@@ -162,11 +162,7 @@ static void test_bucket_stats(struct rhashtable *ht, unsigned int entries)
return;
}
- err = rhashtable_walk_start(&hti);
- if (err && err != -EAGAIN) {
- pr_warn("Test failed: iterator failed: %d\n", err);
- return;
- }
+ rhashtable_walk_start(&hti);
while ((pos = rhashtable_walk_next(&hti))) {
if (PTR_ERR(pos) == -EAGAIN) {
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 6eb5e68f112a..44c39c5f0638 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -512,9 +512,7 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
struct ila_map *ila;
int ret;
- ret = rhashtable_walk_start(rhiter);
- if (ret && ret != -EAGAIN)
- goto done;
+ rhashtable_walk_start(rhiter);
for (;;) {
ila = rhashtable_walk_next(rhiter);
diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
index c81407770956..7f5621d09571 100644
--- a/net/ipv6/seg6.c
+++ b/net/ipv6/seg6.c
@@ -306,9 +306,7 @@ static int seg6_genl_dumphmac(struct sk_buff *skb, struct netlink_callback *cb)
struct seg6_hmac_info *hinfo;
int ret;
- ret = rhashtable_walk_start(iter);
- if (ret && ret != -EAGAIN)
- goto done;
+ rhashtable_walk_start(iter);
for (;;) {
hinfo = rhashtable_walk_next(iter);
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 86c8dfef56a4..a5125624a76d 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -257,9 +257,7 @@ __mesh_path_lookup_by_idx(struct mesh_table *tbl, int idx)
if (ret)
return NULL;
- ret = rhashtable_walk_start(&iter);
- if (ret && ret != -EAGAIN)
- goto err;
+ rhashtable_walk_start(&iter);
while ((mpath = rhashtable_walk_next(&iter))) {
if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
@@ -269,7 +267,6 @@ __mesh_path_lookup_by_idx(struct mesh_table *tbl, int idx)
if (i++ == idx)
break;
}
-err:
rhashtable_walk_stop(&iter);
rhashtable_walk_exit(&iter);
@@ -513,9 +510,7 @@ void mesh_plink_broken(struct sta_info *sta)
if (ret)
return;
- ret = rhashtable_walk_start(&iter);
- if (ret && ret != -EAGAIN)
- goto out;
+ rhashtable_walk_start(&iter);
while ((mpath = rhashtable_walk_next(&iter))) {
if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
@@ -535,7 +530,6 @@ void mesh_plink_broken(struct sta_info *sta)
WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast);
}
}
-out:
rhashtable_walk_stop(&iter);
rhashtable_walk_exit(&iter);
}
@@ -584,9 +578,7 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
if (ret)
return;
- ret = rhashtable_walk_start(&iter);
- if (ret && ret != -EAGAIN)
- goto out;
+ rhashtable_walk_start(&iter);
while ((mpath = rhashtable_walk_next(&iter))) {
if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
@@ -597,7 +589,7 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
if (rcu_access_pointer(mpath->next_hop) == sta)
__mesh_path_del(tbl, mpath);
}
-out:
+
rhashtable_walk_stop(&iter);
rhashtable_walk_exit(&iter);
}
@@ -614,9 +606,7 @@ static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata,
if (ret)
return;
- ret = rhashtable_walk_start(&iter);
- if (ret && ret != -EAGAIN)
- goto out;
+ rhashtable_walk_start(&iter);
while ((mpath = rhashtable_walk_next(&iter))) {
if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
@@ -627,7 +617,7 @@ static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata,
if (ether_addr_equal(mpath->mpp, proxy))
__mesh_path_del(tbl, mpath);
}
-out:
+
rhashtable_walk_stop(&iter);
rhashtable_walk_exit(&iter);
}
@@ -642,9 +632,7 @@ static void table_flush_by_iface(struct mesh_table *tbl)
if (ret)
return;
- ret = rhashtable_walk_start(&iter);
- if (ret && ret != -EAGAIN)
- goto out;
+ rhashtable_walk_start(&iter);
while ((mpath = rhashtable_walk_next(&iter))) {
if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
@@ -653,7 +641,7 @@ static void table_flush_by_iface(struct mesh_table *tbl)
break;
__mesh_path_del(tbl, mpath);
}
-out:
+
rhashtable_walk_stop(&iter);
rhashtable_walk_exit(&iter);
}
@@ -873,9 +861,7 @@ void mesh_path_tbl_expire(struct ieee80211_sub_if_data *sdata,
if (ret)
return;
- ret = rhashtable_walk_start(&iter);
- if (ret && ret != -EAGAIN)
- goto out;
+ rhashtable_walk_start(&iter);
while ((mpath = rhashtable_walk_next(&iter))) {
if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
@@ -887,7 +873,7 @@ void mesh_path_tbl_expire(struct ieee80211_sub_if_data *sdata,
time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
__mesh_path_del(tbl, mpath);
}
-out:
+
rhashtable_walk_stop(&iter);
rhashtable_walk_exit(&iter);
}
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
index f8166c1d5430..3f1624ee056f 100644
--- a/net/netfilter/nft_set_hash.c
+++ b/net/netfilter/nft_set_hash.c
@@ -251,11 +251,7 @@ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set,
if (err)
return;
- err = rhashtable_walk_start(&hti);
- if (err && err != -EAGAIN) {
- iter->err = err;
- goto out;
- }
+ rhashtable_walk_start(&hti);
while ((he = rhashtable_walk_next(&hti))) {
if (IS_ERR(he)) {
@@ -306,9 +302,7 @@ static void nft_rhash_gc(struct work_struct *work)
if (err)
goto schedule;
- err = rhashtable_walk_start(&hti);
- if (err && err != -EAGAIN)
- goto out;
+ rhashtable_walk_start(&hti);
while ((he = rhashtable_walk_next(&hti))) {
if (IS_ERR(he)) {
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index b9e0ee4e22f5..ab325d4d6fef 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2478,8 +2478,9 @@ static int netlink_walk_start(struct nl_seq_iter *iter)
return err;
}
- err = rhashtable_walk_start(&iter->hti);
- return err == -EAGAIN ? 0 : err;
+ rhashtable_walk_start(&iter->hti);
+
+ return 0;
}
static void netlink_walk_stop(struct nl_seq_iter *iter)
diff --git a/net/netlink/diag.c b/net/netlink/diag.c
index 8faa20b4d457..7dda33b9b784 100644
--- a/net/netlink/diag.c
+++ b/net/netlink/diag.c
@@ -115,11 +115,7 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
if (!s_num)
rhashtable_walk_enter(&tbl->hash, hti);
- ret = rhashtable_walk_start(hti);
- if (ret == -EAGAIN)
- ret = 0;
- if (ret)
- goto stop;
+ rhashtable_walk_start(hti);
while ((nlsk = rhashtable_walk_next(hti))) {
if (IS_ERR(nlsk)) {
@@ -146,8 +142,8 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
}
}
-stop:
rhashtable_walk_stop(hti);
+
if (ret)
goto done;
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 26b4be6b4172..4545bc2aff84 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -288,12 +288,8 @@ struct sctp_ht_iter {
static void *sctp_transport_seq_start(struct seq_file *seq, loff_t *pos)
{
struct sctp_ht_iter *iter = seq->private;
- int err = sctp_transport_walk_start(&iter->hti);
- if (err) {
- iter->start_fail = 1;
- return ERR_PTR(err);
- }
+ sctp_transport_walk_start(&iter->hti);
iter->start_fail = 0;
return sctp_transport_get_idx(seq_file_net(seq), &iter->hti, *pos);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 014847e25648..1dae4742cac4 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4676,20 +4676,11 @@ int sctp_get_sctp_info(struct sock *sk, struct sctp_association *asoc,
EXPORT_SYMBOL_GPL(sctp_get_sctp_info);
/* use callback to avoid exporting the core structure */
-int sctp_transport_walk_start(struct rhashtable_iter *iter)
+void sctp_transport_walk_start(struct rhashtable_iter *iter)
{
- int err;
-
rhltable_walk_enter(&sctp_transport_hashtable, iter);
- err = rhashtable_walk_start(iter);
- if (err && err != -EAGAIN) {
- rhashtable_walk_stop(iter);
- rhashtable_walk_exit(iter);
- return err;
- }
-
- return 0;
+ rhashtable_walk_start(iter);
}
void sctp_transport_walk_stop(struct rhashtable_iter *iter)
@@ -4780,12 +4771,10 @@ int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *),
struct net *net, int *pos, void *p) {
struct rhashtable_iter hti;
struct sctp_transport *tsp;
- int ret;
+ int ret = 0;
again:
- ret = sctp_transport_walk_start(&hti);
- if (ret)
- return ret;
+ sctp_transport_walk_start(&hti);
tsp = sctp_transport_get_idx(net, &hti, *pos + 1);
for (; !IS_ERR_OR_NULL(tsp); tsp = sctp_transport_get_next(net, &hti)) {
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 5d18c0caa92b..22c4fd8a9dfe 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -2640,9 +2640,7 @@ void tipc_sk_reinit(struct net *net)
rhashtable_walk_enter(&tn->sk_rht, &iter);
do {
- tsk = ERR_PTR(rhashtable_walk_start(&iter));
- if (IS_ERR(tsk))
- goto walk_stop;
+ rhashtable_walk_start(&iter);
while ((tsk = rhashtable_walk_next(&iter)) && !IS_ERR(tsk)) {
spin_lock_bh(&tsk->sk.sk_lock.slock);
@@ -2651,7 +2649,7 @@ void tipc_sk_reinit(struct net *net)
msg_set_orignode(msg, tn->own_addr);
spin_unlock_bh(&tsk->sk.sk_lock.slock);
}
-walk_stop:
+
rhashtable_walk_stop(&iter);
} while (tsk == ERR_PTR(-EAGAIN));
}
--
2.11.0
^ permalink raw reply related
* [PATCH v2 net-next 0/5] rhashtable: New features in walk and bucket
From: Tom Herbert @ 2017-12-04 18:31 UTC (permalink / raw)
To: davem; +Cc: netdev, herbert, rohit, Tom Herbert
This patch contains some changes to related rhashtable:
- Above allow rhashtable_walk_start to return void
- Add a functon to peek at the next entry during a walk
- Abstract out function to compute a has for a table
- A library function to alloc a spinlocks bucket array
- Call the above function for rhashtable locks allocation
Tested: Exercised using various operations on an ILA xlat
table.
v2:
- Apply feedback from Herbert. Don't change semantics of resize
event reporting and -EAGAIN, just simplify API for callers that
ignore those.
- Add end_of_table in iter to reliably tell when the iterator has
reached to the eno.
Tom Herbert (5):
rhashtable: Change rhashtable_walk_start to return void
rhashtable: Add rhastable_walk_peek
rhashtable: abstract out function to get hash
spinlock: Add library function to allocate spinlock buckets array
rhashtable: Call library function alloc_bucket_locks
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 6 +-
.../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c | 7 +-
fs/gfs2/glock.c | 7 +-
include/linux/rhashtable.h | 38 +++--
include/linux/spinlock.h | 6 +
include/net/sctp/sctp.h | 2 +-
lib/Makefile | 2 +-
lib/bucket_locks.c | 54 +++++++
lib/rhashtable.c | 160 +++++++++++++--------
lib/test_rhashtable.c | 6 +-
net/ipv6/ila/ila_xlat.c | 4 +-
net/ipv6/seg6.c | 4 +-
net/mac80211/mesh_pathtbl.c | 34 ++---
net/netfilter/nft_set_hash.c | 10 +-
net/netlink/af_netlink.c | 5 +-
net/netlink/diag.c | 8 +-
net/sctp/proc.c | 6 +-
net/sctp/socket.c | 19 +--
net/tipc/socket.c | 6 +-
19 files changed, 224 insertions(+), 160 deletions(-)
create mode 100644 lib/bucket_locks.c
--
2.11.0
^ permalink raw reply
* [Patch net v2] tipc: fix a null pointer deref on error path
From: Cong Wang @ 2017-12-04 18:31 UTC (permalink / raw)
To: netdev; +Cc: tipc-discussion, Cong Wang, Jon Maloy, Ying Xue
In tipc_topsrv_kern_subscr() when s->tipc_conn_new() fails
we call tipc_close_conn() to clean up, but in this case
calling conn_put() is just enough.
This fixes the folllowing crash:
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault: 0000 [#1] SMP KASAN
Dumping ftrace buffer:
(ftrace buffer empty)
Modules linked in:
CPU: 0 PID: 3085 Comm: syzkaller064164 Not tainted 4.15.0-rc1+ #137
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
task: 00000000c24413a5 task.stack: 000000005e8160b5
RIP: 0010:__lock_acquire+0xd55/0x47f0 kernel/locking/lockdep.c:3378
RSP: 0018:ffff8801cb5474a8 EFLAGS: 00010002
RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
RDX: 0000000000000004 RSI: 0000000000000000 RDI: ffffffff85ecb400
RBP: ffff8801cb547830 R08: 0000000000000001 R09: 0000000000000000
R10: 0000000000000000 R11: ffffffff87489d60 R12: ffff8801cd2980c0
R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000020
FS: 00000000014ee880(0000) GS:ffff8801db400000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ffee2426e40 CR3: 00000001cb85a000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
lock_acquire+0x1d5/0x580 kernel/locking/lockdep.c:4004
__raw_spin_lock_bh include/linux/spinlock_api_smp.h:135 [inline]
_raw_spin_lock_bh+0x31/0x40 kernel/locking/spinlock.c:175
spin_lock_bh include/linux/spinlock.h:320 [inline]
tipc_subscrb_subscrp_delete+0x8f/0x470 net/tipc/subscr.c:201
tipc_subscrb_delete net/tipc/subscr.c:238 [inline]
tipc_subscrb_release_cb+0x17/0x30 net/tipc/subscr.c:316
tipc_close_conn+0x171/0x270 net/tipc/server.c:204
tipc_topsrv_kern_subscr+0x724/0x810 net/tipc/server.c:514
tipc_group_create+0x702/0x9c0 net/tipc/group.c:184
tipc_sk_join net/tipc/socket.c:2747 [inline]
tipc_setsockopt+0x249/0xc10 net/tipc/socket.c:2861
SYSC_setsockopt net/socket.c:1851 [inline]
SyS_setsockopt+0x189/0x360 net/socket.c:1830
entry_SYSCALL_64_fastpath+0x1f/0x96
Fixes: 14c04493cb77 ("tipc: add ability to order and receive topology events in driver")
Reported-by: syzbot <syzkaller@googlegroups.com>
Cc: Jon Maloy <jon.maloy@ericsson.com>
Cc: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
net/tipc/server.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/tipc/server.c b/net/tipc/server.c
index acaef80fb88c..2710101ba4c1 100644
--- a/net/tipc/server.c
+++ b/net/tipc/server.c
@@ -511,7 +511,7 @@ bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type,
s = con->server;
scbr = s->tipc_conn_new(*conid);
if (!scbr) {
- tipc_close_conn(con);
+ conn_put(con);
return false;
}
--
2.13.0
^ permalink raw reply related
* Re: [PATCH v3 1/6] perf: prepare perf_event.h for new types perf_kprobe and perf_uprobe
From: Alexei Starovoitov @ 2017-12-04 18:26 UTC (permalink / raw)
To: Song Liu, Alexei Starovoitov
Cc: Peter Zijlstra, Steven Rostedt, mingo@redhat.com, David Miller,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
daniel@iogearbox.net, Kernel Team
In-Reply-To: <D0757E13-27E8-4392-972A-399D6E132111@fb.com>
On 12/4/17 10:24 AM, Song Liu wrote:
>
>> On Dec 3, 2017, at 9:03 AM, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
>>
>> On Thu, Nov 30, 2017 at 03:50:18PM -0800, Song Liu wrote:
>>> Two new perf types, perf_kprobe and perf_uprobe, will be added to allow
>>> creating [k,u]probe with perf_event_open. These [k,u]probe are associated
>>> with the file decriptor created by perf_event_open, thus are easy to
>>> clean when the file descriptor is destroyed.
>>>
>>> kprobe_func and uprobe_path are added to union config1 for pointers to
>>> function name for kprobe or binary path for uprobe.
>>>
>>> kprobe_addr and probe_offset are added to union config2 for kernel
>>> address (when kprobe_func is NULL), or [k,u]probe offset.
>>>
>>> Signed-off-by: Song Liu <songliubraving@fb.com>
>>> Reviewed-by: Yonghong Song <yhs@fb.com>
>>> Reviewed-by: Josef Bacik <jbacik@fb.com>
>>> Acked-by: Alexei Starovoitov <ast@kernel.org>
>>> ---
>>> include/uapi/linux/perf_event.h | 6 ++++++
>>> 1 file changed, 6 insertions(+)
>>>
>>> diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
>>> index 362493a..247c6cb 100644
>>> --- a/include/uapi/linux/perf_event.h
>>> +++ b/include/uapi/linux/perf_event.h
>>> @@ -299,6 +299,8 @@ enum perf_event_read_format {
>>> #define PERF_ATTR_SIZE_VER4 104 /* add: sample_regs_intr */
>>> #define PERF_ATTR_SIZE_VER5 112 /* add: aux_watermark */
>>>
>>> +#define MAX_PROBE_FUNC_NAME_LEN 64
>>
>> I think we have to remove this restriction.
>> There are already functions with names longer than 64 characters
>> in the current vmlinux:
>> trace_event_define_fields_ext4_ext_convert_to_initialized_fastpath
>> trace_event_define_fields_mm_vmscan_direct_reclaim_begin_template
>>
>> How about we drop this restriction and use NAME_MAX internally
>> without adding new uapi defines ?
>
> Yeah, I agree that we should drop this uapi define. How about we use
>
> #define KSYM_NAME_LEN 128
>
> If a function name is longer than KSYM_NAME_LEN, we get warning like:
>
> Symbol long_long_name_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_ too long for kallsyms (204 vs 128).
> Please increase KSYM_NAME_LEN both in kernel and kallsyms.c
right. that's better.
Thanks
^ permalink raw reply
* Re: [PATCH 4/7 v2] net: ethernet: i825xx: Fix platform_get_irq's error checking
From: David Miller @ 2017-12-04 18:25 UTC (permalink / raw)
To: arvind.yadav.cs
Cc: wg, mkl, michal.simek, opendmb, f.fainelli, linux-kernel,
linux-arm-kernel, netdev
In-Reply-To: <1512409703-20881-5-git-send-email-arvind.yadav.cs@gmail.com>
From: Arvind Yadav <arvind.yadav.cs@gmail.com>
Date: Mon, 4 Dec 2017 23:18:20 +0530
> @@ -120,9 +120,10 @@ static int sni_82596_probe(struct platform_device *dev)
> netdevice->dev_addr[5] = readb(eth_addr + 0x06);
> iounmap(eth_addr);
>
> - if (!netdevice->irq) {
> + if (netdevice->irq <= 0) {
> printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
> __FILE__, netdevice->base_addr);
> + retval = netdevice->irq ? netdevice->irq : -ENODEV;
> goto probe_failed;
> }
Ok, thinking about this some more...
It is impossible to use platform_get_irq() without every single call
site having this funny:
ret = val ? val : -ENODEV;
sequence.
This is unnecessary duplication and it is also error prone, so I
really think this logic belongs in platform_get_irq() itself. It can
convert '0' to -ENODEV and that way we need no special logic in the
callers at all.
^ permalink raw reply
* Re: [PATCH v3 1/6] perf: prepare perf_event.h for new types perf_kprobe and perf_uprobe
From: Song Liu @ 2017-12-04 18:24 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Peter Zijlstra, Steven Rostedt, mingo@redhat.com, David Miller,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
daniel@iogearbox.net, Kernel Team
In-Reply-To: <20171203170312.rvjo6ifl2pgpjkcs@ast-mbp>
> On Dec 3, 2017, at 9:03 AM, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
>
> On Thu, Nov 30, 2017 at 03:50:18PM -0800, Song Liu wrote:
>> Two new perf types, perf_kprobe and perf_uprobe, will be added to allow
>> creating [k,u]probe with perf_event_open. These [k,u]probe are associated
>> with the file decriptor created by perf_event_open, thus are easy to
>> clean when the file descriptor is destroyed.
>>
>> kprobe_func and uprobe_path are added to union config1 for pointers to
>> function name for kprobe or binary path for uprobe.
>>
>> kprobe_addr and probe_offset are added to union config2 for kernel
>> address (when kprobe_func is NULL), or [k,u]probe offset.
>>
>> Signed-off-by: Song Liu <songliubraving@fb.com>
>> Reviewed-by: Yonghong Song <yhs@fb.com>
>> Reviewed-by: Josef Bacik <jbacik@fb.com>
>> Acked-by: Alexei Starovoitov <ast@kernel.org>
>> ---
>> include/uapi/linux/perf_event.h | 6 ++++++
>> 1 file changed, 6 insertions(+)
>>
>> diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
>> index 362493a..247c6cb 100644
>> --- a/include/uapi/linux/perf_event.h
>> +++ b/include/uapi/linux/perf_event.h
>> @@ -299,6 +299,8 @@ enum perf_event_read_format {
>> #define PERF_ATTR_SIZE_VER4 104 /* add: sample_regs_intr */
>> #define PERF_ATTR_SIZE_VER5 112 /* add: aux_watermark */
>>
>> +#define MAX_PROBE_FUNC_NAME_LEN 64
>
> I think we have to remove this restriction.
> There are already functions with names longer than 64 characters
> in the current vmlinux:
> trace_event_define_fields_ext4_ext_convert_to_initialized_fastpath
> trace_event_define_fields_mm_vmscan_direct_reclaim_begin_template
>
> How about we drop this restriction and use NAME_MAX internally
> without adding new uapi defines ?
Yeah, I agree that we should drop this uapi define. How about we use
#define KSYM_NAME_LEN 128
If a function name is longer than KSYM_NAME_LEN, we get warning like:
Symbol long_long_name_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_ too long for kallsyms (204 vs 128).
Please increase KSYM_NAME_LEN both in kernel and kallsyms.c
Thanks,
Song
^ permalink raw reply
* Re: [PATCH net-next 1/4] net: Introduce NETIF_F_GRO_HW
From: Michael Chan @ 2017-12-04 18:23 UTC (permalink / raw)
To: Alexander Duyck; +Cc: David Miller, Netdev, Ariel Elior, everest-linux-l2
In-Reply-To: <CAKgT0Ue6G=kqYmhXE3eYiE58YJ0+x0AkSNGcro+tW-zs-RMuDg@mail.gmail.com>
On Mon, Dec 4, 2017 at 8:47 AM, Alexander Duyck
<alexander.duyck@gmail.com> wrote:
> On Mon, Dec 4, 2017 at 3:12 AM, Michael Chan <michael.chan@broadcom.com> wrote:
>> Introduce NETIF_F_GRO_HW feature flag for NICs that support hardware
>> GRO. With this flag, we can now independently turn on or off hardware
>> GRO when GRO is on. Hardware GRO guarantees that packets can be
>> re-segmented by TSO/GSO to reconstruct the original packet stream.
>>
>> Cc: Ariel Elior <Ariel.Elior@cavium.com>
>> Cc: everest-linux-l2@cavium.com
>> Signed-off-by: Michael Chan <michael.chan@broadcom.com>
>
> Do we really need yet another feature bit for this? We already have
> LRO and GRO and now we have to add something that isn't quite either
> one?
I think so, to be consistent with TSO/GSO on the transmit side. On
the receive side, we have LRO/GRO_HW/GRO. There is difference between
LRO/GRO_HW that we need to distinguish between the 2.
>
> I think I would rather have something like a netdev private flag that
> says LRO assembled frames are routable and just have this all run over
> the LRO flag with a test for the private flag to avoid triggering the
> LRO disable in the case of the flag being present. Really this is just
> a clean LRO implementation anyway so maybe we should just go that
> route where LRO is the hardware offload and GRO is the generic
> software implementation of that offload. That way when GRO gets some
> new feature that your hardware doesn't support we don't have to argue
> about the differences since LRO is meant to be a limited
> implementation anyway due to the nature of it being in hardware.
Private flag will work. But a standard feature flag is better since
there are multiple drivers supporting this. A standard way to turn
this on/off is a better user experience. It's also consistent with
TSO/GSO on the transmit side.
>
> To me it just seems like this is an attempt to use the GRO name as a
> marketing term and I really don't like the feel of it.
>
I disagree with this. It's more than a marketing term.
^ permalink raw reply
* Re: linux-next: build warning after merge of the net-next tree
From: David Miller @ 2017-12-04 18:21 UTC (permalink / raw)
To: sfr; +Cc: netdev, linux-next, linux-kernel, hkallweit1
In-Reply-To: <20171204110249.0d21a17d@canb.auug.org.au>
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Mon, 4 Dec 2017 11:02:49 +1100
> After merging the net-next tree, today's linux-next build (arm
> multi_v7_defconfig) produced this warning:
>
> drivers/net/phy/broadcom.c:391:12: warning: 'bcm5482_read_status' defined but not used [-Wunused-function]
> static int bcm5482_read_status(struct phy_device *phydev)
> ^
> drivers/net/phy/broadcom.c:411:12: warning: 'bcm5481_config_aneg' defined but not used [-Wunused-function]
> static int bcm5481_config_aneg(struct phy_device *phydev)
> ^
>
> Introduced by commit
>
> 80274abafc60 ("net: phy: remove generic settings for callbacks config_aneg and read_status from drivers")
This shoudl be resolved now, thanks for the report.
^ permalink raw reply
* [PATCH net-next] rtnetlink: ipv6: convert remaining users to rtnl_register_module
From: Florian Westphal @ 2017-12-04 18:19 UTC (permalink / raw)
To: netdev; +Cc: Florian Westphal
convert remaining users of rtnl_register to rtnl_register_module
and un-export rtnl_register.
Requested-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/net/addrconf.h | 2 +-
net/core/rtnetlink.c | 1 -
net/ipv6/addrconf.c | 4 +++-
net/ipv6/addrlabel.c | 24 +++++++++++++++++-------
net/ipv6/ip6mr.c | 9 ++++++---
5 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index b623b65a79d1..c4185a7b0e90 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -180,7 +180,7 @@ static inline int addrconf_finite_timeout(unsigned long timeout)
*/
int ipv6_addr_label_init(void);
void ipv6_addr_label_cleanup(void);
-void ipv6_addr_label_rtnl_register(void);
+int ipv6_addr_label_rtnl_register(void);
u32 ipv6_addr_label(struct net *net, const struct in6_addr *addr,
int type, int ifindex);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index fb2d61df1e2f..eb2a88426d0c 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -265,7 +265,6 @@ void rtnl_register(int protocol, int msgtype,
pr_err("Unable to register rtnetlink message handler, "
"protocol = %d, message type = %d\n", protocol, msgtype);
}
-EXPORT_SYMBOL_GPL(rtnl_register);
/**
* rtnl_unregister - Unregister a rtnetlink message type
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a5ad8425551a..ed06b1190f05 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -6627,7 +6627,9 @@ int __init addrconf_init(void)
RTNL_FLAG_DOIT_UNLOCKED);
if (err < 0)
goto errout;
- ipv6_addr_label_rtnl_register();
+ err = ipv6_addr_label_rtnl_register();
+ if (err < 0)
+ goto errout;
return 0;
errout:
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index 303fcce5beef..1d6ced37ad71 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -547,12 +547,22 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
return err;
}
-void __init ipv6_addr_label_rtnl_register(void)
+int __init ipv6_addr_label_rtnl_register(void)
{
- rtnl_register(PF_INET6, RTM_NEWADDRLABEL, ip6addrlbl_newdel,
- NULL, RTNL_FLAG_DOIT_UNLOCKED);
- rtnl_register(PF_INET6, RTM_DELADDRLABEL, ip6addrlbl_newdel,
- NULL, RTNL_FLAG_DOIT_UNLOCKED);
- rtnl_register(PF_INET6, RTM_GETADDRLABEL, ip6addrlbl_get,
- ip6addrlbl_dump, RTNL_FLAG_DOIT_UNLOCKED);
+ int ret;
+
+ ret = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_NEWADDRLABEL,
+ ip6addrlbl_newdel,
+ NULL, RTNL_FLAG_DOIT_UNLOCKED);
+ if (ret < 0)
+ return ret;
+ ret = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_DELADDRLABEL,
+ ip6addrlbl_newdel,
+ NULL, RTNL_FLAG_DOIT_UNLOCKED);
+ if (ret < 0)
+ return ret;
+ ret = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETADDRLABEL,
+ ip6addrlbl_get,
+ ip6addrlbl_dump, RTNL_FLAG_DOIT_UNLOCKED);
+ return ret;
}
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index a2e1a864eb46..890f9bda06a4 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1425,10 +1425,13 @@ int __init ip6_mr_init(void)
goto add_proto_fail;
}
#endif
- rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL,
- ip6mr_rtm_dumproute, 0);
- return 0;
+ err = rtnl_register_module(THIS_MODULE, RTNL_FAMILY_IP6MR, RTM_GETROUTE,
+ NULL, ip6mr_rtm_dumproute, 0);
+ if (err == 0)
+ return 0;
+
#ifdef CONFIG_IPV6_PIMSM_V2
+ inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
add_proto_fail:
unregister_netdevice_notifier(&ip6_mr_notifier);
#endif
--
2.13.6
^ permalink raw reply related
* Re: pull-request: can-next 2017-12-01,Re: pull-request: can-next 2017-12-01
From: David Miller @ 2017-12-04 18:20 UTC (permalink / raw)
To: mkl; +Cc: netdev, kernel, linux-can
In-Reply-To: <85177a44-2bf7-80f8-08c4-df133cd48917@pengutronix.de>
From: Marc Kleine-Budde <mkl@pengutronix.de>
Date: Fri, 1 Dec 2017 14:50:04 +0100
> On 12/01/2017 02:37 PM, Marc Kleine-Budde wrote:
>> Doh, I had an error in my script which produced the wrong Linux version
>> in the tag. The correct name of the tag is:
>
> First test - than post - here's the correct tag:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
> tags/linux-can-next-for-4.16-20171201
Pulled, thanks!
^ permalink raw reply
* Re: [Patch net] tipc: fix a null pointer deref on error path
From: Cong Wang @ 2017-12-04 18:19 UTC (permalink / raw)
To: Ying Xue; +Cc: Linux Kernel Network Developers, tipc-discussion, Jon Maloy
In-Reply-To: <fb73a71c-9638-29fb-70d8-e4a986277b7f@windriver.com>
On Mon, Dec 4, 2017 at 4:43 AM, Ying Xue <ying.xue@windriver.com> wrote:
> On 12/04/2017 11:54 AM, Cong Wang wrote:
>> In tipc_topsrv_kern_subscr() when s->tipc_conn_new() fails
>> we call tipc_close_conn() to clean up, but in this case
>> con->usr_data is NULL, tipc_subscrb_delete() should be skipped.
>>
>> This fixes the folllowing crash:
>>
>> kasan: GPF could be caused by NULL-ptr deref or user memory access
>> general protection fault: 0000 [#1] SMP KASAN
>> Dumping ftrace buffer:
>> (ftrace buffer empty)
>> Modules linked in:
>> CPU: 0 PID: 3085 Comm: syzkaller064164 Not tainted 4.15.0-rc1+ #137
>> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
>> task: 00000000c24413a5 task.stack: 000000005e8160b5
>> RIP: 0010:__lock_acquire+0xd55/0x47f0 kernel/locking/lockdep.c:3378
>> RSP: 0018:ffff8801cb5474a8 EFLAGS: 00010002
>> RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
>> RDX: 0000000000000004 RSI: 0000000000000000 RDI: ffffffff85ecb400
>> RBP: ffff8801cb547830 R08: 0000000000000001 R09: 0000000000000000
>> R10: 0000000000000000 R11: ffffffff87489d60 R12: ffff8801cd2980c0
>> R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000020
>> FS: 00000000014ee880(0000) GS:ffff8801db400000(0000) knlGS:0000000000000000
>> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>> CR2: 00007ffee2426e40 CR3: 00000001cb85a000 CR4: 00000000001406f0
>> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
>> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
>> Call Trace:
>> lock_acquire+0x1d5/0x580 kernel/locking/lockdep.c:4004
>> __raw_spin_lock_bh include/linux/spinlock_api_smp.h:135 [inline]
>> _raw_spin_lock_bh+0x31/0x40 kernel/locking/spinlock.c:175
>> spin_lock_bh include/linux/spinlock.h:320 [inline]
>> tipc_subscrb_subscrp_delete+0x8f/0x470 net/tipc/subscr.c:201
>> tipc_subscrb_delete net/tipc/subscr.c:238 [inline]
>> tipc_subscrb_release_cb+0x17/0x30 net/tipc/subscr.c:316
>> tipc_close_conn+0x171/0x270 net/tipc/server.c:204
>> tipc_topsrv_kern_subscr+0x724/0x810 net/tipc/server.c:514
>> tipc_group_create+0x702/0x9c0 net/tipc/group.c:184
>> tipc_sk_join net/tipc/socket.c:2747 [inline]
>> tipc_setsockopt+0x249/0xc10 net/tipc/socket.c:2861
>> SYSC_setsockopt net/socket.c:1851 [inline]
>> SyS_setsockopt+0x189/0x360 net/socket.c:1830
>> entry_SYSCALL_64_fastpath+0x1f/0x96
>>
>> Reported-by: syzbot <syzkaller@googlegroups.com>
>> Cc: Jon Maloy <jon.maloy@ericsson.com>
>> Cc: Ying Xue <ying.xue@windriver.com>
>> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
>> ---
>> net/tipc/subscr.c | 2 ++
>> 1 file changed, 2 insertions(+)
>>
>> diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
>> index 251065dfd8df..2402a019b8ec 100644
>> --- a/net/tipc/subscr.c
>> +++ b/net/tipc/subscr.c
>> @@ -235,6 +235,8 @@ static struct tipc_subscriber *tipc_subscrb_create(int conid)
>>
>> static void tipc_subscrb_delete(struct tipc_subscriber *subscriber)
>> {
>> + if (!subscriber)
>> + return;
>
> The real root cause of this crash is because when it was failed to
> create a connection through s->tipc_conn_new() in
> tipc_topsrv_kern_subscr(), we just should release the connection
> instance with conn_put() rather than calling tipc_close_conn() to close
> the connection. So a proper fix might look like:
Good point! But con->sock should be already NULL since
we use kzalloc() to allocate con, so just replacing tipc_close_conn()
with con_put() should work.
^ permalink raw reply
* Re: [PATCH net-next 2/4] bnxt_en: Use NETIF_F_GRO_HW.
From: Michael Chan @ 2017-12-04 18:11 UTC (permalink / raw)
To: Or Gerlitz; +Cc: David Miller, Linux Netdev List
In-Reply-To: <CAJ3xEMghbGNkE5N2+aCMJK_nc2Yivyj2FYnFagTf9nF8xrew6g@mail.gmail.com>
On Mon, Dec 4, 2017 at 8:35 AM, Or Gerlitz <gerlitz.or@gmail.com> wrote:
> On Mon, Dec 4, 2017 at 1:12 PM, Michael Chan <michael.chan@broadcom.com> wrote:
>> Advertise NETIF_F_GRO_HW if hardware GRO is supported. Turn on or off
>> hardware GRO based on NETIF_F_GRO_HW.
>
> So the patch only deals with advertisement biz.. and I even failed to
> find a place where you arm
> something in the FW... so this just works OOB, all your buffers && skb
> logic && FW setup are fully
> ready for that? also, nothing you need to put differently on the SKB
> for HW GRO completions?
> can you explain this little further or it's all in your netdev slides...
>
All the logic is already in these 3 drivers in the tree. You can see
the additional logic in any of these drivers. It's just that these
drivers have been using NETIF_F_GRO to turn on this mode in
hardware/firmware. So these patches are just to switch over to use
the new flag to turn on this mode so that it can be independently
turned on or off.
^ permalink raw reply
* Re: [PATCH net-next 1/2 v6] net: ethernet: Add DT bindings for the Gemini ethernet
From: Hans Ulli Kroll @ 2017-12-04 18:06 UTC (permalink / raw)
To: Linus Walleij
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, David S . Miller,
Michał Mirosław, Janos Laube, Paulius Zaleckas,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Hans Ulli Kroll, Florian Fainelli,
devicetree-u79uwXL29TY76Z2rM5mHXA, Tobias Waldvogel
In-Reply-To: <20171202110640.5284-1-linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 900 bytes --]
Hi Linus
On Sat, 2 Dec 2017, Linus Walleij wrote:
> This adds the device tree bindings for the Gemini ethernet
> controller. It is pretty straight-forward, using standard
> bindings and modelling the two child ports as child devices
> under the parent ethernet controller device.
>
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: Tobias Waldvogel <tobias.waldvogel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: Michał Mirosław <mirq-linux-CoA6ZxLDdyEEUmgCuDUIdw@public.gmane.org>
> Signed-off-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> .../bindings/net/cortina,gemini-ethernet.txt | 92 ++++++++++++++++++++++
> 1 file changed, 92 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/cortina,gemini-ethernet.txt
>
Acked-by: Hans Ulli Kroll <ulli.kroll-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
^ permalink raw reply
* Re: [PATCH v2 net-next] net/tcp: trace all TCP/IP state transition with tcp_set_state tracepoint
From: Song Liu @ 2017-12-04 17:49 UTC (permalink / raw)
To: Yafang Shao
Cc: David Miller, kuznet@ms2.inr.ac.ru, yoshfuji@linux-ipv6.org,
Steven Rostedt, Brendan Gregg, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <1512207401-3154-1-git-send-email-laoar.shao@gmail.com>
> On Dec 2, 2017, at 1:36 AM, Yafang Shao <laoar.shao@gmail.com> wrote:
>
> The TCP/IP transition from TCP_LISTEN to TCP_SYN_RECV and some other
> transitions are not traced with tcp_set_state tracepoint.
>
> In order to trace the whole tcp lifespans, two helpers are introduced,
> void __tcp_set_state(struct sock *sk, int state)
> void __sk_state_store(struct sock *sk, int newstate)
>
> When do TCP/IP state transition, we should use these two helpers or use
> tcp_set_state() other than assigning a value to sk_state directly.
>
> Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
>
> ---
> v2: test
> ---
> include/net/tcp.h | 2 ++
> net/ipv4/inet_connection_sock.c | 6 +++---
> net/ipv4/inet_hashtables.c | 2 +-
> net/ipv4/tcp.c | 12 ++++++++++++
> 4 files changed, 18 insertions(+), 4 deletions(-)
>
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index 85ea578..4f2d015 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -1247,6 +1247,8 @@ static inline bool tcp_checksum_complete(struct sk_buff *skb)
> "Close Wait","Last ACK","Listen","Closing"
> };
> #endif
> +void __sk_state_store(struct sock *sk, int newstate);
> +void __tcp_set_state(struct sock *sk, int state);
> void tcp_set_state(struct sock *sk, int state);
>
> void tcp_done(struct sock *sk);
> diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
> index 4ca46dc..f3967f1 100644
> --- a/net/ipv4/inet_connection_sock.c
> +++ b/net/ipv4/inet_connection_sock.c
> @@ -783,7 +783,7 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
> if (newsk) {
> struct inet_connection_sock *newicsk = inet_csk(newsk);
>
> - newsk->sk_state = TCP_SYN_RECV;
> + __tcp_set_state(newsk, TCP_SYN_RECV);
> newicsk->icsk_bind_hash = NULL;
>
> inet_sk(newsk)->inet_dport = inet_rsk(req)->ir_rmt_port;
> @@ -877,7 +877,7 @@ int inet_csk_listen_start(struct sock *sk, int backlog)
> * It is OK, because this socket enters to hash table only
> * after validation is complete.
> */
> - sk_state_store(sk, TCP_LISTEN);
> + __sk_state_store(sk, TCP_LISTEN);
> if (!sk->sk_prot->get_port(sk, inet->inet_num)) {
> inet->inet_sport = htons(inet->inet_num);
>
> @@ -888,7 +888,7 @@ int inet_csk_listen_start(struct sock *sk, int backlog)
> return 0;
> }
>
> - sk->sk_state = TCP_CLOSE;
> + __tcp_set_state(sk, TCP_CLOSE);
> return err;
> }
> EXPORT_SYMBOL_GPL(inet_csk_listen_start);
> diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
> index e7d15fb..72c15b6 100644
> --- a/net/ipv4/inet_hashtables.c
> +++ b/net/ipv4/inet_hashtables.c
> @@ -430,7 +430,7 @@ bool inet_ehash_nolisten(struct sock *sk, struct sock *osk)
> sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
> } else {
> percpu_counter_inc(sk->sk_prot->orphan_count);
> - sk->sk_state = TCP_CLOSE;
> + __tcp_set_state(sk, TCP_CLOSE);
> sock_set_flag(sk, SOCK_DEAD);
> inet_csk_destroy_sock(sk);
> }
> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> index bf97317..2bc7e04 100644
> --- a/net/ipv4/tcp.c
> +++ b/net/ipv4/tcp.c
> @@ -2036,6 +2036,18 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
> }
> EXPORT_SYMBOL(tcp_recvmsg);
>
> +void __sk_state_store(struct sock *sk, int newstate)
> +{
> + trace_tcp_set_state(sk, sk->sk_state, newstate);
> + sk_state_store(sk, newstate);
> +}
> +
> +void __tcp_set_state(struct sock *sk, int state)
> +{
> + trace_tcp_set_state(sk, sk->sk_state, state);
> + sk->sk_state = state;
> +}
> +
> void tcp_set_state(struct sock *sk, int state)
> {
> int oldstate = sk->sk_state;
> --
> 1.8.3.1
>
Asked-by: Song Liu <songliubraving@fb.com>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox