Skip to content

Commit a49049e

Browse files
Björn Töpelborkmann
authored andcommitted
xsk: simplified umem setup
As suggested by Daniel Borkmann, the umem setup code was a too defensive and complex. Here, we reduce the number of checks. Also, the memory pinning is now folded into the umem creation, and we do correct locking. Signed-off-by: Björn Töpel <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]>
1 parent 37b0769 commit a49049e

File tree

3 files changed

+51
-55
lines changed

3 files changed

+51
-55
lines changed

net/xdp/xdp_umem.c

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,25 @@
1616

1717
#define XDP_UMEM_MIN_FRAME_SIZE 2048
1818

19-
int xdp_umem_create(struct xdp_umem **umem)
20-
{
21-
*umem = kzalloc(sizeof(**umem), GFP_KERNEL);
22-
23-
if (!*umem)
24-
return -ENOMEM;
25-
26-
return 0;
27-
}
28-
2919
static void xdp_umem_unpin_pages(struct xdp_umem *umem)
3020
{
3121
unsigned int i;
3222

33-
if (umem->pgs) {
34-
for (i = 0; i < umem->npgs; i++) {
35-
struct page *page = umem->pgs[i];
36-
37-
set_page_dirty_lock(page);
38-
put_page(page);
39-
}
23+
for (i = 0; i < umem->npgs; i++) {
24+
struct page *page = umem->pgs[i];
4025

41-
kfree(umem->pgs);
42-
umem->pgs = NULL;
26+
set_page_dirty_lock(page);
27+
put_page(page);
4328
}
29+
30+
kfree(umem->pgs);
31+
umem->pgs = NULL;
4432
}
4533

4634
static void xdp_umem_unaccount_pages(struct xdp_umem *umem)
4735
{
48-
if (umem->user) {
49-
atomic_long_sub(umem->npgs, &umem->user->locked_vm);
50-
free_uid(umem->user);
51-
}
36+
atomic_long_sub(umem->npgs, &umem->user->locked_vm);
37+
free_uid(umem->user);
5238
}
5339

5440
static void xdp_umem_release(struct xdp_umem *umem)
@@ -66,22 +52,18 @@ static void xdp_umem_release(struct xdp_umem *umem)
6652
umem->cq = NULL;
6753
}
6854

69-
if (umem->pgs) {
70-
xdp_umem_unpin_pages(umem);
71-
72-
task = get_pid_task(umem->pid, PIDTYPE_PID);
73-
put_pid(umem->pid);
74-
if (!task)
75-
goto out;
76-
mm = get_task_mm(task);
77-
put_task_struct(task);
78-
if (!mm)
79-
goto out;
55+
xdp_umem_unpin_pages(umem);
8056

81-
mmput(mm);
82-
umem->pgs = NULL;
83-
}
57+
task = get_pid_task(umem->pid, PIDTYPE_PID);
58+
put_pid(umem->pid);
59+
if (!task)
60+
goto out;
61+
mm = get_task_mm(task);
62+
put_task_struct(task);
63+
if (!mm)
64+
goto out;
8465

66+
mmput(mm);
8567
xdp_umem_unaccount_pages(umem);
8668
out:
8769
kfree(umem);
@@ -167,16 +149,13 @@ static int xdp_umem_account_pages(struct xdp_umem *umem)
167149
return 0;
168150
}
169151

170-
int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
152+
static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
171153
{
172154
u32 frame_size = mr->frame_size, frame_headroom = mr->frame_headroom;
173155
u64 addr = mr->addr, size = mr->len;
174156
unsigned int nframes, nfpp;
175157
int size_chk, err;
176158

177-
if (!umem)
178-
return -EINVAL;
179-
180159
if (frame_size < XDP_UMEM_MIN_FRAME_SIZE || frame_size > PAGE_SIZE) {
181160
/* Strictly speaking we could support this, if:
182161
* - huge pages, or*
@@ -245,6 +224,24 @@ int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
245224
return err;
246225
}
247226

227+
struct xdp_umem *xdp_umem_create(struct xdp_umem_reg *mr)
228+
{
229+
struct xdp_umem *umem;
230+
int err;
231+
232+
umem = kzalloc(sizeof(*umem), GFP_KERNEL);
233+
if (!umem)
234+
return ERR_PTR(-ENOMEM);
235+
236+
err = xdp_umem_reg(umem, mr);
237+
if (err) {
238+
kfree(umem);
239+
return ERR_PTR(err);
240+
}
241+
242+
return umem;
243+
}
244+
248245
bool xdp_umem_validate_queues(struct xdp_umem *umem)
249246
{
250247
return umem->fq && umem->cq;

net/xdp/xdp_umem.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,8 @@ static inline char *xdp_umem_get_data_with_headroom(struct xdp_umem *umem,
5050
}
5151

5252
bool xdp_umem_validate_queues(struct xdp_umem *umem);
53-
int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr);
5453
void xdp_get_umem(struct xdp_umem *umem);
5554
void xdp_put_umem(struct xdp_umem *umem);
56-
int xdp_umem_create(struct xdp_umem **umem);
55+
struct xdp_umem *xdp_umem_create(struct xdp_umem_reg *mr);
5756

5857
#endif /* XDP_UMEM_H_ */

net/xdp/xsk.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -406,25 +406,23 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname,
406406
struct xdp_umem_reg mr;
407407
struct xdp_umem *umem;
408408

409-
if (xs->umem)
410-
return -EBUSY;
411-
412409
if (copy_from_user(&mr, optval, sizeof(mr)))
413410
return -EFAULT;
414411

415412
mutex_lock(&xs->mutex);
416-
err = xdp_umem_create(&umem);
413+
if (xs->umem) {
414+
mutex_unlock(&xs->mutex);
415+
return -EBUSY;
416+
}
417417

418-
err = xdp_umem_reg(umem, &mr);
419-
if (err) {
420-
kfree(umem);
418+
umem = xdp_umem_create(&mr);
419+
if (IS_ERR(umem)) {
421420
mutex_unlock(&xs->mutex);
422-
return err;
421+
return PTR_ERR(umem);
423422
}
424423

425424
/* Make sure umem is ready before it can be seen by others */
426425
smp_wmb();
427-
428426
xs->umem = umem;
429427
mutex_unlock(&xs->mutex);
430428
return 0;
@@ -435,13 +433,15 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname,
435433
struct xsk_queue **q;
436434
int entries;
437435

438-
if (!xs->umem)
439-
return -EINVAL;
440-
441436
if (copy_from_user(&entries, optval, sizeof(entries)))
442437
return -EFAULT;
443438

444439
mutex_lock(&xs->mutex);
440+
if (!xs->umem) {
441+
mutex_unlock(&xs->mutex);
442+
return -EINVAL;
443+
}
444+
445445
q = (optname == XDP_UMEM_FILL_RING) ? &xs->umem->fq :
446446
&xs->umem->cq;
447447
err = xsk_init_queue(entries, q, true);

0 commit comments

Comments
 (0)