mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-05-08 16:24:01 +00:00
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 <bjorn.topel@intel.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
parent
37b076933a
commit
a49049ea25
3 changed files with 52 additions and 56 deletions
|
@ -16,39 +16,25 @@
|
||||||
|
|
||||||
#define XDP_UMEM_MIN_FRAME_SIZE 2048
|
#define XDP_UMEM_MIN_FRAME_SIZE 2048
|
||||||
|
|
||||||
int xdp_umem_create(struct xdp_umem **umem)
|
|
||||||
{
|
|
||||||
*umem = kzalloc(sizeof(**umem), GFP_KERNEL);
|
|
||||||
|
|
||||||
if (!*umem)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void xdp_umem_unpin_pages(struct xdp_umem *umem)
|
static void xdp_umem_unpin_pages(struct xdp_umem *umem)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (umem->pgs) {
|
for (i = 0; i < umem->npgs; i++) {
|
||||||
for (i = 0; i < umem->npgs; i++) {
|
struct page *page = umem->pgs[i];
|
||||||
struct page *page = umem->pgs[i];
|
|
||||||
|
|
||||||
set_page_dirty_lock(page);
|
set_page_dirty_lock(page);
|
||||||
put_page(page);
|
put_page(page);
|
||||||
}
|
|
||||||
|
|
||||||
kfree(umem->pgs);
|
|
||||||
umem->pgs = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kfree(umem->pgs);
|
||||||
|
umem->pgs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xdp_umem_unaccount_pages(struct xdp_umem *umem)
|
static void xdp_umem_unaccount_pages(struct xdp_umem *umem)
|
||||||
{
|
{
|
||||||
if (umem->user) {
|
atomic_long_sub(umem->npgs, &umem->user->locked_vm);
|
||||||
atomic_long_sub(umem->npgs, &umem->user->locked_vm);
|
free_uid(umem->user);
|
||||||
free_uid(umem->user);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xdp_umem_release(struct xdp_umem *umem)
|
static void xdp_umem_release(struct xdp_umem *umem)
|
||||||
|
@ -66,22 +52,18 @@ static void xdp_umem_release(struct xdp_umem *umem)
|
||||||
umem->cq = NULL;
|
umem->cq = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (umem->pgs) {
|
xdp_umem_unpin_pages(umem);
|
||||||
xdp_umem_unpin_pages(umem);
|
|
||||||
|
|
||||||
task = get_pid_task(umem->pid, PIDTYPE_PID);
|
task = get_pid_task(umem->pid, PIDTYPE_PID);
|
||||||
put_pid(umem->pid);
|
put_pid(umem->pid);
|
||||||
if (!task)
|
if (!task)
|
||||||
goto out;
|
goto out;
|
||||||
mm = get_task_mm(task);
|
mm = get_task_mm(task);
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
if (!mm)
|
if (!mm)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
mmput(mm);
|
|
||||||
umem->pgs = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
mmput(mm);
|
||||||
xdp_umem_unaccount_pages(umem);
|
xdp_umem_unaccount_pages(umem);
|
||||||
out:
|
out:
|
||||||
kfree(umem);
|
kfree(umem);
|
||||||
|
@ -167,16 +149,13 @@ static int xdp_umem_account_pages(struct xdp_umem *umem)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
|
static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
|
||||||
{
|
{
|
||||||
u32 frame_size = mr->frame_size, frame_headroom = mr->frame_headroom;
|
u32 frame_size = mr->frame_size, frame_headroom = mr->frame_headroom;
|
||||||
u64 addr = mr->addr, size = mr->len;
|
u64 addr = mr->addr, size = mr->len;
|
||||||
unsigned int nframes, nfpp;
|
unsigned int nframes, nfpp;
|
||||||
int size_chk, err;
|
int size_chk, err;
|
||||||
|
|
||||||
if (!umem)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (frame_size < XDP_UMEM_MIN_FRAME_SIZE || frame_size > PAGE_SIZE) {
|
if (frame_size < XDP_UMEM_MIN_FRAME_SIZE || frame_size > PAGE_SIZE) {
|
||||||
/* Strictly speaking we could support this, if:
|
/* Strictly speaking we could support this, if:
|
||||||
* - huge pages, or*
|
* - huge pages, or*
|
||||||
|
@ -245,6 +224,24 @@ out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct xdp_umem *xdp_umem_create(struct xdp_umem_reg *mr)
|
||||||
|
{
|
||||||
|
struct xdp_umem *umem;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
umem = kzalloc(sizeof(*umem), GFP_KERNEL);
|
||||||
|
if (!umem)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
err = xdp_umem_reg(umem, mr);
|
||||||
|
if (err) {
|
||||||
|
kfree(umem);
|
||||||
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return umem;
|
||||||
|
}
|
||||||
|
|
||||||
bool xdp_umem_validate_queues(struct xdp_umem *umem)
|
bool xdp_umem_validate_queues(struct xdp_umem *umem)
|
||||||
{
|
{
|
||||||
return umem->fq && umem->cq;
|
return umem->fq && umem->cq;
|
||||||
|
|
|
@ -50,9 +50,8 @@ static inline char *xdp_umem_get_data_with_headroom(struct xdp_umem *umem,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool xdp_umem_validate_queues(struct xdp_umem *umem);
|
bool xdp_umem_validate_queues(struct xdp_umem *umem);
|
||||||
int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr);
|
|
||||||
void xdp_get_umem(struct xdp_umem *umem);
|
void xdp_get_umem(struct xdp_umem *umem);
|
||||||
void xdp_put_umem(struct xdp_umem *umem);
|
void xdp_put_umem(struct xdp_umem *umem);
|
||||||
int xdp_umem_create(struct xdp_umem **umem);
|
struct xdp_umem *xdp_umem_create(struct xdp_umem_reg *mr);
|
||||||
|
|
||||||
#endif /* XDP_UMEM_H_ */
|
#endif /* XDP_UMEM_H_ */
|
||||||
|
|
|
@ -406,25 +406,23 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname,
|
||||||
struct xdp_umem_reg mr;
|
struct xdp_umem_reg mr;
|
||||||
struct xdp_umem *umem;
|
struct xdp_umem *umem;
|
||||||
|
|
||||||
if (xs->umem)
|
|
||||||
return -EBUSY;
|
|
||||||
|
|
||||||
if (copy_from_user(&mr, optval, sizeof(mr)))
|
if (copy_from_user(&mr, optval, sizeof(mr)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
mutex_lock(&xs->mutex);
|
mutex_lock(&xs->mutex);
|
||||||
err = xdp_umem_create(&umem);
|
if (xs->umem) {
|
||||||
|
|
||||||
err = xdp_umem_reg(umem, &mr);
|
|
||||||
if (err) {
|
|
||||||
kfree(umem);
|
|
||||||
mutex_unlock(&xs->mutex);
|
mutex_unlock(&xs->mutex);
|
||||||
return err;
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
umem = xdp_umem_create(&mr);
|
||||||
|
if (IS_ERR(umem)) {
|
||||||
|
mutex_unlock(&xs->mutex);
|
||||||
|
return PTR_ERR(umem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure umem is ready before it can be seen by others */
|
/* Make sure umem is ready before it can be seen by others */
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
|
||||||
xs->umem = umem;
|
xs->umem = umem;
|
||||||
mutex_unlock(&xs->mutex);
|
mutex_unlock(&xs->mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -435,13 +433,15 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname,
|
||||||
struct xsk_queue **q;
|
struct xsk_queue **q;
|
||||||
int entries;
|
int entries;
|
||||||
|
|
||||||
if (!xs->umem)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (copy_from_user(&entries, optval, sizeof(entries)))
|
if (copy_from_user(&entries, optval, sizeof(entries)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
mutex_lock(&xs->mutex);
|
mutex_lock(&xs->mutex);
|
||||||
|
if (!xs->umem) {
|
||||||
|
mutex_unlock(&xs->mutex);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
q = (optname == XDP_UMEM_FILL_RING) ? &xs->umem->fq :
|
q = (optname == XDP_UMEM_FILL_RING) ? &xs->umem->fq :
|
||||||
&xs->umem->cq;
|
&xs->umem->cq;
|
||||||
err = xsk_init_queue(entries, q, true);
|
err = xsk_init_queue(entries, q, true);
|
||||||
|
|
Loading…
Add table
Reference in a new issue