From patchwork Mon Sep 26 23:18:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Rosenberg X-Patchwork-Id: 12989551 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B32F5C07E9D for ; Mon, 26 Sep 2022 23:21:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229935AbiIZXV2 (ORCPT ); Mon, 26 Sep 2022 19:21:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37108 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231207AbiIZXUS (ORCPT ); Mon, 26 Sep 2022 19:20:18 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DB1F7615E for ; Mon, 26 Sep 2022 16:19:33 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-349423f04dbso75867297b3.13 for ; Mon, 26 Sep 2022 16:19:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date; bh=IbvaNd7xkv6qLbqXS+UwVE+DkcAWaiLiz540c1KNyRs=; b=Z8drp21nnocmfjMVXdPLwqgBmC3rl5N9wLVtRBXkcdTiN9HL3S6/MfQRW9TJe265Vt qIEo6wfrg6T5gPZQAhFk9PRhRrQCCKzwn67IENRgTm5cKoTyPfR4yFIem3b7ML0UqNkh wrn5vUuQNOVMfApnU54UGot+lFj616P9bn0fgmX+I/ybxgVnEtSZvWVMYMmS84QDzAaf iwQoLTHVzAxyl8KQep8J20Wmd1FEDMkTsYS8NmnIWcQJEXKJHpNg9rMSw1BAboKU3Qhe Hxk6yKFEmTOIq4FJhVZijMLOuUHsubi/mdb8wAvhgFsINlZ6IhiuvGWlyI8TbbgSCVYg KNWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date; bh=IbvaNd7xkv6qLbqXS+UwVE+DkcAWaiLiz540c1KNyRs=; b=Xq7vzeWnRun2z6r3hDQ6DyvfWht3DXr0vN+AkmojrM8nMo4OVJLV0pJeVF7SLdSlqO o6Ct70YXQ5UFYMY9yP64CaY1WVqsUrbAQJ79RHo1zDlU8k+1V/FnAeHI5zUNWRrBAIfh lltV28in3TMubfBCrnbeRbqqt7mP9g6/y6wWNK8PplVozISIkZOv7tT6W2OgmxfySn3O Nn3eqna4ZM6Jv3cnWc2DYBsyOiW0a8PIIJLsiTlAQln0CU8Vfx20/kxhgDh/1QlxkztP CCTS16/jMu2z/2chPs6utj0H46WP+sc8xQiMtZW8zGk+fXf7SjFewAlDyvBiYzICmEv9 l9xg== X-Gm-Message-State: ACrzQf2IkVImFWaHlHYLA2/bmbrd9I6tfBz2tHsnGJh6bx3IQpwGErIu sWGWL3mYhnrgByhuq4Ic6rFVmTZJh70= X-Google-Smtp-Source: AMsMyM6vYxoJSrr3KuG3WwQXnjLQZz0oa4O4bxGnmvWSze+nbZAdsph4QDPFsfZxi4J2rflsR1JgdH5WodE= X-Received: from drosen.mtv.corp.google.com ([2620:15c:211:200:4643:a68e:2b7:f873]) (user=drosen job=sendgmr) by 2002:a0d:d345:0:b0:349:f274:a0f with SMTP id v66-20020a0dd345000000b00349f2740a0fmr21914221ywd.13.1664234373645; Mon, 26 Sep 2022 16:19:33 -0700 (PDT) Date: Mon, 26 Sep 2022 16:18:20 -0700 In-Reply-To: <20220926231822.994383-1-drosen@google.com> Mime-Version: 1.0 References: <20220926231822.994383-1-drosen@google.com> X-Mailer: git-send-email 2.37.3.998.g577e59143f-goog Message-ID: <20220926231822.994383-25-drosen@google.com> Subject: [PATCH 24/26] fuse-bpf: Call bpf for pre/post filters From: Daniel Rosenberg To: Miklos Szeredi , Alexei Starovoitov , Daniel Borkmann , John Fastabend Cc: Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Daniel Rosenberg , Paul Lawrence , Alessio Balsini , David Anderson , Sandeep Patil , linux-fsdevel@vger.kernel.org, bpf@vger.kernel.org, kernel-team@android.com Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org This allows altering input or output parameters to fuse calls that will be handled directly by the backing filesystems. BPF programs can signal whether the entire operation should instead go through regular fuse, or if a postfilter call is needed. Signed-off-by: Daniel Rosenberg Signed-off-by: Paul Lawrence --- fs/fuse/fuse_i.h | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 6fb5c7a1ff11..07b50be2c6e4 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1936,6 +1936,46 @@ static inline void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatf int __init fuse_bpf_init(void); void __exit fuse_bpf_cleanup(void); +static inline void fuse_bpf_set_in_ends(struct bpf_fuse_args *fa) +{ + int i; + + for (i = 0; i < FUSE_MAX_ARGS_IN; i++) + fa->in_args[i].end_offset = (void *) + ((char *)fa->in_args[i].value + + fa->in_args[i].size); +} + +static inline void fuse_bpf_set_in_immutable(struct bpf_fuse_args *fa) +{ + int i; + + for (i = 0; i < FUSE_MAX_ARGS_IN; i++) + fa->in_args[i].flags |= BPF_FUSE_IMMUTABLE; +} + +static inline void fuse_bpf_set_out_ends(struct bpf_fuse_args *fa) +{ + int i; + + for (i = 0; i < FUSE_MAX_ARGS_OUT; i++) + fa->out_args[i].end_offset = (void *) + ((char *)fa->out_args[i].value + + fa->out_args[i].size); +} + +static inline void fuse_bpf_free_alloced(struct bpf_fuse_args *fa) +{ + int i; + + for (i = 0; i < FUSE_MAX_ARGS_IN; i++) + if (fa->in_args[i].flags & BPF_FUSE_ALLOCATED) + kfree(fa->in_args[i].value); + for (i = 0; i < FUSE_MAX_ARGS_OUT; i++) + if (fa->out_args[i].flags & BPF_FUSE_ALLOCATED) + kfree(fa->out_args[i].value); +} + /* * expression statement to wrap the backing filter logic * struct inode *inode: inode with bpf and backing inode @@ -1958,6 +1998,7 @@ void __exit fuse_bpf_cleanup(void); bool initialized = false; \ bool handled = false; \ ssize_t res; \ + int bpf_next; \ io feo = { 0 }; \ int error = 0; \ \ @@ -1969,17 +2010,47 @@ void __exit fuse_bpf_cleanup(void); error = initialize_in(&fa, &feo, args); \ if (error) \ break; \ + fuse_bpf_set_in_ends(&fa); \ + \ + fa.opcode |= FUSE_PREFILTER; \ + bpf_next = fuse_inode->bpf ? \ + bpf_prog_run(fuse_inode->bpf, &fa) : \ + BPF_FUSE_CONTINUE; \ + if (bpf_next < 0) { \ + error = bpf_next; \ + break; \ + } \ + \ + fuse_bpf_set_in_immutable(&fa); \ \ error = initialize_out(&fa, &feo, args); \ if (error) \ break; \ + fuse_bpf_set_out_ends(&fa); \ \ initialized = true; \ + if (bpf_next == BPF_FUSE_USER) { \ + handled = false; \ + break; \ + } \ + \ + fa.opcode &= ~FUSE_PREFILTER; \ \ error = backing(&fa, &out, args); \ if (error < 0) \ fa.error_in = error; \ \ + if (bpf_next == BPF_FUSE_CONTINUE) \ + break; \ + \ + fa.opcode |= FUSE_POSTFILTER; \ + if (bpf_next == BPF_FUSE_POSTFILTER) \ + bpf_next = bpf_prog_run(fuse_inode->bpf, &fa); \ + if (bpf_next < 0) { \ + error = bpf_next; \ + break; \ + } \ + \ } while (false); \ \ if (initialized && handled) { \ @@ -1987,6 +2058,7 @@ void __exit fuse_bpf_cleanup(void); if (res) \ error = res; \ } \ + fuse_bpf_free_alloced(&fa); \ \ out = error ? _Generic((out), \ default : \