Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp6823423ybl; Wed, 15 Jan 2020 10:44:52 -0800 (PST) X-Google-Smtp-Source: APXvYqwCJGslBp644THk/vlrsOEQTtlBPPVmuohnLnOYvkypCCvgijW6TpmmkRcnnGsVyO0TuwnS X-Received: by 2002:aca:b984:: with SMTP id j126mr1007286oif.174.1579113892808; Wed, 15 Jan 2020 10:44:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1579113892; cv=none; d=google.com; s=arc-20160816; b=pK2mqxMzUrmaI3tC5Q0TFtArJAy2kWhHGxxm4CigLbLhmxW0mVgPzBKlSlhk9PuwYB tVjIR/k+yl8vLRJCeXdN4uYfkvrpxRH4Z2Hz6ANnlEW5bgTq/N/Ui1xSexfzWuJxEMOt H0CpELrUNUYn5P+fCS5tDdbdm7FsIu+/qwAOwPLUJouvEy8l/pp8v+fSL2VkGbxfI5UB rEGBnPALOI/GCv112WnqyuhxL5PZ9//ENXtsMKMCrB67CJd0oEdQ3AHXHzLD1vPN8v8h l4VQb1f+zeJe2ZwlN2JvxDIewBSVR2HFG2p3N4cOV8SzXps8nY8okXAKMCBd1DWwXwJ/ n6Pg== 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=+HqP+4pv65tNa2gKmR3/Ufe3GB9e142iVvYjLgWUjzs=; b=FbbPBKzTcyWwvTEzvDhJQ38Bz7OQk8GVlc/aeaqOGOEEG5q3pvXRsB26zODolukrEF rbnZ36BAfEjsruLHDFbkiYH65OUeqKnJzFjebj9rMYfjYHMg2ksOM01W/KWMIDdGwoB9 CM7GXXtV43mV2KHk9ft8lPEszjx6LRD4NlMUxMjR7NZm9b+JPG+SdK2hO9uXIq4wxgYe H1C78vk5Ahi4S87YQ+B2f7+ZLbWuWq1y+XcfKJOJLk2C8CAG8TjIeCbeZ0Kxj3Rg/Rg7 xp/ryXcU8ZS4DThpsP0l3j7us2gw+SfjhoA+kJbAyA0wTW39il0yJ0JRJjlEgy8K0fQR 7cUg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=akYxcL9+; 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 r1si11155955otn.150.2020.01.15.10.44.41; Wed, 15 Jan 2020 10:44:52 -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=akYxcL9+; 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 S1729287AbgAOSnh (ORCPT + 99 others); Wed, 15 Jan 2020 13:43:37 -0500 Received: from mail-pj1-f73.google.com ([209.85.216.73]:41931 "EHLO mail-pj1-f73.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729021AbgAOSna (ORCPT ); Wed, 15 Jan 2020 13:43:30 -0500 Received: by mail-pj1-f73.google.com with SMTP id gn11so457165pjb.6 for ; Wed, 15 Jan 2020 10:43:29 -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=+HqP+4pv65tNa2gKmR3/Ufe3GB9e142iVvYjLgWUjzs=; b=akYxcL9+ITuQ5MSssRxGCnVoBxHKT823lD+O+bV4ruD6VuFQCLd8Mvz3zTqrZJLeuJ 3ELpEryZsOSjEgYTK605geIdA62KHipRYON1jN/zkiqQZGBm0KxZhLk9L4ElMyasjQW0 66VxWAy/NtKXw7mwYiStg3XZSezuaYKMZWPAt3cDbNAOu1Y98syq46Y4o/54ZcPBwe2V 19Y/uOaEEbfzarONYn+1jRMFTdUFGGjMgZizQpk00bZahqrbEGSCDdrxYMZtNHjgNNPz cSz04MN5afU7riHlu1k19g5naPrPM591MhVPFhhtUNmBRppY/RsitCIfKZDWMWiUtpph dlzw== 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=+HqP+4pv65tNa2gKmR3/Ufe3GB9e142iVvYjLgWUjzs=; b=UxUyPqUBdbnQsm3XJIHGBXIL5taF2vl5bhOt/pYwX3MGsgsrUKgsfFVnda6pGf/WwA 1+zbyd7+K87s770gV7ocZOcdGRCqJ8jaMaHQriq8R0oZzp1Wxu7ydMNtKpV/h0/Z4DFd 437xL5zdKZoH9ZfRhORdak83fQ/1vSJmSADdpkHBxnBMkXdcbkfI4km2e9e23imuTab4 CNBd51UgY6SQwyMl1qxp397CzLrZ+9B9e6cbXtFef1GgsuYAmLjb7VdLGmSxtePguEI2 LDMyB3NkMhIzZP5/zkLt3TdC+bJrAs3Z9GmqQw6egl+WENdssM217O0QM90myHB7PTjy 527g== X-Gm-Message-State: APjAAAWZav4RDizsWBPLhbDs6Zq0IevqUIJpyKvKi0MZHiN4fGbx6rQK ymqhYRpG6YEqBLg+BmXIyWmnQ3jDWPg9 X-Received: by 2002:a63:a511:: with SMTP id n17mr33958608pgf.338.1579113809055; Wed, 15 Jan 2020 10:43:29 -0800 (PST) Date: Wed, 15 Jan 2020 10:43:02 -0800 In-Reply-To: <20200115184308.162644-1-brianvv@google.com> Message-Id: <20200115184308.162644-4-brianvv@google.com> Mime-Version: 1.0 References: <20200115184308.162644-1-brianvv@google.com> X-Mailer: git-send-email 2.25.0.rc1.283.g88dfdc4193-goog Subject: [PATCH v5 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 d604ddbb1afbe..ce8244d1ba99c 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, @@ -3219,6 +3324,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); @@ -3325,6 +3434,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