* Re: [RFC PATCH 05/11] net: Infrastructure for per queue aRFS
@ 2020-06-24 21:50 kernel test robot
2020-06-28 8:56 ` Rong Chen
0 siblings, 1 reply; 4+ messages in thread
From: kernel test robot @ 2020-06-24 21:50 UTC (permalink / raw)
To: kbuild
[-- Attachment #1: Type: text/plain, Size: 7829 bytes --]
CC: kbuild-all(a)lists.01.org
In-Reply-To: <20200624171749.11927-6-tom@herbertland.com>
References: <20200624171749.11927-6-tom@herbertland.com>
TO: Tom Herbert <tom@herbertland.com>
Hi Tom,
[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on net/master]
[also build test WARNING on ipvs/master net-next/master linus/master v5.8-rc2 next-20200624]
[cannot apply to cgroup/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Tom-Herbert/ptq-Per-Thread-Queues/20200625-012135
base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git 0275875530f692c725c6f993aced2eca2d6ac50c
:::::: branch date: 4 hours ago
:::::: commit date: 4 hours ago
config: s390-randconfig-s031-20200624 (attached as .config)
compiler: s390-linux-gcc (GCC) 9.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.2-dirty
# save the attached .config to linux build tree
make W=1 C=1 ARCH=s390 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
sparse warnings: (new ones prefixed by >>)
net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@
net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum
net/core/dev.c:3264:23: sparse: got unsigned int
net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum
net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@
net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum
net/core/dev.c:3264:23: sparse: got unsigned int
net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 1 (different base types) @@ expected unsigned int [usertype] val @@ got restricted __wsum @@
net/core/dev.c:3264:23: sparse: expected unsigned int [usertype] val
net/core/dev.c:3264:23: sparse: got restricted __wsum
net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@
net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum
net/core/dev.c:3264:23: sparse: got unsigned int
net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum
net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@
net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum
net/core/dev.c:3264:23: sparse: got unsigned int
net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum
net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@
net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum
net/core/dev.c:3264:23: sparse: got unsigned int
net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum
net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@
net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum
net/core/dev.c:3264:23: sparse: got unsigned int
net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum
>> net/core/dev.c:4451:27: sparse: sparse: cast to non-scalar
>> net/core/dev.c:4451:27: sparse: sparse: cast from non-scalar
net/core/dev.c:5614:1: sparse: sparse: symbol '__pcpu_scope_flush_works' was not declared. Should it be static?
net/core/dev.c:3747:26: sparse: sparse: context imbalance in '__dev_queue_xmit' - different lock contexts for basic block
net/core/dev.c:4922:44: sparse: sparse: context imbalance in 'net_tx_action' - unexpected unlock
# https://github.com/0day-ci/linux/commit/8cf630e2a48d7b6e18be2f46f90cebf8ec5d506c
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout 8cf630e2a48d7b6e18be2f46f90cebf8ec5d506c
vim +4451 net/core/dev.c
c445477d74ab37 Ben Hutchings 2011-01-19 4426
c445477d74ab37 Ben Hutchings 2011-01-19 4427 /**
c445477d74ab37 Ben Hutchings 2011-01-19 4428 * rps_may_expire_flow - check whether an RFS hardware filter may be removed
c445477d74ab37 Ben Hutchings 2011-01-19 4429 * @dev: Device on which the filter was set
c445477d74ab37 Ben Hutchings 2011-01-19 4430 * @rxq_index: RX queue index
c445477d74ab37 Ben Hutchings 2011-01-19 4431 * @flow_id: Flow ID passed to ndo_rx_flow_steer()
c445477d74ab37 Ben Hutchings 2011-01-19 4432 * @filter_id: Filter ID returned by ndo_rx_flow_steer()
c445477d74ab37 Ben Hutchings 2011-01-19 4433 *
c445477d74ab37 Ben Hutchings 2011-01-19 4434 * Drivers that implement ndo_rx_flow_steer() should periodically call
c445477d74ab37 Ben Hutchings 2011-01-19 4435 * this function for each installed filter and remove the filters for
c445477d74ab37 Ben Hutchings 2011-01-19 4436 * which it returns %true.
c445477d74ab37 Ben Hutchings 2011-01-19 4437 */
c445477d74ab37 Ben Hutchings 2011-01-19 4438 bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index,
c445477d74ab37 Ben Hutchings 2011-01-19 4439 u32 flow_id, u16 filter_id)
c445477d74ab37 Ben Hutchings 2011-01-19 4440 {
c445477d74ab37 Ben Hutchings 2011-01-19 4441 struct netdev_rx_queue *rxqueue = dev->_rx + rxq_index;
c445477d74ab37 Ben Hutchings 2011-01-19 4442 struct rps_dev_flow_table *flow_table;
8cf630e2a48d7b Tom Herbert 2020-06-24 4443 struct rps_cpu_qid cpu_qid;
c445477d74ab37 Ben Hutchings 2011-01-19 4444 struct rps_dev_flow *rflow;
c445477d74ab37 Ben Hutchings 2011-01-19 4445 bool expire = true;
c445477d74ab37 Ben Hutchings 2011-01-19 4446
c445477d74ab37 Ben Hutchings 2011-01-19 4447 rcu_read_lock();
c445477d74ab37 Ben Hutchings 2011-01-19 4448 flow_table = rcu_dereference(rxqueue->rps_flow_table);
c445477d74ab37 Ben Hutchings 2011-01-19 4449 if (flow_table && flow_id <= flow_table->mask) {
c445477d74ab37 Ben Hutchings 2011-01-19 4450 rflow = &flow_table->flows[flow_id];
8cf630e2a48d7b Tom Herbert 2020-06-24 @4451 cpu_qid = READ_ONCE(rflow->cpu_qid);
8cf630e2a48d7b Tom Herbert 2020-06-24 4452 if (rflow->filter == filter_id && !cpu_qid.use_qid &&
8cf630e2a48d7b Tom Herbert 2020-06-24 4453 cpu_qid.cpu < nr_cpu_ids &&
8cf630e2a48d7b Tom Herbert 2020-06-24 4454 ((int)(per_cpu(softnet_data, cpu_qid.cpu).input_queue_head -
c445477d74ab37 Ben Hutchings 2011-01-19 4455 rflow->last_qtail) <
c445477d74ab37 Ben Hutchings 2011-01-19 4456 (int)(10 * flow_table->mask)))
c445477d74ab37 Ben Hutchings 2011-01-19 4457 expire = false;
c445477d74ab37 Ben Hutchings 2011-01-19 4458 }
c445477d74ab37 Ben Hutchings 2011-01-19 4459 rcu_read_unlock();
c445477d74ab37 Ben Hutchings 2011-01-19 4460 return expire;
c445477d74ab37 Ben Hutchings 2011-01-19 4461 }
c445477d74ab37 Ben Hutchings 2011-01-19 4462 EXPORT_SYMBOL(rps_may_expire_flow);
c445477d74ab37 Ben Hutchings 2011-01-19 4463
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 19564 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [RFC PATCH 05/11] net: Infrastructure for per queue aRFS 2020-06-24 21:50 [RFC PATCH 05/11] net: Infrastructure for per queue aRFS kernel test robot @ 2020-06-28 8:56 ` Rong Chen 0 siblings, 0 replies; 4+ messages in thread From: Rong Chen @ 2020-06-28 8:56 UTC (permalink / raw) To: kbuild [-- Attachment #1: Type: text/plain, Size: 8293 bytes --] reported On 6/25/20 5:50 AM, kernel test robot wrote: > CC: kbuild-all(a)lists.01.org > In-Reply-To: <20200624171749.11927-6-tom@herbertland.com> > References: <20200624171749.11927-6-tom@herbertland.com> > TO: Tom Herbert <tom@herbertland.com> > > Hi Tom, > > [FYI, it's a private test report for your RFC patch.] > [auto build test WARNING on net/master] > [also build test WARNING on ipvs/master net-next/master linus/master v5.8-rc2 next-20200624] > [cannot apply to cgroup/for-next] > [If your patch is applied to the wrong git tree, kindly drop us a note. > And when submitting patch, we suggest to use as documented in > https://git-scm.com/docs/git-format-patch] > > url: https://github.com/0day-ci/linux/commits/Tom-Herbert/ptq-Per-Thread-Queues/20200625-012135 > base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git 0275875530f692c725c6f993aced2eca2d6ac50c > :::::: branch date: 4 hours ago > :::::: commit date: 4 hours ago > config: s390-randconfig-s031-20200624 (attached as .config) > compiler: s390-linux-gcc (GCC) 9.3.0 > reproduce: > # apt-get install sparse > # sparse version: v0.6.2-dirty > # save the attached .config to linux build tree > make W=1 C=1 ARCH=s390 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' > > If you fix the issue, kindly add following tag as appropriate > Reported-by: kernel test robot <lkp@intel.com> > > > sparse warnings: (new ones prefixed by >>) > > net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@ > net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum > net/core/dev.c:3264:23: sparse: got unsigned int > net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum > net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@ > net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum > net/core/dev.c:3264:23: sparse: got unsigned int > net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 1 (different base types) @@ expected unsigned int [usertype] val @@ got restricted __wsum @@ > net/core/dev.c:3264:23: sparse: expected unsigned int [usertype] val > net/core/dev.c:3264:23: sparse: got restricted __wsum > net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@ > net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum > net/core/dev.c:3264:23: sparse: got unsigned int > net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum > net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@ > net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum > net/core/dev.c:3264:23: sparse: got unsigned int > net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum > net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@ > net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum > net/core/dev.c:3264:23: sparse: got unsigned int > net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum > net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@ > net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum > net/core/dev.c:3264:23: sparse: got unsigned int > net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum >>> net/core/dev.c:4451:27: sparse: sparse: cast to non-scalar >>> net/core/dev.c:4451:27: sparse: sparse: cast from non-scalar > net/core/dev.c:5614:1: sparse: sparse: symbol '__pcpu_scope_flush_works' was not declared. Should it be static? > net/core/dev.c:3747:26: sparse: sparse: context imbalance in '__dev_queue_xmit' - different lock contexts for basic block > net/core/dev.c:4922:44: sparse: sparse: context imbalance in 'net_tx_action' - unexpected unlock > > # https://github.com/0day-ci/linux/commit/8cf630e2a48d7b6e18be2f46f90cebf8ec5d506c > git remote add linux-review https://github.com/0day-ci/linux > git remote update linux-review > git checkout 8cf630e2a48d7b6e18be2f46f90cebf8ec5d506c > vim +4451 net/core/dev.c > > c445477d74ab37 Ben Hutchings 2011-01-19 4426 > c445477d74ab37 Ben Hutchings 2011-01-19 4427 /** > c445477d74ab37 Ben Hutchings 2011-01-19 4428 * rps_may_expire_flow - check whether an RFS hardware filter may be removed > c445477d74ab37 Ben Hutchings 2011-01-19 4429 * @dev: Device on which the filter was set > c445477d74ab37 Ben Hutchings 2011-01-19 4430 * @rxq_index: RX queue index > c445477d74ab37 Ben Hutchings 2011-01-19 4431 * @flow_id: Flow ID passed to ndo_rx_flow_steer() > c445477d74ab37 Ben Hutchings 2011-01-19 4432 * @filter_id: Filter ID returned by ndo_rx_flow_steer() > c445477d74ab37 Ben Hutchings 2011-01-19 4433 * > c445477d74ab37 Ben Hutchings 2011-01-19 4434 * Drivers that implement ndo_rx_flow_steer() should periodically call > c445477d74ab37 Ben Hutchings 2011-01-19 4435 * this function for each installed filter and remove the filters for > c445477d74ab37 Ben Hutchings 2011-01-19 4436 * which it returns %true. > c445477d74ab37 Ben Hutchings 2011-01-19 4437 */ > c445477d74ab37 Ben Hutchings 2011-01-19 4438 bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index, > c445477d74ab37 Ben Hutchings 2011-01-19 4439 u32 flow_id, u16 filter_id) > c445477d74ab37 Ben Hutchings 2011-01-19 4440 { > c445477d74ab37 Ben Hutchings 2011-01-19 4441 struct netdev_rx_queue *rxqueue = dev->_rx + rxq_index; > c445477d74ab37 Ben Hutchings 2011-01-19 4442 struct rps_dev_flow_table *flow_table; > 8cf630e2a48d7b Tom Herbert 2020-06-24 4443 struct rps_cpu_qid cpu_qid; > c445477d74ab37 Ben Hutchings 2011-01-19 4444 struct rps_dev_flow *rflow; > c445477d74ab37 Ben Hutchings 2011-01-19 4445 bool expire = true; > c445477d74ab37 Ben Hutchings 2011-01-19 4446 > c445477d74ab37 Ben Hutchings 2011-01-19 4447 rcu_read_lock(); > c445477d74ab37 Ben Hutchings 2011-01-19 4448 flow_table = rcu_dereference(rxqueue->rps_flow_table); > c445477d74ab37 Ben Hutchings 2011-01-19 4449 if (flow_table && flow_id <= flow_table->mask) { > c445477d74ab37 Ben Hutchings 2011-01-19 4450 rflow = &flow_table->flows[flow_id]; > 8cf630e2a48d7b Tom Herbert 2020-06-24 @4451 cpu_qid = READ_ONCE(rflow->cpu_qid); > 8cf630e2a48d7b Tom Herbert 2020-06-24 4452 if (rflow->filter == filter_id && !cpu_qid.use_qid && > 8cf630e2a48d7b Tom Herbert 2020-06-24 4453 cpu_qid.cpu < nr_cpu_ids && > 8cf630e2a48d7b Tom Herbert 2020-06-24 4454 ((int)(per_cpu(softnet_data, cpu_qid.cpu).input_queue_head - > c445477d74ab37 Ben Hutchings 2011-01-19 4455 rflow->last_qtail) < > c445477d74ab37 Ben Hutchings 2011-01-19 4456 (int)(10 * flow_table->mask))) > c445477d74ab37 Ben Hutchings 2011-01-19 4457 expire = false; > c445477d74ab37 Ben Hutchings 2011-01-19 4458 } > c445477d74ab37 Ben Hutchings 2011-01-19 4459 rcu_read_unlock(); > c445477d74ab37 Ben Hutchings 2011-01-19 4460 return expire; > c445477d74ab37 Ben Hutchings 2011-01-19 4461 } > c445477d74ab37 Ben Hutchings 2011-01-19 4462 EXPORT_SYMBOL(rps_may_expire_flow); > c445477d74ab37 Ben Hutchings 2011-01-19 4463 > > --- > 0-DAY CI Kernel Test Service, Intel Corporation > https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org > > _______________________________________________ > kbuild mailing list -- kbuild(a)lists.01.org > To unsubscribe send an email to kbuild-leave(a)lists.01.org ^ permalink raw reply [flat|nested] 4+ messages in thread
* [RFC PATCH 00/11] ptq: Per Thread Queues
@ 2020-06-24 17:17 Tom Herbert
2020-06-24 17:17 ` [RFC PATCH 05/11] net: Infrastructure for per queue aRFS Tom Herbert
0 siblings, 1 reply; 4+ messages in thread
From: Tom Herbert @ 2020-06-24 17:17 UTC (permalink / raw)
To: netdev; +Cc: Tom Herbert
Per Thread Queues allows application threads to be assigned dedicated
hardware network queues for both transmit and receive. This facility
provides a high degree of traffic isolation between applications and
can also help facilitate high performance due to fine grained packet
steering. An overview and design considerations of Per Thread Queues
has been add to Documentation/networking/scaling.rst.
This patch set provides a basic implementation of Per Thread Queues.
The patch set includes:
- Minor Infrastructure changes to cgroups (just export a
couple of functions)
- netqueue.h to hold generic definitions for network queues
- Minor infrastructure in aRFS and net-sysfs to accommodate
PTQ
- Introduce the concept of "global queues". These are used
in cgroup configuration of PTQ. Global queues can be
mapped to real device queues. A per device queue sysfs
parameter is added to configure the mapping of device
queue to a global queue
- Creation of a new cgroup controller, "net_queues", that
is used to configure Per Thread Queues
- Hook up the transmit path. This has two parts: 1) In
send socket operations record the transmit queue
associated with a task in the sock structure, 2) In
netdev_pick_tx, check if the sock structure of the skb
has a valid transmit global queue set. If so, convert the
queue identifier to a device queue identifier based on the per
device mapping table. This selection precedes XPS
- Hook up the receive path. This has two parts: 1) In
rps_record_sock_flow check if a receive global queue is
assigned to the running task, if so then set it in the
sock_flow_table entry for the flow. Note this in lieu of
setting the running CPU in the entry. 2) Change get_rps_cpu to
query the sock_flow_table to see if a queue index has been
stored (as opposed to a CPU number). If a queue index is
present, use it for steering including for it to be the
target of ndo_rx_flow_steer.
Related features and concepts:
- netprio and prio_tc_map: Similar to those, PTQ allows control,
via cgroups and per device maps, over mapping applications'
packets to transmit queues. However, PTQ is intended to
perform fine grained per application mapping to queues such
that each application thread, possibly thousands of them, can
have its own dedicate transmit queue.
- aRFS: On the transmit side PTQ extends aRFS to steer packets
for a flow based on assigned global queue as opposed to only
running CPU for the processing thread. In PTQ, the queue
"follows" the thread so that when threads are scheduled to
run on a different CPU, the packets for flows of the thread
continue to be received on the right queue. This addresses
a problem in aRFS where when a thread is rescheduled all
of its aRFS steered flows may be to moved to a different queue
(i.e. ndo_rx_flow_steer needs to be called for each flow).
- Busy polling: PTQ provides silo'ing of an application packets
into queues and busy polling of those queue can then be
applied for high performance. This is likely the fist
instantiation of PTQ to combine it with busy polling
(moving interrupts for those queues as threads are scheduled
is most likely prohibitive). Busy polling is only practical
with a few queues, like maybe at most one per CPU, and
won't scale to thousands of per thread queues in use.
(to address that sleeping-busy-poll with completion
queues is suggested below).
- Making Networking Queues a First Class Citizen in the Kernel
https://linuxplumbersconf.org/event/4/contributions/462/
attachments/241/422/LPC_2019_kernel_queue_manager.pdf:
The concept of "global queues" should be a good complement
to this proposal. Global queue provide an abstract
representation of device queues. the abstraction is resolved
when the global queue is mapped to a real hardware queue. This
layering allows exposing queues to the user and configuration
which might be associated with general attributes (like high
priority, QoS characteristics, etc.). The mapping to a
specific device queue gives the low level queue that satisfies
the implied service of the global queue. Any attributes and
associations are configured and in no way hardcoded, so that
the use of queues in the manner is fully extensible and can be
driven be arbitrary user defined policy. Since global queues
are device agnostic they not just can be managed as local
system resource, but also across across the distributed
tasks for a job in the datacenter like as a property of a
container in Kubernetes (similar to how we might manage
network priority as a global DC resource, but global queues
provide much more granularity and richness in what they can
convey).
There are a number of possible extensions to this work
- Queue selection could be done on a per process basis
or a per socket basis as well as a per thread basis. (per
packet basis probably makes little sense due to OOO)
- The mechanism for selecting a queue to assign to a thread
could be programmed. For instance, an eBPF hook could be
added that would allow very fine grained policies to do
queue selection.
- "Global queue groups" could be created where a global queue
identifier maps to some group of device queues and there is
a selection algorithm, possibly another eBPF hook, that
maps to a specific device queue for use.
- Another attribute in the cgroup could be added to enable
or disable aRFS on a per thread basis.
- Extend the net_queues cgroup to allow control over
busy-polling on a per cgroup basis. This could further
be enhanced by eBPF hooks to control busy-polling for
individual sockets of the cgroup per some arbitrary policy
(similar to eBPF hook for SO_RESUSEPORT).
- Elasticity in listener sockets. As described in the
Documentation we expect that a filter can be installed to
direct packets an application to the set of queues for the
applications. The problem is that the application may
create threads on demand so that we don't know a priori
how many queues the application needs. Optimally, we
want a mechanism to dynamically enable/disable a
queue in the filter set so that at any given time the
application is receive packets only on queues it is
actively using. This may entail a new ndo_function.
- The sleeping-busy-poll with completion queue model
described in the documentation could be integrated. This
would most entail creating a reverse mapping from queue
to threads, and then allowing the thread processing a
device completion queue to schedule the threads of interest.
Tom Herbert (11):
cgroup: Export cgroup_{procs,threads}_start and cgroup_procs_next
net: Create netqueue.h and define NO_QUEUE
arfs: Create set_arfs_queue
net-sysfs: Create rps_create_sock_flow_table
net: Infrastructure for per queue aRFS
net: Function to check against maximum number for RPS queues
net: Introduce global queues
ptq: Per Thread Queues
ptq: Hook up transmit side of Per Queue Threads
ptq: Hook up receive side of Per Queue Threads
doc: Documentation for Per Thread Queues
Documentation/networking/scaling.rst | 195 +++++++-
include/linux/cgroup.h | 3 +
include/linux/cgroup_subsys.h | 4 +
include/linux/netdevice.h | 204 +++++++-
include/linux/netqueue.h | 25 +
include/linux/sched.h | 4 +
include/net/ptq.h | 45 ++
include/net/sock.h | 75 ++-
kernel/cgroup/cgroup.c | 9 +-
kernel/fork.c | 4 +
net/Kconfig | 18 +
net/core/Makefile | 1 +
net/core/dev.c | 177 +++++--
net/core/filter.c | 4 +-
net/core/net-sysfs.c | 201 +++++++-
net/core/ptq.c | 688 +++++++++++++++++++++++++++
net/core/sysctl_net_core.c | 152 ++++--
net/ipv4/af_inet.c | 6 +
18 files changed, 1693 insertions(+), 122 deletions(-)
create mode 100644 include/linux/netqueue.h
create mode 100644 include/net/ptq.h
create mode 100644 net/core/ptq.c
--
2.25.1
^ permalink raw reply [flat|nested] 4+ messages in thread* [RFC PATCH 05/11] net: Infrastructure for per queue aRFS 2020-06-24 17:17 [RFC PATCH 00/11] ptq: Per Thread Queues Tom Herbert @ 2020-06-24 17:17 ` Tom Herbert 2020-06-28 8:55 ` kernel test robot 0 siblings, 1 reply; 4+ messages in thread From: Tom Herbert @ 2020-06-24 17:17 UTC (permalink / raw) To: netdev; +Cc: Tom Herbert Infrastructure changes to allow aRFS to be based on Per Thread Queues instead of just CPU. The basic change is to create a field in rps_dev_flow to hold either a CPU or a queue index (not just a CPU that is). Changes include: - Replace u16 cpu field in rps_dev_flow structure with rps_cpu_qid structure that contains either a CPU or a device queue index. Note the structure is still sixteen bits - Helper functions to clear and set the cpu in the rps_cpu_qid of rps_dev_flow - Create a sock_masks structure that contains the partition of the thirty-two bit entry in rps_sock_flow_table. The structure contains two masks, one to extract the upper bits of the hash and one to extract the CPU number or queue index - Replace rps_cpu_mask with sock_masks from rps_sock_flow_table - Add rps_max_num_queues which will be used when creating sock_masks for queue entries in rps_sock_flow_table --- include/linux/netdevice.h | 94 +++++++++++++++++++++++++++++++++----- net/core/dev.c | 47 ++++++++++++------- net/core/net-sysfs.c | 2 +- net/core/sysctl_net_core.c | 6 ++- 4 files changed, 119 insertions(+), 30 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index bf5f2a85da97..d528aa61fea3 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -674,18 +674,65 @@ struct rps_map { }; #define RPS_MAP_SIZE(_num) (sizeof(struct rps_map) + ((_num) * sizeof(u16))) +/* The rps_cpu_qid structure is sixteen bits and holds either a CPU number or + * a queue index. The use_qid field specifies which type of value is set (i.e. + * if use_qid is 1 then cpu_qid contains a fifteen bit queue identifier, and if + * use_qid is 0 then cpu_qid contains a fifteen bit CPU number). No entry is + * signified by RPS_NO_CPU_QID in val which is set to NO_QUEUE (0xffff). So the + * range of CPU numbers that can be stored is 0..32,767 (0x7fff) and the range + * of queue identifiers is 0..32,766. Note that CPU numbers are limited by + * CONFIG_NR_CPUS which currently has a maximum supported value of 8,192 (per + * arch/x86/Kconfig), so WARN_ON is used to check that a CPU number is less + * than 0x8000 when setting the cpu in rps_cpu_qid. The queue index is limited + * by configuration. + */ +struct rps_cpu_qid { + union { + u16 val; + struct { + u16 use_qid: 1; + union { + u16 cpu: 15; + u16 qid: 15; + }; + }; + }; +}; + +#define RPS_NO_CPU_QID NO_QUEUE /* No CPU or qid in rps_cpu_qid */ +#define RPS_MAX_CPU 0x7fff /* Maximum cpu in rps_cpu_qid */ +#define RPS_MAX_QID 0x7ffe /* Maximum qid in rps_cpu_qid */ + /* * The rps_dev_flow structure contains the mapping of a flow to a CPU, the * tail pointer for that CPU's input queue at the time of last enqueue, and * a hardware filter index. */ struct rps_dev_flow { - u16 cpu; + struct rps_cpu_qid cpu_qid; u16 filter; unsigned int last_qtail; }; #define RPS_NO_FILTER 0xffff +static inline void rps_dev_flow_clear(struct rps_dev_flow *dev_flow) +{ + dev_flow->cpu_qid.val = RPS_NO_CPU_QID; +} + +static inline void rps_dev_flow_set_cpu(struct rps_dev_flow *dev_flow, u16 cpu) +{ + struct rps_cpu_qid cpu_qid; + + if (WARN_ON(cpu > RPS_MAX_CPU)) + return; + + /* Set the rflow target to the CPU atomically */ + cpu_qid.use_qid = 0; + cpu_qid.cpu = cpu; + dev_flow->cpu_qid = cpu_qid; +} + /* * The rps_dev_flow_table structure contains a table of flow mappings. */ @@ -697,34 +744,57 @@ struct rps_dev_flow_table { #define RPS_DEV_FLOW_TABLE_SIZE(_num) (sizeof(struct rps_dev_flow_table) + \ ((_num) * sizeof(struct rps_dev_flow))) +struct rps_sock_masks { + u32 mask; + u32 hash_mask; +}; + /* - * The rps_sock_flow_table contains mappings of flows to the last CPU - * on which they were processed by the application (set in recvmsg). - * Each entry is a 32bit value. Upper part is the high-order bits - * of flow hash, lower part is CPU number. - * rps_cpu_mask is used to partition the space, depending on number of - * possible CPUs : rps_cpu_mask = roundup_pow_of_two(nr_cpu_ids) - 1 - * For example, if 64 CPUs are possible, rps_cpu_mask = 0x3f, - * meaning we use 32-6=26 bits for the hash. + * The rps_sock_flow_table contains mappings of flows to the last CPU on which + * they were processed by the application (set in recvmsg), or the mapping of + * the flow to a per thread queue for the application. Each entry is a 32bit + * value. The high order bit indicates whether a CPU number or a queue index is + * stored. The next high-order bits contain the flow hash, and the lower bits + * contain the CPU number or queue index. The sock_flow table contains two + * sets of masks, one for CPU entries (cpu_masks) and one for queue entries + * (queue_masks), that are to used partition the space between the hash bits + * and the CPU number or queue index. For the cpu masks, cpu_masks.mask is set + * to roundup_pow_of_two(nr_cpu_ids) - 1 and the corresponding hash mask, + * cpu_masks.hash_mask, is set to (~cpu_masks.mask & ~RPS_SOCK_FLOW_USE_QID). + * For example, if 64 CPUs are possible, cpu_masks.mask == 0x3f, meaning we use + * 31-6=25 bits for the hash (so cpu_masks.hash_mask == 0x7fffffc0). Similarly, + * queue_masks in rps_sock_flow_table is used to partition the space when a + * queue index is present. */ struct rps_sock_flow_table { u32 mask; + struct rps_sock_masks cpu_masks; + struct rps_sock_masks queue_masks; u32 ents[] ____cacheline_aligned_in_smp; }; #define RPS_SOCK_FLOW_TABLE_SIZE(_num) (offsetof(struct rps_sock_flow_table, ents[_num])) -#define RPS_NO_CPU 0xffff +#define RPS_SOCK_FLOW_USE_QID (1 << 31) +#define RPS_SOCK_FLOW_NO_IDENT -1U -extern u32 rps_cpu_mask; extern struct rps_sock_flow_table __rcu *rps_sock_flow_table; +extern unsigned int rps_max_num_queues; + +static inline void rps_init_sock_masks(struct rps_sock_masks *masks, u32 num) +{ + u32 mask = roundup_pow_of_two(num) - 1; + + masks->mask = mask; + masks->hash_mask = (~mask & ~RPS_SOCK_FLOW_USE_QID); +} static inline void rps_record_sock_flow(struct rps_sock_flow_table *table, u32 hash) { if (table && hash) { + u32 val = hash & table->cpu_masks.hash_mask; unsigned int index = hash & table->mask; - u32 val = hash & ~rps_cpu_mask; /* We only give a hint, preemption can change CPU under us */ val |= raw_smp_processor_id(); diff --git a/net/core/dev.c b/net/core/dev.c index 9f7a3e78e23a..946940bdd583 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4242,8 +4242,7 @@ static inline void ____napi_schedule(struct softnet_data *sd, /* One global table that all flow-based protocols share. */ struct rps_sock_flow_table __rcu *rps_sock_flow_table __read_mostly; EXPORT_SYMBOL(rps_sock_flow_table); -u32 rps_cpu_mask __read_mostly; -EXPORT_SYMBOL(rps_cpu_mask); +unsigned int rps_max_num_queues; struct static_key_false rps_needed __read_mostly; EXPORT_SYMBOL(rps_needed); @@ -4302,7 +4301,7 @@ set_rps_cpu(struct net_device *dev, struct sk_buff *skb, per_cpu(softnet_data, next_cpu).input_queue_head; } - rflow->cpu = next_cpu; + rps_dev_flow_set_cpu(rflow, next_cpu); return rflow; } @@ -4349,22 +4348,39 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, sock_flow_table = rcu_dereference(rps_sock_flow_table); if (flow_table && sock_flow_table) { + u32 next_cpu, comparator, ident; struct rps_dev_flow *rflow; - u32 next_cpu; - u32 ident; /* First check into global flow table if there is a match */ ident = sock_flow_table->ents[hash & sock_flow_table->mask]; - if ((ident ^ hash) & ~rps_cpu_mask) - goto try_rps; + comparator = ((ident & RPS_SOCK_FLOW_USE_QID) ? + sock_flow_table->queue_masks.hash_mask : + sock_flow_table->cpu_masks.hash_mask); - next_cpu = ident & rps_cpu_mask; + if ((ident ^ hash) & comparator) + goto try_rps; /* OK, now we know there is a match, * we can look at the local (per receive queue) flow table */ rflow = &flow_table->flows[hash & flow_table->mask]; - tcpu = rflow->cpu; + + /* The flow_sock entry may refer to either a queue or a + * CPU. Proceed accordingly. + */ + if (ident & RPS_SOCK_FLOW_USE_QID) { + /* A queue identifier is in the sock_flow_table entry */ + + /* Don't use aRFS to set CPU in this case, skip to + * trying RPS + */ + goto try_rps; + } + + /* A CPU number is in the sock_flow_table entry */ + + next_cpu = ident & sock_flow_table->cpu_masks.mask; + tcpu = rflow->cpu_qid.use_qid ? NO_QUEUE : rflow->cpu_qid.cpu; /* * If the desired CPU (where last recvmsg was done) is @@ -4396,10 +4412,8 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, if (map) { tcpu = map->cpus[reciprocal_scale(hash, map->len)]; - if (cpu_online(tcpu)) { + if (cpu_online(tcpu)) cpu = tcpu; - goto done; - } } done: @@ -4424,17 +4438,18 @@ bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index, { struct netdev_rx_queue *rxqueue = dev->_rx + rxq_index; struct rps_dev_flow_table *flow_table; + struct rps_cpu_qid cpu_qid; struct rps_dev_flow *rflow; bool expire = true; - unsigned int cpu; rcu_read_lock(); flow_table = rcu_dereference(rxqueue->rps_flow_table); if (flow_table && flow_id <= flow_table->mask) { rflow = &flow_table->flows[flow_id]; - cpu = READ_ONCE(rflow->cpu); - if (rflow->filter == filter_id && cpu < nr_cpu_ids && - ((int)(per_cpu(softnet_data, cpu).input_queue_head - + cpu_qid = READ_ONCE(rflow->cpu_qid); + if (rflow->filter == filter_id && !cpu_qid.use_qid && + cpu_qid.cpu < nr_cpu_ids && + ((int)(per_cpu(softnet_data, cpu_qid.cpu).input_queue_head - rflow->last_qtail) < (int)(10 * flow_table->mask))) expire = false; diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index e353b822bb15..56d27463d466 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -858,7 +858,7 @@ static ssize_t store_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue, table->mask = mask; for (count = 0; count <= mask; count++) - table->flows[count].cpu = RPS_NO_CPU; + rps_dev_flow_clear(&table->flows[count]); } else { table = NULL; } diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 9c7d46fbb75a..d09471f29d89 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -65,12 +65,16 @@ static int rps_create_sock_flow_table(size_t size, size_t orig_size, return -ENOMEM; sock_table->mask = size - 1; + rps_init_sock_masks(&sock_table->cpu_masks, + nr_cpu_ids); + rps_init_sock_masks(&sock_table->queue_masks, + rps_max_num_queues); } else { sock_table = orig_table; } for (i = 0; i < size; i++) - sock_table->ents[i] = RPS_NO_CPU; + sock_table->ents[i] = RPS_NO_CPU_QID; } else { sock_table = NULL; } -- 2.25.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [RFC PATCH 05/11] net: Infrastructure for per queue aRFS 2020-06-24 17:17 ` [RFC PATCH 05/11] net: Infrastructure for per queue aRFS Tom Herbert @ 2020-06-28 8:55 ` kernel test robot 0 siblings, 0 replies; 4+ messages in thread From: kernel test robot @ 2020-06-28 8:55 UTC (permalink / raw) To: kbuild-all [-- Attachment #1: Type: text/plain, Size: 7732 bytes --] Hi Tom, [FYI, it's a private test report for your RFC patch.] [auto build test WARNING on net/master] [also build test WARNING on ipvs/master net-next/master linus/master v5.8-rc2 next-20200624] [cannot apply to cgroup/for-next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Tom-Herbert/ptq-Per-Thread-Queues/20200625-012135 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git 0275875530f692c725c6f993aced2eca2d6ac50c config: s390-randconfig-s031-20200624 (attached as .config) compiler: s390-linux-gcc (GCC) 9.3.0 reproduce: # apt-get install sparse # sparse version: v0.6.2-dirty # save the attached .config to linux build tree make W=1 C=1 ARCH=s390 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> sparse warnings: (new ones prefixed by >>) net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@ net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum net/core/dev.c:3264:23: sparse: got unsigned int net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@ net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum net/core/dev.c:3264:23: sparse: got unsigned int net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 1 (different base types) @@ expected unsigned int [usertype] val @@ got restricted __wsum @@ net/core/dev.c:3264:23: sparse: expected unsigned int [usertype] val net/core/dev.c:3264:23: sparse: got restricted __wsum net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@ net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum net/core/dev.c:3264:23: sparse: got unsigned int net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@ net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum net/core/dev.c:3264:23: sparse: got unsigned int net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@ net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum net/core/dev.c:3264:23: sparse: got unsigned int net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum net/core/dev.c:3264:23: sparse: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __wsum [usertype] csum @@ got unsigned int @@ net/core/dev.c:3264:23: sparse: expected restricted __wsum [usertype] csum net/core/dev.c:3264:23: sparse: got unsigned int net/core/dev.c:3264:23: sparse: sparse: cast from restricted __wsum >> net/core/dev.c:4451:27: sparse: sparse: cast to non-scalar >> net/core/dev.c:4451:27: sparse: sparse: cast from non-scalar net/core/dev.c:5614:1: sparse: sparse: symbol '__pcpu_scope_flush_works' was not declared. Should it be static? net/core/dev.c:3747:26: sparse: sparse: context imbalance in '__dev_queue_xmit' - different lock contexts for basic block net/core/dev.c:4922:44: sparse: sparse: context imbalance in 'net_tx_action' - unexpected unlock # https://github.com/0day-ci/linux/commit/8cf630e2a48d7b6e18be2f46f90cebf8ec5d506c git remote add linux-review https://github.com/0day-ci/linux git remote update linux-review git checkout 8cf630e2a48d7b6e18be2f46f90cebf8ec5d506c vim +4451 net/core/dev.c c445477d74ab37 Ben Hutchings 2011-01-19 4426 c445477d74ab37 Ben Hutchings 2011-01-19 4427 /** c445477d74ab37 Ben Hutchings 2011-01-19 4428 * rps_may_expire_flow - check whether an RFS hardware filter may be removed c445477d74ab37 Ben Hutchings 2011-01-19 4429 * @dev: Device on which the filter was set c445477d74ab37 Ben Hutchings 2011-01-19 4430 * @rxq_index: RX queue index c445477d74ab37 Ben Hutchings 2011-01-19 4431 * @flow_id: Flow ID passed to ndo_rx_flow_steer() c445477d74ab37 Ben Hutchings 2011-01-19 4432 * @filter_id: Filter ID returned by ndo_rx_flow_steer() c445477d74ab37 Ben Hutchings 2011-01-19 4433 * c445477d74ab37 Ben Hutchings 2011-01-19 4434 * Drivers that implement ndo_rx_flow_steer() should periodically call c445477d74ab37 Ben Hutchings 2011-01-19 4435 * this function for each installed filter and remove the filters for c445477d74ab37 Ben Hutchings 2011-01-19 4436 * which it returns %true. c445477d74ab37 Ben Hutchings 2011-01-19 4437 */ c445477d74ab37 Ben Hutchings 2011-01-19 4438 bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index, c445477d74ab37 Ben Hutchings 2011-01-19 4439 u32 flow_id, u16 filter_id) c445477d74ab37 Ben Hutchings 2011-01-19 4440 { c445477d74ab37 Ben Hutchings 2011-01-19 4441 struct netdev_rx_queue *rxqueue = dev->_rx + rxq_index; c445477d74ab37 Ben Hutchings 2011-01-19 4442 struct rps_dev_flow_table *flow_table; 8cf630e2a48d7b Tom Herbert 2020-06-24 4443 struct rps_cpu_qid cpu_qid; c445477d74ab37 Ben Hutchings 2011-01-19 4444 struct rps_dev_flow *rflow; c445477d74ab37 Ben Hutchings 2011-01-19 4445 bool expire = true; c445477d74ab37 Ben Hutchings 2011-01-19 4446 c445477d74ab37 Ben Hutchings 2011-01-19 4447 rcu_read_lock(); c445477d74ab37 Ben Hutchings 2011-01-19 4448 flow_table = rcu_dereference(rxqueue->rps_flow_table); c445477d74ab37 Ben Hutchings 2011-01-19 4449 if (flow_table && flow_id <= flow_table->mask) { c445477d74ab37 Ben Hutchings 2011-01-19 4450 rflow = &flow_table->flows[flow_id]; 8cf630e2a48d7b Tom Herbert 2020-06-24 @4451 cpu_qid = READ_ONCE(rflow->cpu_qid); 8cf630e2a48d7b Tom Herbert 2020-06-24 4452 if (rflow->filter == filter_id && !cpu_qid.use_qid && 8cf630e2a48d7b Tom Herbert 2020-06-24 4453 cpu_qid.cpu < nr_cpu_ids && 8cf630e2a48d7b Tom Herbert 2020-06-24 4454 ((int)(per_cpu(softnet_data, cpu_qid.cpu).input_queue_head - c445477d74ab37 Ben Hutchings 2011-01-19 4455 rflow->last_qtail) < c445477d74ab37 Ben Hutchings 2011-01-19 4456 (int)(10 * flow_table->mask))) c445477d74ab37 Ben Hutchings 2011-01-19 4457 expire = false; c445477d74ab37 Ben Hutchings 2011-01-19 4458 } c445477d74ab37 Ben Hutchings 2011-01-19 4459 rcu_read_unlock(); c445477d74ab37 Ben Hutchings 2011-01-19 4460 return expire; c445477d74ab37 Ben Hutchings 2011-01-19 4461 } c445477d74ab37 Ben Hutchings 2011-01-19 4462 EXPORT_SYMBOL(rps_may_expire_flow); c445477d74ab37 Ben Hutchings 2011-01-19 4463 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org _______________________________________________ kbuild mailing list -- kbuild(a)lists.01.org To unsubscribe send an email to kbuild-leave(a)lists.01.org [-- Attachment #2: config.gz --] [-- Type: application/gzip, Size: 19564 bytes --] ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-06-28 8:56 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-06-24 21:50 [RFC PATCH 05/11] net: Infrastructure for per queue aRFS kernel test robot 2020-06-28 8:56 ` Rong Chen -- strict thread matches above, loose matches on Subject: below -- 2020-06-24 17:17 [RFC PATCH 00/11] ptq: Per Thread Queues Tom Herbert 2020-06-24 17:17 ` [RFC PATCH 05/11] net: Infrastructure for per queue aRFS Tom Herbert 2020-06-28 8:55 ` kernel test robot
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.