From patchwork Sat Aug 29 04:21:53 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Nan X-Patchwork-Id: 52828 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f200.google.com (mail-wi0-f200.google.com [209.85.212.200]) by patches.linaro.org (Postfix) with ESMTPS id 7212F22FE2 for ; Sat, 29 Aug 2015 04:25:06 +0000 (UTC) Received: by wibvo5 with SMTP id vo5sf8799258wib.0 for ; Fri, 28 Aug 2015 21:25:05 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-type:sender:precedence :list-id:x-original-sender:x-original-authentication-results :mailing-list:list-post:list-help:list-archive:list-unsubscribe; bh=h7PzP30wQmncm7DWc9wrPiP0T4zolqPDTewvKzKnF40=; b=OUQLasyFYQPX+bBVZLcF6OWRfaGS14jPtXhiAGWtKh5Kq7Rkv2OfqRGKOLLNI4RhRx NTTrijIVyhaKst1Kv5/KQIr7B4GIBtHIzNVpXloOFp4WSmcKNzlUUSLKScn92Hj5WcUK BD1Vf2S6bzdef12nq33JrftnI+Bejfp9DT8ZnxIhepdS0zlVaOihN0OMTg0y49wKqIP/ ssC3Ju4aROqRVwOrSd+1J9+hABnNnqFqgFwJm1h/CWbsRy4GQssMXYpsEWAAHkx+sMUG fj8X6el5aGQYhGoJcbJdy4FrVeElOOoUsdBGHfL113xi10rTDxxPxpe6G8phCAg+JiAM 0hgA== X-Gm-Message-State: ALoCoQneeOtnq61ZKNWsKnNJDSxU6VNzhGkfvwHBRpwAjXiQ8MKTdNPCl6SWQeaJSVJ0KgSXn6ed X-Received: by 10.112.90.225 with SMTP id bz1mr3521006lbb.12.1440822305759; Fri, 28 Aug 2015 21:25:05 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.170.197 with SMTP id ao5ls15233lac.53.gmail; Fri, 28 Aug 2015 21:25:05 -0700 (PDT) X-Received: by 10.112.77.168 with SMTP id t8mr6242307lbw.70.1440822305596; Fri, 28 Aug 2015 21:25:05 -0700 (PDT) Received: from mail-la0-f51.google.com (mail-la0-f51.google.com. [209.85.215.51]) by mx.google.com with ESMTPS id sc4si7661548lbb.99.2015.08.28.21.25.05 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 28 Aug 2015 21:25:05 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.51 as permitted sender) client-ip=209.85.215.51; Received: by laba3 with SMTP id a3so43300335lab.1 for ; Fri, 28 Aug 2015 21:25:05 -0700 (PDT) X-Received: by 10.152.5.228 with SMTP id v4mr6482928lav.36.1440822305422; Fri, 28 Aug 2015 21:25:05 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.151.194 with SMTP id us2csp267784lbb; Fri, 28 Aug 2015 21:25:04 -0700 (PDT) X-Received: by 10.68.254.99 with SMTP id ah3mr20298714pbd.15.1440822304251; Fri, 28 Aug 2015 21:25:04 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id pt9si3397699pbc.137.2015.08.28.21.25.02; Fri, 28 Aug 2015 21:25:04 -0700 (PDT) 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; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752911AbbH2EY0 (ORCPT + 28 others); Sat, 29 Aug 2015 00:24:26 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:3781 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752810AbbH2EYR (ORCPT ); Sat, 29 Aug 2015 00:24:17 -0400 Received: from 172.24.1.47 (EHLO szxeml431-hub.china.huawei.com) ([172.24.1.47]) by szxrg03-dlp.huawei.com (MOS 4.4.3-GA FastPath queued) with ESMTP id BLW04312; Sat, 29 Aug 2015 12:23:23 +0800 (CST) Received: from linux-4hy3.site (10.107.193.248) by szxeml431-hub.china.huawei.com (10.82.67.208) with Microsoft SMTP Server id 14.3.235.1; Sat, 29 Aug 2015 12:23:11 +0800 From: Wang Nan To: , , CC: , , , Wang Nan , He Kuang , Brendan Gregg , Daniel Borkmann , "David Ahern" , Jiri Olsa , Kaixu Xia , Masami Hiramatsu , Namhyung Kim , Paul Mackerras , Peter Zijlstra Subject: [PATCH 19/31] bpf tools: Load a program with different instances using preprocessor Date: Sat, 29 Aug 2015 04:21:53 +0000 Message-ID: <1440822125-52691-20-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1440822125-52691-1-git-send-email-wangnan0@huawei.com> References: <1440822125-52691-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.107.193.248] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020204.55E133BB.00D3, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: a882a55f2da0d7d17f31679c14a7329e Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: wangnan0@huawei.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.51 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , In this patch, caller of libbpf is able to control the loaded programs by installing a preprocessor callback for a BPF program. With preprocessor, different instances can be created from one BPF program. This patch will be used by perf to generate different prologue for different 'struct probe_trace_event' instances matched by one 'struct perf_probe_event'. bpf_program__set_prep() is added to support this feature. Caller should pass libbpf the number of instances should be created and a preprocessor function which will be called when doing real loading. The callback should return instructions arrays for each instances. fd field in bpf_programs is replaced by instance, which has an nr field and fds array. bpf_program__nth_fd() is introduced for read fd of instances. Old interface bpf_program__fd() is reimplemented by returning the first fd. Signed-off-by: Wang Nan Signed-off-by: He Kuang Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: David Ahern Cc: He Kuang Cc: Jiri Olsa Cc: Kaixu Xia Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Zefan Li Cc: pi3orama@163.com Cc: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/n/1436445342-1402-29-git-send-email-wangnan0@huawei.com [wangnan: Add missing '!', allows bpf_program__unload() when prog->instance.nr == -1 ] --- tools/lib/bpf/libbpf.c | 143 +++++++++++++++++++++++++++++++++++++++++++++---- tools/lib/bpf/libbpf.h | 22 ++++++++ 2 files changed, 156 insertions(+), 9 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 4252fc2..6a07b26 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -98,7 +98,11 @@ struct bpf_program { } *reloc_desc; int nr_reloc; - int fd; + struct { + int nr; + int *fds; + } instance; + bpf_program_prep_t preprocessor; struct bpf_object *obj; void *priv; @@ -152,10 +156,24 @@ struct bpf_object { static void bpf_program__unload(struct bpf_program *prog) { + int i; + if (!prog) return; - zclose(prog->fd); + /* + * If the object is opened but the program is never loaded, + * it is possible that prog->instance.nr == -1. + */ + if (prog->instance.nr > 0) { + for (i = 0; i < prog->instance.nr; i++) + zclose(prog->instance.fds[i]); + } else if (prog->instance.nr != -1) + pr_warning("Internal error: instance.nr is %d\n", + prog->instance.nr); + + prog->instance.nr = -1; + zfree(&prog->instance.fds); } static void bpf_program__exit(struct bpf_program *prog) @@ -206,7 +224,8 @@ bpf_program__init(void *data, size_t size, char *name, int idx, memcpy(prog->insns, data, prog->insns_cnt * sizeof(struct bpf_insn)); prog->idx = idx; - prog->fd = -1; + prog->instance.fds = NULL; + prog->instance.nr = -1; return 0; errout: @@ -795,13 +814,71 @@ static int bpf_program__load(struct bpf_program *prog, char *license, u32 kern_version) { - int err, fd; + int err = 0, fd, i; + + if (prog->instance.nr < 0 || !prog->instance.fds) { + if (prog->preprocessor) { + pr_warning("Internal error: can't load program '%s'\n", + prog->section_name); + return -EINVAL; + } + + prog->instance.fds = malloc(sizeof(int)); + if (!prog->instance.fds) { + pr_warning("No enough memory for fds\n"); + return -ENOMEM; + } + prog->instance.nr = 1; + prog->instance.fds[0] = -1; + } + + if (!prog->preprocessor) { + if (prog->instance.nr != 1) + pr_warning("Program '%s' inconsistent: nr(%d) not 1\n", + prog->section_name, prog->instance.nr); - err = load_program(prog->insns, prog->insns_cnt, - license, kern_version, &fd); - if (!err) - prog->fd = fd; + err = load_program(prog->insns, prog->insns_cnt, + license, kern_version, &fd); + if (!err) + prog->instance.fds[0] = fd; + goto out; + } + + for (i = 0; i < prog->instance.nr; i++) { + struct bpf_prog_prep_result result; + bpf_program_prep_t preprocessor = prog->preprocessor; + + bzero(&result, sizeof(result)); + err = preprocessor(prog, i, prog->insns, + prog->insns_cnt, &result); + if (err) { + pr_warning("Preprocessing %dth instance of program '%s' failed\n", + i, prog->section_name); + goto out; + } + + if (!result.new_insn_ptr || !result.new_insn_cnt) { + pr_debug("Skip loading %dth instance of program '%s'\n", + i, prog->section_name); + prog->instance.fds[i] = -1; + continue; + } + + err = load_program(result.new_insn_ptr, + result.new_insn_cnt, + license, kern_version, &fd); + + if (err) { + pr_warning("Loading %dth instance of program '%s' failed\n", + i, prog->section_name); + goto out; + } + if (result.pfd) + *result.pfd = fd; + prog->instance.fds[i] = fd; + } +out: if (err) pr_warning("failed to load program '%s'\n", prog->section_name); @@ -1052,5 +1129,53 @@ const char *bpf_program__title(struct bpf_program *prog, bool dup) int bpf_program__fd(struct bpf_program *prog) { - return prog->fd; + return bpf_program__nth_fd(prog, 0); +} + +int bpf_program__set_prep(struct bpf_program *prog, int nr_instance, + bpf_program_prep_t prep) +{ + int *instance_fds; + + if (nr_instance <= 0 || !prep) + return -EINVAL; + + if (prog->instance.nr > 0 || prog->instance.fds) { + pr_warning("Can't set pre-processor after loading\n"); + return -EINVAL; + } + + instance_fds = malloc(sizeof(int) * nr_instance); + if (!instance_fds) { + pr_warning("alloc memory failed for instance of fds\n"); + return -ENOMEM; + } + + /* fill all fd with -1 */ + memset(instance_fds, 0xff, sizeof(int) * nr_instance); + + prog->instance.nr = nr_instance; + prog->instance.fds = instance_fds; + prog->preprocessor = prep; + return 0; +} + +int bpf_program__nth_fd(struct bpf_program *prog, int n) +{ + int fd; + + if (n >= prog->instance.nr || n < 0) { + pr_warning("Can't get the %dth fd from program %s: only %d instances\n", + n, prog->section_name, prog->instance.nr); + return -EINVAL; + } + + fd = prog->instance.fds[n]; + if (fd < 0) { + pr_warning("%dth instance of program '%s' is invalid\n", + n, prog->section_name); + return -ENOENT; + } + + return fd; } diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index f16170c..d82b89e 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -67,6 +67,28 @@ const char *bpf_program__title(struct bpf_program *prog, bool dup); int bpf_program__fd(struct bpf_program *prog); +struct bpf_insn; +struct bpf_prog_prep_result { + /* + * If not NULL, load new instruction array. + * If set to NULL, don't load this instance. + */ + struct bpf_insn *new_insn_ptr; + int new_insn_cnt; + + /* If not NULL, result fd is set to it */ + int *pfd; +}; + +typedef int (*bpf_program_prep_t)(struct bpf_program *, int n, + struct bpf_insn *, int insn_cnt, + struct bpf_prog_prep_result *res); + +int bpf_program__set_prep(struct bpf_program *prog, int nr_instance, + bpf_program_prep_t prep); + +int bpf_program__nth_fd(struct bpf_program *prog, int n); + /* * We don't need __attribute__((packed)) now since it is * unnecessary for 'bpf_map_def' because they are all aligned.