From patchwork Mon Jan 11 15:56:57 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ming Lei X-Patchwork-Id: 566013 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id C2E821402C4 for ; Tue, 12 Jan 2016 02:59:14 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=XcjZcwC2; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933674AbcAKP5d (ORCPT ); Mon, 11 Jan 2016 10:57:33 -0500 Received: from mail-pa0-f65.google.com ([209.85.220.65]:33225 "EHLO mail-pa0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933454AbcAKP5b (ORCPT ); Mon, 11 Jan 2016 10:57:31 -0500 Received: by mail-pa0-f65.google.com with SMTP id pv5so25718610pac.0; Mon, 11 Jan 2016 07:57:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+u2/7+X1yYJv1RtVPNwcKmiRx+gG+q/Zl/YSiPy3I+0=; b=XcjZcwC2RK0k7p6BNrglMJ2GI6cbUxceTf4FOBr4mIW8RRLXVccCScBbBYQKNUHarL lXDWG1JjrkzM8RSa6wvILujgqmSqftutUe0NLpfRgul02UphdTlHblxQo9WmkpsrLDWF bVDftUoHlygLNfHTTLDUfi6yNMfgDDk22Abi0KATbws6M/fZsQ7WKoOuGy2bjA3SDTOU K/yAz7GaLW3A5tEp9g4XZ/ZtkyW9bjp7Q0A7bt0VmBC/iKjoIky2IsTBQhiHUUlxxMNN 8+I+wcAwhVvkNcZHKwOxEWro6YanOishaIBxOh/KEtbaur3MwwKO6/XwHhwk5ZDEdtMv XiTA== X-Received: by 10.67.1.69 with SMTP id be5mr16059131pad.6.1452527850776; Mon, 11 Jan 2016 07:57:30 -0800 (PST) Received: from localhost ([103.192.227.7]) by smtp.gmail.com with ESMTPSA id xv2sm18236167pab.10.2016.01.11.07.57.29 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Mon, 11 Jan 2016 07:57:30 -0800 (PST) From: Ming Lei To: linux-kernel@vger.kernel.org, Alexei Starovoitov Cc: "David S. Miller" , netdev@vger.kernel.org, Daniel Borkmann , Martin KaFai Lau , Ming Lei Subject: [PATCH 5/9] bpf: syscall: add percpu version of lookup/update elem Date: Mon, 11 Jan 2016 23:56:57 +0800 Message-Id: <1452527821-12276-6-git-send-email-tom.leiming@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1452527821-12276-1-git-send-email-tom.leiming@gmail.com> References: <1452527821-12276-1-git-send-email-tom.leiming@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Prepare for supporting percpu map in the following patch. Now userspace can lookup/update mapped value in one specific CPU in case of percpu map. Signed-off-by: Ming Lei --- include/uapi/linux/bpf.h | 3 +++ kernel/bpf/syscall.c | 48 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 2658917..63b04c6 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -73,6 +73,8 @@ enum bpf_cmd { BPF_PROG_LOAD, BPF_OBJ_PIN, BPF_OBJ_GET, + BPF_MAP_LOOKUP_ELEM_PERCPU, + BPF_MAP_UPDATE_ELEM_PERCPU, }; enum bpf_map_type { @@ -114,6 +116,7 @@ union bpf_attr { __aligned_u64 next_key; }; __u64 flags; + __u32 cpu; }; struct { /* anonymous struct used by BPF_PROG_LOAD command */ diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 6373970..280c93b 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -231,8 +231,9 @@ static void __user *u64_to_ptr(__u64 val) /* last field in 'union bpf_attr' used by this command */ #define BPF_MAP_LOOKUP_ELEM_LAST_FIELD value +#define BPF_MAP_LOOKUP_ELEM_PERCPU_LAST_FIELD cpu -static int map_lookup_elem(union bpf_attr *attr) +static int map_lookup_elem(union bpf_attr *attr, bool percpu) { void __user *ukey = u64_to_ptr(attr->key); void __user *uvalue = u64_to_ptr(attr->value); @@ -242,8 +243,14 @@ static int map_lookup_elem(union bpf_attr *attr) struct fd f; int err; - if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM)) - return -EINVAL; + if (!percpu) { + if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM)) + return -EINVAL; + } else { + if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM_PERCPU) || + attr->cpu >= num_possible_cpus()) + return -EINVAL; + } f = fdget(ufd); map = __bpf_map_get(f); @@ -265,7 +272,10 @@ static int map_lookup_elem(union bpf_attr *attr) goto free_key; rcu_read_lock(); - ptr = map->ops->map_lookup_elem(map, key); + if (!percpu) + ptr = map->ops->map_lookup_elem(map, key); + else + ptr = map->ops->map_lookup_elem_percpu(map, key, attr->cpu); if (ptr) memcpy(value, ptr, map->value_size); rcu_read_unlock(); @@ -290,8 +300,9 @@ err_put: } #define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags +#define BPF_MAP_UPDATE_ELEM_PERCPU_LAST_FIELD cpu -static int map_update_elem(union bpf_attr *attr) +static int map_update_elem(union bpf_attr *attr, bool percpu) { void __user *ukey = u64_to_ptr(attr->key); void __user *uvalue = u64_to_ptr(attr->value); @@ -301,8 +312,14 @@ static int map_update_elem(union bpf_attr *attr) struct fd f; int err; - if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM)) - return -EINVAL; + if (!percpu) { + if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM)) + return -EINVAL; + } else { + if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM_PERCPU) || + attr->cpu >= num_possible_cpus()) + return -EINVAL; + } f = fdget(ufd); map = __bpf_map_get(f); @@ -331,7 +348,12 @@ static int map_update_elem(union bpf_attr *attr) * therefore all map accessors rely on this fact, so do the same here */ rcu_read_lock(); - err = map->ops->map_update_elem(map, key, value, attr->flags); + if (!percpu) + err = map->ops->map_update_elem(map, key, value, attr->flags); + else + err = map->ops->map_update_elem_percpu(map, key, value, + attr->flags, attr->cpu); + rcu_read_unlock(); free_value: @@ -772,10 +794,16 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz err = map_create(&attr); break; case BPF_MAP_LOOKUP_ELEM: - err = map_lookup_elem(&attr); + err = map_lookup_elem(&attr, false); + break; + case BPF_MAP_LOOKUP_ELEM_PERCPU: + err = map_lookup_elem(&attr, true); break; case BPF_MAP_UPDATE_ELEM: - err = map_update_elem(&attr); + err = map_update_elem(&attr, false); + break; + case BPF_MAP_UPDATE_ELEM_PERCPU: + err = map_update_elem(&attr, true); break; case BPF_MAP_DELETE_ELEM: err = map_delete_elem(&attr);