Skip to content

Commit 4bfc471

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2020-12-28 The following pull-request contains BPF updates for your *net* tree. There is a small merge conflict between bpf tree commit 69ca310 ("bpf: Save correct stopping point in file seq iteration") and net tree commit 66ed594 ("bpf/task_iter: In task_file_seq_get_next use task_lookup_next_fd_rcu"). The get_files_struct() does not exist anymore in net, so take the hunk in HEAD and add the `info->tid = curr_tid` to the error path: [...] curr_task = task_seq_get_next(ns, &curr_tid, true); if (!curr_task) { info->task = NULL; info->tid = curr_tid; return NULL; } /* set info->task and info->tid */ [...] We've added 10 non-merge commits during the last 9 day(s) which contain a total of 11 files changed, 75 insertions(+), 20 deletions(-). The main changes are: 1) Various AF_XDP fixes such as fill/completion ring leak on failed bind and fixing a race in skb mode's backpressure mechanism, from Magnus Karlsson. 2) Fix latency spikes on lockdep enabled kernels by adding a rescheduling point to BPF hashtab initialization, from Eric Dumazet. 3) Fix a splat in task iterator by saving the correct stopping point in the seq file iteration, from Jonathan Lemon. 4) Fix BPF maps selftest by adding retries in case hashtab returns EBUSY errors on update/deletes, from Andrii Nakryiko. 5) Fix BPF selftest error reporting to something more user friendly if the vmlinux BTF cannot be found, from Kamal Mostafa. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 1fef735 + a61daaf commit 4bfc471

File tree

11 files changed

+81
-27
lines changed

11 files changed

+81
-27
lines changed

include/net/xdp_sock.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,6 @@ struct xdp_sock {
5858

5959
struct xsk_queue *tx ____cacheline_aligned_in_smp;
6060
struct list_head tx_list;
61-
/* Mutual exclusion of NAPI TX thread and sendmsg error paths
62-
* in the SKB destructor callback.
63-
*/
64-
spinlock_t tx_completion_lock;
6561
/* Protects generic receive. */
6662
spinlock_t rx_lock;
6763

include/net/xsk_buff_pool.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ struct xsk_buff_pool {
7373
bool dma_need_sync;
7474
bool unaligned;
7575
void *addrs;
76+
/* Mutual exclusion of the completion ring in the SKB mode. Two cases to protect:
77+
* NAPI TX thread and sendmsg error paths in the SKB destructor callback and when
78+
* sockets share a single cq when the same netdev and queue id is shared.
79+
*/
80+
spinlock_t cq_lock;
7681
struct xdp_buff_xsk *free_heads[];
7782
};
7883

kernel/bpf/hashtab.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ static void htab_init_buckets(struct bpf_htab *htab)
152152
lockdep_set_class(&htab->buckets[i].lock,
153153
&htab->lockdep_key);
154154
}
155+
cond_resched();
155156
}
156157
}
157158

kernel/bpf/syscall.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include <linux/fs.h>
1818
#include <linux/license.h>
1919
#include <linux/filter.h>
20-
#include <linux/version.h>
2120
#include <linux/kernel.h>
2221
#include <linux/idr.h>
2322
#include <linux/cred.h>

kernel/bpf/task_iter.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ static struct task_struct *task_seq_get_next(struct pid_namespace *ns,
3737
if (!task) {
3838
++*tid;
3939
goto retry;
40-
} else if (skip_if_dup_files && task->tgid != task->pid &&
40+
} else if (skip_if_dup_files && !thread_group_leader(task) &&
4141
task->files == task->group_leader->files) {
4242
put_task_struct(task);
4343
task = NULL;
@@ -151,14 +151,14 @@ task_file_seq_get_next(struct bpf_iter_seq_task_file_info *info)
151151
curr_task = info->task;
152152
curr_fd = info->fd;
153153
} else {
154-
curr_task = task_seq_get_next(ns, &curr_tid, true);
155-
if (!curr_task) {
156-
info->task = NULL;
157-
return NULL;
158-
}
159-
160-
/* set info->task and info->tid */
161-
info->task = curr_task;
154+
curr_task = task_seq_get_next(ns, &curr_tid, true);
155+
if (!curr_task) {
156+
info->task = NULL;
157+
info->tid = curr_tid;
158+
return NULL;
159+
}
160+
161+
/* set info->task and info->tid */
162162
if (curr_tid == info->tid) {
163163
curr_fd = info->fd;
164164
} else {

net/xdp/xsk.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,9 @@ static void xsk_destruct_skb(struct sk_buff *skb)
423423
struct xdp_sock *xs = xdp_sk(skb->sk);
424424
unsigned long flags;
425425

426-
spin_lock_irqsave(&xs->tx_completion_lock, flags);
426+
spin_lock_irqsave(&xs->pool->cq_lock, flags);
427427
xskq_prod_submit_addr(xs->pool->cq, addr);
428-
spin_unlock_irqrestore(&xs->tx_completion_lock, flags);
428+
spin_unlock_irqrestore(&xs->pool->cq_lock, flags);
429429

430430
sock_wfree(skb);
431431
}
@@ -437,6 +437,7 @@ static int xsk_generic_xmit(struct sock *sk)
437437
bool sent_frame = false;
438438
struct xdp_desc desc;
439439
struct sk_buff *skb;
440+
unsigned long flags;
440441
int err = 0;
441442

442443
mutex_lock(&xs->mutex);
@@ -468,10 +469,13 @@ static int xsk_generic_xmit(struct sock *sk)
468469
* if there is space in it. This avoids having to implement
469470
* any buffering in the Tx path.
470471
*/
472+
spin_lock_irqsave(&xs->pool->cq_lock, flags);
471473
if (unlikely(err) || xskq_prod_reserve(xs->pool->cq)) {
474+
spin_unlock_irqrestore(&xs->pool->cq_lock, flags);
472475
kfree_skb(skb);
473476
goto out;
474477
}
478+
spin_unlock_irqrestore(&xs->pool->cq_lock, flags);
475479

476480
skb->dev = xs->dev;
477481
skb->priority = sk->sk_priority;
@@ -483,6 +487,9 @@ static int xsk_generic_xmit(struct sock *sk)
483487
if (err == NETDEV_TX_BUSY) {
484488
/* Tell user-space to retry the send */
485489
skb->destructor = sock_wfree;
490+
spin_lock_irqsave(&xs->pool->cq_lock, flags);
491+
xskq_prod_cancel(xs->pool->cq);
492+
spin_unlock_irqrestore(&xs->pool->cq_lock, flags);
486493
/* Free skb without triggering the perf drop trace */
487494
consume_skb(skb);
488495
err = -EAGAIN;
@@ -878,6 +885,10 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
878885
}
879886
}
880887

888+
/* FQ and CQ are now owned by the buffer pool and cleaned up with it. */
889+
xs->fq_tmp = NULL;
890+
xs->cq_tmp = NULL;
891+
881892
xs->dev = dev;
882893
xs->zc = xs->umem->zc;
883894
xs->queue_id = qid;
@@ -1299,7 +1310,6 @@ static int xsk_create(struct net *net, struct socket *sock, int protocol,
12991310
xs->state = XSK_READY;
13001311
mutex_init(&xs->mutex);
13011312
spin_lock_init(&xs->rx_lock);
1302-
spin_lock_init(&xs->tx_completion_lock);
13031313

13041314
INIT_LIST_HEAD(&xs->map_list);
13051315
spin_lock_init(&xs->map_list_lock);

net/xdp/xsk_buff_pool.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,11 @@ struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs,
7171
INIT_LIST_HEAD(&pool->free_list);
7272
INIT_LIST_HEAD(&pool->xsk_tx_list);
7373
spin_lock_init(&pool->xsk_tx_list_lock);
74+
spin_lock_init(&pool->cq_lock);
7475
refcount_set(&pool->users, 1);
7576

7677
pool->fq = xs->fq_tmp;
7778
pool->cq = xs->cq_tmp;
78-
xs->fq_tmp = NULL;
79-
xs->cq_tmp = NULL;
8079

8180
for (i = 0; i < pool->free_heads_cnt; i++) {
8281
xskb = &pool->heads[i];

net/xdp/xsk_queue.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,11 @@ static inline bool xskq_prod_is_full(struct xsk_queue *q)
334334
return xskq_prod_nb_free(q, 1) ? false : true;
335335
}
336336

337+
static inline void xskq_prod_cancel(struct xsk_queue *q)
338+
{
339+
q->cached_prod--;
340+
}
341+
337342
static inline int xskq_prod_reserve(struct xsk_queue *q)
338343
{
339344
if (xskq_prod_is_full(q))

tools/testing/selftests/bpf/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux) \
121121
/sys/kernel/btf/vmlinux \
122122
/boot/vmlinux-$(shell uname -r)
123123
VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS))))
124+
ifeq ($(VMLINUX_BTF),)
125+
$(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)")
126+
endif
124127

125128
# Define simple and short `make test_progs`, `make test_sysctl`, etc targets
126129
# to build individual tests.

tools/testing/selftests/bpf/test_maps.c

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,22 +1312,58 @@ static void test_map_stress(void)
13121312
#define DO_UPDATE 1
13131313
#define DO_DELETE 0
13141314

1315+
#define MAP_RETRIES 20
1316+
1317+
static int map_update_retriable(int map_fd, const void *key, const void *value,
1318+
int flags, int attempts)
1319+
{
1320+
while (bpf_map_update_elem(map_fd, key, value, flags)) {
1321+
if (!attempts || (errno != EAGAIN && errno != EBUSY))
1322+
return -errno;
1323+
1324+
usleep(1);
1325+
attempts--;
1326+
}
1327+
1328+
return 0;
1329+
}
1330+
1331+
static int map_delete_retriable(int map_fd, const void *key, int attempts)
1332+
{
1333+
while (bpf_map_delete_elem(map_fd, key)) {
1334+
if (!attempts || (errno != EAGAIN && errno != EBUSY))
1335+
return -errno;
1336+
1337+
usleep(1);
1338+
attempts--;
1339+
}
1340+
1341+
return 0;
1342+
}
1343+
13151344
static void test_update_delete(unsigned int fn, void *data)
13161345
{
13171346
int do_update = ((int *)data)[1];
13181347
int fd = ((int *)data)[0];
1319-
int i, key, value;
1348+
int i, key, value, err;
13201349

13211350
for (i = fn; i < MAP_SIZE; i += TASKS) {
13221351
key = value = i;
13231352

13241353
if (do_update) {
1325-
assert(bpf_map_update_elem(fd, &key, &value,
1326-
BPF_NOEXIST) == 0);
1327-
assert(bpf_map_update_elem(fd, &key, &value,
1328-
BPF_EXIST) == 0);
1354+
err = map_update_retriable(fd, &key, &value, BPF_NOEXIST, MAP_RETRIES);
1355+
if (err)
1356+
printf("error %d %d\n", err, errno);
1357+
assert(err == 0);
1358+
err = map_update_retriable(fd, &key, &value, BPF_EXIST, MAP_RETRIES);
1359+
if (err)
1360+
printf("error %d %d\n", err, errno);
1361+
assert(err == 0);
13291362
} else {
1330-
assert(bpf_map_delete_elem(fd, &key) == 0);
1363+
err = map_delete_retriable(fd, &key, MAP_RETRIES);
1364+
if (err)
1365+
printf("error %d %d\n", err, errno);
1366+
assert(err == 0);
13311367
}
13321368
}
13331369
}

0 commit comments

Comments
 (0)