Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH][net-next] net: drop_monitor: change the stats variable to u64 in net_dm_stats_put
From: Ido Schimmel @ 2019-08-22 11:59 UTC (permalink / raw)
  To: Li RongQing; +Cc: netdev, idosch
In-Reply-To: <1566454953-29321-1-git-send-email-lirongqing@baidu.com>

On Thu, Aug 22, 2019 at 02:22:33PM +0800, Li RongQing wrote:
> only the element drop of struct net_dm_stats is used, so simplify it to u64

Thanks for the patch, but I don't really see the value here. The struct
allows for easy extensions in the future. What do you gain from this
change? We merely read stats and report them to user space, so I guess
it's not about performance either.

> 
> Signed-off-by: Li RongQing <lirongqing@baidu.com>
> ---
>  net/core/drop_monitor.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
> index bfc024024aa3..ed10a40cf629 100644
> --- a/net/core/drop_monitor.c
> +++ b/net/core/drop_monitor.c
> @@ -1329,11 +1329,11 @@ static int net_dm_cmd_config_get(struct sk_buff *skb, struct genl_info *info)
>  	return rc;
>  }
>  
> -static void net_dm_stats_read(struct net_dm_stats *stats)
> +static void net_dm_stats_read(u64 *stats)
>  {
>  	int cpu;
>  
> -	memset(stats, 0, sizeof(*stats));
> +	*stats = 0;
>  	for_each_possible_cpu(cpu) {
>  		struct per_cpu_dm_data *data = &per_cpu(dm_cpu_data, cpu);
>  		struct net_dm_stats *cpu_stats = &data->stats;
> @@ -1345,14 +1345,14 @@ static void net_dm_stats_read(struct net_dm_stats *stats)
>  			dropped = cpu_stats->dropped;
>  		} while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
>  
> -		stats->dropped += dropped;
> +		*stats += dropped;
>  	}
>  }
>  
>  static int net_dm_stats_put(struct sk_buff *msg)
>  {
> -	struct net_dm_stats stats;
>  	struct nlattr *attr;
> +	u64 stats;
>  
>  	net_dm_stats_read(&stats);
>  
> @@ -1361,7 +1361,7 @@ static int net_dm_stats_put(struct sk_buff *msg)
>  		return -EMSGSIZE;
>  
>  	if (nla_put_u64_64bit(msg, NET_DM_ATTR_STATS_DROPPED,
> -			      stats.dropped, NET_DM_ATTR_PAD))
> +			      stats, NET_DM_ATTR_PAD))
>  		goto nla_put_failure;
>  
>  	nla_nest_end(msg, attr);
> -- 
> 2.16.2
> 

^ permalink raw reply

* Re: [RFC bpf-next 4/5] iproute2: Allow compiling against libbpf
From: Toke Høiland-Jørgensen @ 2019-08-22 12:04 UTC (permalink / raw)
  To: Daniel Borkmann, Stephen Hemminger, Alexei Starovoitov
  Cc: Martin KaFai Lau, Song Liu, Yonghong Song, David Miller,
	Jesper Dangaard Brouer, netdev, bpf, andrii.nakryiko
In-Reply-To: <0c3d78eb-d305-9266-b505-c2f9181d5c89@iogearbox.net>

Daniel Borkmann <daniel@iogearbox.net> writes:

> On 8/22/19 12:43 PM, Toke Høiland-Jørgensen wrote:
>> Daniel Borkmann <daniel@iogearbox.net> writes:
>>> On 8/20/19 1:47 PM, Toke Høiland-Jørgensen wrote:
>>>> This adds a configure check for libbpf and renames functions to allow
>>>> lib/bpf.c to be compiled with it present. This makes it possible to
>>>> port functionality piecemeal to use libbpf.
>>>>
>>>> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
>>>> ---
>>>>    configure          | 16 ++++++++++++++++
>>>>    include/bpf_util.h |  6 +++---
>>>>    ip/ipvrf.c         |  4 ++--
>>>>    lib/bpf.c          | 33 +++++++++++++++++++--------------
>>>>    4 files changed, 40 insertions(+), 19 deletions(-)
>>>>
>>>> diff --git a/configure b/configure
>>>> index 45fcffb6..5a89ee9f 100755
>>>> --- a/configure
>>>> +++ b/configure
>>>> @@ -238,6 +238,19 @@ check_elf()
>>>>        fi
>>>>    }
>>>>    
>>>> +check_libbpf()
>>>> +{
>>>> +    if ${PKG_CONFIG} libbpf --exists; then
>>>> +	echo "HAVE_LIBBPF:=y" >>$CONFIG
>>>> +	echo "yes"
>>>> +
>>>> +	echo 'CFLAGS += -DHAVE_LIBBPF' `${PKG_CONFIG} libbpf --cflags` >> $CONFIG
>>>> +	echo 'LDLIBS += ' `${PKG_CONFIG} libbpf --libs` >>$CONFIG
>>>> +    else
>>>> +	echo "no"
>>>> +    fi
>>>> +}
>>>> +
>>>>    check_selinux()
>>>
>>> More of an implementation detail at this point in time, but want to
>>> make sure this doesn't get missed along the way: as discussed at
>>> bpfconf [0] best for iproute2 to handle libbpf support would be the
>>> same way of integration as pahole does, that is, to integrate it via
>>> submodule [1] to allow kernel and libbpf features to be in sync with
>>> iproute2 releases and therefore easily consume extensions we're adding
>>> to libbpf to aide iproute2 integration.
>> 
>> I can sorta see the point wrt keeping in sync with kernel features. But
>> how will this work with distros that package libbpf as a regular
>> library? Have you guys given up on regular library symbol versioning for
>> libbpf?
>
> Not at all, and I hope you know that. ;-)

Good! Didn't really expect you had, just checking ;)

> The reason I added lib/bpf.c integration into iproute2 directly back
> then was exactly such that users can start consuming BPF for tc and
> XDP via iproute2 /everywhere/ with only a simple libelf dependency
> which is also available on all distros since pretty much forever. If
> it was an external library, we could have waited till hell freezes
> over and initial distro adoption would have pretty much taken forever:
> to pick one random example here wrt the pace of some downstream
> distros [0]. The main rationale is pretty much the same as with added
> kernel features that land complementary iproute2 patches for that
> kernel release and as libbpf is developed alongside it is reasonable
> to guarantee user expectations that iproute2 released for kernel
> version x can make use of BPF features added to kernel x with same
> loader support from x.

Well, for iproute2 I would expect this to be solved by version
dependencies. I.e. iproute2 version X would depend on libbpf version Y+
(like, I dunno, the version of libbpf included in the same kernel source
tree as the kernel version iproute2 is targeting? :)).

If we vendor libbpf into every project using it, we'll end up with
dozens of different versions statically linked into each binary, kinda
defeating the purpose of having it as a shared library in the first
place...

-Toke

^ permalink raw reply

* Re: BUG: MAX_STACK_TRACE_ENTRIES too low in tipc_topsrv_exit_net
From: Andrey Konovalov @ 2019-08-22 12:03 UTC (permalink / raw)
  To: syzbot, David S. Miller, jon.maloy, LKML, netdev, syzkaller-bugs,
	tipc-discussion, ying.xue
In-Reply-To: <20190822030549.GA6111@zzz.localdomain>

On Thu, Aug 22, 2019 at 5:05 AM Eric Biggers <ebiggers@kernel.org> wrote:
>
> On Mon, Aug 19, 2019 at 05:22:07AM -0700, syzbot wrote:
> > Hello,
> >
> > syzbot found the following crash on:
> >
> > HEAD commit:    5181b473 net: phy: realtek: add NBase-T PHY auto-detection
> > git tree:       net-next
> > console output: https://syzkaller.appspot.com/x/log.txt?x=156b731c600000
> > kernel config:  https://syzkaller.appspot.com/x/.config?x=d4cf1ffb87d590d7
> > dashboard link: https://syzkaller.appspot.com/bug?extid=5f97459a05652f579f6c
> > compiler:       gcc (GCC) 9.0.0 20181231 (experimental)
> >
> > Unfortunately, I don't have any reproducer for this crash yet.
> >
> > IMPORTANT: if you fix the bug, please add the following tag to the commit:
> > Reported-by: syzbot+5f97459a05652f579f6c@syzkaller.appspotmail.com
> >
> > BUG: MAX_STACK_TRACE_ENTRIES too low!
> > turning off the locking correctness validator.
> > CPU: 0 PID: 2581 Comm: kworker/u4:4 Not tainted 5.3.0-rc3+ #132
> > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> > Google 01/01/2011
> > Workqueue: netns cleanup_net
> > Call Trace:
> >  __dump_stack lib/dump_stack.c:77 [inline]
> >  dump_stack+0x172/0x1f0 lib/dump_stack.c:113
> >  save_trace kernel/locking/lockdep.c:473 [inline]
> >  save_trace.isra.0.cold+0x14/0x19 kernel/locking/lockdep.c:458
> >  mark_lock+0x3db/0x11e0 kernel/locking/lockdep.c:3583
> >  mark_usage kernel/locking/lockdep.c:3517 [inline]
> >  __lock_acquire+0x538/0x4c30 kernel/locking/lockdep.c:3834
> >  lock_acquire+0x190/0x410 kernel/locking/lockdep.c:4412
> >  flush_workqueue+0x126/0x14b0 kernel/workqueue.c:2774
> >  drain_workqueue+0x1b4/0x470 kernel/workqueue.c:2939
> >  destroy_workqueue+0x21/0x6c0 kernel/workqueue.c:4320
> >  tipc_topsrv_work_stop net/tipc/topsrv.c:636 [inline]
> >  tipc_topsrv_stop net/tipc/topsrv.c:694 [inline]
> >  tipc_topsrv_exit_net+0x3fe/0x5d8 net/tipc/topsrv.c:706
> >  ops_exit_list.isra.0+0xaa/0x150 net/core/net_namespace.c:172
> >  cleanup_net+0x4e2/0xa70 net/core/net_namespace.c:594
> >  process_one_work+0x9af/0x1740 kernel/workqueue.c:2269
> >  worker_thread+0x98/0xe40 kernel/workqueue.c:2415
> >  kthread+0x361/0x430 kernel/kthread.c:255
> >  ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352
> > kobject: 'rx-0' (000000000e2c91cd): kobject_cleanup, parent 000000002003fefb
> > kobject: 'rx-0' (000000000e2c91cd): auto cleanup 'remove' event
> > kobject: 'rx-0' (000000000e2c91cd): kobject_uevent_env
> > kobject: 'rx-0' (000000000e2c91cd): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000000e2c91cd): auto cleanup kobject_del
> > kobject: 'rx-0' (000000000e2c91cd): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (0000000058b6f726): kobject_cleanup, parent 000000002003fefb
> > kobject: 'tx-0' (0000000058b6f726): auto cleanup 'remove' event
> > kobject: 'tx-0' (0000000058b6f726): kobject_uevent_env
> > kobject: 'tx-0' (0000000058b6f726): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (0000000058b6f726): auto cleanup kobject_del
> > kobject: 'tx-0' (0000000058b6f726): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000002003fefb): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000002003fefb): calling ktype release
> > kobject: 'queues' (000000002003fefb): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6gre0' (0000000018a24d65): kobject_uevent_env
> > kobject: 'ip6gre0' (0000000018a24d65): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000940b22b0): kobject_cleanup, parent 0000000005a1fc3a
> > kobject: 'rx-0' (00000000940b22b0): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000940b22b0): kobject_uevent_env
> > kobject: 'rx-0' (00000000940b22b0): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000940b22b0): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000940b22b0): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000278e85e2): kobject_cleanup, parent 0000000005a1fc3a
> > kobject: 'tx-0' (00000000278e85e2): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000278e85e2): kobject_uevent_env
> > kobject: 'tx-0' (00000000278e85e2): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000278e85e2): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000278e85e2): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (0000000005a1fc3a): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (0000000005a1fc3a): calling ktype release
> > kobject: 'queues' (0000000005a1fc3a): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6gre0' (00000000c78b955b): kobject_uevent_env
> > kobject: 'ip6gre0' (00000000c78b955b): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000000fa7c1d1): kobject_cleanup, parent 00000000d264d5b4
> > kobject: 'rx-0' (000000000fa7c1d1): auto cleanup 'remove' event
> > kobject: 'rx-0' (000000000fa7c1d1): kobject_uevent_env
> > kobject: 'rx-0' (000000000fa7c1d1): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000000fa7c1d1): auto cleanup kobject_del
> > kobject: 'rx-0' (000000000fa7c1d1): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (000000000f66c80c): kobject_cleanup, parent 00000000d264d5b4
> > kobject: 'tx-0' (000000000f66c80c): auto cleanup 'remove' event
> > kobject: 'tx-0' (000000000f66c80c): kobject_uevent_env
> > kobject: 'tx-0' (000000000f66c80c): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (000000000f66c80c): auto cleanup kobject_del
> > kobject: 'tx-0' (000000000f66c80c): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (00000000d264d5b4): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (00000000d264d5b4): calling ktype release
> > kobject: 'queues' (00000000d264d5b4): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6gre0' (00000000ef80dc29): kobject_uevent_env
> > kobject: 'ip6gre0' (00000000ef80dc29): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000f928d911): kobject_cleanup, parent 000000003c7c9951
> > kobject: 'rx-0' (00000000f928d911): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000f928d911): kobject_uevent_env
> > kobject: 'rx-0' (00000000f928d911): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000f928d911): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000f928d911): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (000000009bf7cc90): kobject_cleanup, parent 000000003c7c9951
> > kobject: 'tx-0' (000000009bf7cc90): auto cleanup 'remove' event
> > kobject: 'tx-0' (000000009bf7cc90): kobject_uevent_env
> > kobject: 'tx-0' (000000009bf7cc90): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (000000009bf7cc90): auto cleanup kobject_del
> > kobject: 'tx-0' (000000009bf7cc90): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000003c7c9951): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000003c7c9951): calling ktype release
> > kobject: 'queues' (000000003c7c9951): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6gre0' (00000000acb4e121): kobject_uevent_env
> > kobject: 'ip6gre0' (00000000acb4e121): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (0000000045fca4e1): kobject_cleanup, parent 000000001c9d9e42
> > kobject: 'rx-0' (0000000045fca4e1): auto cleanup 'remove' event
> > kobject: 'rx-0' (0000000045fca4e1): kobject_uevent_env
> > kobject: 'rx-0' (0000000045fca4e1): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (0000000045fca4e1): auto cleanup kobject_del
> > kobject: 'rx-0' (0000000045fca4e1): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000a309e805): kobject_cleanup, parent 000000001c9d9e42
> > kobject: 'tx-0' (00000000a309e805): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000a309e805): kobject_uevent_env
> > kobject: 'tx-0' (00000000a309e805): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000a309e805): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000a309e805): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000001c9d9e42): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000001c9d9e42): calling ktype release
> > kobject: 'queues' (000000001c9d9e42): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6gre0' (0000000094fbf7bb): kobject_uevent_env
> > kobject: 'ip6gre0' (0000000094fbf7bb): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000443242e0): kobject_cleanup, parent 000000009f9df3e8
> > kobject: 'rx-0' (00000000443242e0): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000443242e0): kobject_uevent_env
> > kobject: 'rx-0' (00000000443242e0): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000443242e0): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000443242e0): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (000000005588ef99): kobject_cleanup, parent 000000009f9df3e8
> > kobject: 'tx-0' (000000005588ef99): auto cleanup 'remove' event
> > kobject: 'tx-0' (000000005588ef99): kobject_uevent_env
> > kobject: 'tx-0' (000000005588ef99): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (000000005588ef99): auto cleanup kobject_del
> > kobject: 'tx-0' (000000005588ef99): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000009f9df3e8): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000009f9df3e8): calling ktype release
> > kobject: 'queues' (000000009f9df3e8): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6gre0' (0000000060028093): kobject_uevent_env
> > kobject: 'ip6gre0' (0000000060028093): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (0000000002c2db56): kobject_cleanup, parent 000000000ee23264
> > kobject: 'rx-0' (0000000002c2db56): auto cleanup 'remove' event
> > kobject: 'rx-0' (0000000002c2db56): kobject_uevent_env
> > kobject: 'rx-0' (0000000002c2db56): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (0000000002c2db56): auto cleanup kobject_del
> > kobject: 'rx-0' (0000000002c2db56): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000831daf90): kobject_cleanup, parent 000000000ee23264
> > kobject: 'tx-0' (00000000831daf90): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000831daf90): kobject_uevent_env
> > kobject: 'tx-0' (00000000831daf90): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000831daf90): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000831daf90): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000000ee23264): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000000ee23264): calling ktype release
> > kobject: 'queues' (000000000ee23264): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6gre0' (00000000e217374d): kobject_uevent_env
> > kobject: 'ip6gre0' (00000000e217374d): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000f8e7f44b): kobject_cleanup, parent 000000003daaa7c9
> > kobject: 'rx-0' (00000000f8e7f44b): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000f8e7f44b): kobject_uevent_env
> > kobject: 'rx-0' (00000000f8e7f44b): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000f8e7f44b): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000f8e7f44b): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (000000001277c9de): kobject_cleanup, parent 000000003daaa7c9
> > kobject: 'tx-0' (000000001277c9de): auto cleanup 'remove' event
> > kobject: 'tx-0' (000000001277c9de): kobject_uevent_env
> > kobject: 'tx-0' (000000001277c9de): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (000000001277c9de): auto cleanup kobject_del
> > kobject: 'tx-0' (000000001277c9de): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000003daaa7c9): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000003daaa7c9): calling ktype release
> > kobject: 'queues' (000000003daaa7c9): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6gre0' (00000000597e3c0a): kobject_uevent_env
> > kobject: 'ip6gre0' (00000000597e3c0a): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000eb376580): kobject_cleanup, parent 0000000054d719cb
> > kobject: 'rx-0' (00000000eb376580): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000eb376580): kobject_uevent_env
> > kobject: 'rx-0' (00000000eb376580): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000eb376580): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000eb376580): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (0000000040024191): kobject_cleanup, parent 0000000054d719cb
> > kobject: 'tx-0' (0000000040024191): auto cleanup 'remove' event
> > kobject: 'tx-0' (0000000040024191): kobject_uevent_env
> > kobject: 'tx-0' (0000000040024191): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (0000000040024191): auto cleanup kobject_del
> > kobject: 'tx-0' (0000000040024191): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (0000000054d719cb): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (0000000054d719cb): calling ktype release
> > kobject: 'queues' (0000000054d719cb): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6gre0' (00000000995a4c19): kobject_uevent_env
> > kobject: 'ip6gre0' (00000000995a4c19): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'ip6gre0' (0000000018a24d65): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6gre0' (0000000018a24d65): calling ktype release
> > kobject: 'ip6gre0': free name
> > kobject: 'ip6gre0' (00000000c78b955b): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6gre0' (00000000c78b955b): calling ktype release
> > kobject: 'ip6gre0': free name
> > kobject: 'ip6gre0' (00000000ef80dc29): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6gre0' (00000000ef80dc29): calling ktype release
> > kobject: 'ip6gre0': free name
> > kobject: 'ip6gre0' (00000000acb4e121): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6gre0' (00000000acb4e121): calling ktype release
> > kobject: 'ip6gre0': free name
> > kobject: 'ip6gre0' (0000000094fbf7bb): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6gre0' (0000000094fbf7bb): calling ktype release
> > kobject: 'ip6gre0': free name
> > kobject: 'ip6gre0' (0000000060028093): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6gre0' (0000000060028093): calling ktype release
> > kobject: 'ip6gre0': free name
> > kobject: 'ip6gre0' (00000000e217374d): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6gre0' (00000000e217374d): calling ktype release
> > kobject: 'ip6gre0': free name
> > kobject: 'ip6gre0' (00000000597e3c0a): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6gre0' (00000000597e3c0a): calling ktype release
> > kobject: 'ip6gre0': free name
> > kobject: 'ip6gre0' (00000000995a4c19): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6gre0' (00000000995a4c19): calling ktype release
> > kobject: 'ip6gre0': free name
> > kobject: 'rx-0' (00000000a530319b): kobject_cleanup, parent 0000000044c197cb
> > kobject: 'rx-0' (00000000a530319b): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000a530319b): kobject_uevent_env
> > kobject: 'rx-0' (00000000a530319b): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000a530319b): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000a530319b): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (0000000036817586): kobject_cleanup, parent 0000000044c197cb
> > kobject: 'tx-0' (0000000036817586): auto cleanup 'remove' event
> > kobject: 'tx-0' (0000000036817586): kobject_uevent_env
> > kobject: 'tx-0' (0000000036817586): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (0000000036817586): auto cleanup kobject_del
> > kobject: 'tx-0' (0000000036817586): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (0000000044c197cb): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (0000000044c197cb): calling ktype release
> > kobject: 'queues' (0000000044c197cb): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6tnl0' (000000004d7cdca9): kobject_uevent_env
> > kobject: 'ip6tnl0' (000000004d7cdca9): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000009ad0ffcd): kobject_cleanup, parent 000000006632a50a
> > kobject: 'rx-0' (000000009ad0ffcd): auto cleanup 'remove' event
> > kobject: 'rx-0' (000000009ad0ffcd): kobject_uevent_env
> > kobject: 'rx-0' (000000009ad0ffcd): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000009ad0ffcd): auto cleanup kobject_del
> > kobject: 'rx-0' (000000009ad0ffcd): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000cc8f7d89): kobject_cleanup, parent 000000006632a50a
> > kobject: 'tx-0' (00000000cc8f7d89): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000cc8f7d89): kobject_uevent_env
> > kobject: 'tx-0' (00000000cc8f7d89): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000cc8f7d89): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000cc8f7d89): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000006632a50a): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000006632a50a): calling ktype release
> > kobject: 'queues' (000000006632a50a): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6tnl0' (00000000af12a50a): kobject_uevent_env
> > kobject: 'ip6tnl0' (00000000af12a50a): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000000f3a002b): kobject_cleanup, parent 000000008e667009
> > kobject: 'rx-0' (000000000f3a002b): auto cleanup 'remove' event
> > kobject: 'rx-0' (000000000f3a002b): kobject_uevent_env
> > kobject: 'rx-0' (000000000f3a002b): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000000f3a002b): auto cleanup kobject_del
> > kobject: 'rx-0' (000000000f3a002b): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (000000003dd814d2): kobject_cleanup, parent 000000008e667009
> > kobject: 'tx-0' (000000003dd814d2): auto cleanup 'remove' event
> > kobject: 'tx-0' (000000003dd814d2): kobject_uevent_env
> > kobject: 'tx-0' (000000003dd814d2): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (000000003dd814d2): auto cleanup kobject_del
> > kobject: 'tx-0' (000000003dd814d2): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000008e667009): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000008e667009): calling ktype release
> > kobject: 'queues' (000000008e667009): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6tnl0' (00000000ad24f481): kobject_uevent_env
> > kobject: 'ip6tnl0' (00000000ad24f481): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000b57b4b94): kobject_cleanup, parent 00000000c8f88c97
> > kobject: 'rx-0' (00000000b57b4b94): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000b57b4b94): kobject_uevent_env
> > kobject: 'rx-0' (00000000b57b4b94): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000b57b4b94): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000b57b4b94): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000035a9b1c): kobject_cleanup, parent 00000000c8f88c97
> > kobject: 'tx-0' (00000000035a9b1c): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000035a9b1c): kobject_uevent_env
> > kobject: 'tx-0' (00000000035a9b1c): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000035a9b1c): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000035a9b1c): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (00000000c8f88c97): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (00000000c8f88c97): calling ktype release
> > kobject: 'queues' (00000000c8f88c97): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6tnl0' (00000000e4871037): kobject_uevent_env
> > kobject: 'ip6tnl0' (00000000e4871037): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000009e5eabee): kobject_cleanup, parent 000000000bef0c44
> > kobject: 'rx-0' (000000009e5eabee): auto cleanup 'remove' event
> > kobject: 'rx-0' (000000009e5eabee): kobject_uevent_env
> > kobject: 'rx-0' (000000009e5eabee): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000009e5eabee): auto cleanup kobject_del
> > kobject: 'rx-0' (000000009e5eabee): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000917837d7): kobject_cleanup, parent 000000000bef0c44
> > kobject: 'tx-0' (00000000917837d7): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000917837d7): kobject_uevent_env
> > kobject: 'tx-0' (00000000917837d7): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000917837d7): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000917837d7): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000000bef0c44): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000000bef0c44): calling ktype release
> > kobject: 'queues' (000000000bef0c44): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6tnl0' (00000000a48d6ad0): kobject_uevent_env
> > kobject: 'ip6tnl0' (00000000a48d6ad0): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (0000000099277526): kobject_cleanup, parent 0000000085f382c3
> > kobject: 'rx-0' (0000000099277526): auto cleanup 'remove' event
> > kobject: 'rx-0' (0000000099277526): kobject_uevent_env
> > kobject: 'rx-0' (0000000099277526): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (0000000099277526): auto cleanup kobject_del
> > kobject: 'rx-0' (0000000099277526): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000e28e65a5): kobject_cleanup, parent 0000000085f382c3
> > kobject: 'tx-0' (00000000e28e65a5): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000e28e65a5): kobject_uevent_env
> > kobject: 'tx-0' (00000000e28e65a5): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000e28e65a5): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000e28e65a5): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (0000000085f382c3): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (0000000085f382c3): calling ktype release
> > kobject: 'queues' (0000000085f382c3): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6tnl0' (000000002480b06a): kobject_uevent_env
> > kobject: 'ip6tnl0' (000000002480b06a): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000ad1f374e): kobject_cleanup, parent 000000004552107a
> > kobject: 'rx-0' (00000000ad1f374e): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000ad1f374e): kobject_uevent_env
> > kobject: 'rx-0' (00000000ad1f374e): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000ad1f374e): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000ad1f374e): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000a52c4930): kobject_cleanup, parent 000000004552107a
> > kobject: 'tx-0' (00000000a52c4930): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000a52c4930): kobject_uevent_env
> > kobject: 'tx-0' (00000000a52c4930): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000a52c4930): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000a52c4930): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000004552107a): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000004552107a): calling ktype release
> > kobject: 'queues' (000000004552107a): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6tnl0' (00000000b5c75a98): kobject_uevent_env
> > kobject: 'ip6tnl0' (00000000b5c75a98): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (0000000069cf2cec): kobject_cleanup, parent 000000000effb6b7
> > kobject: 'rx-0' (0000000069cf2cec): auto cleanup 'remove' event
> > kobject: 'rx-0' (0000000069cf2cec): kobject_uevent_env
> > kobject: 'rx-0' (0000000069cf2cec): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (0000000069cf2cec): auto cleanup kobject_del
> > kobject: 'rx-0' (0000000069cf2cec): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000f6dd67a1): kobject_cleanup, parent 000000000effb6b7
> > kobject: 'tx-0' (00000000f6dd67a1): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000f6dd67a1): kobject_uevent_env
> > kobject: 'tx-0' (00000000f6dd67a1): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000f6dd67a1): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000f6dd67a1): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000000effb6b7): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000000effb6b7): calling ktype release
> > kobject: 'queues' (000000000effb6b7): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6tnl0' (0000000017bab338): kobject_uevent_env
> > kobject: 'ip6tnl0' (0000000017bab338): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000005bed9a62): kobject_cleanup, parent 000000002a90c11d
> > kobject: 'rx-0' (000000005bed9a62): auto cleanup 'remove' event
> > kobject: 'rx-0' (000000005bed9a62): kobject_uevent_env
> > kobject: 'rx-0' (000000005bed9a62): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000005bed9a62): auto cleanup kobject_del
> > kobject: 'rx-0' (000000005bed9a62): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000148a89bb): kobject_cleanup, parent 000000002a90c11d
> > kobject: 'tx-0' (00000000148a89bb): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000148a89bb): kobject_uevent_env
> > kobject: 'tx-0' (00000000148a89bb): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000148a89bb): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000148a89bb): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000002a90c11d): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000002a90c11d): calling ktype release
> > kobject: 'queues' (000000002a90c11d): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6tnl0' (000000007855542e): kobject_uevent_env
> > kobject: 'ip6tnl0' (000000007855542e): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'ip6tnl0' (000000004d7cdca9): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6tnl0' (000000004d7cdca9): calling ktype release
> > kobject: 'ip6tnl0': free name
> > kobject: 'ip6tnl0' (00000000af12a50a): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6tnl0' (00000000af12a50a): calling ktype release
> > kobject: 'ip6tnl0': free name
> > kobject: 'ip6tnl0' (00000000ad24f481): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6tnl0' (00000000ad24f481): calling ktype release
> > kobject: 'ip6tnl0': free name
> > kobject: 'ip6tnl0' (00000000e4871037): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6tnl0' (00000000e4871037): calling ktype release
> > kobject: 'ip6tnl0': free name
> > kobject: 'ip6tnl0' (00000000a48d6ad0): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6tnl0' (00000000a48d6ad0): calling ktype release
> > kobject: 'ip6tnl0': free name
> > kobject: 'ip6tnl0' (000000002480b06a): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6tnl0' (000000002480b06a): calling ktype release
> > kobject: 'ip6tnl0': free name
> > kobject: 'ip6tnl0' (00000000b5c75a98): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6tnl0' (00000000b5c75a98): calling ktype release
> > kobject: 'ip6tnl0': free name
> > kobject: 'ip6tnl0' (0000000017bab338): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6tnl0' (0000000017bab338): calling ktype release
> > kobject: 'ip6tnl0': free name
> > kobject: 'ip6tnl0' (000000007855542e): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6tnl0' (000000007855542e): calling ktype release
> > kobject: 'ip6tnl0': free name
> > kobject: 'rx-0' (00000000faff8a75): kobject_cleanup, parent 000000003555e997
> > kobject: 'rx-0' (00000000faff8a75): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000faff8a75): kobject_uevent_env
> > kobject: 'rx-0' (00000000faff8a75): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000faff8a75): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000faff8a75): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (000000003377944b): kobject_cleanup, parent 000000003555e997
> > kobject: 'tx-0' (000000003377944b): auto cleanup 'remove' event
> > kobject: 'tx-0' (000000003377944b): kobject_uevent_env
> > kobject: 'tx-0' (000000003377944b): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (000000003377944b): auto cleanup kobject_del
> > kobject: 'tx-0' (000000003377944b): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000003555e997): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000003555e997): calling ktype release
> > kobject: 'queues' (000000003555e997): kset_release
> > kobject: 'queues': free name
> > kobject: 'sit0' (00000000ba6470e9): kobject_uevent_env
> > kobject: 'sit0' (00000000ba6470e9): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000003577adaa): kobject_cleanup, parent 00000000c5fbab92
> > kobject: 'rx-0' (000000003577adaa): auto cleanup 'remove' event
> > kobject: 'rx-0' (000000003577adaa): kobject_uevent_env
> > kobject: 'rx-0' (000000003577adaa): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000003577adaa): auto cleanup kobject_del
> > kobject: 'rx-0' (000000003577adaa): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000f519527f): kobject_cleanup, parent 00000000c5fbab92
> > kobject: 'tx-0' (00000000f519527f): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000f519527f): kobject_uevent_env
> > kobject: 'tx-0' (00000000f519527f): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000f519527f): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000f519527f): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (00000000c5fbab92): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (00000000c5fbab92): calling ktype release
> > kobject: 'queues' (00000000c5fbab92): kset_release
> > kobject: 'queues': free name
> > kobject: 'sit0' (000000009f74c826): kobject_uevent_env
> > kobject: 'sit0' (000000009f74c826): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000137dfc9e): kobject_cleanup, parent 00000000e8ee822b
> > kobject: 'rx-0' (00000000137dfc9e): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000137dfc9e): kobject_uevent_env
> > kobject: 'rx-0' (00000000137dfc9e): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000137dfc9e): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000137dfc9e): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000cf51e058): kobject_cleanup, parent 00000000e8ee822b
> > kobject: 'tx-0' (00000000cf51e058): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000cf51e058): kobject_uevent_env
> > kobject: 'tx-0' (00000000cf51e058): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000cf51e058): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000cf51e058): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (00000000e8ee822b): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (00000000e8ee822b): calling ktype release
> > kobject: 'queues' (00000000e8ee822b): kset_release
> > kobject: 'queues': free name
> > kobject: 'sit0' (0000000065e536c8): kobject_uevent_env
> > kobject: 'sit0' (0000000065e536c8): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000265aa8c8): kobject_cleanup, parent 000000001c613bad
> > kobject: 'rx-0' (00000000265aa8c8): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000265aa8c8): kobject_uevent_env
> > kobject: 'rx-0' (00000000265aa8c8): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000265aa8c8): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000265aa8c8): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000669b1a88): kobject_cleanup, parent 000000001c613bad
> > kobject: 'tx-0' (00000000669b1a88): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000669b1a88): kobject_uevent_env
> > kobject: 'tx-0' (00000000669b1a88): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000669b1a88): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000669b1a88): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000001c613bad): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000001c613bad): calling ktype release
> > kobject: 'queues' (000000001c613bad): kset_release
> > kobject: 'queues': free name
> > kobject: 'sit0' (00000000b0b0bf77): kobject_uevent_env
> > kobject: 'sit0' (00000000b0b0bf77): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000c08b3e35): kobject_cleanup, parent 000000004d964cab
> > kobject: 'rx-0' (00000000c08b3e35): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000c08b3e35): kobject_uevent_env
> > kobject: 'rx-0' (00000000c08b3e35): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000c08b3e35): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000c08b3e35): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (000000006bb20443): kobject_cleanup, parent 000000004d964cab
> > kobject: 'tx-0' (000000006bb20443): auto cleanup 'remove' event
> > kobject: 'tx-0' (000000006bb20443): kobject_uevent_env
> > kobject: 'tx-0' (000000006bb20443): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (000000006bb20443): auto cleanup kobject_del
> > kobject: 'tx-0' (000000006bb20443): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000004d964cab): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000004d964cab): calling ktype release
> > kobject: 'queues' (000000004d964cab): kset_release
> > kobject: 'queues': free name
> > kobject: 'sit0' (00000000e3a2a337): kobject_uevent_env
> > kobject: 'sit0' (00000000e3a2a337): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000fcf6c2df): kobject_cleanup, parent 000000001f378765
> > kobject: 'rx-0' (00000000fcf6c2df): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000fcf6c2df): kobject_uevent_env
> > kobject: 'rx-0' (00000000fcf6c2df): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000fcf6c2df): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000fcf6c2df): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000306e361a): kobject_cleanup, parent 000000001f378765
> > kobject: 'tx-0' (00000000306e361a): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000306e361a): kobject_uevent_env
> > kobject: 'tx-0' (00000000306e361a): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000306e361a): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000306e361a): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000001f378765): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000001f378765): calling ktype release
> > kobject: 'queues' (000000001f378765): kset_release
> > kobject: 'queues': free name
> > kobject: 'sit0' (0000000058d12d0d): kobject_uevent_env
> > kobject: 'sit0' (0000000058d12d0d): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000078d95bd): kobject_cleanup, parent 000000003596feb5
> > kobject: 'rx-0' (00000000078d95bd): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000078d95bd): kobject_uevent_env
> > kobject: 'rx-0' (00000000078d95bd): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000078d95bd): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000078d95bd): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (0000000037709752): kobject_cleanup, parent 000000003596feb5
> > kobject: 'tx-0' (0000000037709752): auto cleanup 'remove' event
> > kobject: 'tx-0' (0000000037709752): kobject_uevent_env
> > kobject: 'tx-0' (0000000037709752): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (0000000037709752): auto cleanup kobject_del
> > kobject: 'tx-0' (0000000037709752): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000003596feb5): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000003596feb5): calling ktype release
> > kobject: 'queues' (000000003596feb5): kset_release
> > kobject: 'queues': free name
> > kobject: 'sit0' (000000008276eda5): kobject_uevent_env
> > kobject: 'sit0' (000000008276eda5): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000004d3b044b): kobject_cleanup, parent 000000006b53a9a0
> > kobject: 'rx-0' (000000004d3b044b): auto cleanup 'remove' event
> > kobject: 'rx-0' (000000004d3b044b): kobject_uevent_env
> > kobject: 'rx-0' (000000004d3b044b): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000004d3b044b): auto cleanup kobject_del
> > kobject: 'rx-0' (000000004d3b044b): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000273da9ae): kobject_cleanup, parent 000000006b53a9a0
> > kobject: 'tx-0' (00000000273da9ae): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000273da9ae): kobject_uevent_env
> > kobject: 'tx-0' (00000000273da9ae): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000273da9ae): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000273da9ae): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000006b53a9a0): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000006b53a9a0): calling ktype release
> > kobject: 'queues' (000000006b53a9a0): kset_release
> > kobject: 'queues': free name
> > kobject: 'sit0' (000000005ed040cc): kobject_uevent_env
> > kobject: 'sit0' (000000005ed040cc): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000f150476e): kobject_cleanup, parent 00000000a0cff6dd
> > kobject: 'rx-0' (00000000f150476e): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000f150476e): kobject_uevent_env
> > kobject: 'rx-0' (00000000f150476e): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000f150476e): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000f150476e): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000c81ff56b): kobject_cleanup, parent 00000000a0cff6dd
> > kobject: 'tx-0' (00000000c81ff56b): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000c81ff56b): kobject_uevent_env
> > kobject: 'tx-0' (00000000c81ff56b): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000c81ff56b): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000c81ff56b): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (00000000a0cff6dd): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (00000000a0cff6dd): calling ktype release
> > kobject: 'queues' (00000000a0cff6dd): kset_release
> > kobject: 'queues': free name
> > kobject: 'sit0' (000000009ebda3df): kobject_uevent_env
> > kobject: 'sit0' (000000009ebda3df): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'sit0' (00000000ba6470e9): kobject_cleanup, parent 000000009c061a32
> > kobject: 'sit0' (00000000ba6470e9): calling ktype release
> > kobject: 'sit0': free name
> > kobject: 'sit0' (000000009f74c826): kobject_cleanup, parent 000000009c061a32
> > kobject: 'sit0' (000000009f74c826): calling ktype release
> > kobject: 'sit0': free name
> > kobject: 'sit0' (0000000065e536c8): kobject_cleanup, parent 000000009c061a32
> > kobject: 'sit0' (0000000065e536c8): calling ktype release
> > kobject: 'sit0': free name
> > kobject: 'sit0' (00000000b0b0bf77): kobject_cleanup, parent 000000009c061a32
> > kobject: 'sit0' (00000000b0b0bf77): calling ktype release
> > kobject: 'sit0': free name
> > kobject: 'sit0' (00000000e3a2a337): kobject_cleanup, parent 000000009c061a32
> > kobject: 'sit0' (00000000e3a2a337): calling ktype release
> > kobject: 'sit0': free name
> > kobject: 'sit0' (0000000058d12d0d): kobject_cleanup, parent 000000009c061a32
> > kobject: 'sit0' (0000000058d12d0d): calling ktype release
> > kobject: 'sit0': free name
> > kobject: 'sit0' (000000008276eda5): kobject_cleanup, parent 000000009c061a32
> > kobject: 'sit0' (000000008276eda5): calling ktype release
> > kobject: 'sit0': free name
> > kobject: 'sit0' (000000005ed040cc): kobject_cleanup, parent 000000009c061a32
> > kobject: 'sit0' (000000005ed040cc): calling ktype release
> > kobject: 'sit0': free name
> > kobject: 'sit0' (000000009ebda3df): kobject_cleanup, parent 000000009c061a32
> > kobject: 'sit0' (000000009ebda3df): calling ktype release
> > kobject: 'sit0': free name
> > kobject: 'rx-0' (00000000011781b4): kobject_cleanup, parent 0000000037662b61
> > kobject: 'rx-0' (00000000011781b4): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000011781b4): kobject_uevent_env
> > kobject: 'rx-0' (00000000011781b4): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000011781b4): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000011781b4): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (000000002bafd647): kobject_cleanup, parent 0000000037662b61
> > kobject: 'tx-0' (000000002bafd647): auto cleanup 'remove' event
> > kobject: 'tx-0' (000000002bafd647): kobject_uevent_env
> > kobject: 'tx-0' (000000002bafd647): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (000000002bafd647): auto cleanup kobject_del
> > kobject: 'tx-0' (000000002bafd647): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (0000000037662b61): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (0000000037662b61): calling ktype release
> > kobject: 'queues' (0000000037662b61): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6_vti0' (000000000e5b1a5c): kobject_uevent_env
> > kobject: 'ip6_vti0' (000000000e5b1a5c): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (0000000068311350): kobject_cleanup, parent 00000000facffc2f
> > kobject: 'rx-0' (0000000068311350): auto cleanup 'remove' event
> > kobject: 'rx-0' (0000000068311350): kobject_uevent_env
> > kobject: 'rx-0' (0000000068311350): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (0000000068311350): auto cleanup kobject_del
> > kobject: 'rx-0' (0000000068311350): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000d6e81326): kobject_cleanup, parent 00000000facffc2f
> > kobject: 'tx-0' (00000000d6e81326): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000d6e81326): kobject_uevent_env
> > kobject: 'tx-0' (00000000d6e81326): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000d6e81326): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000d6e81326): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (00000000facffc2f): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (00000000facffc2f): calling ktype release
> > kobject: 'queues' (00000000facffc2f): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6_vti0' (0000000084bcfa3e): kobject_uevent_env
> > kobject: 'ip6_vti0' (0000000084bcfa3e): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000ce1fbf9a): kobject_cleanup, parent 00000000faad76b9
> > kobject: 'rx-0' (00000000ce1fbf9a): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000ce1fbf9a): kobject_uevent_env
> > kobject: 'rx-0' (00000000ce1fbf9a): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000ce1fbf9a): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000ce1fbf9a): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (0000000054a9318d): kobject_cleanup, parent 00000000faad76b9
> > kobject: 'tx-0' (0000000054a9318d): auto cleanup 'remove' event
> > kobject: 'tx-0' (0000000054a9318d): kobject_uevent_env
> > kobject: 'tx-0' (0000000054a9318d): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (0000000054a9318d): auto cleanup kobject_del
> > kobject: 'tx-0' (0000000054a9318d): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (00000000faad76b9): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (00000000faad76b9): calling ktype release
> > kobject: 'queues' (00000000faad76b9): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6_vti0' (00000000a17dcb7a): kobject_uevent_env
> > kobject: 'ip6_vti0' (00000000a17dcb7a): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000e1ec0489): kobject_cleanup, parent 0000000032133323
> > kobject: 'rx-0' (00000000e1ec0489): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000e1ec0489): kobject_uevent_env
> > kobject: 'rx-0' (00000000e1ec0489): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000e1ec0489): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000e1ec0489): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000c69707b0): kobject_cleanup, parent 0000000032133323
> > kobject: 'tx-0' (00000000c69707b0): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000c69707b0): kobject_uevent_env
> > kobject: 'tx-0' (00000000c69707b0): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000c69707b0): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000c69707b0): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (0000000032133323): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (0000000032133323): calling ktype release
> > kobject: 'queues' (0000000032133323): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6_vti0' (00000000f1a1ebea): kobject_uevent_env
> > kobject: 'ip6_vti0' (00000000f1a1ebea): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000310059d9): kobject_cleanup, parent 000000002f7c701e
> > kobject: 'rx-0' (00000000310059d9): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000310059d9): kobject_uevent_env
> > kobject: 'rx-0' (00000000310059d9): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000310059d9): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000310059d9): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000463fbeb0): kobject_cleanup, parent 000000002f7c701e
> > kobject: 'tx-0' (00000000463fbeb0): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000463fbeb0): kobject_uevent_env
> > kobject: 'tx-0' (00000000463fbeb0): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000463fbeb0): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000463fbeb0): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000002f7c701e): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000002f7c701e): calling ktype release
> > kobject: 'queues' (000000002f7c701e): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6_vti0' (00000000e99a1c16): kobject_uevent_env
> > kobject: 'ip6_vti0' (00000000e99a1c16): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000fc3878f1): kobject_cleanup, parent 0000000039005ce6
> > kobject: 'rx-0' (00000000fc3878f1): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000fc3878f1): kobject_uevent_env
> > kobject: 'rx-0' (00000000fc3878f1): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000fc3878f1): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000fc3878f1): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (000000003da8a217): kobject_cleanup, parent 0000000039005ce6
> > kobject: 'tx-0' (000000003da8a217): auto cleanup 'remove' event
> > kobject: 'tx-0' (000000003da8a217): kobject_uevent_env
> > kobject: 'tx-0' (000000003da8a217): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (000000003da8a217): auto cleanup kobject_del
> > kobject: 'tx-0' (000000003da8a217): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (0000000039005ce6): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (0000000039005ce6): calling ktype release
> > kobject: 'queues' (0000000039005ce6): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6_vti0' (000000003f213163): kobject_uevent_env
> > kobject: 'ip6_vti0' (000000003f213163): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (0000000066dc1b5f): kobject_cleanup, parent 00000000e169d802
> > kobject: 'rx-0' (0000000066dc1b5f): auto cleanup 'remove' event
> > kobject: 'rx-0' (0000000066dc1b5f): kobject_uevent_env
> > kobject: 'rx-0' (0000000066dc1b5f): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (0000000066dc1b5f): auto cleanup kobject_del
> > kobject: 'rx-0' (0000000066dc1b5f): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000b99448c7): kobject_cleanup, parent 00000000e169d802
> > kobject: 'tx-0' (00000000b99448c7): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000b99448c7): kobject_uevent_env
> > kobject: 'tx-0' (00000000b99448c7): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000b99448c7): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000b99448c7): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (00000000e169d802): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (00000000e169d802): calling ktype release
> > kobject: 'queues' (00000000e169d802): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6_vti0' (000000003422603c): kobject_uevent_env
> > kobject: 'ip6_vti0' (000000003422603c): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000b6464399): kobject_cleanup, parent 00000000785ed365
> > kobject: 'rx-0' (00000000b6464399): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000b6464399): kobject_uevent_env
> > kobject: 'rx-0' (00000000b6464399): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000b6464399): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000b6464399): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000c2beb7d2): kobject_cleanup, parent 00000000785ed365
> > kobject: 'tx-0' (00000000c2beb7d2): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000c2beb7d2): kobject_uevent_env
> > kobject: 'tx-0' (00000000c2beb7d2): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000c2beb7d2): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000c2beb7d2): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (00000000785ed365): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (00000000785ed365): calling ktype release
> > kobject: 'queues' (00000000785ed365): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6_vti0' (0000000031ab464d): kobject_uevent_env
> > kobject: 'ip6_vti0' (0000000031ab464d): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000a7d5a6f7): kobject_cleanup, parent 00000000ed628333
> > kobject: 'rx-0' (00000000a7d5a6f7): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000a7d5a6f7): kobject_uevent_env
> > kobject: 'rx-0' (00000000a7d5a6f7): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000a7d5a6f7): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000a7d5a6f7): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000564c497f): kobject_cleanup, parent 00000000ed628333
> > kobject: 'tx-0' (00000000564c497f): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000564c497f): kobject_uevent_env
> > kobject: 'tx-0' (00000000564c497f): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000564c497f): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000564c497f): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (00000000ed628333): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (00000000ed628333): calling ktype release
> > kobject: 'queues' (00000000ed628333): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip6_vti0' (00000000fb053a2a): kobject_uevent_env
> > kobject: 'ip6_vti0' (00000000fb053a2a): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'ip6_vti0' (000000000e5b1a5c): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6_vti0' (000000000e5b1a5c): calling ktype release
> > kobject: 'ip6_vti0': free name
> > kobject: 'ip6_vti0' (0000000084bcfa3e): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6_vti0' (0000000084bcfa3e): calling ktype release
> > kobject: 'ip6_vti0': free name
> > kobject: 'ip6_vti0' (00000000a17dcb7a): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6_vti0' (00000000a17dcb7a): calling ktype release
> > kobject: 'ip6_vti0': free name
> > kobject: 'ip6_vti0' (00000000f1a1ebea): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6_vti0' (00000000f1a1ebea): calling ktype release
> > kobject: 'ip6_vti0': free name
> > kobject: 'ip6_vti0' (00000000e99a1c16): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6_vti0' (00000000e99a1c16): calling ktype release
> > kobject: 'ip6_vti0': free name
> > kobject: 'ip6_vti0' (000000003f213163): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6_vti0' (000000003f213163): calling ktype release
> > kobject: 'ip6_vti0': free name
> > kobject: 'ip6_vti0' (000000003422603c): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6_vti0' (000000003422603c): calling ktype release
> > kobject: 'ip6_vti0': free name
> > kobject: 'ip6_vti0' (0000000031ab464d): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6_vti0' (0000000031ab464d): calling ktype release
> > kobject: 'ip6_vti0': free name
> > kobject: 'ip6_vti0' (00000000fb053a2a): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'ip6_vti0' (00000000fb053a2a): calling ktype release
> > kobject: 'ip6_vti0': free name
> > kobject: 'rx-0' (00000000c827514b): kobject_cleanup, parent 000000004e70d3ea
> > kobject: 'rx-0' (00000000c827514b): auto cleanup 'remove' event
> > kobject: 'rx-0' (00000000c827514b): kobject_uevent_env
> > kobject: 'rx-0' (00000000c827514b): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (00000000c827514b): auto cleanup kobject_del
> > kobject: 'rx-0' (00000000c827514b): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (00000000e9330ec4): kobject_cleanup, parent 000000004e70d3ea
> > kobject: 'tx-0' (00000000e9330ec4): auto cleanup 'remove' event
> > kobject: 'tx-0' (00000000e9330ec4): kobject_uevent_env
> > kobject: 'tx-0' (00000000e9330ec4): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (00000000e9330ec4): auto cleanup kobject_del
> > kobject: 'tx-0' (00000000e9330ec4): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (000000004e70d3ea): kobject_cleanup, parent
> > 000000009c061a32
> > kobject: 'queues' (000000004e70d3ea): calling ktype release
> > kobject: 'queues' (000000004e70d3ea): kset_release
> > kobject: 'queues': free name
> > kobject: 'ip_vti0' (000000004ee7ad23): kobject_uevent_env
> > kobject: 'ip_vti0' (000000004ee7ad23): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000004dda38d8): kobject_cleanup, parent 00000000025cb3fe
> > kobject: 'rx-0' (000000004dda38d8): auto cleanup 'remove' event
> > kobject: 'rx-0' (000000004dda38d8): kobject_uevent_env
> > kobject: 'rx-0' (000000004dda38d8): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'rx-0' (000000004dda38d8): auto cleanup kobject_del
> > kobject: 'rx-0' (000000004dda38d8): calling ktype release
> > kobject: 'rx-0': free name
> > kobject: 'tx-0' (0000000097fba38d): kobject_cleanup, parent 00000000025cb3fe
> > kobject: 'tx-0' (0000000097fba38d): auto cleanup 'remove' event
> > kobject: 'tx-0' (0000000097fba38d): kobject_uevent_env
> > kobject: 'tx-0' (0000000097fba38d): kobject_uevent_env: uevent_suppress
> > caused the event to drop!
> > kobject: 'tx-0' (0000000097fba38d): auto cleanup kobject_del
> > kobject: 'tx-0' (0000000097fba38d): calling ktype release
> > kobject: 'tx-0': free name
> > kobject: 'queues' (00000000025cb3fe): kobject_cleanup, parent
> > 000000009c061a32
> >
> >
> > ---
> > This bug is generated by a bot. It may contain errors.
> > See https://goo.gl/tpsmEJ for more information about syzbot.
> > syzbot engineers can be reached at syzkaller@googlegroups.com.
> >
> > syzbot will keep track of this bug report. See:
> > https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
> >
> > --
> > You received this message because you are subscribed to the Google Groups "syzkaller-bugs" group.
> > To unsubscribe from this group and stop receiving emails from it, send an email to syzkaller-bugs+unsubscribe@googlegroups.com.
> > To view this discussion on the web visit https://groups.google.com/d/msgid/syzkaller-bugs/00000000000071c72c0590776357%40google.com.
>
> Looks to be:
>
> #syz dup: BUG: MAX_STACK_TRACE_ENTRIES too low! (2)
>
> Original thread: https://lkml.kernel.org/lkml/0000000000005ff8b20585395280@google.com/T/#u
>
> The caller isn't really meaningful for "MAX_STACK_TRACE_ENTRIES too low" bugs,
> so I think
> https://github.com/google/syzkaller/pull/1332/commits/ccbd11f30158d198e84953b1bb5eaa33464d9311
> should be reverted...
>
> - Eric

Hm, when I looked at the stack traces of the reports they all seemed
to be coming from only a few particular origins. But looking at the
code it seems there's a global array of stack trace entries that can
only grow, so this can be triggered anywhere. I'll revert the change.

^ permalink raw reply

* Re: [PATCH v2 0/2] Simplify mtty driver and mdev core
From: Jiri Pirko @ 2019-08-22 12:19 UTC (permalink / raw)
  To: Parav Pandit
  Cc: Alex Williamson, Jiri Pirko, David S . Miller, Kirti Wankhede,
	Cornelia Huck, kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	cjia, netdev@vger.kernel.org
In-Reply-To: <AM0PR05MB4866144FD76C302D04DA04B9D1A50@AM0PR05MB4866.eurprd05.prod.outlook.com>

Thu, Aug 22, 2019 at 12:04:02PM CEST, parav@mellanox.com wrote:
>
>
>> -----Original Message-----
>> From: Jiri Pirko <jiri@resnulli.us>
>> Sent: Thursday, August 22, 2019 3:28 PM
>> To: Parav Pandit <parav@mellanox.com>
>> Cc: Alex Williamson <alex.williamson@redhat.com>; Jiri Pirko
>> <jiri@mellanox.com>; David S . Miller <davem@davemloft.net>; Kirti
>> Wankhede <kwankhede@nvidia.com>; Cornelia Huck <cohuck@redhat.com>;
>> kvm@vger.kernel.org; linux-kernel@vger.kernel.org; cjia <cjia@nvidia.com>;
>> netdev@vger.kernel.org
>> Subject: Re: [PATCH v2 0/2] Simplify mtty driver and mdev core
>> 
>> Thu, Aug 22, 2019 at 11:42:13AM CEST, parav@mellanox.com wrote:
>> >
>> >
>> >> -----Original Message-----
>> >> From: Jiri Pirko <jiri@resnulli.us>
>> >> Sent: Thursday, August 22, 2019 2:59 PM
>> >> To: Parav Pandit <parav@mellanox.com>
>> >> Cc: Alex Williamson <alex.williamson@redhat.com>; Jiri Pirko
>> >> <jiri@mellanox.com>; David S . Miller <davem@davemloft.net>; Kirti
>> >> Wankhede <kwankhede@nvidia.com>; Cornelia Huck
>> <cohuck@redhat.com>;
>> >> kvm@vger.kernel.org; linux-kernel@vger.kernel.org; cjia
>> >> <cjia@nvidia.com>; netdev@vger.kernel.org
>> >> Subject: Re: [PATCH v2 0/2] Simplify mtty driver and mdev core
>> >>
>> >> Wed, Aug 21, 2019 at 08:23:17AM CEST, parav@mellanox.com wrote:
>> >> >
>> >> >
>> >> >> -----Original Message-----
>> >> >> From: Alex Williamson <alex.williamson@redhat.com>
>> >> >> Sent: Wednesday, August 21, 2019 10:56 AM
>> >> >> To: Parav Pandit <parav@mellanox.com>
>> >> >> Cc: Jiri Pirko <jiri@mellanox.com>; David S . Miller
>> >> >> <davem@davemloft.net>; Kirti Wankhede <kwankhede@nvidia.com>;
>> >> >> Cornelia Huck <cohuck@redhat.com>; kvm@vger.kernel.org;
>> >> >> linux-kernel@vger.kernel.org; cjia <cjia@nvidia.com>;
>> >> >> netdev@vger.kernel.org
>> >> >> Subject: Re: [PATCH v2 0/2] Simplify mtty driver and mdev core
>> >> >>
>> >> >> > > > > Just an example of the alias, not proposing how it's set.
>> >> >> > > > > In fact, proposing that the user does not set it,
>> >> >> > > > > mdev-core provides one
>> >> >> > > automatically.
>> >> >> > > > >
>> >> >> > > > > > > Since there seems to be some prefix overhead, as I ask
>> >> >> > > > > > > about above in how many characters we actually have to
>> >> >> > > > > > > work with in IFNAMESZ, maybe we start with 8
>> >> >> > > > > > > characters (matching your "index" namespace) and
>> >> >> > > > > > > expand as necessary for
>> >> disambiguation.
>> >> >> > > > > > > If we can eliminate overhead in IFNAMESZ, let's start with 12.
>> >> >> > > > > > > Thanks,
>> >> >> > > > > > >
>> >> >> > > > > > If user is going to choose the alias, why does it have
>> >> >> > > > > > to be limited to
>> >> >> sha1?
>> >> >> > > > > > Or you just told it as an example?
>> >> >> > > > > >
>> >> >> > > > > > It can be an alpha-numeric string.
>> >> >> > > > >
>> >> >> > > > > No, I'm proposing a different solution where mdev-core
>> >> >> > > > > creates an alias based on an abbreviated sha1.  The user
>> >> >> > > > > does not provide the
>> >> >> alias.
>> >> >> > > > >
>> >> >> > > > > > Instead of mdev imposing number of characters on the
>> >> >> > > > > > alias, it should be best
>> >> >> > > > > left to the user.
>> >> >> > > > > > Because in future if netdev improves on the naming
>> >> >> > > > > > scheme, mdev will be
>> >> >> > > > > limiting it, which is not right.
>> >> >> > > > > > So not restricting alias size seems right to me.
>> >> >> > > > > > User configuring mdev for networking devices in a given
>> >> >> > > > > > kernel knows what
>> >> >> > > > > user is doing.
>> >> >> > > > > > So user can choose alias name size as it finds suitable.
>> >> >> > > > >
>> >> >> > > > > That's not what I'm proposing, please read again.  Thanks,
>> >> >> > > >
>> >> >> > > > I understood your point. But mdev doesn't know how user is
>> >> >> > > > going to use
>> >> >> > > udev/systemd to name the netdev.
>> >> >> > > > So even if mdev chose to pick 12 characters, it could result in
>> collision.
>> >> >> > > > Hence the proposal to provide the alias by the user, as user
>> >> >> > > > know the best
>> >> >> > > policy for its use case in the environment its using.
>> >> >> > > > So 12 character sha1 method will still work by user.
>> >> >> > >
>> >> >> > > Haven't you already provided examples where certain drivers or
>> >> >> > > subsystems have unique netdev prefixes?  If mdev provides a
>> >> >> > > unique alias within the subsystem, couldn't we simply define a
>> >> >> > > netdev prefix for the mdev subsystem and avoid all other
>> >> >> > > collisions?  I'm not in favor of the user providing both a
>> >> >> > > uuid and an alias/instance.  Thanks,
>> >> >> > >
>> >> >> > For a given prefix, say ens2f0, can two UUID->sha1 first 9
>> >> >> > characters have
>> >> >> collision?
>> >> >>
>> >> >> I think it would be a mistake to waste so many chars on a prefix,
>> >> >> but
>> >> >> 9 characters of sha1 likely wouldn't have a collision before we
>> >> >> have 10s of thousands of devices.  Thanks,
>> >> >>
>> >> >> Alex
>> >> >
>> >> >Jiri, Dave,
>> >> >Are you ok with it for devlink/netdev part?
>> >> >Mdev core will create an alias from a UUID.
>> >> >
>> >> >This will be supplied during devlink port attr set such as,
>> >> >
>> >> >devlink_port_attrs_mdev_set(struct devlink_port *port, const char
>> >> >*mdev_alias);
>> >> >
>> >> >This alias is used to generate representor netdev's phys_port_name.
>> >> >This alias from the mdev device's sysfs will be used by the
>> >> >udev/systemd to
>> >> generate predicable netdev's name.
>> >> >Example: enm<mdev_alias_first_12_chars>
>> >>
>> >> What happens in unlikely case of 2 UUIDs collide?
>> >>
>> >Since users sees two devices with same phys_port_name, user should destroy
>> recently created mdev and recreate mdev with different UUID?
>> 
>> Driver should make sure phys port name wont collide, 
>So when mdev creation is initiated, mdev core calculates the alias and if there is any other mdev with same alias exist, it returns -EEXIST error before progressing further.
>This way user will get to know upfront in event of collision before the mdev device gets created.
>How about that?

Sounds fine to me. Now the question is how many chars do we want to
have.

>
>
>> in this case that it does
>> not provide 2 same attrs for 2 different ports.
>> Hmm, so the order of creation matters. That is not good.
>> 
>> >>
>> >> >I took Ethernet mdev as an example.
>> >> >New prefix 'm' stands for mediated device.
>> >> >Remaining 12 characters are first 12 chars of the mdev alias.
>> >>
>> >> Does this resolve the identification of devlink port representor?
>> >Not sure if I understood your question correctly, attemping to answer below.
>> >phys_port_name of devlink port is defined by the first 12 characters of mdev
>> alias.
>> >> I assume you want to use the same 12(or so) chars, don't you?
>> >Mdev's netdev will also use the same mdev alias from the sysfs to rename
>> netdev name from ethX to enm<mdev_alias>, where en=Etherenet, m=mdev.
>> >
>> >So yes, same 12 characters are use for mdev's netdev and mdev devlink port's
>> phys_port_name.
>> >
>> >Is that what are you asking?
>> 
>> Yes. Then you have 3 chars to handle the rest of the name (pci, pf)...

^ permalink raw reply

* [PATCH][next] mac80211: minstrel_ht: fix infinite loop because supported is not being shifted
From: Colin King @ 2019-08-22 12:20 UTC (permalink / raw)
  To: Felix Fietkau, Johannes Berg, David S . Miller, linux-wireless,
	netdev
  Cc: kernel-janitors, linux-kernel

From: Colin Ian King <colin.king@canonical.com>

Currently the for-loop will spin forever if variable supported is
non-zero because supported is never changed.  Fix this by adding in
the missing right shift of supported.

Addresses-Coverity: ("Infinite loop")
Fixes: 48cb39522a9d ("mac80211: minstrel_ht: improve rate probing for devices with static fallback")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 net/mac80211/rc80211_minstrel_ht.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index a01168514840..0ef2633349b5 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -634,7 +634,7 @@ minstrel_ht_rate_sample_switch(struct minstrel_priv *mp,
 		u16 supported = mi->supported[g_idx];
 
 		supported >>= mi->max_tp_rate[0] % MCS_GROUP_RATES;
-		for (i = 0; supported; i++) {
+		for (i = 0; supported; supported >>= 1, i++) {
 			if (!(supported & 1))
 				continue;
 
-- 
2.20.1


^ permalink raw reply related

* [PATCH net 0/9] rxrpc: Fix use of skb_cow_data()
From: David Howells @ 2019-08-22 12:22 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel


Here's a series of patches that fixes the use of skb_cow_data() in rxrpc.
The problem is that skb_cow_data() indirectly requires that the maximum
usage count on an sk_buff be 1, and it may generate an assertion failure in
pskb_expand_head() if not.

This can occur because rxrpc_input_data() may be still holding a ref when
it has just attached the sk_buff to the rx ring and given that attachment
its own ref.  If recvmsg happens fast enough, skb_cow_data() can see the
ref still held by the softirq handler.

Further, a packet may contain multiple subpackets, each of which gets its
own attachment to the ring and its own ref - also making skb_cow_data() go
bang.

Fix this by:

 (1) The DATA packet is currently parsed for subpackets twice by the input
     routines.  Parse it just once instead and make notes in the sk_buff
     private data.

 (2) Use the notes from (1) when attaching the packet to the ring multiple
     times.  Once the packet is attached to the ring, recvmsg can see it
     and cow it and start modifying it, so the softirq handler is not
     permitted to look inside it from that point.

 (3) Stick a second reference count in the skb private data, in struct
     rxrpc_skb_priv, to count the refs held by the ring on the packet.  All
     these refs together hold one single ref on the sk_buff main ref
     counter.

 (4) Pass the ref from the input code to the ring rather than getting an
     extra ref.  rxrpc_input_data() uses a ref on the second refcount to
     prevent the packet from evaporating under it.

 (5) rxkad currently calls skb_cow_data() once for each subpacket it needs
     to decrypt.  It should only be calling this once, however, so move
     that into recvmsg and only do it when we first see a new packet.

There's also a patch to improve the rxrpc_skb tracepoint to make sure that
Tx-derived buffers are identified separately from Rx-derived buffers in the
trace.


The patches are tagged here:

	git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
	rxrpc-fixes-20190820

and can also be found on the following branch:

	http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-fixes

David
---
David Howells (9):
      rxrpc: Pass the input handler's data skb reference to the Rx ring
      rxrpc: Improve jumbo packet counting
      rxrpc: Use info in skbuff instead of reparsing a jumbo packet
      rxrpc: Add a private skb flag to indicate transmission-phase skbs
      rxrpc: Abstract out rxtx ring cleanup
      rxrpc: Use the tx-phase skb flag to simplify tracing
      rxrpc: Add a shadow refcount in the skb private data
      rxrpc: Use shadow refcount for packets in the RxTx ring
      rxrpc: Only call skb_cow_data() once per packet


 include/trace/events/rxrpc.h |   62 +++++----
 net/rxrpc/ar-internal.h      |   18 ++-
 net/rxrpc/call_event.c       |    8 +
 net/rxrpc/call_object.c      |   33 ++---
 net/rxrpc/conn_event.c       |    6 -
 net/rxrpc/input.c            |  285 ++++++++++++++++++++++--------------------
 net/rxrpc/local_event.c      |    4 -
 net/rxrpc/output.c           |    6 -
 net/rxrpc/peer_event.c       |   10 +
 net/rxrpc/protocol.h         |    9 +
 net/rxrpc/recvmsg.c          |   58 +++++----
 net/rxrpc/rxkad.c            |   32 +----
 net/rxrpc/sendmsg.c          |   14 +-
 net/rxrpc/skbuff.c           |   72 +++++++++--
 14 files changed, 348 insertions(+), 269 deletions(-)


^ permalink raw reply

* [PATCH net 0/9] rxrpc: Fix use of skb_cow_data()
From: David Howells @ 2019-08-22 12:23 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel


Here's a series of patches that fixes the use of skb_cow_data() in rxrpc.
The problem is that skb_cow_data() indirectly requires that the maximum
usage count on an sk_buff be 1, and it may generate an assertion failure in
pskb_expand_head() if not.

This can occur because rxrpc_input_data() may be still holding a ref when
it has just attached the sk_buff to the rx ring and given that attachment
its own ref.  If recvmsg happens fast enough, skb_cow_data() can see the
ref still held by the softirq handler.

Further, a packet may contain multiple subpackets, each of which gets its
own attachment to the ring and its own ref - also making skb_cow_data() go
bang.

Fix this by:

 (1) The DATA packet is currently parsed for subpackets twice by the input
     routines.  Parse it just once instead and make notes in the sk_buff
     private data.

 (2) Use the notes from (1) when attaching the packet to the ring multiple
     times.  Once the packet is attached to the ring, recvmsg can see it
     and cow it and start modifying it, so the softirq handler is not
     permitted to look inside it from that point.

 (3) Stick a second reference count in the skb private data, in struct
     rxrpc_skb_priv, to count the refs held by the ring on the packet.  All
     these refs together hold one single ref on the sk_buff main ref
     counter.

 (4) Pass the ref from the input code to the ring rather than getting an
     extra ref.  rxrpc_input_data() uses a ref on the second refcount to
     prevent the packet from evaporating under it.

 (5) rxkad currently calls skb_cow_data() once for each subpacket it needs
     to decrypt.  It should only be calling this once, however, so move
     that into recvmsg and only do it when we first see a new packet.

There's also a patch to improve the rxrpc_skb tracepoint to make sure that
Tx-derived buffers are identified separately from Rx-derived buffers in the
trace.

Tested-by: Marc Dionne <marc.dionne@auristor.com>

The patches are tagged here:

	git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
	rxrpc-fixes-20190820

and can also be found on the following branch:

	http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-fixes

David
---
David Howells (9):
      rxrpc: Pass the input handler's data skb reference to the Rx ring
      rxrpc: Improve jumbo packet counting
      rxrpc: Use info in skbuff instead of reparsing a jumbo packet
      rxrpc: Add a private skb flag to indicate transmission-phase skbs
      rxrpc: Abstract out rxtx ring cleanup
      rxrpc: Use the tx-phase skb flag to simplify tracing
      rxrpc: Add a shadow refcount in the skb private data
      rxrpc: Use shadow refcount for packets in the RxTx ring
      rxrpc: Only call skb_cow_data() once per packet


 include/trace/events/rxrpc.h |   62 +++++----
 net/rxrpc/ar-internal.h      |   18 ++-
 net/rxrpc/call_event.c       |    8 +
 net/rxrpc/call_object.c      |   33 ++---
 net/rxrpc/conn_event.c       |    6 -
 net/rxrpc/input.c            |  285 ++++++++++++++++++++++--------------------
 net/rxrpc/local_event.c      |    4 -
 net/rxrpc/output.c           |    6 -
 net/rxrpc/peer_event.c       |   10 +
 net/rxrpc/protocol.h         |    9 +
 net/rxrpc/recvmsg.c          |   58 +++++----
 net/rxrpc/rxkad.c            |   32 +----
 net/rxrpc/sendmsg.c          |   14 +-
 net/rxrpc/skbuff.c           |   72 +++++++++--
 14 files changed, 348 insertions(+), 269 deletions(-)


^ permalink raw reply

* [PATCH net 1/9] rxrpc: Pass the input handler's data skb reference to the Rx ring
From: David Howells @ 2019-08-22 12:23 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <156647659913.11061.13764606104739742865.stgit@warthog.procyon.org.uk>

Pass the reference held on a DATA skb in the rxrpc input handler into the
Rx ring rather than getting an additional ref for this and then dropping
the original ref at the end.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/input.c |   48 ++++++++++++++++++++++++++++++++++--------------
 1 file changed, 34 insertions(+), 14 deletions(-)

diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index dd47d465d1d3..5789ec5ad54f 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -416,7 +416,8 @@ static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
 }
 
 /*
- * Process a DATA packet, adding the packet to the Rx ring.
+ * Process a DATA packet, adding the packet to the Rx ring.  The caller's
+ * packet ref must be passed on or discarded.
  */
 static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 {
@@ -425,20 +426,22 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 	unsigned int offset = sizeof(struct rxrpc_wire_header);
 	unsigned int ix;
 	rxrpc_serial_t serial = sp->hdr.serial, ack_serial = 0;
-	rxrpc_seq_t seq = sp->hdr.seq, hard_ack;
+	rxrpc_seq_t seq0 = sp->hdr.seq, seq, hard_ack;
 	bool immediate_ack = false, jumbo_bad = false, queued;
 	u16 len;
-	u8 ack = 0, flags, annotation = 0;
+	u8 ack = 0, flags, jumbo_flags, annotation = 0;
 
 	_enter("{%u,%u},{%u,%u}",
 	       call->rx_hard_ack, call->rx_top, skb->len, seq);
 
 	_proto("Rx DATA %%%u { #%u f=%02x }",
-	       sp->hdr.serial, seq, sp->hdr.flags);
+	       sp->hdr.serial, seq0, sp->hdr.flags);
 
 	state = READ_ONCE(call->state);
-	if (state >= RXRPC_CALL_COMPLETE)
+	if (state >= RXRPC_CALL_COMPLETE) {
+		rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
 		return;
+	}
 
 	if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST) {
 		unsigned long timo = READ_ONCE(call->next_req_timo);
@@ -463,7 +466,8 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 	    !rxrpc_receiving_reply(call))
 		goto unlock;
 
-	call->ackr_prev_seq = seq;
+	call->ackr_prev_seq = seq0;
+	seq = seq0;
 
 	hard_ack = READ_ONCE(call->rx_hard_ack);
 	if (after(seq, hard_ack + call->rx_winsize)) {
@@ -533,12 +537,25 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 	 * Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window()
 	 * and also rxrpc_fill_out_ack().
 	 */
-	rxrpc_get_skb(skb, rxrpc_skb_rx_got);
+	if (flags & RXRPC_JUMBO_PACKET) {
+		rxrpc_get_skb(skb, rxrpc_skb_rx_got);
+		if (skb_copy_bits(skb, offset, &jumbo_flags, 1) < 0) {
+			rxrpc_proto_abort("XJF", call, seq);
+			goto unlock;
+		}
+	}
 	call->rxtx_annotations[ix] = annotation;
 	smp_wmb();
 	call->rxtx_buffer[ix] = skb;
 	if (after(seq, call->rx_top)) {
 		smp_store_release(&call->rx_top, seq);
+		if (!(flags & RXRPC_JUMBO_PACKET)) {
+			/* From this point on, we're not allowed to touch the
+			 * packet any longer as its ref now belongs to the Rx
+			 * ring.
+			 */
+			skb = NULL;
+		}
 	} else if (before(seq, call->rx_top)) {
 		/* Send an immediate ACK if we fill in a hole */
 		if (!ack) {
@@ -567,10 +584,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 skip:
 	offset += len;
 	if (flags & RXRPC_JUMBO_PACKET) {
-		if (skb_copy_bits(skb, offset, &flags, 1) < 0) {
-			rxrpc_proto_abort("XJF", call, seq);
-			goto unlock;
-		}
+		flags = jumbo_flags;
 		offset += sizeof(struct rxrpc_jumbo_header);
 		seq++;
 		serial++;
@@ -606,13 +620,14 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 				  false, true,
 				  rxrpc_propose_ack_input_data);
 
-	if (sp->hdr.seq == READ_ONCE(call->rx_hard_ack) + 1) {
+	if (seq0 == READ_ONCE(call->rx_hard_ack) + 1) {
 		trace_rxrpc_notify_socket(call->debug_id, serial);
 		rxrpc_notify_socket(call);
 	}
 
 unlock:
 	spin_unlock(&call->input_lock);
+	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
 	_leave(" [queued]");
 }
 
@@ -1021,7 +1036,7 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
 	switch (sp->hdr.type) {
 	case RXRPC_PACKET_TYPE_DATA:
 		rxrpc_input_data(call, skb);
-		break;
+		goto no_free;
 
 	case RXRPC_PACKET_TYPE_ACK:
 		rxrpc_input_ack(call, skb);
@@ -1048,6 +1063,8 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
 		break;
 	}
 
+	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+no_free:
 	_leave("");
 }
 
@@ -1373,8 +1390,11 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
 		mutex_unlock(&call->user_mutex);
 	}
 
+	/* Process a call packet; this either discards or passes on the ref
+	 * elsewhere.
+	 */
 	rxrpc_input_call_packet(call, skb);
-	goto discard;
+	goto out;
 
 discard:
 	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);


^ permalink raw reply related

* [PATCH net 2/9] rxrpc: Improve jumbo packet counting
From: David Howells @ 2019-08-22 12:23 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <156647659913.11061.13764606104739742865.stgit@warthog.procyon.org.uk>

Improve the information stored about jumbo packets so that we don't need to
reparse them so much later.

Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
---

 net/rxrpc/ar-internal.h |   10 +++++++---
 net/rxrpc/input.c       |   23 ++++++++++++++---------
 net/rxrpc/protocol.h    |    9 +++++++++
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 145335611af6..87cff6c218b6 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -185,11 +185,15 @@ struct rxrpc_host_header {
  * - max 48 bytes (struct sk_buff::cb)
  */
 struct rxrpc_skb_priv {
-	union {
-		u8		nr_jumbo;	/* Number of jumbo subpackets */
-	};
+	u8		nr_subpackets;		/* Number of subpackets */
+	u8		rx_flags;		/* Received packet flags */
+#define RXRPC_SKB_INCL_LAST	0x01		/* - Includes last packet */
 	union {
 		int		remain;		/* amount of space remaining for next write */
+
+		/* List of requested ACKs on subpackets */
+		unsigned long	rx_req_ack[(RXRPC_MAX_NR_JUMBO + BITS_PER_LONG - 1) /
+					   BITS_PER_LONG];
 	};
 
 	struct rxrpc_host_header hdr;		/* RxRPC packet header from this packet */
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 5789ec5ad54f..b24492e5e429 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -347,7 +347,7 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
 }
 
 /*
- * Scan a jumbo packet to validate its structure and to work out how many
+ * Scan a data packet to validate its structure and to work out how many
  * subpackets it contains.
  *
  * A jumbo packet is a collection of consecutive packets glued together with
@@ -358,16 +358,21 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
  * the last are RXRPC_JUMBO_DATALEN in size.  The last subpacket may be of any
  * size.
  */
-static bool rxrpc_validate_jumbo(struct sk_buff *skb)
+static bool rxrpc_validate_data(struct sk_buff *skb)
 {
 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 	unsigned int offset = sizeof(struct rxrpc_wire_header);
 	unsigned int len = skb->len;
-	int nr_jumbo = 1;
 	u8 flags = sp->hdr.flags;
 
-	do {
-		nr_jumbo++;
+	for (;;) {
+		if (flags & RXRPC_REQUEST_ACK)
+			__set_bit(sp->nr_subpackets, sp->rx_req_ack);
+		sp->nr_subpackets++;
+
+		if (!(flags & RXRPC_JUMBO_PACKET))
+			break;
+
 		if (len - offset < RXRPC_JUMBO_SUBPKTLEN)
 			goto protocol_error;
 		if (flags & RXRPC_LAST_PACKET)
@@ -376,9 +381,10 @@ static bool rxrpc_validate_jumbo(struct sk_buff *skb)
 		if (skb_copy_bits(skb, offset, &flags, 1) < 0)
 			goto protocol_error;
 		offset += sizeof(struct rxrpc_jumbo_header);
-	} while (flags & RXRPC_JUMBO_PACKET);
+	}
 
-	sp->nr_jumbo = nr_jumbo;
+	if (flags & RXRPC_LAST_PACKET)
+		sp->rx_flags |= RXRPC_SKB_INCL_LAST;
 	return true;
 
 protocol_error:
@@ -1254,8 +1260,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
 		if (sp->hdr.callNumber == 0 ||
 		    sp->hdr.seq == 0)
 			goto bad_message;
-		if (sp->hdr.flags & RXRPC_JUMBO_PACKET &&
-		    !rxrpc_validate_jumbo(skb))
+		if (!rxrpc_validate_data(skb))
 			goto bad_message;
 		break;
 
diff --git a/net/rxrpc/protocol.h b/net/rxrpc/protocol.h
index 99ce322d7caa..49bb972539aa 100644
--- a/net/rxrpc/protocol.h
+++ b/net/rxrpc/protocol.h
@@ -89,6 +89,15 @@ struct rxrpc_jumbo_header {
 #define RXRPC_JUMBO_DATALEN	1412	/* non-terminal jumbo packet data length */
 #define RXRPC_JUMBO_SUBPKTLEN	(RXRPC_JUMBO_DATALEN + sizeof(struct rxrpc_jumbo_header))
 
+/*
+ * The maximum number of subpackets that can possibly fit in a UDP packet is:
+ *
+ *	((max_IP - IP_hdr - UDP_hdr) / RXRPC_JUMBO_SUBPKTLEN) + 1
+ *	= ((65535 - 28 - 28) / 1416) + 1
+ *	= 46 non-terminal packets and 1 terminal packet.
+ */
+#define RXRPC_MAX_NR_JUMBO	47
+
 /*****************************************************************************/
 /*
  * on-the-wire Rx ACK packet data payload


^ permalink raw reply related

* [PATCH net 3/9] rxrpc: Use info in skbuff instead of reparsing a jumbo packet
From: David Howells @ 2019-08-22 12:23 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <156647659913.11061.13764606104739742865.stgit@warthog.procyon.org.uk>

Use the information now cached in the skbuff private data to avoid the need
to reparse a jumbo packet.  We can find all the subpackets by dead
reckoning, so it's only necessary to note how many there are, whether the
last one is flagged as LAST_PACKET and whether any have the REQUEST_ACK
flag set.

This is necessary as once recvmsg() can see the packet, it can start
modifying it, such as doing in-place decryption.

Fixes: 248f219cb8bc ("rxrpc: Rewrite the data and ack handling code")
Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/ar-internal.h |    3 -
 net/rxrpc/input.c       |  233 ++++++++++++++++++++++-------------------------
 net/rxrpc/recvmsg.c     |   41 +++++---
 3 files changed, 135 insertions(+), 142 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 87cff6c218b6..20d7907a5bc6 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -617,8 +617,7 @@ struct rxrpc_call {
 #define RXRPC_TX_ANNO_LAST	0x04
 #define RXRPC_TX_ANNO_RESENT	0x08
 
-#define RXRPC_RX_ANNO_JUMBO	0x3f		/* Jumbo subpacket number + 1 if not zero */
-#define RXRPC_RX_ANNO_JLAST	0x40		/* Set if last element of a jumbo packet */
+#define RXRPC_RX_ANNO_SUBPACKET	0x3f		/* Subpacket number in jumbogram */
 #define RXRPC_RX_ANNO_VERIFIED	0x80		/* Set if verified and decrypted */
 	rxrpc_seq_t		tx_hard_ack;	/* Dead slot in buffer; the first transmitted but
 						 * not hard-ACK'd packet follows this.
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index b24492e5e429..140cede77655 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -405,10 +405,10 @@ static bool rxrpc_validate_data(struct sk_buff *skb)
  * (that information is encoded in the ACK packet).
  */
 static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
-				 u8 annotation, bool *_jumbo_bad)
+				 bool is_jumbo, bool *_jumbo_bad)
 {
 	/* Discard normal packets that are duplicates. */
-	if (annotation == 0)
+	if (is_jumbo)
 		return;
 
 	/* Skip jumbo subpackets that are duplicates.  When we've had three or
@@ -429,19 +429,17 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 {
 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 	enum rxrpc_call_state state;
-	unsigned int offset = sizeof(struct rxrpc_wire_header);
-	unsigned int ix;
+	unsigned int j;
 	rxrpc_serial_t serial = sp->hdr.serial, ack_serial = 0;
-	rxrpc_seq_t seq0 = sp->hdr.seq, seq, hard_ack;
-	bool immediate_ack = false, jumbo_bad = false, queued;
-	u16 len;
-	u8 ack = 0, flags, jumbo_flags, annotation = 0;
+	rxrpc_seq_t seq0 = sp->hdr.seq, hard_ack;
+	bool immediate_ack = false, jumbo_bad = false;
+	u8 ack = 0;
 
 	_enter("{%u,%u},{%u,%u}",
-	       call->rx_hard_ack, call->rx_top, skb->len, seq);
+	       call->rx_hard_ack, call->rx_top, skb->len, seq0);
 
-	_proto("Rx DATA %%%u { #%u f=%02x }",
-	       sp->hdr.serial, seq0, sp->hdr.flags);
+	_proto("Rx DATA %%%u { #%u f=%02x n=%u }",
+	       sp->hdr.serial, seq0, sp->hdr.flags, sp->nr_subpackets);
 
 	state = READ_ONCE(call->state);
 	if (state >= RXRPC_CALL_COMPLETE) {
@@ -473,147 +471,136 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 		goto unlock;
 
 	call->ackr_prev_seq = seq0;
-	seq = seq0;
-
 	hard_ack = READ_ONCE(call->rx_hard_ack);
-	if (after(seq, hard_ack + call->rx_winsize)) {
-		ack = RXRPC_ACK_EXCEEDS_WINDOW;
-		ack_serial = serial;
-		goto ack;
-	}
 
-	flags = sp->hdr.flags;
-	if (flags & RXRPC_JUMBO_PACKET) {
+	if (sp->nr_subpackets > 1) {
 		if (call->nr_jumbo_bad > 3) {
 			ack = RXRPC_ACK_NOSPACE;
 			ack_serial = serial;
 			goto ack;
 		}
-		annotation = 1;
 	}
 
-next_subpacket:
-	queued = false;
-	ix = seq & RXRPC_RXTX_BUFF_MASK;
-	len = skb->len;
-	if (flags & RXRPC_JUMBO_PACKET)
-		len = RXRPC_JUMBO_DATALEN;
-
-	if (flags & RXRPC_LAST_PACKET) {
-		if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
-		    seq != call->rx_top) {
-			rxrpc_proto_abort("LSN", call, seq);
-			goto unlock;
+	for (j = 0; j < sp->nr_subpackets; j++) {
+		rxrpc_serial_t serial = sp->hdr.serial + j;
+		rxrpc_seq_t seq = seq0 + j;
+		unsigned int ix = seq & RXRPC_RXTX_BUFF_MASK;
+		bool terminal = (j == sp->nr_subpackets - 1);
+		bool last = terminal && (sp->rx_flags & RXRPC_SKB_INCL_LAST);
+		u8 flags, annotation = j;
+
+		_proto("Rx DATA+%u %%%u { #%x t=%u l=%u }",
+		     j, serial, seq, terminal, last);
+
+		if (last) {
+			if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
+			    seq != call->rx_top) {
+				rxrpc_proto_abort("LSN", call, seq);
+				goto unlock;
+			}
+		} else {
+			if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
+			    after_eq(seq, call->rx_top)) {
+				rxrpc_proto_abort("LSA", call, seq);
+				goto unlock;
+			}
 		}
-	} else {
-		if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
-		    after_eq(seq, call->rx_top)) {
-			rxrpc_proto_abort("LSA", call, seq);
-			goto unlock;
+
+		flags = 0;
+		if (last)
+			flags |= RXRPC_LAST_PACKET;
+		if (!terminal)
+			flags |= RXRPC_JUMBO_PACKET;
+		if (test_bit(j, sp->rx_req_ack))
+			flags |= RXRPC_REQUEST_ACK;
+		trace_rxrpc_rx_data(call->debug_id, seq, serial, flags, annotation);
+
+		if (before_eq(seq, hard_ack)) {
+			ack = RXRPC_ACK_DUPLICATE;
+			ack_serial = serial;
+			continue;
 		}
-	}
 
-	trace_rxrpc_rx_data(call->debug_id, seq, serial, flags, annotation);
-	if (before_eq(seq, hard_ack)) {
-		ack = RXRPC_ACK_DUPLICATE;
-		ack_serial = serial;
-		goto skip;
-	}
+		if (call->rxtx_buffer[ix]) {
+			rxrpc_input_dup_data(call, seq, sp->nr_subpackets > 1,
+					     &jumbo_bad);
+			if (ack != RXRPC_ACK_DUPLICATE) {
+				ack = RXRPC_ACK_DUPLICATE;
+				ack_serial = serial;
+			}
+			immediate_ack = true;
+			continue;
+		}
 
-	if (flags & RXRPC_REQUEST_ACK && !ack) {
-		ack = RXRPC_ACK_REQUESTED;
-		ack_serial = serial;
-	}
+		if (after(seq, hard_ack + call->rx_winsize)) {
+			ack = RXRPC_ACK_EXCEEDS_WINDOW;
+			ack_serial = serial;
+			if (flags & RXRPC_JUMBO_PACKET) {
+				if (!jumbo_bad) {
+					call->nr_jumbo_bad++;
+					jumbo_bad = true;
+				}
+			}
 
-	if (call->rxtx_buffer[ix]) {
-		rxrpc_input_dup_data(call, seq, annotation, &jumbo_bad);
-		if (ack != RXRPC_ACK_DUPLICATE) {
-			ack = RXRPC_ACK_DUPLICATE;
+			goto ack;
+		}
+
+		if (flags & RXRPC_REQUEST_ACK && !ack) {
+			ack = RXRPC_ACK_REQUESTED;
 			ack_serial = serial;
 		}
-		immediate_ack = true;
-		goto skip;
-	}
 
-	/* Queue the packet.  We use a couple of memory barriers here as need
-	 * to make sure that rx_top is perceived to be set after the buffer
-	 * pointer and that the buffer pointer is set after the annotation and
-	 * the skb data.
-	 *
-	 * Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window()
-	 * and also rxrpc_fill_out_ack().
-	 */
-	if (flags & RXRPC_JUMBO_PACKET) {
-		rxrpc_get_skb(skb, rxrpc_skb_rx_got);
-		if (skb_copy_bits(skb, offset, &jumbo_flags, 1) < 0) {
-			rxrpc_proto_abort("XJF", call, seq);
-			goto unlock;
+		/* Queue the packet.  We use a couple of memory barriers here as need
+		 * to make sure that rx_top is perceived to be set after the buffer
+		 * pointer and that the buffer pointer is set after the annotation and
+		 * the skb data.
+		 *
+		 * Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window()
+		 * and also rxrpc_fill_out_ack().
+		 */
+		if (!terminal)
+			rxrpc_get_skb(skb, rxrpc_skb_rx_got);
+		call->rxtx_annotations[ix] = annotation;
+		smp_wmb();
+		call->rxtx_buffer[ix] = skb;
+		if (after(seq, call->rx_top)) {
+			smp_store_release(&call->rx_top, seq);
+		} else if (before(seq, call->rx_top)) {
+			/* Send an immediate ACK if we fill in a hole */
+			if (!ack) {
+				ack = RXRPC_ACK_DELAY;
+				ack_serial = serial;
+			}
+			immediate_ack = true;
 		}
-	}
-	call->rxtx_annotations[ix] = annotation;
-	smp_wmb();
-	call->rxtx_buffer[ix] = skb;
-	if (after(seq, call->rx_top)) {
-		smp_store_release(&call->rx_top, seq);
-		if (!(flags & RXRPC_JUMBO_PACKET)) {
+
+		if (terminal) {
 			/* From this point on, we're not allowed to touch the
 			 * packet any longer as its ref now belongs to the Rx
 			 * ring.
 			 */
 			skb = NULL;
 		}
-	} else if (before(seq, call->rx_top)) {
-		/* Send an immediate ACK if we fill in a hole */
-		if (!ack) {
-			ack = RXRPC_ACK_DELAY;
-			ack_serial = serial;
-		}
-		immediate_ack = true;
-	}
-	if (flags & RXRPC_LAST_PACKET) {
-		set_bit(RXRPC_CALL_RX_LAST, &call->flags);
-		trace_rxrpc_receive(call, rxrpc_receive_queue_last, serial, seq);
-	} else {
-		trace_rxrpc_receive(call, rxrpc_receive_queue, serial, seq);
-	}
-	queued = true;
 
-	if (after_eq(seq, call->rx_expect_next)) {
-		if (after(seq, call->rx_expect_next)) {
-			_net("OOS %u > %u", seq, call->rx_expect_next);
-			ack = RXRPC_ACK_OUT_OF_SEQUENCE;
-			ack_serial = serial;
+		if (last) {
+			set_bit(RXRPC_CALL_RX_LAST, &call->flags);
+			if (!ack) {
+				ack = RXRPC_ACK_DELAY;
+				ack_serial = serial;
+			}
+			trace_rxrpc_receive(call, rxrpc_receive_queue_last, serial, seq);
+		} else {
+			trace_rxrpc_receive(call, rxrpc_receive_queue, serial, seq);
 		}
-		call->rx_expect_next = seq + 1;
-	}
 
-skip:
-	offset += len;
-	if (flags & RXRPC_JUMBO_PACKET) {
-		flags = jumbo_flags;
-		offset += sizeof(struct rxrpc_jumbo_header);
-		seq++;
-		serial++;
-		annotation++;
-		if (flags & RXRPC_JUMBO_PACKET)
-			annotation |= RXRPC_RX_ANNO_JLAST;
-		if (after(seq, hard_ack + call->rx_winsize)) {
-			ack = RXRPC_ACK_EXCEEDS_WINDOW;
-			ack_serial = serial;
-			if (!jumbo_bad) {
-				call->nr_jumbo_bad++;
-				jumbo_bad = true;
+		if (after_eq(seq, call->rx_expect_next)) {
+			if (after(seq, call->rx_expect_next)) {
+				_net("OOS %u > %u", seq, call->rx_expect_next);
+				ack = RXRPC_ACK_OUT_OF_SEQUENCE;
+				ack_serial = serial;
 			}
-			goto ack;
+			call->rx_expect_next = seq + 1;
 		}
-
-		_proto("Rx DATA Jumbo %%%u", serial);
-		goto next_subpacket;
-	}
-
-	if (queued && flags & RXRPC_LAST_PACKET && !ack) {
-		ack = RXRPC_ACK_DELAY;
-		ack_serial = serial;
 	}
 
 ack:
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index 9a7e1bc9791d..e49eacfaf4d6 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -177,7 +177,8 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
 	struct sk_buff *skb;
 	rxrpc_serial_t serial;
 	rxrpc_seq_t hard_ack, top;
-	u8 flags;
+	bool last = false;
+	u8 subpacket;
 	int ix;
 
 	_enter("%d", call->debug_id);
@@ -191,10 +192,13 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
 	skb = call->rxtx_buffer[ix];
 	rxrpc_see_skb(skb, rxrpc_skb_rx_rotated);
 	sp = rxrpc_skb(skb);
-	flags = sp->hdr.flags;
-	serial = sp->hdr.serial;
-	if (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO)
-		serial += (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO) - 1;
+
+	subpacket = call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET;
+	serial = sp->hdr.serial + subpacket;
+
+	if (subpacket == sp->nr_subpackets - 1 &&
+	    sp->rx_flags & RXRPC_SKB_INCL_LAST)
+		last = true;
 
 	call->rxtx_buffer[ix] = NULL;
 	call->rxtx_annotations[ix] = 0;
@@ -203,9 +207,8 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
 
 	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
 
-	_debug("%u,%u,%02x", hard_ack, top, flags);
 	trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack);
-	if (flags & RXRPC_LAST_PACKET) {
+	if (last) {
 		rxrpc_end_rx_phase(call, serial);
 	} else {
 		/* Check to see if there's an ACK that needs sending. */
@@ -233,18 +236,19 @@ static int rxrpc_verify_packet(struct rxrpc_call *call, struct sk_buff *skb,
 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 	rxrpc_seq_t seq = sp->hdr.seq;
 	u16 cksum = sp->hdr.cksum;
+	u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET;
 
 	_enter("");
 
 	/* For all but the head jumbo subpacket, the security checksum is in a
 	 * jumbo header immediately prior to the data.
 	 */
-	if ((annotation & RXRPC_RX_ANNO_JUMBO) > 1) {
+	if (subpacket > 0) {
 		__be16 tmp;
 		if (skb_copy_bits(skb, offset - 2, &tmp, 2) < 0)
 			BUG();
 		cksum = ntohs(tmp);
-		seq += (annotation & RXRPC_RX_ANNO_JUMBO) - 1;
+		seq += subpacket;
 	}
 
 	return call->conn->security->verify_packet(call, skb, offset, len,
@@ -265,19 +269,18 @@ static int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb,
 			     u8 *_annotation,
 			     unsigned int *_offset, unsigned int *_len)
 {
+	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 	unsigned int offset = sizeof(struct rxrpc_wire_header);
 	unsigned int len;
 	int ret;
 	u8 annotation = *_annotation;
+	u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET;
 
 	/* Locate the subpacket */
+	offset += subpacket * RXRPC_JUMBO_SUBPKTLEN;
 	len = skb->len - offset;
-	if ((annotation & RXRPC_RX_ANNO_JUMBO) > 0) {
-		offset += (((annotation & RXRPC_RX_ANNO_JUMBO) - 1) *
-			   RXRPC_JUMBO_SUBPKTLEN);
-		len = (annotation & RXRPC_RX_ANNO_JLAST) ?
-			skb->len - offset : RXRPC_JUMBO_SUBPKTLEN;
-	}
+	if (subpacket < sp->nr_subpackets - 1)
+		len = RXRPC_JUMBO_DATALEN;
 
 	if (!(annotation & RXRPC_RX_ANNO_VERIFIED)) {
 		ret = rxrpc_verify_packet(call, skb, annotation, offset, len);
@@ -303,6 +306,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
 {
 	struct rxrpc_skb_priv *sp;
 	struct sk_buff *skb;
+	rxrpc_serial_t serial;
 	rxrpc_seq_t hard_ack, top, seq;
 	size_t remain;
 	bool last;
@@ -339,9 +343,12 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
 		rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
 		sp = rxrpc_skb(skb);
 
-		if (!(flags & MSG_PEEK))
+		if (!(flags & MSG_PEEK)) {
+			serial = sp->hdr.serial;
+			serial += call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET;
 			trace_rxrpc_receive(call, rxrpc_receive_front,
-					    sp->hdr.serial, seq);
+					    serial, seq);
+		}
 
 		if (msg)
 			sock_recv_timestamp(msg, sock->sk, skb);


^ permalink raw reply related

* [PATCH net 4/9] rxrpc: Add a private skb flag to indicate transmission-phase skbs
From: David Howells @ 2019-08-22 12:23 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <156647659913.11061.13764606104739742865.stgit@warthog.procyon.org.uk>

Add a flag in the private data on an skbuff to indicate that this is a
transmission-phase buffer rather than a receive-phase buffer.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/ar-internal.h |    1 +
 net/rxrpc/sendmsg.c     |    3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 20d7907a5bc6..63d3a91ce5e9 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -188,6 +188,7 @@ struct rxrpc_skb_priv {
 	u8		nr_subpackets;		/* Number of subpackets */
 	u8		rx_flags;		/* Received packet flags */
 #define RXRPC_SKB_INCL_LAST	0x01		/* - Includes last packet */
+#define RXRPC_SKB_TX_BUFFER	0x02		/* - Is transmit buffer */
 	union {
 		int		remain;		/* amount of space remaining for next write */
 
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index bae14438f869..472dc3b7d91f 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -336,6 +336,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
 			if (!skb)
 				goto maybe_error;
 
+			sp = rxrpc_skb(skb);
+			sp->rx_flags |= RXRPC_SKB_TX_BUFFER;
 			rxrpc_new_skb(skb, rxrpc_skb_tx_new);
 
 			_debug("ALLOC SEND %p", skb);
@@ -346,7 +348,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
 			skb_reserve(skb, call->conn->security_size);
 			skb->len += call->conn->security_size;
 
-			sp = rxrpc_skb(skb);
 			sp->remain = chunk;
 			if (sp->remain > skb_tailroom(skb))
 				sp->remain = skb_tailroom(skb);


^ permalink raw reply related

* [PATCH net 5/9] rxrpc: Abstract out rxtx ring cleanup
From: David Howells @ 2019-08-22 12:23 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <156647659913.11061.13764606104739742865.stgit@warthog.procyon.org.uk>

Abstract out rxtx ring cleanup into its own function from its two callers.
This makes it easier to apply the same changes to both.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/call_object.c |   33 +++++++++++++++++----------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 217b12be9e08..c9ab2da957fe 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -421,6 +421,21 @@ void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op)
 	trace_rxrpc_call(call, op, n, here, NULL);
 }
 
+/*
+ * Clean up the RxTx skb ring.
+ */
+static void rxrpc_cleanup_ring(struct rxrpc_call *call)
+{
+	int i;
+
+	for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
+		rxrpc_free_skb(call->rxtx_buffer[i],
+			       (call->tx_phase ? rxrpc_skb_tx_cleaned :
+				rxrpc_skb_rx_cleaned));
+		call->rxtx_buffer[i] = NULL;
+	}
+}
+
 /*
  * Detach a call from its owning socket.
  */
@@ -429,7 +444,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
 	const void *here = __builtin_return_address(0);
 	struct rxrpc_connection *conn = call->conn;
 	bool put = false;
-	int i;
 
 	_enter("{%d,%d}", call->debug_id, atomic_read(&call->usage));
 
@@ -479,13 +493,7 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
 	if (conn)
 		rxrpc_disconnect_call(call);
 
-	for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
-		rxrpc_free_skb(call->rxtx_buffer[i],
-			       (call->tx_phase ? rxrpc_skb_tx_cleaned :
-				rxrpc_skb_rx_cleaned));
-		call->rxtx_buffer[i] = NULL;
-	}
-
+	rxrpc_cleanup_ring(call);
 	_leave("");
 }
 
@@ -568,8 +576,6 @@ static void rxrpc_rcu_destroy_call(struct rcu_head *rcu)
  */
 void rxrpc_cleanup_call(struct rxrpc_call *call)
 {
-	int i;
-
 	_net("DESTROY CALL %d", call->debug_id);
 
 	memset(&call->sock_node, 0xcd, sizeof(call->sock_node));
@@ -580,12 +586,7 @@ void rxrpc_cleanup_call(struct rxrpc_call *call)
 	ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags));
 	ASSERTCMP(call->conn, ==, NULL);
 
-	/* Clean up the Rx/Tx buffer */
-	for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++)
-		rxrpc_free_skb(call->rxtx_buffer[i],
-			       (call->tx_phase ? rxrpc_skb_tx_cleaned :
-				rxrpc_skb_rx_cleaned));
-
+	rxrpc_cleanup_ring(call);
 	rxrpc_free_skb(call->tx_pending, rxrpc_skb_tx_cleaned);
 
 	call_rcu(&call->rcu, rxrpc_rcu_destroy_call);


^ permalink raw reply related

* [PATCH net 6/9] rxrpc: Use the tx-phase skb flag to simplify tracing
From: David Howells @ 2019-08-22 12:24 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <156647659913.11061.13764606104739742865.stgit@warthog.procyon.org.uk>

Use the previously-added transmit-phase skbuff private flag to simplify the
socket buffer tracing a bit.  Which phase the skbuff comes from can now be
divined from the skb rather than having to be guessed from the call state.

We can also reduce the number of rxrpc_skb_trace values by eliminating the
difference between Tx and Rx in the symbols.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 include/trace/events/rxrpc.h |   51 ++++++++++++++++++------------------------
 net/rxrpc/ar-internal.h      |    1 +
 net/rxrpc/call_event.c       |    8 +++----
 net/rxrpc/call_object.c      |    6 ++---
 net/rxrpc/conn_event.c       |    6 ++---
 net/rxrpc/input.c            |   22 +++++++++---------
 net/rxrpc/local_event.c      |    4 ++-
 net/rxrpc/output.c           |    6 ++---
 net/rxrpc/peer_event.c       |   10 ++++----
 net/rxrpc/recvmsg.c          |    6 ++---
 net/rxrpc/sendmsg.c          |   10 ++++----
 net/rxrpc/skbuff.c           |   15 +++++++-----
 12 files changed, 69 insertions(+), 76 deletions(-)

diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index fa06b528c73c..e2356c51883b 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -23,20 +23,15 @@
 #define __RXRPC_DECLARE_TRACE_ENUMS_ONCE_ONLY
 
 enum rxrpc_skb_trace {
-	rxrpc_skb_rx_cleaned,
-	rxrpc_skb_rx_freed,
-	rxrpc_skb_rx_got,
-	rxrpc_skb_rx_lost,
-	rxrpc_skb_rx_purged,
-	rxrpc_skb_rx_received,
-	rxrpc_skb_rx_rotated,
-	rxrpc_skb_rx_seen,
-	rxrpc_skb_tx_cleaned,
-	rxrpc_skb_tx_freed,
-	rxrpc_skb_tx_got,
-	rxrpc_skb_tx_new,
-	rxrpc_skb_tx_rotated,
-	rxrpc_skb_tx_seen,
+	rxrpc_skb_cleaned,
+	rxrpc_skb_freed,
+	rxrpc_skb_got,
+	rxrpc_skb_lost,
+	rxrpc_skb_new,
+	rxrpc_skb_purged,
+	rxrpc_skb_received,
+	rxrpc_skb_rotated,
+	rxrpc_skb_seen,
 };
 
 enum rxrpc_local_trace {
@@ -228,20 +223,15 @@ enum rxrpc_tx_point {
  * Declare tracing information enums and their string mappings for display.
  */
 #define rxrpc_skb_traces \
-	EM(rxrpc_skb_rx_cleaned,		"Rx CLN") \
-	EM(rxrpc_skb_rx_freed,			"Rx FRE") \
-	EM(rxrpc_skb_rx_got,			"Rx GOT") \
-	EM(rxrpc_skb_rx_lost,			"Rx *L*") \
-	EM(rxrpc_skb_rx_purged,			"Rx PUR") \
-	EM(rxrpc_skb_rx_received,		"Rx RCV") \
-	EM(rxrpc_skb_rx_rotated,		"Rx ROT") \
-	EM(rxrpc_skb_rx_seen,			"Rx SEE") \
-	EM(rxrpc_skb_tx_cleaned,		"Tx CLN") \
-	EM(rxrpc_skb_tx_freed,			"Tx FRE") \
-	EM(rxrpc_skb_tx_got,			"Tx GOT") \
-	EM(rxrpc_skb_tx_new,			"Tx NEW") \
-	EM(rxrpc_skb_tx_rotated,		"Tx ROT") \
-	E_(rxrpc_skb_tx_seen,			"Tx SEE")
+	EM(rxrpc_skb_cleaned,			"CLN") \
+	EM(rxrpc_skb_freed,			"FRE") \
+	EM(rxrpc_skb_got,			"GOT") \
+	EM(rxrpc_skb_lost,			"*L*") \
+	EM(rxrpc_skb_new,			"NEW") \
+	EM(rxrpc_skb_purged,			"PUR") \
+	EM(rxrpc_skb_received,			"RCV") \
+	EM(rxrpc_skb_rotated,			"ROT") \
+	E_(rxrpc_skb_seen,			"SEE")
 
 #define rxrpc_local_traces \
 	EM(rxrpc_local_got,			"GOT") \
@@ -650,6 +640,7 @@ TRACE_EVENT(rxrpc_skb,
 	    TP_STRUCT__entry(
 		    __field(struct sk_buff *,		skb		)
 		    __field(enum rxrpc_skb_trace,	op		)
+		    __field(u8,				flags		)
 		    __field(int,			usage		)
 		    __field(int,			mod_count	)
 		    __field(const void *,		where		)
@@ -657,14 +648,16 @@ TRACE_EVENT(rxrpc_skb,
 
 	    TP_fast_assign(
 		    __entry->skb = skb;
+		    __entry->flags = rxrpc_skb(skb)->rx_flags;
 		    __entry->op = op;
 		    __entry->usage = usage;
 		    __entry->mod_count = mod_count;
 		    __entry->where = where;
 			   ),
 
-	    TP_printk("s=%p %s u=%d m=%d p=%pSR",
+	    TP_printk("s=%p %cx %s u=%d m=%d p=%pSR",
 		      __entry->skb,
+		      __entry->flags & RXRPC_SKB_TX_BUFFER ? 'T' : 'R',
 		      __print_symbolic(__entry->op, rxrpc_skb_traces),
 		      __entry->usage,
 		      __entry->mod_count,
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 63d3a91ce5e9..2d5294f3e62f 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -185,6 +185,7 @@ struct rxrpc_host_header {
  * - max 48 bytes (struct sk_buff::cb)
  */
 struct rxrpc_skb_priv {
+	atomic_t	nr_ring_pins;		/* Number of rxtx ring pins */
 	u8		nr_subpackets;		/* Number of subpackets */
 	u8		rx_flags;		/* Received packet flags */
 #define RXRPC_SKB_INCL_LAST	0x01		/* - Includes last packet */
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
index c767679bfa5d..cedbbb3a7c2e 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -199,7 +199,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
 			continue;
 
 		skb = call->rxtx_buffer[ix];
-		rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
+		rxrpc_see_skb(skb, rxrpc_skb_seen);
 
 		if (anno_type == RXRPC_TX_ANNO_UNACK) {
 			if (ktime_after(skb->tstamp, max_age)) {
@@ -255,18 +255,18 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
 			continue;
 
 		skb = call->rxtx_buffer[ix];
-		rxrpc_get_skb(skb, rxrpc_skb_tx_got);
+		rxrpc_get_skb(skb, rxrpc_skb_got);
 		spin_unlock_bh(&call->lock);
 
 		if (rxrpc_send_data_packet(call, skb, true) < 0) {
-			rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+			rxrpc_free_skb(skb, rxrpc_skb_freed);
 			return;
 		}
 
 		if (rxrpc_is_client_call(call))
 			rxrpc_expose_client_call(call);
 
-		rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+		rxrpc_free_skb(skb, rxrpc_skb_freed);
 		spin_lock_bh(&call->lock);
 
 		/* We need to clear the retransmit state, but there are two
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index c9ab2da957fe..014548c259ce 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -429,9 +429,7 @@ static void rxrpc_cleanup_ring(struct rxrpc_call *call)
 	int i;
 
 	for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
-		rxrpc_free_skb(call->rxtx_buffer[i],
-			       (call->tx_phase ? rxrpc_skb_tx_cleaned :
-				rxrpc_skb_rx_cleaned));
+		rxrpc_free_skb(call->rxtx_buffer[i], rxrpc_skb_cleaned);
 		call->rxtx_buffer[i] = NULL;
 	}
 }
@@ -587,7 +585,7 @@ void rxrpc_cleanup_call(struct rxrpc_call *call)
 	ASSERTCMP(call->conn, ==, NULL);
 
 	rxrpc_cleanup_ring(call);
-	rxrpc_free_skb(call->tx_pending, rxrpc_skb_tx_cleaned);
+	rxrpc_free_skb(call->tx_pending, rxrpc_skb_cleaned);
 
 	call_rcu(&call->rcu, rxrpc_rcu_destroy_call);
 }
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index df6624c140be..a1ceef4f5cd0 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -472,7 +472,7 @@ void rxrpc_process_connection(struct work_struct *work)
 	/* go through the conn-level event packets, releasing the ref on this
 	 * connection that each one has when we've finished with it */
 	while ((skb = skb_dequeue(&conn->rx_queue))) {
-		rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
+		rxrpc_see_skb(skb, rxrpc_skb_seen);
 		ret = rxrpc_process_event(conn, skb, &abort_code);
 		switch (ret) {
 		case -EPROTO:
@@ -484,7 +484,7 @@ void rxrpc_process_connection(struct work_struct *work)
 			goto requeue_and_leave;
 		case -ECONNABORTED:
 		default:
-			rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+			rxrpc_free_skb(skb, rxrpc_skb_freed);
 			break;
 		}
 	}
@@ -501,6 +501,6 @@ void rxrpc_process_connection(struct work_struct *work)
 protocol_error:
 	if (rxrpc_abort_connection(conn, ret, abort_code) < 0)
 		goto requeue_and_leave;
-	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+	rxrpc_free_skb(skb, rxrpc_skb_freed);
 	goto out;
 }
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 140cede77655..31090bdf1fae 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -233,7 +233,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
 		ix = call->tx_hard_ack & RXRPC_RXTX_BUFF_MASK;
 		skb = call->rxtx_buffer[ix];
 		annotation = call->rxtx_annotations[ix];
-		rxrpc_see_skb(skb, rxrpc_skb_tx_rotated);
+		rxrpc_see_skb(skb, rxrpc_skb_rotated);
 		call->rxtx_buffer[ix] = NULL;
 		call->rxtx_annotations[ix] = 0;
 		skb->next = list;
@@ -258,7 +258,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
 		skb = list;
 		list = skb->next;
 		skb_mark_not_on_list(skb);
-		rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+		rxrpc_free_skb(skb, rxrpc_skb_freed);
 	}
 
 	return rot_last;
@@ -443,7 +443,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 
 	state = READ_ONCE(call->state);
 	if (state >= RXRPC_CALL_COMPLETE) {
-		rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+		rxrpc_free_skb(skb, rxrpc_skb_freed);
 		return;
 	}
 
@@ -559,7 +559,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 		 * and also rxrpc_fill_out_ack().
 		 */
 		if (!terminal)
-			rxrpc_get_skb(skb, rxrpc_skb_rx_got);
+			rxrpc_get_skb(skb, rxrpc_skb_got);
 		call->rxtx_annotations[ix] = annotation;
 		smp_wmb();
 		call->rxtx_buffer[ix] = skb;
@@ -620,7 +620,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 
 unlock:
 	spin_unlock(&call->input_lock);
-	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+	rxrpc_free_skb(skb, rxrpc_skb_freed);
 	_leave(" [queued]");
 }
 
@@ -1056,7 +1056,7 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
 		break;
 	}
 
-	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+	rxrpc_free_skb(skb, rxrpc_skb_freed);
 no_free:
 	_leave("");
 }
@@ -1119,7 +1119,7 @@ static void rxrpc_post_packet_to_local(struct rxrpc_local *local,
 		skb_queue_tail(&local->event_queue, skb);
 		rxrpc_queue_local(local);
 	} else {
-		rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+		rxrpc_free_skb(skb, rxrpc_skb_freed);
 	}
 }
 
@@ -1134,7 +1134,7 @@ static void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb)
 		skb_queue_tail(&local->reject_queue, skb);
 		rxrpc_queue_local(local);
 	} else {
-		rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+		rxrpc_free_skb(skb, rxrpc_skb_freed);
 	}
 }
 
@@ -1198,7 +1198,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
 	if (skb->tstamp == 0)
 		skb->tstamp = ktime_get_real();
 
-	rxrpc_new_skb(skb, rxrpc_skb_rx_received);
+	rxrpc_new_skb(skb, rxrpc_skb_received);
 
 	skb_pull(skb, sizeof(struct udphdr));
 
@@ -1215,7 +1215,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
 		static int lose;
 		if ((lose++ & 7) == 7) {
 			trace_rxrpc_rx_lose(sp);
-			rxrpc_free_skb(skb, rxrpc_skb_rx_lost);
+			rxrpc_free_skb(skb, rxrpc_skb_lost);
 			return 0;
 		}
 	}
@@ -1389,7 +1389,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
 	goto out;
 
 discard:
-	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+	rxrpc_free_skb(skb, rxrpc_skb_freed);
 out:
 	trace_rxrpc_rx_done(0, 0);
 	return 0;
diff --git a/net/rxrpc/local_event.c b/net/rxrpc/local_event.c
index e93a78f7c05e..3ce6d628cd75 100644
--- a/net/rxrpc/local_event.c
+++ b/net/rxrpc/local_event.c
@@ -90,7 +90,7 @@ void rxrpc_process_local_events(struct rxrpc_local *local)
 	if (skb) {
 		struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 
-		rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
+		rxrpc_see_skb(skb, rxrpc_skb_seen);
 		_debug("{%d},{%u}", local->debug_id, sp->hdr.type);
 
 		switch (sp->hdr.type) {
@@ -108,7 +108,7 @@ void rxrpc_process_local_events(struct rxrpc_local *local)
 			break;
 		}
 
-		rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+		rxrpc_free_skb(skb, rxrpc_skb_freed);
 	}
 
 	_leave("");
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index 369e516c4bdf..935bb60fff56 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -565,7 +565,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
 	memset(&whdr, 0, sizeof(whdr));
 
 	while ((skb = skb_dequeue(&local->reject_queue))) {
-		rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
+		rxrpc_see_skb(skb, rxrpc_skb_seen);
 		sp = rxrpc_skb(skb);
 
 		switch (skb->mark) {
@@ -581,7 +581,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
 			ioc = 2;
 			break;
 		default:
-			rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+			rxrpc_free_skb(skb, rxrpc_skb_freed);
 			continue;
 		}
 
@@ -606,7 +606,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
 						      rxrpc_tx_point_reject);
 		}
 
-		rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+		rxrpc_free_skb(skb, rxrpc_skb_freed);
 	}
 
 	_leave("");
diff --git a/net/rxrpc/peer_event.c b/net/rxrpc/peer_event.c
index 7666ec72d37e..c97ebdc043e4 100644
--- a/net/rxrpc/peer_event.c
+++ b/net/rxrpc/peer_event.c
@@ -163,11 +163,11 @@ void rxrpc_error_report(struct sock *sk)
 		_leave("UDP socket errqueue empty");
 		return;
 	}
-	rxrpc_new_skb(skb, rxrpc_skb_rx_received);
+	rxrpc_new_skb(skb, rxrpc_skb_received);
 	serr = SKB_EXT_ERR(skb);
 	if (!skb->len && serr->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING) {
 		_leave("UDP empty message");
-		rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+		rxrpc_free_skb(skb, rxrpc_skb_freed);
 		return;
 	}
 
@@ -177,7 +177,7 @@ void rxrpc_error_report(struct sock *sk)
 		peer = NULL;
 	if (!peer) {
 		rcu_read_unlock();
-		rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+		rxrpc_free_skb(skb, rxrpc_skb_freed);
 		_leave(" [no peer]");
 		return;
 	}
@@ -189,7 +189,7 @@ void rxrpc_error_report(struct sock *sk)
 	     serr->ee.ee_code == ICMP_FRAG_NEEDED)) {
 		rxrpc_adjust_mtu(peer, serr);
 		rcu_read_unlock();
-		rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+		rxrpc_free_skb(skb, rxrpc_skb_freed);
 		rxrpc_put_peer(peer);
 		_leave(" [MTU update]");
 		return;
@@ -197,7 +197,7 @@ void rxrpc_error_report(struct sock *sk)
 
 	rxrpc_store_error(peer, serr);
 	rcu_read_unlock();
-	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+	rxrpc_free_skb(skb, rxrpc_skb_freed);
 	rxrpc_put_peer(peer);
 
 	_leave("");
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index e49eacfaf4d6..3b0becb12041 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -190,7 +190,7 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
 	hard_ack++;
 	ix = hard_ack & RXRPC_RXTX_BUFF_MASK;
 	skb = call->rxtx_buffer[ix];
-	rxrpc_see_skb(skb, rxrpc_skb_rx_rotated);
+	rxrpc_see_skb(skb, rxrpc_skb_rotated);
 	sp = rxrpc_skb(skb);
 
 	subpacket = call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET;
@@ -205,7 +205,7 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
 	/* Barrier against rxrpc_input_data(). */
 	smp_store_release(&call->rx_hard_ack, hard_ack);
 
-	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+	rxrpc_free_skb(skb, rxrpc_skb_freed);
 
 	trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack);
 	if (last) {
@@ -340,7 +340,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
 			break;
 		}
 		smp_rmb();
-		rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
+		rxrpc_see_skb(skb, rxrpc_skb_seen);
 		sp = rxrpc_skb(skb);
 
 		if (!(flags & MSG_PEEK)) {
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index 472dc3b7d91f..6a1547b270fe 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -176,7 +176,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
 	skb->tstamp = ktime_get_real();
 
 	ix = seq & RXRPC_RXTX_BUFF_MASK;
-	rxrpc_get_skb(skb, rxrpc_skb_tx_got);
+	rxrpc_get_skb(skb, rxrpc_skb_got);
 	call->rxtx_annotations[ix] = annotation;
 	smp_wmb();
 	call->rxtx_buffer[ix] = skb;
@@ -248,7 +248,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
 	}
 
 out:
-	rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+	rxrpc_free_skb(skb, rxrpc_skb_freed);
 	_leave(" = %d", ret);
 	return ret;
 }
@@ -289,7 +289,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
 
 	skb = call->tx_pending;
 	call->tx_pending = NULL;
-	rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
+	rxrpc_see_skb(skb, rxrpc_skb_seen);
 
 	copied = 0;
 	do {
@@ -338,7 +338,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
 
 			sp = rxrpc_skb(skb);
 			sp->rx_flags |= RXRPC_SKB_TX_BUFFER;
-			rxrpc_new_skb(skb, rxrpc_skb_tx_new);
+			rxrpc_new_skb(skb, rxrpc_skb_new);
 
 			_debug("ALLOC SEND %p", skb);
 
@@ -440,7 +440,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
 	return ret;
 
 call_terminated:
-	rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+	rxrpc_free_skb(skb, rxrpc_skb_freed);
 	_leave(" = %d", call->error);
 	return call->error;
 
diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c
index 9ad5045b7c2f..8e6f45f84b9b 100644
--- a/net/rxrpc/skbuff.c
+++ b/net/rxrpc/skbuff.c
@@ -14,7 +14,8 @@
 #include <net/af_rxrpc.h>
 #include "ar-internal.h"
 
-#define select_skb_count(op) (op >= rxrpc_skb_tx_cleaned ? &rxrpc_n_tx_skbs : &rxrpc_n_rx_skbs)
+#define is_tx_skb(skb) (rxrpc_skb(skb)->rx_flags & RXRPC_SKB_TX_BUFFER)
+#define select_skb_count(skb) (is_tx_skb(skb) ? &rxrpc_n_tx_skbs : &rxrpc_n_rx_skbs)
 
 /*
  * Note the allocation or reception of a socket buffer.
@@ -22,7 +23,7 @@
 void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 {
 	const void *here = __builtin_return_address(0);
-	int n = atomic_inc_return(select_skb_count(op));
+	int n = atomic_inc_return(select_skb_count(skb));
 	trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
 }
 
@@ -33,7 +34,7 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 {
 	const void *here = __builtin_return_address(0);
 	if (skb) {
-		int n = atomic_read(select_skb_count(op));
+		int n = atomic_read(select_skb_count(skb));
 		trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
 	}
 }
@@ -44,7 +45,7 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 {
 	const void *here = __builtin_return_address(0);
-	int n = atomic_inc_return(select_skb_count(op));
+	int n = atomic_inc_return(select_skb_count(skb));
 	trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
 	skb_get(skb);
 }
@@ -58,7 +59,7 @@ void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 	if (skb) {
 		int n;
 		CHECK_SLAB_OKAY(&skb->users);
-		n = atomic_dec_return(select_skb_count(op));
+		n = atomic_dec_return(select_skb_count(skb));
 		trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
 		kfree_skb(skb);
 	}
@@ -72,8 +73,8 @@ void rxrpc_purge_queue(struct sk_buff_head *list)
 	const void *here = __builtin_return_address(0);
 	struct sk_buff *skb;
 	while ((skb = skb_dequeue((list))) != NULL) {
-		int n = atomic_dec_return(select_skb_count(rxrpc_skb_rx_purged));
-		trace_rxrpc_skb(skb, rxrpc_skb_rx_purged,
+		int n = atomic_dec_return(select_skb_count(skb));
+		trace_rxrpc_skb(skb, rxrpc_skb_purged,
 				refcount_read(&skb->users), n, here);
 		kfree_skb(skb);
 	}


^ permalink raw reply related

* [PATCH net 7/9] rxrpc: Add a shadow refcount in the skb private data
From: David Howells @ 2019-08-22 12:24 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <156647659913.11061.13764606104739742865.stgit@warthog.procyon.org.uk>

Add a shadow refcount to count pins from the Rx/Tx ring on an sk_buff so
that we can hold multiple refs on it without causing skb_cow_data() to
throw an assertion.

This is stored in the private part of the sk_buff as laid out in struct
rxrpc_skb_priv.

Add two accessor functions for pinning (adding) or unpinning (discarding) a
shadow ref.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 include/trace/events/rxrpc.h |   15 ++++++++---
 net/rxrpc/ar-internal.h      |    2 +
 net/rxrpc/skbuff.c           |   57 ++++++++++++++++++++++++++++++++++++++----
 3 files changed, 65 insertions(+), 9 deletions(-)

diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index e2356c51883b..34237ea8ceb0 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -28,10 +28,12 @@ enum rxrpc_skb_trace {
 	rxrpc_skb_got,
 	rxrpc_skb_lost,
 	rxrpc_skb_new,
+	rxrpc_skb_pin,
 	rxrpc_skb_purged,
 	rxrpc_skb_received,
 	rxrpc_skb_rotated,
 	rxrpc_skb_seen,
+	rxrpc_skb_unpin,
 };
 
 enum rxrpc_local_trace {
@@ -228,10 +230,12 @@ enum rxrpc_tx_point {
 	EM(rxrpc_skb_got,			"GOT") \
 	EM(rxrpc_skb_lost,			"*L*") \
 	EM(rxrpc_skb_new,			"NEW") \
+	EM(rxrpc_skb_pin,			"PIN") \
 	EM(rxrpc_skb_purged,			"PUR") \
 	EM(rxrpc_skb_received,			"RCV") \
 	EM(rxrpc_skb_rotated,			"ROT") \
-	E_(rxrpc_skb_seen,			"SEE")
+	EM(rxrpc_skb_seen,			"SEE") \
+	E_(rxrpc_skb_unpin,			"UPN")
 
 #define rxrpc_local_traces \
 	EM(rxrpc_local_got,			"GOT") \
@@ -633,14 +637,15 @@ TRACE_EVENT(rxrpc_call,
 
 TRACE_EVENT(rxrpc_skb,
 	    TP_PROTO(struct sk_buff *skb, enum rxrpc_skb_trace op,
-		     int usage, int mod_count, const void *where),
+		     int usage, int mod_count, int pins, const void *where),
 
-	    TP_ARGS(skb, op, usage, mod_count, where),
+	    TP_ARGS(skb, op, usage, mod_count, pins, where),
 
 	    TP_STRUCT__entry(
 		    __field(struct sk_buff *,		skb		)
 		    __field(enum rxrpc_skb_trace,	op		)
 		    __field(u8,				flags		)
+		    __field(u8,				pins		)
 		    __field(int,			usage		)
 		    __field(int,			mod_count	)
 		    __field(const void *,		where		)
@@ -651,16 +656,18 @@ TRACE_EVENT(rxrpc_skb,
 		    __entry->flags = rxrpc_skb(skb)->rx_flags;
 		    __entry->op = op;
 		    __entry->usage = usage;
+		    __entry->pins = pins;
 		    __entry->mod_count = mod_count;
 		    __entry->where = where;
 			   ),
 
-	    TP_printk("s=%p %cx %s u=%d m=%d p=%pSR",
+	    TP_printk("s=%p %cx %s u=%d m=%d r=%u p=%pSR",
 		      __entry->skb,
 		      __entry->flags & RXRPC_SKB_TX_BUFFER ? 'T' : 'R',
 		      __print_symbolic(__entry->op, rxrpc_skb_traces),
 		      __entry->usage,
 		      __entry->mod_count,
+		      __entry->pins,
 		      __entry->where)
 	    );
 
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 2d5294f3e62f..d784d58e0a0d 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -1113,6 +1113,8 @@ void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_purge_queue(struct sk_buff_head *);
+void rxrpc_pin_skb(struct sk_buff *, enum rxrpc_skb_trace);
+void rxrpc_unpin_skb(struct sk_buff *, enum rxrpc_skb_trace);
 
 /*
  * sysctl.c
diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c
index 8e6f45f84b9b..f9986a1510d3 100644
--- a/net/rxrpc/skbuff.c
+++ b/net/rxrpc/skbuff.c
@@ -22,9 +22,12 @@
  */
 void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 {
+	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 	const void *here = __builtin_return_address(0);
 	int n = atomic_inc_return(select_skb_count(skb));
-	trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
+
+	atomic_set(&sp->nr_ring_pins, 1);
+	trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, 1, here);
 }
 
 /*
@@ -33,9 +36,12 @@ void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 {
 	const void *here = __builtin_return_address(0);
+
 	if (skb) {
+		struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 		int n = atomic_read(select_skb_count(skb));
-		trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
+		trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
+				atomic_read(&sp->nr_ring_pins), here);
 	}
 }
 
@@ -44,9 +50,11 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
  */
 void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 {
+	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 	const void *here = __builtin_return_address(0);
 	int n = atomic_inc_return(select_skb_count(skb));
-	trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
+	trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
+			atomic_read(&sp->nr_ring_pins), here);
 	skb_get(skb);
 }
 
@@ -56,11 +64,14 @@ void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 {
 	const void *here = __builtin_return_address(0);
+
 	if (skb) {
+		struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 		int n;
 		CHECK_SLAB_OKAY(&skb->users);
 		n = atomic_dec_return(select_skb_count(skb));
-		trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
+		trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
+				atomic_read(&sp->nr_ring_pins), here);
 		kfree_skb(skb);
 	}
 }
@@ -72,10 +83,46 @@ void rxrpc_purge_queue(struct sk_buff_head *list)
 {
 	const void *here = __builtin_return_address(0);
 	struct sk_buff *skb;
+
 	while ((skb = skb_dequeue((list))) != NULL) {
+		struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 		int n = atomic_dec_return(select_skb_count(skb));
 		trace_rxrpc_skb(skb, rxrpc_skb_purged,
-				refcount_read(&skb->users), n, here);
+				refcount_read(&skb->users), n,
+				atomic_read(&sp->nr_ring_pins), here);
 		kfree_skb(skb);
 	}
 }
+
+/*
+ * Add a secondary ref on the socket buffer.
+ */
+void rxrpc_pin_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
+{
+	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+	const void *here = __builtin_return_address(0);
+	int n = atomic_read(select_skb_count(skb));
+	int np;
+
+	np = atomic_inc_return(&sp->nr_ring_pins);
+	trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, np, here);
+}
+
+/*
+ * Remove a secondary ref on the socket buffer.
+ */
+void rxrpc_unpin_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
+{
+	const void *here = __builtin_return_address(0);
+
+	if (skb) {
+		struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+		int n = atomic_read(select_skb_count(skb));
+		int np;
+
+		np = atomic_dec_return(&sp->nr_ring_pins);
+		trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, np, here);
+		if (np == 0)
+			rxrpc_free_skb(skb, op);
+	}
+}


^ permalink raw reply related

* [PATCH net 8/9] rxrpc: Use shadow refcount for packets in the RxTx ring
From: David Howells @ 2019-08-22 12:24 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <156647659913.11061.13764606104739742865.stgit@warthog.procyon.org.uk>

Use the previously added shadow refcount for packets that are in the Rx/Tx
ring so that the ring itself only ever holds a single ref on the skbuff.

This allows skb_cow_data() to be used by the recvmsg code to make the data
modifyable for in-place decryption without triggering the assertion in
pskb_expand_head:

	BUG_ON(skb_shared(skb));

This *should* be okay as:

 (1) Once rxrpc_input_data() starts attaching the sk_buff to the ring, it
     no longer looks inside the packet (all the parsing was done previously
     and notes were taken in struct rxrpc_skb_priv).

 (2) rxrpc_recvmsg_data() may not run in parallel for a particular call.

 (3) rxrpc_recvmsg_data() cow's the sk_buff the first time it sees it and
     then steps through each pointer from the buffer in order, unpinning as
     it goes.

     Each subpacket is individually and sequentially decrypted in place in
     the sk_buff, hence the need for skb_cow_data().

 (4) No one else can be looking in a packet in the Rx ring once it's there.

The problem was occuring because the softirq handler may be holding a ref
or the ring may be holding multiple refs when skb_cow_data() is called in
rxkad_verify_packet(), and so skb_shared() returns true and
__pskb_pull_tail() dislikes that.  If this occurs, something like the
following report will be generated.

	kernel BUG at net/core/skbuff.c:1463!
	...
	RIP: 0010:pskb_expand_head+0x253/0x2b0
	...
	Call Trace:
	 __pskb_pull_tail+0x49/0x460
	 skb_cow_data+0x6f/0x300
	 rxkad_verify_packet+0x18b/0xb10 [rxrpc]
	 rxrpc_recvmsg_data.isra.11+0x4a8/0xa10 [rxrpc]
	 rxrpc_kernel_recv_data+0x126/0x240 [rxrpc]
	 afs_extract_data+0x51/0x2d0 [kafs]
	 afs_deliver_fs_fetch_data+0x188/0x400 [kafs]
	 afs_deliver_to_call+0xac/0x430 [kafs]
	 afs_wait_for_call_to_complete+0x22f/0x3d0 [kafs]
	 afs_make_call+0x282/0x3f0 [kafs]
	 afs_fs_fetch_data+0x164/0x300 [kafs]
	 afs_fetch_data+0x54/0x130 [kafs]
	 afs_readpages+0x20d/0x340 [kafs]
	 read_pages+0x66/0x180
	 __do_page_cache_readahead+0x188/0x1a0
	 ondemand_readahead+0x17d/0x2e0
	 generic_file_read_iter+0x740/0xc10
	 __vfs_read+0x145/0x1a0
	 vfs_read+0x8c/0x140
	 ksys_read+0x4a/0xb0
	 do_syscall_64+0x43/0xf0
	 entry_SYSCALL_64_after_hwframe+0x44/0xa9

Fixes: 248f219cb8bc ("rxrpc: Rewrite the data and ack handling code")
Reported-by: Julian Wollrath <jwollrath@web.de>
Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/call_object.c |    2 +-
 net/rxrpc/input.c       |   22 ++++++++++------------
 net/rxrpc/recvmsg.c     |    2 +-
 net/rxrpc/sendmsg.c     |    1 +
 4 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 014548c259ce..830b6152dfa3 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -429,7 +429,7 @@ static void rxrpc_cleanup_ring(struct rxrpc_call *call)
 	int i;
 
 	for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
-		rxrpc_free_skb(call->rxtx_buffer[i], rxrpc_skb_cleaned);
+		rxrpc_unpin_skb(call->rxtx_buffer[i], rxrpc_skb_cleaned);
 		call->rxtx_buffer[i] = NULL;
 	}
 }
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 31090bdf1fae..660b7eed39b7 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -258,7 +258,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
 		skb = list;
 		list = skb->next;
 		skb_mark_not_on_list(skb);
-		rxrpc_free_skb(skb, rxrpc_skb_freed);
+		rxrpc_unpin_skb(skb, rxrpc_skb_unpin);
 	}
 
 	return rot_last;
@@ -447,6 +447,8 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 		return;
 	}
 
+	atomic_set(&sp->nr_ring_pins, 1);
+
 	if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST) {
 		unsigned long timo = READ_ONCE(call->next_req_timo);
 		unsigned long now, expect_req_by;
@@ -550,6 +552,12 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 			ack_serial = serial;
 		}
 
+		/* Each insertion into the rxtx_buffer holds a ring pin.  This
+		 * allows a single ref on the buffer to be shared, thereby
+		 * allowing skb_cow_data() to be used.
+		 */
+		rxrpc_pin_skb(skb, rxrpc_skb_pin);
+
 		/* Queue the packet.  We use a couple of memory barriers here as need
 		 * to make sure that rx_top is perceived to be set after the buffer
 		 * pointer and that the buffer pointer is set after the annotation and
@@ -558,8 +566,6 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 		 * Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window()
 		 * and also rxrpc_fill_out_ack().
 		 */
-		if (!terminal)
-			rxrpc_get_skb(skb, rxrpc_skb_got);
 		call->rxtx_annotations[ix] = annotation;
 		smp_wmb();
 		call->rxtx_buffer[ix] = skb;
@@ -574,14 +580,6 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 			immediate_ack = true;
 		}
 
-		if (terminal) {
-			/* From this point on, we're not allowed to touch the
-			 * packet any longer as its ref now belongs to the Rx
-			 * ring.
-			 */
-			skb = NULL;
-		}
-
 		if (last) {
 			set_bit(RXRPC_CALL_RX_LAST, &call->flags);
 			if (!ack) {
@@ -620,7 +618,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 
 unlock:
 	spin_unlock(&call->input_lock);
-	rxrpc_free_skb(skb, rxrpc_skb_freed);
+	rxrpc_unpin_skb(skb, rxrpc_skb_unpin);
 	_leave(" [queued]");
 }
 
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index 3b0becb12041..82bb48d96526 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -205,7 +205,7 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
 	/* Barrier against rxrpc_input_data(). */
 	smp_store_release(&call->rx_hard_ack, hard_ack);
 
-	rxrpc_free_skb(skb, rxrpc_skb_freed);
+	rxrpc_unpin_skb(skb, rxrpc_skb_unpin);
 
 	trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack);
 	if (last) {
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index 6a1547b270fe..ba0e2aa268b1 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -175,6 +175,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
 	 */
 	skb->tstamp = ktime_get_real();
 
+	atomic_set(&sp->nr_ring_pins, 1);
 	ix = seq & RXRPC_RXTX_BUFF_MASK;
 	rxrpc_get_skb(skb, rxrpc_skb_got);
 	call->rxtx_annotations[ix] = annotation;


^ permalink raw reply related

* [PATCH net 9/9] rxrpc: Only call skb_cow_data() once per packet
From: David Howells @ 2019-08-22 12:24 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <156647659913.11061.13764606104739742865.stgit@warthog.procyon.org.uk>

Move the call of skb_cow_data() from rxkad into rxrpc_recvmsg_data() and do
it as soon as the packet is first seen.  This means that we only call this
function once per packet, even for a jumbo packet with a bunch of
subpackets.

In rxkad, we then have to guess how large a scatter-gather table we need
for decryption, particularly in rxkad_verify_packet_2().  We do this either
by creating an sg table that should be large enough, or by looking at
nr_frags on the skb.

Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both")
Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/ar-internal.h |    1 +
 net/rxrpc/input.c       |    1 +
 net/rxrpc/recvmsg.c     |   11 ++++++++++-
 net/rxrpc/rxkad.c       |   32 +++++++++-----------------------
 4 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index d784d58e0a0d..a42d6b833675 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -190,6 +190,7 @@ struct rxrpc_skb_priv {
 	u8		rx_flags;		/* Received packet flags */
 #define RXRPC_SKB_INCL_LAST	0x01		/* - Includes last packet */
 #define RXRPC_SKB_TX_BUFFER	0x02		/* - Is transmit buffer */
+#define RXRPC_SKB_NEEDS_COW	0x04		/* - Needs skb_cow_data() calling */
 	union {
 		int		remain;		/* amount of space remaining for next write */
 
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 660b7eed39b7..4df39f391e9d 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -448,6 +448,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 	}
 
 	atomic_set(&sp->nr_ring_pins, 1);
+	sp->rx_flags |= RXRPC_SKB_NEEDS_COW;
 
 	if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST) {
 		unsigned long timo = READ_ONCE(call->next_req_timo);
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index 82bb48d96526..ef50580b5295 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -305,7 +305,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
 			      size_t len, int flags, size_t *_offset)
 {
 	struct rxrpc_skb_priv *sp;
-	struct sk_buff *skb;
+	struct sk_buff *skb, *trailer;
 	rxrpc_serial_t serial;
 	rxrpc_seq_t hard_ack, top, seq;
 	size_t remain;
@@ -343,6 +343,15 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
 		rxrpc_see_skb(skb, rxrpc_skb_seen);
 		sp = rxrpc_skb(skb);
 
+		if (sp->rx_flags & RXRPC_SKB_NEEDS_COW) {
+			ret2 = skb_cow_data(skb, 0, &trailer);
+			if (ret2 < 0) {
+				ret = ret2;
+				goto out;
+			}
+			sp->rx_flags &= ~RXRPC_SKB_NEEDS_COW;
+		}
+
 		if (!(flags & MSG_PEEK)) {
 			serial = sp->hdr.serial;
 			serial += call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET;
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index ae8cd8926456..c60c520fde7c 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -187,10 +187,8 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
 	struct rxrpc_skb_priv *sp;
 	struct rxrpc_crypt iv;
 	struct scatterlist sg[16];
-	struct sk_buff *trailer;
 	unsigned int len;
 	u16 check;
-	int nsg;
 	int err;
 
 	sp = rxrpc_skb(skb);
@@ -214,15 +212,14 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
 	crypto_skcipher_encrypt(req);
 
 	/* we want to encrypt the skbuff in-place */
-	nsg = skb_cow_data(skb, 0, &trailer);
-	err = -ENOMEM;
-	if (nsg < 0 || nsg > 16)
+	err = -EMSGSIZE;
+	if (skb_shinfo(skb)->nr_frags > 16)
 		goto out;
 
 	len = data_size + call->conn->size_align - 1;
 	len &= ~(call->conn->size_align - 1);
 
-	sg_init_table(sg, nsg);
+	sg_init_table(sg, ARRAY_SIZE(sg));
 	err = skb_to_sgvec(skb, sg, 0, len);
 	if (unlikely(err < 0))
 		goto out;
@@ -319,11 +316,10 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
 	struct rxkad_level1_hdr sechdr;
 	struct rxrpc_crypt iv;
 	struct scatterlist sg[16];
-	struct sk_buff *trailer;
 	bool aborted;
 	u32 data_size, buf;
 	u16 check;
-	int nsg, ret;
+	int ret;
 
 	_enter("");
 
@@ -336,11 +332,7 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
 	/* Decrypt the skbuff in-place.  TODO: We really want to decrypt
 	 * directly into the target buffer.
 	 */
-	nsg = skb_cow_data(skb, 0, &trailer);
-	if (nsg < 0 || nsg > 16)
-		goto nomem;
-
-	sg_init_table(sg, nsg);
+	sg_init_table(sg, ARRAY_SIZE(sg));
 	ret = skb_to_sgvec(skb, sg, offset, 8);
 	if (unlikely(ret < 0))
 		return ret;
@@ -388,10 +380,6 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
 	if (aborted)
 		rxrpc_send_abort_packet(call);
 	return -EPROTO;
-
-nomem:
-	_leave(" = -ENOMEM");
-	return -ENOMEM;
 }
 
 /*
@@ -406,7 +394,6 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
 	struct rxkad_level2_hdr sechdr;
 	struct rxrpc_crypt iv;
 	struct scatterlist _sg[4], *sg;
-	struct sk_buff *trailer;
 	bool aborted;
 	u32 data_size, buf;
 	u16 check;
@@ -423,12 +410,11 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
 	/* Decrypt the skbuff in-place.  TODO: We really want to decrypt
 	 * directly into the target buffer.
 	 */
-	nsg = skb_cow_data(skb, 0, &trailer);
-	if (nsg < 0)
-		goto nomem;
-
 	sg = _sg;
-	if (unlikely(nsg > 4)) {
+	nsg = skb_shinfo(skb)->nr_frags;
+	if (nsg <= 4) {
+		nsg = 4;
+	} else {
 		sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO);
 		if (!sg)
 			goto nomem;


^ permalink raw reply related

* Re: [PATCH net 0/9] rxrpc: Fix use of skb_cow_data()
From: David Howells @ 2019-08-22 12:25 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <156647655350.10908.12081183247715153431.stgit@warthog.procyon.org.uk>

Sorry, I forgot to add a tested-by.  Will resend.

David

^ permalink raw reply

* [PATCH net] rxrpc: Fix lack of conn cleanup when local endpoint is cleaned up
From: David Howells @ 2019-08-22 12:26 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, marc.dionne, linux-afs, linux-kernel

When a local endpoint is ceases to be in use, such as when the kafs module
is unloaded, the kernel will emit an assertion failure if there are any
outstanding client connections:

	rxrpc: Assertion failed
	------------[ cut here ]------------
	kernel BUG at net/rxrpc/local_object.c:433!

and even beyond that, will evince other oopses if there are service
connections still present.

Fix this by:

 (1) Removing the triggering of connection reaping when an rxrpc socket is
     released.  These don't actually clean up the connections anyway - and
     further, the local endpoint may still be in use through another
     socket.

 (2) Mark the local endpoint as dead when we start the process of tearing
     it down.

 (3) When destroying a local endpoint, strip all of its client connections
     from the idle list and discard the ref on each that the list was
     holding.

 (4) When destroying a local endpoint, call the service connection reaper
     directly (rather than through a workqueue) to immediately kill off all
     outstanding service connections.

 (5) Make the service connection reaper reap connections for which the
     local endpoint is marked dead.

Only after destroying the connections can we close the socket lest we get
an oops in a workqueue that's looking at a connection or a peer.

Fixes: 3d18cbb7fd0c ("rxrpc: Fix conn expiry timers")
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Marc Dionne <marc.dionne@auristor.com>
---

 net/rxrpc/af_rxrpc.c     |    3 ---
 net/rxrpc/ar-internal.h  |    1 +
 net/rxrpc/conn_client.c  |   49 ++++++++++++++++++++++++++++++++++++++++++++++
 net/rxrpc/conn_object.c  |    2 +-
 net/rxrpc/local_object.c |    5 ++++-
 5 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 0dbbfd1b6487..d72ddb67bb74 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -862,7 +862,6 @@ static void rxrpc_sock_destructor(struct sock *sk)
 static int rxrpc_release_sock(struct sock *sk)
 {
 	struct rxrpc_sock *rx = rxrpc_sk(sk);
-	struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk));
 
 	_enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt));
 
@@ -898,8 +897,6 @@ static int rxrpc_release_sock(struct sock *sk)
 	rxrpc_release_calls_on_socket(rx);
 	flush_workqueue(rxrpc_workqueue);
 	rxrpc_purge_queue(&sk->sk_receive_queue);
-	rxrpc_queue_work(&rxnet->service_conn_reaper);
-	rxrpc_queue_work(&rxnet->client_conn_reaper);
 
 	rxrpc_unuse_local(rx->local);
 	rx->local = NULL;
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index a42d6b833675..ef5aa28e679c 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -911,6 +911,7 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *);
 void rxrpc_put_client_conn(struct rxrpc_connection *);
 void rxrpc_discard_expired_client_conns(struct work_struct *);
 void rxrpc_destroy_all_client_connections(struct rxrpc_net *);
+void rxrpc_clean_up_local_conns(struct rxrpc_local *);
 
 /*
  * conn_event.c
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index aea82f909c60..2244fb7f53ec 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -1162,3 +1162,52 @@ void rxrpc_destroy_all_client_connections(struct rxrpc_net *rxnet)
 
 	_leave("");
 }
+
+/*
+ * Clean up the client connections on a local endpoint.
+ */
+void rxrpc_clean_up_local_conns(struct rxrpc_local *local)
+{
+	struct rxrpc_connection *conn, *tmp;
+	struct rxrpc_net *rxnet = local->rxnet;
+	unsigned int nr_active;
+	LIST_HEAD(graveyard);
+
+	_enter("");
+
+	spin_lock(&rxnet->client_conn_cache_lock);
+	nr_active = rxnet->nr_active_client_conns;
+
+	list_for_each_entry_safe(conn, tmp, &rxnet->idle_client_conns,
+				 cache_link) {
+		if (conn->params.local == local) {
+			ASSERTCMP(conn->cache_state, ==, RXRPC_CONN_CLIENT_IDLE);
+
+			trace_rxrpc_client(conn, -1, rxrpc_client_discard);
+			if (!test_and_clear_bit(RXRPC_CONN_EXPOSED, &conn->flags))
+				BUG();
+			conn->cache_state = RXRPC_CONN_CLIENT_INACTIVE;
+			list_move(&conn->cache_link, &graveyard);
+			nr_active--;
+		}
+	}
+
+	rxnet->nr_active_client_conns = nr_active;
+	spin_unlock(&rxnet->client_conn_cache_lock);
+	ASSERTCMP(nr_active, >=, 0);
+
+	spin_lock(&rxnet->client_conn_cache_lock);
+	while (!list_empty(&graveyard)) {
+		conn = list_entry(graveyard.next,
+				  struct rxrpc_connection, cache_link);
+		list_del_init(&conn->cache_link);
+		spin_unlock(&rxnet->client_conn_cache_lock);
+
+		rxrpc_put_connection(conn);
+
+		spin_lock(&rxnet->client_conn_cache_lock);
+	}
+	spin_unlock(&rxnet->client_conn_cache_lock);
+
+	_leave(" [culled]");
+}
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
index 434ef392212b..ed05b6922132 100644
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -398,7 +398,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
 		if (conn->state == RXRPC_CONN_SERVICE_PREALLOC)
 			continue;
 
-		if (rxnet->live) {
+		if (rxnet->live && !conn->params.local->dead) {
 			idle_timestamp = READ_ONCE(conn->idle_timestamp);
 			expire_at = idle_timestamp + rxrpc_connection_expiry * HZ;
 			if (conn->params.local->service_closed)
diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c
index 72a6e12a9304..36587260cabd 100644
--- a/net/rxrpc/local_object.c
+++ b/net/rxrpc/local_object.c
@@ -426,11 +426,14 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local)
 
 	_enter("%d", local->debug_id);
 
+	local->dead = true;
+
 	mutex_lock(&rxnet->local_mutex);
 	list_del_init(&local->link);
 	mutex_unlock(&rxnet->local_mutex);
 
-	ASSERT(RB_EMPTY_ROOT(&local->client_conns));
+	rxrpc_clean_up_local_conns(local);
+	rxrpc_service_connection_reaper(&rxnet->service_conn_reaper);
 	ASSERT(!local->service);
 
 	if (socket) {


^ permalink raw reply related

* [PATCH net v2] ixgbe: fix double clean of tx descriptors with xdp
From: Ilya Maximets @ 2019-08-22 12:30 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, bpf, David S. Miller, Björn Töpel,
	Magnus Karlsson, Jakub Kicinski, Alexei Starovoitov,
	Daniel Borkmann, Jeff Kirsher, intel-wired-lan, Eelco Chaudron,
	William Tu, Alexander Duyck, Ilya Maximets
In-Reply-To: <CGME20190822123045eucas1p125b6e106f0310bdb50e759ef41993a91@eucas1p1.samsung.com>

Tx code doesn't clear the descriptors' status after cleaning.
So, if the budget is larger than number of used elems in a ring, some
descriptors will be accounted twice and xsk_umem_complete_tx will move
prod_tail far beyond the prod_head breaking the comletion queue ring.

Fix that by limiting the number of descriptors to clean by the number
of used descriptors in the tx ring.

'ixgbe_clean_xdp_tx_irq()' function refactored to look more like
'ixgbe_xsk_clean_tx_ring()' since we don't need most of the
complications implemented in the regular 'ixgbe_clean_tx_irq()'
and we're allowed to directly use 'next_to_clean' and 'next_to_use'
indexes.

Fixes: 8221c5eba8c1 ("ixgbe: add AF_XDP zero-copy Tx support")
Signed-off-by: Ilya Maximets <i.maximets@samsung.com>
---

Version 2:
  * 'ixgbe_clean_xdp_tx_irq()' refactored to look more like
    'ixgbe_xsk_clean_tx_ring()'.

 drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c | 34 ++++++++------------
 1 file changed, 13 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
index 6b609553329f..d1297660e14a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
@@ -633,22 +633,23 @@ static void ixgbe_clean_xdp_tx_buffer(struct ixgbe_ring *tx_ring,
 bool ixgbe_clean_xdp_tx_irq(struct ixgbe_q_vector *q_vector,
 			    struct ixgbe_ring *tx_ring, int napi_budget)
 {
+	u16 ntc = tx_ring->next_to_clean, ntu = tx_ring->next_to_use;
 	unsigned int total_packets = 0, total_bytes = 0;
-	u32 i = tx_ring->next_to_clean, xsk_frames = 0;
 	unsigned int budget = q_vector->tx.work_limit;
 	struct xdp_umem *umem = tx_ring->xsk_umem;
-	union ixgbe_adv_tx_desc *tx_desc;
-	struct ixgbe_tx_buffer *tx_bi;
+	u32 xsk_frames = 0;
 	bool xmit_done;
 
-	tx_bi = &tx_ring->tx_buffer_info[i];
-	tx_desc = IXGBE_TX_DESC(tx_ring, i);
-	i -= tx_ring->count;
+	while (likely(ntc != ntu && budget)) {
+		union ixgbe_adv_tx_desc *tx_desc;
+		struct ixgbe_tx_buffer *tx_bi;
+
+		tx_desc = IXGBE_TX_DESC(tx_ring, ntc);
 
-	do {
 		if (!(tx_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)))
 			break;
 
+		tx_bi = &tx_ring->tx_buffer_info[ntc];
 		total_bytes += tx_bi->bytecount;
 		total_packets += tx_bi->gso_segs;
 
@@ -659,24 +660,15 @@ bool ixgbe_clean_xdp_tx_irq(struct ixgbe_q_vector *q_vector,
 
 		tx_bi->xdpf = NULL;
 
-		tx_bi++;
-		tx_desc++;
-		i++;
-		if (unlikely(!i)) {
-			i -= tx_ring->count;
-			tx_bi = tx_ring->tx_buffer_info;
-			tx_desc = IXGBE_TX_DESC(tx_ring, 0);
-		}
-
-		/* issue prefetch for next Tx descriptor */
-		prefetch(tx_desc);
+		ntc++;
+		if (unlikely(ntc == tx_ring->count))
+			ntc = 0;
 
 		/* update budget accounting */
 		budget--;
-	} while (likely(budget));
+	}
 
-	i += tx_ring->count;
-	tx_ring->next_to_clean = i;
+	tx_ring->next_to_clean = ntc;
 
 	u64_stats_update_begin(&tx_ring->syncp);
 	tx_ring->stats.bytes += total_bytes;
-- 
2.17.1


^ permalink raw reply related

* 答复: [PATCH][net-next] net: drop_monitor: change the stats variable to u64 in net_dm_stats_put
From: Li,Rongqing @ 2019-08-22 12:31 UTC (permalink / raw)
  To: Ido Schimmel; +Cc: netdev@vger.kernel.org, idosch@mellanox.com
In-Reply-To: <20190822115946.GA25090@splinter>



> -----邮件原件-----
> 发件人: Ido Schimmel [mailto:idosch@idosch.org]
> 发送时间: 2019年8月22日 20:00
> 收件人: Li,Rongqing <lirongqing@baidu.com>
> 抄送: netdev@vger.kernel.org; idosch@mellanox.com
> 主题: Re: [PATCH][net-next] net: drop_monitor: change the stats variable to
> u64 in net_dm_stats_put
> 
> On Thu, Aug 22, 2019 at 02:22:33PM +0800, Li RongQing wrote:
> > only the element drop of struct net_dm_stats is used, so simplify it
> > to u64
> 
> Thanks for the patch, but I don't really see the value here. The struct allows for
> easy extensions in the future. What do you gain from this change? We merely
> read stats and report them to user space, so I guess it's not about
> performance either.
> 

I think u64 can reduce to call memset and dereference stats.drop

If it is for future, keep it

-RongQing

^ permalink raw reply

* Re: [RFC bpf-next 4/5] iproute2: Allow compiling against libbpf
From: Daniel Borkmann @ 2019-08-22 12:33 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, Stephen Hemminger,
	Alexei Starovoitov
  Cc: Martin KaFai Lau, Song Liu, Yonghong Song, David Miller,
	Jesper Dangaard Brouer, netdev, bpf, andrii.nakryiko
In-Reply-To: <877e75pftb.fsf@toke.dk>

On 8/22/19 2:04 PM, Toke Høiland-Jørgensen wrote:
> Daniel Borkmann <daniel@iogearbox.net> writes:
>> On 8/22/19 12:43 PM, Toke Høiland-Jørgensen wrote:
>>> Daniel Borkmann <daniel@iogearbox.net> writes:
>>>> On 8/20/19 1:47 PM, Toke Høiland-Jørgensen wrote:
>>>>> This adds a configure check for libbpf and renames functions to allow
>>>>> lib/bpf.c to be compiled with it present. This makes it possible to
>>>>> port functionality piecemeal to use libbpf.
>>>>>
>>>>> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
>>>>> ---
>>>>>     configure          | 16 ++++++++++++++++
>>>>>     include/bpf_util.h |  6 +++---
>>>>>     ip/ipvrf.c         |  4 ++--
>>>>>     lib/bpf.c          | 33 +++++++++++++++++++--------------
>>>>>     4 files changed, 40 insertions(+), 19 deletions(-)
>>>>>
>>>>> diff --git a/configure b/configure
>>>>> index 45fcffb6..5a89ee9f 100755
>>>>> --- a/configure
>>>>> +++ b/configure
>>>>> @@ -238,6 +238,19 @@ check_elf()
>>>>>         fi
>>>>>     }
>>>>>     
>>>>> +check_libbpf()
>>>>> +{
>>>>> +    if ${PKG_CONFIG} libbpf --exists; then
>>>>> +	echo "HAVE_LIBBPF:=y" >>$CONFIG
>>>>> +	echo "yes"
>>>>> +
>>>>> +	echo 'CFLAGS += -DHAVE_LIBBPF' `${PKG_CONFIG} libbpf --cflags` >> $CONFIG
>>>>> +	echo 'LDLIBS += ' `${PKG_CONFIG} libbpf --libs` >>$CONFIG
>>>>> +    else
>>>>> +	echo "no"
>>>>> +    fi
>>>>> +}
>>>>> +
>>>>>     check_selinux()
>>>>
>>>> More of an implementation detail at this point in time, but want to
>>>> make sure this doesn't get missed along the way: as discussed at
>>>> bpfconf [0] best for iproute2 to handle libbpf support would be the
>>>> same way of integration as pahole does, that is, to integrate it via
>>>> submodule [1] to allow kernel and libbpf features to be in sync with
>>>> iproute2 releases and therefore easily consume extensions we're adding
>>>> to libbpf to aide iproute2 integration.
>>>
>>> I can sorta see the point wrt keeping in sync with kernel features. But
>>> how will this work with distros that package libbpf as a regular
>>> library? Have you guys given up on regular library symbol versioning for
>>> libbpf?
>>
>> Not at all, and I hope you know that. ;-)
> 
> Good! Didn't really expect you had, just checking ;)
> 
>> The reason I added lib/bpf.c integration into iproute2 directly back
>> then was exactly such that users can start consuming BPF for tc and
>> XDP via iproute2 /everywhere/ with only a simple libelf dependency
>> which is also available on all distros since pretty much forever. If
>> it was an external library, we could have waited till hell freezes
>> over and initial distro adoption would have pretty much taken forever:
>> to pick one random example here wrt the pace of some downstream
>> distros [0]. The main rationale is pretty much the same as with added
>> kernel features that land complementary iproute2 patches for that
>> kernel release and as libbpf is developed alongside it is reasonable
>> to guarantee user expectations that iproute2 released for kernel
>> version x can make use of BPF features added to kernel x with same
>> loader support from x.
> 
> Well, for iproute2 I would expect this to be solved by version
> dependencies. I.e. iproute2 version X would depend on libbpf version Y+
> (like, I dunno, the version of libbpf included in the same kernel source
> tree as the kernel version iproute2 is targeting? :)).

This sounds nice in theory, but from what I've seen major (!) distros
already seem to have a hard time releasing kernel x along with iproute2
package x, concrete example was that distro kernel was on 4.13 and its
official iproute2 package on 4.9, adding yet another variable that needs
to be in sync with kernel is simply impractical especially for a _core_
package like iproute2 that should have as little dependencies as possible.
I also don't want to make a bet on whether libbpf will be available on
every distro that also ships iproute2. Hence approach that pahole (and
also bcc by the way) takes is most reasonable to have the best user
experience.

Thanks,
Daniel

^ permalink raw reply

* [PATCH] Staging: isdn/gigaset : Fix bare unsigned warnings and trailing lines errors
From: Martin Tomes @ 2019-08-21 15:27 UTC (permalink / raw)
  To: isdn; +Cc: gregkh, linux-kernel, devel, netdev, Martin Tomes

There are many bare use of unsigned warnings and trailing statements should be on next line errors from checkpatch.pl script.
Change the code by adding 'unsigned int'. Move 'break' statement of 'switch' command to next line.

Signed-off-by: Martin Tomes <tomesm@gmail.com>
---
 drivers/staging/isdn/gigaset/usb-gigaset.c | 52 ++++++++++++++++++------------
 1 file changed, 31 insertions(+), 21 deletions(-)

diff --git a/drivers/staging/isdn/gigaset/usb-gigaset.c b/drivers/staging/isdn/gigaset/usb-gigaset.c
index 1b9b436..d565242 100644
--- a/drivers/staging/isdn/gigaset/usb-gigaset.c
+++ b/drivers/staging/isdn/gigaset/usb-gigaset.c
@@ -143,16 +143,16 @@ struct usb_cardstate {
 	char			bchars[6];		/* for request 0x19 */
 };
 
-static inline unsigned tiocm_to_gigaset(unsigned state)
+static inline unsigned int tiocm_to_gigaset(unsigned int state)
 {
 	return ((state & TIOCM_DTR) ? 1 : 0) | ((state & TIOCM_RTS) ? 2 : 0);
 }
 
-static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
-				  unsigned new_state)
+static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned int old_state,
+				  unsigned int new_state)
 {
 	struct usb_device *udev = cs->hw.usb->udev;
-	unsigned mask, val;
+	unsigned int mask, val;
 	int r;
 
 	mask = tiocm_to_gigaset(old_state ^ new_state);
@@ -178,7 +178,7 @@ static int set_value(struct cardstate *cs, u8 req, u16 val)
 	int r, r2;
 
 	gig_dbg(DEBUG_USBREQ, "request %02x (%04x)",
-		(unsigned)req, (unsigned)val);
+		(unsigned int)req, (unsigned int)val);
 	r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x12, 0x41,
 			    0xf /*?*/, 0, NULL, 0, 2000 /*?*/);
 	/* no idea what this does */
@@ -191,7 +191,7 @@ static int set_value(struct cardstate *cs, u8 req, u16 val)
 			    val, 0, NULL, 0, 2000 /*?*/);
 	if (r < 0)
 		dev_err(&udev->dev, "error %d on request 0x%02x\n",
-			-r, (unsigned)req);
+			-r, (unsigned int)req);
 
 	r2 = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41,
 			     0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/);
@@ -205,7 +205,7 @@ static int set_value(struct cardstate *cs, u8 req, u16 val)
  * set the baud rate on the internal serial adapter
  * using the undocumented parameter setting command
  */
-static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
+static int gigaset_baud_rate(struct cardstate *cs, unsigned int cflag)
 {
 	u16 val;
 	u32 rate;
@@ -213,16 +213,26 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
 	cflag &= CBAUD;
 
 	switch (cflag) {
-	case    B300: rate =     300; break;
-	case    B600: rate =     600; break;
-	case   B1200: rate =    1200; break;
-	case   B2400: rate =    2400; break;
-	case   B4800: rate =    4800; break;
-	case   B9600: rate =    9600; break;
-	case  B19200: rate =   19200; break;
-	case  B38400: rate =   38400; break;
-	case  B57600: rate =   57600; break;
-	case B115200: rate =  115200; break;
+	case    B300: rate =     300;
+		      break;
+	case    B600: rate =     600;
+		      break;
+	case   B1200: rate =    1200;
+		      break;
+	case   B2400: rate =    2400;
+		      break;
+	case   B4800: rate =    4800;
+		      break;
+	case   B9600: rate =    9600;
+		      break;
+	case  B19200: rate =   19200;
+		      break;
+	case  B38400: rate =   38400;
+		      break;
+	case  B57600: rate =   57600;
+		      break;
+	case B115200: rate =  115200;
+		      break;
 	default:
 		rate =  9600;
 		dev_err(cs->dev, "unsupported baudrate request 0x%x,"
@@ -345,7 +355,7 @@ static void gigaset_read_int_callback(struct urb *urb)
 	struct inbuf_t *inbuf = cs->inbuf;
 	int status = urb->status;
 	int r;
-	unsigned numbytes;
+	unsigned int numbytes;
 	unsigned char *src;
 	unsigned long flags;
 
@@ -357,7 +367,7 @@ static void gigaset_read_int_callback(struct urb *urb)
 			if (unlikely(*src))
 				dev_warn(cs->dev,
 					 "%s: There was no leading 0, but 0x%02x!\n",
-					 __func__, (unsigned) *src);
+					 __func__, (unsigned int) *src);
 			++src; /* skip leading 0x00 */
 			--numbytes;
 			if (gigaset_fill_inbuf(inbuf, src, numbytes)) {
@@ -517,7 +527,7 @@ static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
 
 static int gigaset_write_room(struct cardstate *cs)
 {
-	unsigned bytes;
+	unsigned int bytes;
 
 	bytes = cs->cmdbytes;
 	return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0;
@@ -611,7 +621,7 @@ static int write_modem(struct cardstate *cs)
 	}
 
 	/* Copy data to bulk out buffer and transmit data */
-	count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size);
+	count = min(bcs->tx_skb->len, (unsigned int) ucs->bulk_out_size);
 	skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count);
 	skb_pull(bcs->tx_skb, count);
 	ucs->busy = 1;
-- 
1.8.3.1


^ permalink raw reply related

* Re: [PATCH] Staging: isdn/gigaset : Fix bare unsigned warnings and trailing lines errors
From: Dan Carpenter @ 2019-08-22 12:42 UTC (permalink / raw)
  To: Martin Tomes; +Cc: isdn, devel, gregkh, linux-kernel, netdev
In-Reply-To: <1566401259-16921-1-git-send-email-tomesm@gmail.com>

Hi Martin,

These drivers are ancient and going to be deleted soon.  We're not
accepting cleanups for them at this point.

On Wed, Aug 21, 2019 at 03:27:39PM +0000, Martin Tomes wrote:
> There are many bare use of unsigned warnings and trailing statements should be on next line errors from checkpatch.pl script.
> Change the code by adding 'unsigned int'. Move 'break' statement of 'switch' command to next line.

For future reference, this should be split up so each patch fixes
one kind of style issue.  And the commit message lines of text are too
long.  The limit is 75 characters for commit messages (like an email).

regards,
dan carpenter


^ permalink raw reply

* [PATCH net-next 04/10] net: sched: notify classifier on successful offload add/delete
From: Vlad Buslov @ 2019-08-22 12:43 UTC (permalink / raw)
  To: netdev
  Cc: jhs, xiyou.wangcong, jiri, davem, jakub.kicinski, pablo,
	Vlad Buslov, Jiri Pirko
In-Reply-To: <20190822124353.16902-1-vladbu@mellanox.com>

To remove dependency on rtnl lock, extend classifier ops with new
ops->hw_add() and ops->hw_del() callbacks. Call them from cls API while
holding cb_lock every time filter if successfully added to or deleted from
hardware.

Implement the new API in flower classifier. Use it to manage hw_filters
list under cb_lock protection, instead of relying on rtnl lock to
synchronize with concurrent fl_reoffload() call.

Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/sch_generic.h |  4 ++++
 net/sched/cls_api.c       | 25 +++++++++++++++++++------
 net/sched/cls_flower.c    | 33 ++++++++++++++++++++++++++-------
 3 files changed, 49 insertions(+), 13 deletions(-)

diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 373f9476c1de..4ad43335cae5 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -312,6 +312,10 @@ struct tcf_proto_ops {
 	int			(*reoffload)(struct tcf_proto *tp, bool add,
 					     flow_setup_cb_t *cb, void *cb_priv,
 					     struct netlink_ext_ack *extack);
+	void			(*hw_add)(struct tcf_proto *tp,
+					  void *type_data);
+	void			(*hw_del)(struct tcf_proto *tp,
+					  void *type_data);
 	void			(*bind_class)(void *, u32, unsigned long);
 	void *			(*tmplt_create)(struct net *net,
 						struct tcf_chain *chain,
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 4215c849f4a3..d8ef7a9e6906 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -3099,9 +3099,13 @@ int tc_setup_cb_add(struct tcf_block *block, struct tcf_proto *tp,
 	}
 
 	ok_count = __tc_setup_cb_call(block, type, type_data, err_stop);
-	if (ok_count > 0)
-		tc_cls_offload_cnt_update(block, tp, in_hw_count, flags,
-					  ok_count, true);
+	if (ok_count >= 0) {
+		if (tp->ops->hw_add)
+			tp->ops->hw_add(tp, type_data);
+		if (ok_count > 0)
+			tc_cls_offload_cnt_update(block, tp, in_hw_count, flags,
+						  ok_count, true);
+	}
 errout:
 	up_read(&block->cb_lock);
 	return ok_count;
@@ -3130,11 +3134,17 @@ int tc_setup_cb_replace(struct tcf_block *block, struct tcf_proto *tp,
 	}
 
 	tc_cls_offload_cnt_reset(block, tp, old_in_hw_count, old_flags);
+	if (tp->ops->hw_del)
+		tp->ops->hw_del(tp, type_data);
 
 	ok_count = __tc_setup_cb_call(block, type, type_data, err_stop);
-	if (ok_count > 0)
-		tc_cls_offload_cnt_update(block, tp, new_in_hw_count, new_flags,
-					  ok_count, true);
+	if (ok_count >= 0) {
+		if (tp->ops->hw_add)
+			tp->ops->hw_add(tp, type_data);
+		if (ok_count > 0)
+			tc_cls_offload_cnt_update(block, tp, new_in_hw_count,
+						  new_flags, ok_count, true);
+	}
 errout:
 	up_read(&block->cb_lock);
 	return ok_count;
@@ -3155,6 +3165,9 @@ int tc_setup_cb_destroy(struct tcf_block *block, struct tcf_proto *tp,
 	ok_count = __tc_setup_cb_call(block, type, type_data, err_stop);
 
 	tc_cls_offload_cnt_reset(block, tp, in_hw_count, flags);
+	if (tp->ops->hw_del)
+		tp->ops->hw_del(tp, type_data);
+
 	up_read(&block->cb_lock);
 	return ok_count;
 }
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 0001a933d48b..cd1686a5abe7 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -421,9 +421,6 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f,
 
 	tc_setup_cb_destroy(block, tp, TC_SETUP_CLSFLOWER, &cls_flower, false,
 			    &f->flags, &f->in_hw_count, true);
-	spin_lock(&tp->lock);
-	list_del_init(&f->hw_list);
-	spin_unlock(&tp->lock);
 
 	if (!rtnl_held)
 		rtnl_unlock();
@@ -433,7 +430,6 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
 				struct cls_fl_filter *f, bool rtnl_held,
 				struct netlink_ext_ack *extack)
 {
-	struct cls_fl_head *head = fl_head_dereference(tp);
 	struct tcf_block *block = tp->chain->block;
 	struct flow_cls_offload cls_flower = {};
 	bool skip_sw = tc_skip_sw(f->flags);
@@ -482,9 +478,6 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
 		goto errout;
 	}
 
-	spin_lock(&tp->lock);
-	list_add(&f->hw_list, &head->hw_filters);
-	spin_unlock(&tp->lock);
 errout:
 	if (!rtnl_held)
 		rtnl_unlock();
@@ -1861,6 +1854,30 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
 	return 0;
 }
 
+static void fl_hw_add(struct tcf_proto *tp, void *type_data)
+{
+	struct flow_cls_offload *cls_flower = type_data;
+	struct cls_fl_filter *f =
+		(struct cls_fl_filter *) cls_flower->cookie;
+	struct cls_fl_head *head = fl_head_dereference(tp);
+
+	spin_lock(&tp->lock);
+	list_add(&f->hw_list, &head->hw_filters);
+	spin_unlock(&tp->lock);
+}
+
+static void fl_hw_del(struct tcf_proto *tp, void *type_data)
+{
+	struct flow_cls_offload *cls_flower = type_data;
+	struct cls_fl_filter *f =
+		(struct cls_fl_filter *) cls_flower->cookie;
+
+	spin_lock(&tp->lock);
+	if (!list_empty(&f->hw_list))
+		list_del_init(&f->hw_list);
+	spin_unlock(&tp->lock);
+}
+
 static int fl_hw_create_tmplt(struct tcf_chain *chain,
 			      struct fl_flow_tmplt *tmplt)
 {
@@ -2521,6 +2538,8 @@ static struct tcf_proto_ops cls_fl_ops __read_mostly = {
 	.delete		= fl_delete,
 	.walk		= fl_walk,
 	.reoffload	= fl_reoffload,
+	.hw_add		= fl_hw_add,
+	.hw_del		= fl_hw_del,
 	.dump		= fl_dump,
 	.bind_class	= fl_bind_class,
 	.tmplt_create	= fl_tmplt_create,
-- 
2.21.0


^ permalink raw reply related

* [PATCH net-next 05/10] net: sched: add API for registering unlocked offload block callbacks
From: Vlad Buslov @ 2019-08-22 12:43 UTC (permalink / raw)
  To: netdev
  Cc: jhs, xiyou.wangcong, jiri, davem, jakub.kicinski, pablo,
	Vlad Buslov, Jiri Pirko
In-Reply-To: <20190822124353.16902-1-vladbu@mellanox.com>

Extend struct flow_block_offload with "unlocked_driver_cb" flag to allow
registering and unregistering block hardware offload callbacks that do not
require caller to hold rtnl lock. Extend tcf_block with additional
lockeddevcnt counter that is incremented for each non-unlocked driver
callback attached to device. This counter is necessary to conditionally
obtain rtnl lock before calling hardware callbacks in following patches.

Register mlx5 tc block offload callbacks as "unlocked".

Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 ++
 drivers/net/ethernet/mellanox/mlx5/core/en_rep.c  | 3 +++
 include/net/flow_offload.h                        | 1 +
 include/net/sch_generic.h                         | 1 +
 net/sched/cls_api.c                               | 6 ++++++
 5 files changed, 13 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 7fdea6479ff6..8abdef1f8470 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3469,10 +3469,12 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
 			  void *type_data)
 {
 	struct mlx5e_priv *priv = netdev_priv(dev);
+	struct flow_block_offload *f = type_data;
 
 	switch (type) {
 #ifdef CONFIG_MLX5_ESWITCH
 	case TC_SETUP_BLOCK:
+		f->unlocked_driver_cb = true;
 		return flow_block_cb_setup_simple(type_data,
 						  &mlx5e_block_cb_list,
 						  mlx5e_setup_tc_block_cb,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 3c0d36b2b91c..e7ac6233037d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -763,6 +763,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
 	if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
 		return -EOPNOTSUPP;
 
+	f->unlocked_driver_cb = true;
 	f->driver_block_list = &mlx5e_block_cb_list;
 
 	switch (f->command) {
@@ -1245,9 +1246,11 @@ static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
 			      void *type_data)
 {
 	struct mlx5e_priv *priv = netdev_priv(dev);
+	struct flow_block_offload *f = type_data;
 
 	switch (type) {
 	case TC_SETUP_BLOCK:
+		f->unlocked_driver_cb = true;
 		return flow_block_cb_setup_simple(type_data,
 						  &mlx5e_rep_block_cb_list,
 						  mlx5e_rep_setup_tc_cb,
diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
index 757fa84de654..fc881875f856 100644
--- a/include/net/flow_offload.h
+++ b/include/net/flow_offload.h
@@ -284,6 +284,7 @@ struct flow_block_offload {
 	enum flow_block_command command;
 	enum flow_block_binder_type binder_type;
 	bool block_shared;
+	bool unlocked_driver_cb;
 	struct net *net;
 	struct flow_block *block;
 	struct list_head cb_list;
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 4ad43335cae5..d0c282e3630b 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -408,6 +408,7 @@ struct tcf_block {
 	bool keep_dst;
 	atomic_t offloadcnt; /* Number of oddloaded filters */
 	unsigned int nooffloaddevcnt; /* Number of devs unable to do offload */
+	unsigned int lockeddevcnt; /* Number of devs that require rtnl lock. */
 	struct {
 		struct tcf_chain *chain;
 		struct list_head filter_chain_list;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index d8ef7a9e6906..02a547aa77c0 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1418,6 +1418,8 @@ static int tcf_block_bind(struct tcf_block *block,
 						  bo->extack);
 		if (err)
 			goto err_unroll;
+		if (!bo->unlocked_driver_cb)
+			block->lockeddevcnt++;
 
 		i++;
 	}
@@ -1433,6 +1435,8 @@ static int tcf_block_bind(struct tcf_block *block,
 						    block_cb->cb_priv, false,
 						    tcf_block_offload_in_use(block),
 						    NULL);
+			if (!bo->unlocked_driver_cb)
+				block->lockeddevcnt--;
 		}
 		flow_block_cb_free(block_cb);
 	}
@@ -1454,6 +1458,8 @@ static void tcf_block_unbind(struct tcf_block *block,
 					    NULL);
 		list_del(&block_cb->list);
 		flow_block_cb_free(block_cb);
+		if (!bo->unlocked_driver_cb)
+			block->lockeddevcnt--;
 	}
 }
 
-- 
2.21.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox