Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp5430669ybl; Tue, 14 Jan 2020 08:49:04 -0800 (PST) X-Google-Smtp-Source: APXvYqw/Dqvyy63MDeNyPjd9DSvp7CjE7SiBYjNw5WXdtNgT/Y+2g7jvOS4j0bj5qY0UbYxRGyRH X-Received: by 2002:a05:6830:18ce:: with SMTP id v14mr12736069ote.36.1579020544906; Tue, 14 Jan 2020 08:49:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1579020544; cv=none; d=google.com; s=arc-20160816; b=wrb4vXYZYJxb1/6h9wfYib0mGwnv4SZTNwqYb/EjMbpdyGZF6d+F7HYs5ISHtvQRyX OTS+w/O+eTs7A+y88s47BROXtl5AqLzeh9kvSbhsxRy5wkBWc+Ta4y9pN+pxKxzIhLOe 9pAoEs4XRh9HthwH3w1Jl0S/p7Dp2UZZdth2Zm/ZBpdPkHsAZna6E9zl3trGVjMLGKvI 3iuc+De3L9TUHk9qEn+nPtpeBFNpyn36DqfonO4quQ4w8NtZJqqD2fME+MBquqfBiPZ/ luyIKqvRX6YdGF+zX6tv4CQ2w7inq9SN0TiFUGmUjNKzajMiPZBXCOjCB8WraPIXzYFo 7uDA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:dkim-signature; bh=IRlKatwJeTkkAyX6vfla/t8ZI87eW9srrnw4F61EIh4=; b=T2enINnQhpVp5mIOIJoKMoOIRm2vuf2XO0rgTT8M05zDsKUPL17cFcih01WRBHnf0M OdIVCPd6cJLadypsnft+8nbMFx11Dja6ihmt/vKM30nWVaL5Osd/Re9x1zrrBpp+eAjY cROGmplAbFpdyrikVmcOCxHCgNssvv+33Nem5Ru6pTts3hhYk/yi6B6uCIDROKOSh0OJ FVtP8sl+/oDGqFUdLg+g+9lSoZfw0kpy55xjwXWVoBAgr6aLtt+Wb2hi8bGdCiJ2J/Dj cxytC46X0So4Au0IZECruEcXSOhcYEb07eVhkF3Lpwj3n/xBnEhjNEUAYI+rnTbDRD/Y 080w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=i9gQvdqD; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i12si7608424oik.171.2020.01.14.08.48.54; Tue, 14 Jan 2020 08:49:04 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=i9gQvdqD; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728978AbgANQqo (ORCPT + 99 others); Tue, 14 Jan 2020 11:46:44 -0500 Received: from mail-pg1-f202.google.com ([209.85.215.202]:44170 "EHLO mail-pg1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728953AbgANQqm (ORCPT ); Tue, 14 Jan 2020 11:46:42 -0500 Received: by mail-pg1-f202.google.com with SMTP id o21so8720084pgm.11 for ; Tue, 14 Jan 2020 08:46:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=IRlKatwJeTkkAyX6vfla/t8ZI87eW9srrnw4F61EIh4=; b=i9gQvdqDubiqI71J3DzzKcwks7J8EKVQmZLrfV0XIy1g0IqAgbYOqylHyJjd2HchyA dHNCdvGybScD5EbATZuPIVPNj2Pv6vE5R2nLWVdVLx8oUoNtVQocqkK6oNUOcOoiCLJP 2cIBOz9zqOhbyOAF4lti4CIZZbY9YfXQVkqghKfeI3KuX+dJGD7p5a7UWefendQcrmHr OBjS/fpaAUVrRu/NVgGoYCLKhcoZApAhF4j9j3v8EHNr0mELKjK2GveyX2P7mhBWsMPe TFGqfyzHa1aJlYAegBEJDKm+UFhJ3Z7VoAvwN4I7MuG484ahrZZ+qL2xkR9nMiu4/H61 6M7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=IRlKatwJeTkkAyX6vfla/t8ZI87eW9srrnw4F61EIh4=; b=Yq3iV86TEXwqReEJxwnvarU31MBbejgvSuM5ctBrzOa/fCKVeqtT+xNdaxVEOXqsrs TM2Q5KnhUW7FQs212ORoB/71f2cT07KspupwNbuITJFbnOdocNd1aO9MtkX0fDFQpKJ3 9PgQDtbOThDd7YliN4s0PNH0AHYALNrqvlC/a7Z+uFMQDpxRSKL4neaMH+fFIEjlx9kf P4/7qCOAwmrKadjmTZoVGPmfF7LBl8hRUsl6XhZiGRaKaO4xeQJUzZ2RHzXs6OeDfHfO ctPLEzBULISB3c2TZSt274DElFX2nftpOvfwob0UaUYTkXsNprreOTIXIxU/C/g5d9SW Azqg== X-Gm-Message-State: APjAAAXdGFdTPWqxDa/hVffQQd8INN0j9tnCvXGOQFi8nzE2Z037kMtf RynywXdsk3LVrD5y0cPPgrqzrmSYWZ+B X-Received: by 2002:a63:a53:: with SMTP id z19mr27748373pgk.267.1579020401723; Tue, 14 Jan 2020 08:46:41 -0800 (PST) Date: Tue, 14 Jan 2020 08:46:07 -0800 In-Reply-To: <20200114164614.47029-1-brianvv@google.com> Message-Id: <20200114164614.47029-4-brianvv@google.com> Mime-Version: 1.0 References: <20200114164614.47029-1-brianvv@google.com> X-Mailer: git-send-email 2.25.0.rc1.283.g88dfdc4193-goog Subject: [PATCH v4 bpf-next 3/9] bpf: add generic support for update and delete batch ops From: Brian Vazquez To: Brian Vazquez , Brian Vazquez , Alexei Starovoitov , Daniel Borkmann , "David S . Miller" Cc: Yonghong Song , Andrii Nakryiko , Stanislav Fomichev , Petar Penkov , Willem de Bruijn , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This commit adds generic support for update and delete batch ops that can be used for almost all the bpf maps. These commands share the same UAPI attr that lookup and lookup_and_delete batch ops use and the syscall commands are: BPF_MAP_UPDATE_BATCH BPF_MAP_DELETE_BATCH The main difference between update/delete and lookup batch ops is that for update/delete keys/values must be specified for userspace and because of that, neither in_batch nor out_batch are used. Suggested-by: Stanislav Fomichev Signed-off-by: Brian Vazquez Signed-off-by: Yonghong Song --- include/linux/bpf.h | 10 ++++ include/uapi/linux/bpf.h | 2 + kernel/bpf/syscall.c | 115 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 807744ecaa5a1..05466ad6cf1c5 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -46,6 +46,10 @@ struct bpf_map_ops { void *(*map_lookup_elem_sys_only)(struct bpf_map *map, void *key); int (*map_lookup_batch)(struct bpf_map *map, const union bpf_attr *attr, union bpf_attr __user *uattr); + int (*map_update_batch)(struct bpf_map *map, const union bpf_attr *attr, + union bpf_attr __user *uattr); + int (*map_delete_batch)(struct bpf_map *map, const union bpf_attr *attr, + union bpf_attr __user *uattr); /* funcs callable from userspace and from eBPF programs */ void *(*map_lookup_elem)(struct bpf_map *map, void *key); @@ -987,6 +991,12 @@ void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr); int generic_map_lookup_batch(struct bpf_map *map, const union bpf_attr *attr, union bpf_attr __user *uattr); +int generic_map_update_batch(struct bpf_map *map, + const union bpf_attr *attr, + union bpf_attr __user *uattr); +int generic_map_delete_batch(struct bpf_map *map, + const union bpf_attr *attr, + union bpf_attr __user *uattr); extern int sysctl_unprivileged_bpf_disabled; diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 8185f1542daa1..e8df9ca680e0c 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -108,6 +108,8 @@ enum bpf_cmd { BPF_MAP_FREEZE, BPF_BTF_GET_NEXT_ID, BPF_MAP_LOOKUP_BATCH, + BPF_MAP_UPDATE_BATCH, + BPF_MAP_DELETE_BATCH, }; enum bpf_map_type { diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index d4acb6eb5ef9e..2f631eb67d00c 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1218,6 +1218,111 @@ static int map_get_next_key(union bpf_attr *attr) return err; } +int generic_map_delete_batch(struct bpf_map *map, + const union bpf_attr *attr, + union bpf_attr __user *uattr) +{ + void __user *keys = u64_to_user_ptr(attr->batch.keys); + u32 cp, max_count; + int err = 0; + void *key; + + if (attr->batch.elem_flags & ~BPF_F_LOCK) + return -EINVAL; + + if ((attr->batch.elem_flags & BPF_F_LOCK) && + !map_value_has_spin_lock(map)) { + return -EINVAL; + } + + max_count = attr->batch.count; + if (!max_count) + return 0; + + for (cp = 0; cp < max_count; cp++) { + key = __bpf_copy_key(keys + cp * map->key_size, map->key_size); + if (IS_ERR(key)) { + err = PTR_ERR(key); + break; + } + + if (bpf_map_is_dev_bound(map)) { + err = bpf_map_offload_delete_elem(map, key); + break; + } + + preempt_disable(); + __this_cpu_inc(bpf_prog_active); + rcu_read_lock(); + err = map->ops->map_delete_elem(map, key); + rcu_read_unlock(); + __this_cpu_dec(bpf_prog_active); + preempt_enable(); + maybe_wait_bpf_programs(map); + if (err) + break; + } + if (copy_to_user(&uattr->batch.count, &cp, sizeof(cp))) + err = -EFAULT; + return err; +} + +int generic_map_update_batch(struct bpf_map *map, + const union bpf_attr *attr, + union bpf_attr __user *uattr) +{ + void __user *values = u64_to_user_ptr(attr->batch.values); + void __user *keys = u64_to_user_ptr(attr->batch.keys); + u32 value_size, cp, max_count; + int ufd = attr->map_fd; + void *key, *value; + struct fd f; + int err = 0; + + f = fdget(ufd); + if (attr->batch.elem_flags & ~BPF_F_LOCK) + return -EINVAL; + + if ((attr->batch.elem_flags & BPF_F_LOCK) && + !map_value_has_spin_lock(map)) { + return -EINVAL; + } + + value_size = bpf_map_value_size(map); + + max_count = attr->batch.count; + if (!max_count) + return 0; + + value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); + if (!value) + return -ENOMEM; + + for (cp = 0; cp < max_count; cp++) { + key = __bpf_copy_key(keys + cp * map->key_size, map->key_size); + if (IS_ERR(key)) { + err = PTR_ERR(key); + break; + } + err = -EFAULT; + if (copy_from_user(value, values + cp * value_size, value_size)) + break; + + err = bpf_map_update_value(map, f, key, value, + attr->batch.elem_flags); + + if (err) + break; + } + + if (copy_to_user(&uattr->batch.count, &cp, sizeof(cp))) + err = -EFAULT; + + kfree(value); + kfree(key); + return err; +} + #define MAP_LOOKUP_RETRIES 3 int generic_map_lookup_batch(struct bpf_map *map, @@ -3213,6 +3318,10 @@ static int bpf_map_do_batch(const union bpf_attr *attr, if (cmd == BPF_MAP_LOOKUP_BATCH) BPF_DO_BATCH(map->ops->map_lookup_batch); + else if (cmd == BPF_MAP_UPDATE_BATCH) + BPF_DO_BATCH(map->ops->map_update_batch); + else + BPF_DO_BATCH(map->ops->map_delete_batch); err_put: fdput(f); @@ -3319,6 +3428,12 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz case BPF_MAP_LOOKUP_BATCH: err = bpf_map_do_batch(&attr, uattr, BPF_MAP_LOOKUP_BATCH); break; + case BPF_MAP_UPDATE_BATCH: + err = bpf_map_do_batch(&attr, uattr, BPF_MAP_UPDATE_BATCH); + break; + case BPF_MAP_DELETE_BATCH: + err = bpf_map_do_batch(&attr, uattr, BPF_MAP_DELETE_BATCH); + break; default: err = -EINVAL; break; -- 2.25.0.rc1.283.g88dfdc4193-goog