From patchwork Mon Jan 25 15:30:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alessio Balsini X-Patchwork-Id: 12048255 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 92865C433DB for ; Tue, 26 Jan 2021 20:12:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 451BF22255 for ; Tue, 26 Jan 2021 20:12:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728438AbhAZFZC (ORCPT ); Tue, 26 Jan 2021 00:25:02 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60358 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730195AbhAYPl1 (ORCPT ); Mon, 25 Jan 2021 10:41:27 -0500 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 99D9CC061A2A for ; Mon, 25 Jan 2021 07:31:09 -0800 (PST) Received: by mail-wr1-x42d.google.com with SMTP id d16so12380022wro.11 for ; Mon, 25 Jan 2021 07:31:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=android.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PmbAjVrlHcxm5n/bwgc2+WaEfTI9G00ILEGpn8g1B2s=; b=pIm9gqCvzmGTZV5I8GJ9+T38akNqP4Kv15XEl58FJ71C/wUV1CO5KYx/nMnV+i2/Dl qR2HzLG4y6z8xn0KKJTNhw+HMKNivW1uUtcHd/LVwJU2m75Pa8XWF/gbDmrjTAHHSAQB pESLS8gsM5Zh1RQTbjNVUuQ8f0u3ZUcRXrdhanvhM1fE3iby45cDBitZOFJxTUgVjEtE slJ2S+nlFGi9dlw8duihGV4vSBlSBRqAXj9oVWCHXwFqB+T0nzSL3cNK00yvheytIjHv mryS+brTv1Gwdzcj6szMHZa3XFA9yisIsdG0ipRLdGZQfi4Qrm/qn8OcwJ9oRhgUJrmY k4YA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=PmbAjVrlHcxm5n/bwgc2+WaEfTI9G00ILEGpn8g1B2s=; b=Uy8OLOTh/i4NxS6kWtMD6bL4kwvNoqxDU7zOQLah0jrHaxTzsu9NEeHgI33HGurX4Q hUAEIcT2Cj+539hlwq/km8R1obcCWLQYk18/M0stpmUQ5IggAjb1Y6w642Kn5AJZRula S0iruWJCFp0ccRoQKZyBM9orlXDOXh8EeefxO70gDnAHFWxhE4z4V7tOrthpMn5SllFf AGTO+9c9b4/rlG9MV2zzTS7s6VcSBpFw4GKSbA1Rma84mXAT62IG0F4cjau8WjPzfvPg KppScYgzkmXEpiRfvWgfetnOwTfAcqZaWqd2+H0hjWK2ClaT3v7TuUkX6ho4STb7rrad DGqA== X-Gm-Message-State: AOAM533ITwGqD4S6wJR1rje1eggVRQZt5a8OfW+rhlIgftllEz6TCotf skkSpaiI5qif/4mRYGK9cpjzrA== X-Google-Smtp-Source: ABdhPJxGVLJp9p/xvJrz9/Q0C+7UywtvCTwYVi0tfEJCCCl9SPSmP4RdW+yUMSRO5tFoxeDes2PdAA== X-Received: by 2002:adf:fc8a:: with SMTP id g10mr1632693wrr.189.1611588668411; Mon, 25 Jan 2021 07:31:08 -0800 (PST) Received: from balsini.lon.corp.google.com ([2a00:79e0:d:210:4cd4:5994:40fe:253d]) by smtp.gmail.com with ESMTPSA id o14sm22611965wri.48.2021.01.25.07.31.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 07:31:08 -0800 (PST) From: Alessio Balsini To: Miklos Szeredi Cc: Akilesh Kailash , Amir Goldstein , Antonio SJ Musumeci , David Anderson , Giuseppe Scrivano , Jann Horn , Jens Axboe , Martijn Coenen , Palmer Dabbelt , Paul Lawrence , Peng Tao , Stefano Duo , Zimuzo Ezeozue , wuyan , fuse-devel@lists.sourceforge.net, kernel-team@android.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH RESEND V12 1/8] fs: Generic function to convert iocb to rw flags Date: Mon, 25 Jan 2021 15:30:50 +0000 Message-Id: <20210125153057.3623715-2-balsini@android.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog In-Reply-To: <20210125153057.3623715-1-balsini@android.com> References: <20210125153057.3623715-1-balsini@android.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org OverlayFS implements its own function to translate iocb flags into rw flags, so that they can be passed into another vfs call. With commit ce71bfea207b4 ("fs: align IOCB_* flags with RWF_* flags") Jens created a 1:1 matching between the iocb flags and rw flags, simplifying the conversion. Reduce the OverlayFS code by making the flag conversion function generic and reusable. Signed-off-by: Alessio Balsini --- fs/overlayfs/file.c | 23 +++++------------------ include/linux/fs.h | 5 +++++ 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index bd9dd38347ae..56be2ffc5a14 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -15,6 +15,8 @@ #include #include "overlayfs.h" +#define OVL_IOCB_MASK (IOCB_DSYNC | IOCB_HIPRI | IOCB_NOWAIT | IOCB_SYNC) + struct ovl_aio_req { struct kiocb iocb; struct kiocb *orig_iocb; @@ -236,22 +238,6 @@ static void ovl_file_accessed(struct file *file) touch_atime(&file->f_path); } -static rwf_t ovl_iocb_to_rwf(int ifl) -{ - rwf_t flags = 0; - - if (ifl & IOCB_NOWAIT) - flags |= RWF_NOWAIT; - if (ifl & IOCB_HIPRI) - flags |= RWF_HIPRI; - if (ifl & IOCB_DSYNC) - flags |= RWF_DSYNC; - if (ifl & IOCB_SYNC) - flags |= RWF_SYNC; - - return flags; -} - static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req) { struct kiocb *iocb = &aio_req->iocb; @@ -299,7 +285,8 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter) old_cred = ovl_override_creds(file_inode(file)->i_sb); if (is_sync_kiocb(iocb)) { ret = vfs_iter_read(real.file, iter, &iocb->ki_pos, - ovl_iocb_to_rwf(iocb->ki_flags)); + iocb_to_rw_flags(iocb->ki_flags, + OVL_IOCB_MASK)); } else { struct ovl_aio_req *aio_req; @@ -356,7 +343,7 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) if (is_sync_kiocb(iocb)) { file_start_write(real.file); ret = vfs_iter_write(real.file, iter, &iocb->ki_pos, - ovl_iocb_to_rwf(ifl)); + iocb_to_rw_flags(ifl, OVL_IOCB_MASK)); file_end_write(real.file); /* Update size */ ovl_copyattr(ovl_inode_real(inode), inode); diff --git a/include/linux/fs.h b/include/linux/fs.h index fd47deea7c17..647c35423545 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3275,6 +3275,11 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t flags) return 0; } +static inline rwf_t iocb_to_rw_flags(int ifl, int iocb_mask) +{ + return ifl & iocb_mask; +} + static inline ino_t parent_ino(struct dentry *dentry) { ino_t res; From patchwork Mon Jan 25 15:30:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alessio Balsini X-Patchwork-Id: 12043641 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 246EDC433E0 for ; Mon, 25 Jan 2021 15:42:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D3475230FA for ; Mon, 25 Jan 2021 15:42:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730243AbhAYPmT (ORCPT ); Mon, 25 Jan 2021 10:42:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60410 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730207AbhAYPmB (ORCPT ); Mon, 25 Jan 2021 10:42:01 -0500 Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9FFC2C061A2D for ; Mon, 25 Jan 2021 07:31:10 -0800 (PST) Received: by mail-wm1-x331.google.com with SMTP id e15so11469716wme.0 for ; Mon, 25 Jan 2021 07:31:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=android.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=iwpIKZJEqgcyH9jTEkHY/oqU7zr1rLx1xK5r1q299wU=; b=M5mY7gcIWm30rHRLFfpJ6dVKIbqVpY567QMlr+38KgnT63CeaQnTw5jMWuzyX5Ue78 FXAAWtbuJX7k3a0w1/3gqITeZIjPn1WBnFrAhx3NF3sFhgiPs/rsah2Smt4Ux8jAMiMr OWJWrXDyfFjJOk+iCDJviGaBVc6zTTyQDdhTX5AYdNw9+j/AsKMiBXVUSuyHzt1k+PSe 4F66kv3CX8hEme1SqkXYXX2Oym13u8YKvbfDI9df8QdPYwxowcZG6VNKFhhdZniKNvRI xOM84w8hekDeXCS+otrcssbVpw8d3eH1Os42KAYdwVIYybE/T30cJKino7oY2KNHJg4h RBCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=iwpIKZJEqgcyH9jTEkHY/oqU7zr1rLx1xK5r1q299wU=; b=NBcLXYM1dn/48h5/kbdJEENz9ikDowjqfSseRTsGtCAArlbC7VTkH43Po4f0ZDoqYs fegbCfO0EnqLxpPkqvCh4T+ZOjc9p30Gk97uYzIKYwdHtCIJMeeIMMaq85mZILtIpAHO heKv9czcUr6OhoJhofcSz6x4xKmdA7dlVCOcx49Ms1+PLPNvnagidSqYKB6H7KOjWUUo yFRhUzzdSKUn7u2Ut/NnCL8g4dyrOF2m4MxXYK/MMJzFxiYK3NvtSXEQ8NhvGCvQqrRz LwlsBklNYoWmVxE/NzKksxhWW38SiOKsl7jsWxwB8hMbsZOanoGSYu6AD2/xBCgtfqnR Lk1A== X-Gm-Message-State: AOAM5336CIDm0UZGY6BVn1Qi4AMHsyESomHfdVc2PqZWCd28sKlWQSFy HZSDbS8fZo+s8SQavTN/5hidRQ== X-Google-Smtp-Source: ABdhPJx3VC0jelypwqOAnjslGn7yu3b7OKbCzFWEs1qu6YAjEOp2s1YkzSYOzf11YVv3sUG7XqmzYg== X-Received: by 2002:a7b:ca4c:: with SMTP id m12mr638086wml.115.1611588669362; Mon, 25 Jan 2021 07:31:09 -0800 (PST) Received: from balsini.lon.corp.google.com ([2a00:79e0:d:210:4cd4:5994:40fe:253d]) by smtp.gmail.com with ESMTPSA id o14sm22611965wri.48.2021.01.25.07.31.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 07:31:08 -0800 (PST) From: Alessio Balsini To: Miklos Szeredi Cc: Akilesh Kailash , Amir Goldstein , Antonio SJ Musumeci , David Anderson , Giuseppe Scrivano , Jann Horn , Jens Axboe , Martijn Coenen , Palmer Dabbelt , Paul Lawrence , Peng Tao , Stefano Duo , Zimuzo Ezeozue , wuyan , fuse-devel@lists.sourceforge.net, kernel-team@android.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH RESEND V12 2/8] fuse: 32-bit user space ioctl compat for fuse device Date: Mon, 25 Jan 2021 15:30:51 +0000 Message-Id: <20210125153057.3623715-3-balsini@android.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog In-Reply-To: <20210125153057.3623715-1-balsini@android.com> References: <20210125153057.3623715-1-balsini@android.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org With a 64-bit kernel build the FUSE device cannot handle ioctl requests coming from 32-bit user space. This is due to the ioctl command translation that generates different command identifiers that thus cannot be used for direct comparisons without proper manipulation. Explicitly extract type and number from the ioctl command to enable 32-bit user space compatibility on 64-bit kernel builds. Signed-off-by: Alessio Balsini --- fs/fuse/dev.c | 29 ++++++++++++++++++----------- include/uapi/linux/fuse.h | 3 ++- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 588f8d1240aa..ff9f3b83f879 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2233,37 +2233,44 @@ static int fuse_device_clone(struct fuse_conn *fc, struct file *new) static long fuse_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int err = -ENOTTY; + int res; + int oldfd; + struct fuse_dev *fud = NULL; - if (cmd == FUSE_DEV_IOC_CLONE) { - int oldfd; + if (_IOC_TYPE(cmd) != FUSE_DEV_IOC_MAGIC) + return -EINVAL; - err = -EFAULT; - if (!get_user(oldfd, (__u32 __user *) arg)) { + switch (_IOC_NR(cmd)) { + case _IOC_NR(FUSE_DEV_IOC_CLONE): + res = -EFAULT; + if (!get_user(oldfd, (__u32 __user *)arg)) { struct file *old = fget(oldfd); - err = -EINVAL; + res = -EINVAL; if (old) { - struct fuse_dev *fud = NULL; - /* * Check against file->f_op because CUSE * uses the same ioctl handler. */ if (old->f_op == file->f_op && - old->f_cred->user_ns == file->f_cred->user_ns) + old->f_cred->user_ns == + file->f_cred->user_ns) fud = fuse_get_dev(old); if (fud) { mutex_lock(&fuse_mutex); - err = fuse_device_clone(fud->fc, file); + res = fuse_device_clone(fud->fc, file); mutex_unlock(&fuse_mutex); } fput(old); } } + break; + default: + res = -ENOTTY; + break; } - return err; + return res; } const struct file_operations fuse_dev_operations = { diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 98ca64d1beb6..54442612c48b 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -903,7 +903,8 @@ struct fuse_notify_retrieve_in { }; /* Device ioctls: */ -#define FUSE_DEV_IOC_CLONE _IOR(229, 0, uint32_t) +#define FUSE_DEV_IOC_MAGIC 229 +#define FUSE_DEV_IOC_CLONE _IOR(FUSE_DEV_IOC_MAGIC, 0, uint32_t) struct fuse_lseek_in { uint64_t fh; From patchwork Mon Jan 25 15:30:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alessio Balsini X-Patchwork-Id: 12048241 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8A2B9C433E0 for ; Tue, 26 Jan 2021 20:11:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2E38E22241 for ; Tue, 26 Jan 2021 20:11:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732671AbhAZFZn (ORCPT ); Tue, 26 Jan 2021 00:25:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60412 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730265AbhAYPmq (ORCPT ); Mon, 25 Jan 2021 10:42:46 -0500 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 75D3DC061A31 for ; Mon, 25 Jan 2021 07:31:11 -0800 (PST) Received: by mail-wr1-x429.google.com with SMTP id v15so13044200wrx.4 for ; Mon, 25 Jan 2021 07:31:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=android.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ct9PhrrOuETu1TZRiUnqvRkBgYvkOjSl9yA+Mh+fZkE=; b=d93RGymDI8SrwfWZ4+U5KGIE4ej0/9iOF0WtM9yKr4V7dIpUSnPusH7FkaZQhX7Ups mYy1EnkZLM//7ewHBRPVfs1yhMGkkfmcjuqtr6BXiavq7nGS0Pv7mWYhQHQCKr6hy1yO 7T1h95Sx+qCZ7ozjVWfuXiaLAHrC8J/hf+3TMkXDSziP+mdR1IgqgA1AC+95uRnGoUjr ZS0u9z50PXmREzCKKEmxTJrJ34lv2X755Y4B+YKjYIOC4ywF828bD5sD56xIyqVo9Q4a sXoZPnU0lY1IVMB+VTU59sh7QDk7RFL9qbr63yQErpcNFkANlovu/ys+yvj8pgTyT7/P qf2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ct9PhrrOuETu1TZRiUnqvRkBgYvkOjSl9yA+Mh+fZkE=; b=OG7zPEeqfRw1mRIXFHfZXlu/7ybeLmmzCYZTeub8iYKYoKTRd1V3LFrjkTppxeiise hILqXPBlgkN/AjQNL3fVnMyRS8oTN10kr7tG01Z2nw5OVAoowswU/GnxmW0JKLzOpvtk 4fEIMTGyzz5qrrH/WjTjmSroSTxW2fyi9JN6UjT6x+tw0hx90ZWyNn14BCSA3CPEE9Rq HVvtayFVQOaPhZKwexOTSHkfMKcFYe+kgZclMb46Y3B8kstqiqJ7Zctn+neQXlIIuA7w 1ZMo4WVIhhgQHyu+qatExfxOtkI9e3+laWFRy6FmiknrP48gJtWGtJTvP+Po7aMKfu86 VNSQ== X-Gm-Message-State: AOAM530nfPDxFyg0+lxsHaKA2Iz3YuFDqxLYEJ085gWqSL2BdDWSs9QX o53HAZF1OzB6e6OGH3WfH37wwQ== X-Google-Smtp-Source: ABdhPJyz4iM1784q2nVRJNfNeVWmWxr+WW51+AFKTN/cIcbKerVTBQT95wRgvmKp2wxuqlvic2XoLA== X-Received: by 2002:adf:8b41:: with SMTP id v1mr1592261wra.282.1611588670233; Mon, 25 Jan 2021 07:31:10 -0800 (PST) Received: from balsini.lon.corp.google.com ([2a00:79e0:d:210:4cd4:5994:40fe:253d]) by smtp.gmail.com with ESMTPSA id o14sm22611965wri.48.2021.01.25.07.31.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 07:31:09 -0800 (PST) From: Alessio Balsini To: Miklos Szeredi Cc: Akilesh Kailash , Amir Goldstein , Antonio SJ Musumeci , David Anderson , Giuseppe Scrivano , Jann Horn , Jens Axboe , Martijn Coenen , Palmer Dabbelt , Paul Lawrence , Peng Tao , Stefano Duo , Zimuzo Ezeozue , wuyan , fuse-devel@lists.sourceforge.net, kernel-team@android.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH RESEND V12 3/8] fuse: Definitions and ioctl for passthrough Date: Mon, 25 Jan 2021 15:30:52 +0000 Message-Id: <20210125153057.3623715-4-balsini@android.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog In-Reply-To: <20210125153057.3623715-1-balsini@android.com> References: <20210125153057.3623715-1-balsini@android.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Expose the FUSE_PASSTHROUGH interface to user space and declare all the basic data structures and functions as the skeleton on top of which the FUSE passthrough functionality will be built. As part of this, introduce the new FUSE passthrough ioctl, which allows the FUSE daemon to specify a direct connection between a FUSE file and a lower file system file. Such ioctl requires user space to pass the file descriptor of one of its opened files through the fuse_passthrough_out data structure introduced in this patch. This structure includes extra fields for possible future extensions. Also, add the passthrough functions for the set-up and tear-down of the data structures and locks that will be used both when fuse_conns and fuse_files are created/deleted. Signed-off-by: Alessio Balsini --- fs/fuse/Makefile | 1 + fs/fuse/dev.c | 12 ++++++++++++ fs/fuse/dir.c | 2 ++ fs/fuse/file.c | 4 +++- fs/fuse/fuse_i.h | 27 +++++++++++++++++++++++++++ fs/fuse/inode.c | 17 ++++++++++++++++- fs/fuse/passthrough.c | 21 +++++++++++++++++++++ include/uapi/linux/fuse.h | 11 ++++++++++- 8 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 fs/fuse/passthrough.c diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile index 8c7021fb2cd4..20ed23aa16fa 100644 --- a/fs/fuse/Makefile +++ b/fs/fuse/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_CUSE) += cuse.o obj-$(CONFIG_VIRTIO_FS) += virtiofs.o fuse-y := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o +fuse-y += passthrough.o fuse-$(CONFIG_FUSE_DAX) += dax.o virtiofs-y := virtio_fs.o diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index ff9f3b83f879..5446f13db5a0 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2236,6 +2236,7 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd, int res; int oldfd; struct fuse_dev *fud = NULL; + struct fuse_passthrough_out pto; if (_IOC_TYPE(cmd) != FUSE_DEV_IOC_MAGIC) return -EINVAL; @@ -2266,6 +2267,17 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd, } } break; + case _IOC_NR(FUSE_DEV_IOC_PASSTHROUGH_OPEN): + res = -EFAULT; + if (!copy_from_user(&pto, + (struct fuse_passthrough_out __user *)arg, + sizeof(pto))) { + res = -EINVAL; + fud = fuse_get_dev(file); + if (fud) + res = fuse_passthrough_open(fud, &pto); + } + break; default: res = -ENOTTY; break; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 78f9f209078c..c9a1b33c5481 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -513,6 +513,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, { int err; struct inode *inode; + struct fuse_conn *fc = get_fuse_conn(dir); struct fuse_mount *fm = get_fuse_mount(dir); FUSE_ARGS(args); struct fuse_forget_link *forget; @@ -574,6 +575,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, ff->fh = outopen.fh; ff->nodeid = outentry.nodeid; ff->open_flags = outopen.open_flags; + fuse_passthrough_setup(fc, ff, &outopen); inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, &outentry.attr, entry_attr_timeout(&outentry), 0); if (!inode) { diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 8cccecb55fb8..953f3034c375 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -158,7 +158,7 @@ int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, if (!err) { ff->fh = outarg.fh; ff->open_flags = outarg.open_flags; - + fuse_passthrough_setup(fc, ff, &outarg); } else if (err != -ENOSYS) { fuse_file_free(ff); return err; @@ -304,6 +304,8 @@ void fuse_release_common(struct file *file, bool isdir) struct fuse_release_args *ra = ff->release_args; int opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; + fuse_passthrough_release(&ff->passthrough); + fuse_prepare_release(fi, ff, file->f_flags, opcode); if (ff->flock) { diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 7c4b8cb93f9f..8d39f5304a11 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -180,6 +180,14 @@ struct fuse_conn; struct fuse_mount; struct fuse_release_args; +/** + * Reference to lower filesystem file for read/write operations handled in + * passthrough mode + */ +struct fuse_passthrough { + struct file *filp; +}; + /** FUSE specific file data */ struct fuse_file { /** Fuse connection for this file */ @@ -225,6 +233,9 @@ struct fuse_file { } readdir; + /** Container for data related to the passthrough functionality */ + struct fuse_passthrough passthrough; + /** RB node to be linked on fuse_conn->polled_files */ struct rb_node polled_node; @@ -755,6 +766,9 @@ struct fuse_conn { /* Auto-mount submounts announced by the server */ unsigned int auto_submounts:1; + /** Passthrough mode for read/write IO */ + unsigned int passthrough:1; + /** The number of requests waiting for completion */ atomic_t num_waiting; @@ -798,6 +812,12 @@ struct fuse_conn { /** List of filesystems using this connection */ struct list_head mounts; + + /** IDR for passthrough requests */ + struct idr passthrough_req; + + /** Protects passthrough_req */ + spinlock_t passthrough_req_lock; }; /* @@ -1213,4 +1233,11 @@ void fuse_dax_inode_cleanup(struct inode *inode); bool fuse_dax_check_alignment(struct fuse_conn *fc, unsigned int map_alignment); void fuse_dax_cancel_work(struct fuse_conn *fc); +/* passthrough.c */ +int fuse_passthrough_open(struct fuse_dev *fud, + struct fuse_passthrough_out *pto); +int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, + struct fuse_open_out *openarg); +void fuse_passthrough_release(struct fuse_passthrough *passthrough); + #endif /* _FS_FUSE_I_H */ diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index b0e18b470e91..a1104d5abb70 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -691,6 +691,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm, memset(fc, 0, sizeof(*fc)); spin_lock_init(&fc->lock); spin_lock_init(&fc->bg_lock); + spin_lock_init(&fc->passthrough_req_lock); init_rwsem(&fc->killsb); refcount_set(&fc->count, 1); atomic_set(&fc->dev_count, 1); @@ -699,6 +700,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm, INIT_LIST_HEAD(&fc->bg_queue); INIT_LIST_HEAD(&fc->entry); INIT_LIST_HEAD(&fc->devices); + idr_init(&fc->passthrough_req); atomic_set(&fc->num_waiting, 0); fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; @@ -1052,6 +1054,12 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args, fc->handle_killpriv_v2 = 1; fm->sb->s_flags |= SB_NOSEC; } + if (arg->flags & FUSE_PASSTHROUGH) { + fc->passthrough = 1; + /* Prevent further stacking */ + fm->sb->s_stack_depth = + FILESYSTEM_MAX_STACK_DEPTH; + } } else { ra_pages = fc->max_read / PAGE_SIZE; fc->no_lock = 1; @@ -1095,7 +1103,7 @@ void fuse_send_init(struct fuse_mount *fm) FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL | FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS | FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA | - FUSE_HANDLE_KILLPRIV_V2; + FUSE_HANDLE_KILLPRIV_V2 | FUSE_PASSTHROUGH; #ifdef CONFIG_FUSE_DAX if (fm->fc->dax) ia->in.flags |= FUSE_MAP_ALIGNMENT; @@ -1123,9 +1131,16 @@ void fuse_send_init(struct fuse_mount *fm) } EXPORT_SYMBOL_GPL(fuse_send_init); +static int free_fuse_passthrough(int id, void *p, void *data) +{ + return 0; +} + void fuse_free_conn(struct fuse_conn *fc) { WARN_ON(!list_empty(&fc->devices)); + idr_for_each(&fc->passthrough_req, free_fuse_passthrough, NULL); + idr_destroy(&fc->passthrough_req); kfree_rcu(fc, rcu); } EXPORT_SYMBOL_GPL(fuse_free_conn); diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c new file mode 100644 index 000000000000..594060c654f8 --- /dev/null +++ b/fs/fuse/passthrough.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "fuse_i.h" + +#include + +int fuse_passthrough_open(struct fuse_dev *fud, + struct fuse_passthrough_out *pto) +{ + return -EINVAL; +} + +int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, + struct fuse_open_out *openarg) +{ + return -EINVAL; +} + +void fuse_passthrough_release(struct fuse_passthrough *passthrough) +{ +} diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 54442612c48b..9d7685ce0acd 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -360,6 +360,7 @@ struct fuse_file_lock { #define FUSE_MAP_ALIGNMENT (1 << 26) #define FUSE_SUBMOUNTS (1 << 27) #define FUSE_HANDLE_KILLPRIV_V2 (1 << 28) +#define FUSE_PASSTHROUGH (1 << 29) /** * CUSE INIT request/reply flags @@ -625,7 +626,7 @@ struct fuse_create_in { struct fuse_open_out { uint64_t fh; uint32_t open_flags; - uint32_t padding; + uint32_t passthrough_fh; }; struct fuse_release_in { @@ -828,6 +829,13 @@ struct fuse_in_header { uint32_t padding; }; +struct fuse_passthrough_out { + uint32_t fd; + /* For future implementation */ + uint32_t len; + void *vec; +}; + struct fuse_out_header { uint32_t len; int32_t error; @@ -905,6 +913,7 @@ struct fuse_notify_retrieve_in { /* Device ioctls: */ #define FUSE_DEV_IOC_MAGIC 229 #define FUSE_DEV_IOC_CLONE _IOR(FUSE_DEV_IOC_MAGIC, 0, uint32_t) +#define FUSE_DEV_IOC_PASSTHROUGH_OPEN _IOW(FUSE_DEV_IOC_MAGIC, 1, struct fuse_passthrough_out) struct fuse_lseek_in { uint64_t fh; From patchwork Mon Jan 25 15:30:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alessio Balsini X-Patchwork-Id: 12045341 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 26301C433DB for ; Tue, 26 Jan 2021 05:25:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id ED85722795 for ; Tue, 26 Jan 2021 05:25:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730577AbhAZFZU (ORCPT ); Tue, 26 Jan 2021 00:25:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60602 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730252AbhAYPmb (ORCPT ); Mon, 25 Jan 2021 10:42:31 -0500 Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 68A25C0610D6 for ; Mon, 25 Jan 2021 07:31:12 -0800 (PST) Received: by mail-wm1-x32d.google.com with SMTP id y187so11474575wmd.3 for ; Mon, 25 Jan 2021 07:31:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=android.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=K33/kOxBcJ35u0ayW/ijJxNjK4mLraYNnDTliI6dnXg=; b=kEj9BGL5vLSacxvqiOxwxcXXj8ycWN/r3TCV1Hwysj38wWty0mJygofEQqWU26ui1M nSiKhu2j2W8JnvD8/P9Fecc8f6MmDioumRGUsVD1hlExvJ18kILVeqHFfiSrxVrXceUC EipXBOeNwHRtCdrckg8JGa2BqXsxzlX4awNOH25pPAbcE2zjU8E+9u12SERC+BBCWFkh DorvOEgbrys+KXkZ5Wm8YAqfPdg6tU76o0PRXGTCzJgC1lQbI0kVc9D5NO18BMN9oqPg U1VNlFw/T1jB79L7fD2O1y0zh5XwdnI7Zg8Hlf27ZtuOLoff0e0s6OWsM6D8AJpYwowe mJSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=K33/kOxBcJ35u0ayW/ijJxNjK4mLraYNnDTliI6dnXg=; b=lPVXUDoXjAcidhGG+gbWwJ+cQr01vs940XgzlpZS2EaCS1/gbb/JZenXb7B4g+bzYI 1afEcW6Odd4Hn1Vu2z4dtBJbTjSxjyza6VnKSdc+LphrTVkp43yBiArzWkTREDwnnVBp 2FuOhY6O7lFJsMHDTqp2wU1k1CKZrfeLC5p3Wn9aXh3feOtAw/cliC/d6gda5+qrYo5r azjNTVZqoJrUAT0PXap2yRr7GEMEGrRptrMaY7uCja60HmUzJ1HUAiLH3/hneKaY3ens F1PlU8e76BMkizDhasb3kOFOD97NqoxXL0sxVP15zF0R+JKVw49ZG24jHHvXkgyj6c6j 9CNg== X-Gm-Message-State: AOAM532pcKGKUjkWpYRmb/zIcX6iPf96lpcRR7bK5Q7mAI3ctq8mU13F UhAAjcukG+ry9eb6qXO7OM2CBw== X-Google-Smtp-Source: ABdhPJxl8xZzl0+FEyNEX1aEMDptA5wDn7nR38epMj7SLt7Ns8ljT/fbQdKsorC/hddSaYL8bPtaZQ== X-Received: by 2002:a7b:c942:: with SMTP id i2mr642875wml.51.1611588671158; Mon, 25 Jan 2021 07:31:11 -0800 (PST) Received: from balsini.lon.corp.google.com ([2a00:79e0:d:210:4cd4:5994:40fe:253d]) by smtp.gmail.com with ESMTPSA id o14sm22611965wri.48.2021.01.25.07.31.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 07:31:10 -0800 (PST) From: Alessio Balsini To: Miklos Szeredi Cc: Akilesh Kailash , Amir Goldstein , Antonio SJ Musumeci , David Anderson , Giuseppe Scrivano , Jann Horn , Jens Axboe , Martijn Coenen , Palmer Dabbelt , Paul Lawrence , Peng Tao , Stefano Duo , Zimuzo Ezeozue , wuyan , fuse-devel@lists.sourceforge.net, kernel-team@android.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH RESEND V12 4/8] fuse: Passthrough initialization and release Date: Mon, 25 Jan 2021 15:30:53 +0000 Message-Id: <20210125153057.3623715-5-balsini@android.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog In-Reply-To: <20210125153057.3623715-1-balsini@android.com> References: <20210125153057.3623715-1-balsini@android.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Implement the FUSE passthrough ioctl that associates the lower (passthrough) file system file with the fuse_file. The file descriptor passed to the ioctl by the FUSE daemon is used to access the relative file pointer, that will be copied to the fuse_file data structure to consolidate the link between the FUSE and lower file system. To enable the passthrough mode, user space triggers the FUSE_DEV_IOC_PASSTHROUGH_OPEN ioctl and, if the call succeeds, receives back an identifier that will be used at open/create response time in the fuse_open_out field to associate the FUSE file to the lower file system file. The value returned by the ioctl to user space can be: - > 0: success, the identifier can be used as part of an open/create reply. - <= 0: an error occurred. The value 0 represents an error to preserve backward compatibility: the fuse_open_out field that is used to pass the passthrough_fh back to the kernel uses the same bits that were previously as struct padding, and is commonly zero-initialized (e.g., in the libfuse implementation). Removing 0 from the correct values fixes the ambiguity between the case in which 0 corresponds to a real passthrough_fh, a missing implementation of FUSE passthrough or a request for a normal FUSE file, simplifying the user space implementation. For the passthrough mode to be successfully activated, the lower file system file must implement both read_iter and write_iter file operations. This extra check avoids special pseudo files to be targeted for this feature. Passthrough comes with another limitation: no further file system stacking is allowed for those FUSE file systems using passthrough. Signed-off-by: Alessio Balsini --- fs/fuse/inode.c | 5 +++ fs/fuse/passthrough.c | 87 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index a1104d5abb70..7ebc398fbacb 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -1133,6 +1133,11 @@ EXPORT_SYMBOL_GPL(fuse_send_init); static int free_fuse_passthrough(int id, void *p, void *data) { + struct fuse_passthrough *passthrough = (struct fuse_passthrough *)p; + + fuse_passthrough_release(passthrough); + kfree(p); + return 0; } diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index 594060c654f8..cf993e83803e 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -3,19 +3,102 @@ #include "fuse_i.h" #include +#include int fuse_passthrough_open(struct fuse_dev *fud, struct fuse_passthrough_out *pto) { - return -EINVAL; + int res; + struct file *passthrough_filp; + struct fuse_conn *fc = fud->fc; + struct inode *passthrough_inode; + struct super_block *passthrough_sb; + struct fuse_passthrough *passthrough; + + if (!fc->passthrough) + return -EPERM; + + /* This field is reserved for future implementation */ + if (pto->len != 0) + return -EINVAL; + + passthrough_filp = fget(pto->fd); + if (!passthrough_filp) { + pr_err("FUSE: invalid file descriptor for passthrough.\n"); + return -EBADF; + } + + if (!passthrough_filp->f_op->read_iter || + !passthrough_filp->f_op->write_iter) { + pr_err("FUSE: passthrough file misses file operations.\n"); + res = -EBADF; + goto err_free_file; + } + + passthrough_inode = file_inode(passthrough_filp); + passthrough_sb = passthrough_inode->i_sb; + if (passthrough_sb->s_stack_depth >= FILESYSTEM_MAX_STACK_DEPTH) { + pr_err("FUSE: fs stacking depth exceeded for passthrough\n"); + res = -EINVAL; + goto err_free_file; + } + + passthrough = kmalloc(sizeof(struct fuse_passthrough), GFP_KERNEL); + if (!passthrough) { + res = -ENOMEM; + goto err_free_file; + } + + passthrough->filp = passthrough_filp; + + idr_preload(GFP_KERNEL); + spin_lock(&fc->passthrough_req_lock); + res = idr_alloc(&fc->passthrough_req, passthrough, 1, 0, GFP_ATOMIC); + spin_unlock(&fc->passthrough_req_lock); + idr_preload_end(); + + if (res > 0) + return res; + + fuse_passthrough_release(passthrough); + kfree(passthrough); + +err_free_file: + fput(passthrough_filp); + + return res; } int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, struct fuse_open_out *openarg) { - return -EINVAL; + struct fuse_passthrough *passthrough; + int passthrough_fh = openarg->passthrough_fh; + + if (!fc->passthrough) + return -EPERM; + + /* Default case, passthrough is not requested */ + if (passthrough_fh <= 0) + return -EINVAL; + + spin_lock(&fc->passthrough_req_lock); + passthrough = idr_remove(&fc->passthrough_req, passthrough_fh); + spin_unlock(&fc->passthrough_req_lock); + + if (!passthrough) + return -EINVAL; + + ff->passthrough = *passthrough; + kfree(passthrough); + + return 0; } void fuse_passthrough_release(struct fuse_passthrough *passthrough) { + if (passthrough->filp) { + fput(passthrough->filp); + passthrough->filp = NULL; + } } From patchwork Mon Jan 25 15:30:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alessio Balsini X-Patchwork-Id: 12045343 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6911DC433E6 for ; Tue, 26 Jan 2021 05:25:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 40E4C206F7 for ; Tue, 26 Jan 2021 05:25:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732040AbhAZFZ1 (ORCPT ); Tue, 26 Jan 2021 00:25:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730253AbhAYPmb (ORCPT ); Mon, 25 Jan 2021 10:42:31 -0500 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6410BC061BD1 for ; Mon, 25 Jan 2021 07:31:13 -0800 (PST) Received: by mail-wr1-x429.google.com with SMTP id a9so13051856wrt.5 for ; Mon, 25 Jan 2021 07:31:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=android.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=czRDsr9ZveGlA8Lh9Z/2Mcsvya5PJVoy03eWuT8s21A=; b=Nc7odzg9UfBt9Cztyn7oJXUuGuEaPINkh4HcF8tCwL6QydMJTw2bmDU18RP2eOhhfw ePgjf3pmTG4MpLsKkntdB/KkguZ5V8AEK3F/hVhEzxkD+9MYckgjKpbPyGGTXU50PV4c E93p427a15/+JjVI3J5lppYDaKZhg9X2eJ9b3wqC2WIMcsUopruusKcBT3rzagEZ/8dd JF14cHgqdQMwp3QCnGmkWzRC/tVyfIdi3pd5yycPwcnWNwOASenr21U2u8o8+Q729+hf zGYb22YwmOOafGvfRwM882pHOVBY6+XER5CMGcBz75hLYQ8BhB5FKmyOTFzH8iuHgQi7 4dpg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=czRDsr9ZveGlA8Lh9Z/2Mcsvya5PJVoy03eWuT8s21A=; b=tZk5bVaV+GDYTKO6yP48RUCXzCi/xJ3n3oBYP2OL9KbvDqFQs4JxggH6rF5uZEPNWc pWQAzs0FAtDRIz2axUxn5EUnrm7Hb7PesMknnnyK/tmoQBWmGYEVXK/ilwH35k+iPgxT rNQqWOUPKQvpu+NB58anWpcwql/vFUimWG46NK7el/Mg86B2H/2CWasmrVDb6DBG3U7L qwPvfbh66jT08qbbZZOCy5VImlJ2iljZQG96GrGUcuro8u8WdQO7rozQnl6RGmroVyFa pwj5bUly/65swfBxAHlAbM4QM4uwjyLjvTFsGfPsAGsGtXDT8QW7GYSN3ETdvUaNmEby iUPQ== X-Gm-Message-State: AOAM5316W5c40+Jd0Mm5ro/pgTxWidJHxKtzL171kPHyJQfKT+C48EbZ Y2DocgHDD+ZqKmlbrHF4ml/jWw== X-Google-Smtp-Source: ABdhPJxRalGgtsXNqfUpShWnl29ttfx4tBQRgzfNHdPdlZQBfdjgX6kBkwceyp+jLPxO4iLmohi6HQ== X-Received: by 2002:adf:b78d:: with SMTP id s13mr1611637wre.344.1611588672186; Mon, 25 Jan 2021 07:31:12 -0800 (PST) Received: from balsini.lon.corp.google.com ([2a00:79e0:d:210:4cd4:5994:40fe:253d]) by smtp.gmail.com with ESMTPSA id o14sm22611965wri.48.2021.01.25.07.31.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 07:31:11 -0800 (PST) From: Alessio Balsini To: Miklos Szeredi Cc: Akilesh Kailash , Amir Goldstein , Antonio SJ Musumeci , David Anderson , Giuseppe Scrivano , Jann Horn , Jens Axboe , Martijn Coenen , Palmer Dabbelt , Paul Lawrence , Peng Tao , Stefano Duo , Zimuzo Ezeozue , wuyan , fuse-devel@lists.sourceforge.net, kernel-team@android.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH RESEND V12 5/8] fuse: Introduce synchronous read and write for passthrough Date: Mon, 25 Jan 2021 15:30:54 +0000 Message-Id: <20210125153057.3623715-6-balsini@android.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog In-Reply-To: <20210125153057.3623715-1-balsini@android.com> References: <20210125153057.3623715-1-balsini@android.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org All the read and write operations performed on fuse_files which have the passthrough feature enabled are forwarded to the associated lower file system file via VFS. Sending the request directly to the lower file system avoids the userspace round-trip that, because of possible context switches and additional operations might reduce the overall performance, especially in those cases where caching doesn't help, for example in reads at random offsets. Verifying if a fuse_file has a lower file system file associated with can be done by checking the validity of its passthrough_filp pointer. This pointer is not NULL only if passthrough has been successfully enabled via the appropriate ioctl(). When a read/write operation is requested for a FUSE file with passthrough enabled, a new equivalent VFS request is generated, which instead targets the lower file system file. The VFS layer performs additional checks that allow for safer operations but may cause the operation to fail if the process accessing the FUSE file system does not have access to the lower file system. This change only implements synchronous requests in passthrough, returning an error in the case of asynchronous operations, yet covering the majority of the use cases. Signed-off-by: Alessio Balsini --- fs/fuse/file.c | 8 ++++-- fs/fuse/fuse_i.h | 2 ++ fs/fuse/passthrough.c | 57 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 953f3034c375..cddada1e8bd9 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1581,7 +1581,9 @@ static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) if (FUSE_IS_DAX(inode)) return fuse_dax_read_iter(iocb, to); - if (!(ff->open_flags & FOPEN_DIRECT_IO)) + if (ff->passthrough.filp) + return fuse_passthrough_read_iter(iocb, to); + else if (!(ff->open_flags & FOPEN_DIRECT_IO)) return fuse_cache_read_iter(iocb, to); else return fuse_direct_read_iter(iocb, to); @@ -1599,7 +1601,9 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) if (FUSE_IS_DAX(inode)) return fuse_dax_write_iter(iocb, from); - if (!(ff->open_flags & FOPEN_DIRECT_IO)) + if (ff->passthrough.filp) + return fuse_passthrough_write_iter(iocb, from); + else if (!(ff->open_flags & FOPEN_DIRECT_IO)) return fuse_cache_write_iter(iocb, from); else return fuse_direct_write_iter(iocb, from); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 8d39f5304a11..c4730d893324 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1239,5 +1239,7 @@ int fuse_passthrough_open(struct fuse_dev *fud, int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, struct fuse_open_out *openarg); void fuse_passthrough_release(struct fuse_passthrough *passthrough); +ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *to); +ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, struct iov_iter *from); #endif /* _FS_FUSE_I_H */ diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index cf993e83803e..d949ca07a83b 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -4,6 +4,63 @@ #include #include +#include + +#define PASSTHROUGH_IOCB_MASK \ + (IOCB_APPEND | IOCB_DSYNC | IOCB_HIPRI | IOCB_NOWAIT | IOCB_SYNC) + +static void fuse_copyattr(struct file *dst_file, struct file *src_file) +{ + struct inode *dst = file_inode(dst_file); + struct inode *src = file_inode(src_file); + + i_size_write(dst, i_size_read(src)); +} + +ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, + struct iov_iter *iter) +{ + ssize_t ret; + struct file *fuse_filp = iocb_fuse->ki_filp; + struct fuse_file *ff = fuse_filp->private_data; + struct file *passthrough_filp = ff->passthrough.filp; + + if (!iov_iter_count(iter)) + return 0; + + ret = vfs_iter_read(passthrough_filp, iter, &iocb_fuse->ki_pos, + iocb_to_rw_flags(iocb_fuse->ki_flags, + PASSTHROUGH_IOCB_MASK)); + + return ret; +} + +ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse, + struct iov_iter *iter) +{ + ssize_t ret; + struct file *fuse_filp = iocb_fuse->ki_filp; + struct fuse_file *ff = fuse_filp->private_data; + struct inode *fuse_inode = file_inode(fuse_filp); + struct file *passthrough_filp = ff->passthrough.filp; + + if (!iov_iter_count(iter)) + return 0; + + inode_lock(fuse_inode); + + file_start_write(passthrough_filp); + ret = vfs_iter_write(passthrough_filp, iter, &iocb_fuse->ki_pos, + iocb_to_rw_flags(iocb_fuse->ki_flags, + PASSTHROUGH_IOCB_MASK)); + file_end_write(passthrough_filp); + if (ret > 0) + fuse_copyattr(fuse_filp, passthrough_filp); + + inode_unlock(fuse_inode); + + return ret; +} int fuse_passthrough_open(struct fuse_dev *fud, struct fuse_passthrough_out *pto) From patchwork Mon Jan 25 15:30:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alessio Balsini X-Patchwork-Id: 12048253 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A40AFC433E6 for ; Tue, 26 Jan 2021 20:12:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 729B622255 for ; Tue, 26 Jan 2021 20:12:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729885AbhAZFZO (ORCPT ); Tue, 26 Jan 2021 00:25:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60358 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730206AbhAYPmM (ORCPT ); Mon, 25 Jan 2021 10:42:12 -0500 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4A0D0C061D73 for ; Mon, 25 Jan 2021 07:31:14 -0800 (PST) Received: by mail-wr1-x42d.google.com with SMTP id b5so13042497wrr.10 for ; Mon, 25 Jan 2021 07:31:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=android.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hvDUp1MzEWxghIK3ZwzGMuRqEDjs1vp2utVl4yg2BMY=; b=ihuQBXJQqcV0KHYVyowgmAWkU5i4M+n8a4Y1xZOwAfNPR/1e34pwStDLhjX0b523ZF B/lpBXGwUbl5fHkkN0+vJo5UzKxluVzrzRl0jB3ffYN8ZkCfj/1OESuBltpZDHvwlpLZ E9uc5mxAC0c/f+V5OlBJCix/DggmtXel5yKDJ5XmKzr3EyaGmBdbSyoPdmk9zoqiJQgr 2uEnt0rP0YnGET8Dg7DJycrVhTN177w0YFu3fHVIymAsckAassNlniCOY9cXbnR47mrH t/hUlTAeaKJLTdPINMFbfBXdczTGtfpO8RzXRRv6h+8oIKOFlu7XBpF/AtGdsogxPmod ovuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hvDUp1MzEWxghIK3ZwzGMuRqEDjs1vp2utVl4yg2BMY=; b=OLvDRbkHNEQsYMsybDlR+JzzLqXk/By+6oMuBSpdGe0jxGtHp/BsmgFXLT+N98cDFf ArkbAj75u8zERaEOinaYT+mI6iAFUViEfGRKb4b1BHRrLHTw4kJFMTFSXmeNoBwbptGl +93Ar6cb2x2UxxHVAVhMi+ZUvX8vzSJkfRlePtUqyjlRbr1m3+rC42BCkkY2cOmNxgpG JUR28RyFmw2CfbyGv72PKpUEleNz4UgFTOOidLzNB9sVIlHQbEbt/z1qWir1sIzxXT84 HN95ctp1y5dFbe3ASvHc7FNdJo27gr0l2DsDB3MHJin50NL8dg1Tqd+tI6TNWW0cbczi eHWA== X-Gm-Message-State: AOAM5316Q39k30xz/R94lE6+oGCIRDuRe46rYb7dY2H0eJojlu0wHfyR iz70xF4qGH/s2dGJJYP+ypLk9A== X-Google-Smtp-Source: ABdhPJzswhyj4Q4ni8SAtO/j8cwjUv2fd1EtXxmMgTyaCO4FiNq4r9s3wF3VYMq6kEMvuP16YtYfig== X-Received: by 2002:a5d:47a2:: with SMTP id 2mr1559520wrb.393.1611588673053; Mon, 25 Jan 2021 07:31:13 -0800 (PST) Received: from balsini.lon.corp.google.com ([2a00:79e0:d:210:4cd4:5994:40fe:253d]) by smtp.gmail.com with ESMTPSA id o14sm22611965wri.48.2021.01.25.07.31.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 07:31:12 -0800 (PST) From: Alessio Balsini To: Miklos Szeredi Cc: Akilesh Kailash , Amir Goldstein , Antonio SJ Musumeci , David Anderson , Giuseppe Scrivano , Jann Horn , Jens Axboe , Martijn Coenen , Palmer Dabbelt , Paul Lawrence , Peng Tao , Stefano Duo , Zimuzo Ezeozue , wuyan , fuse-devel@lists.sourceforge.net, kernel-team@android.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH RESEND V12 6/8] fuse: Handle asynchronous read and write in passthrough Date: Mon, 25 Jan 2021 15:30:55 +0000 Message-Id: <20210125153057.3623715-7-balsini@android.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog In-Reply-To: <20210125153057.3623715-1-balsini@android.com> References: <20210125153057.3623715-1-balsini@android.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Extend the passthrough feature by handling asynchronous IO both for read and write operations. When an AIO request is received, if the request targets a FUSE file with the passthrough functionality enabled, a new identical AIO request is created. The new request targets the lower file system file and gets assigned a special FUSE passthrough AIO completion callback. When the lower file system AIO request is completed, the FUSE passthrough AIO completion callback is executed and propagates the completion signal to the FUSE AIO request by triggering its completion callback as well. Signed-off-by: Alessio Balsini --- fs/fuse/passthrough.c | 89 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 78 insertions(+), 11 deletions(-) diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index d949ca07a83b..c7fa1eeb7639 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -9,6 +9,11 @@ #define PASSTHROUGH_IOCB_MASK \ (IOCB_APPEND | IOCB_DSYNC | IOCB_HIPRI | IOCB_NOWAIT | IOCB_SYNC) +struct fuse_aio_req { + struct kiocb iocb; + struct kiocb *iocb_fuse; +}; + static void fuse_copyattr(struct file *dst_file, struct file *src_file) { struct inode *dst = file_inode(dst_file); @@ -17,6 +22,32 @@ static void fuse_copyattr(struct file *dst_file, struct file *src_file) i_size_write(dst, i_size_read(src)); } +static void fuse_aio_cleanup_handler(struct fuse_aio_req *aio_req) +{ + struct kiocb *iocb = &aio_req->iocb; + struct kiocb *iocb_fuse = aio_req->iocb_fuse; + + if (iocb->ki_flags & IOCB_WRITE) { + __sb_writers_acquired(file_inode(iocb->ki_filp)->i_sb, + SB_FREEZE_WRITE); + file_end_write(iocb->ki_filp); + fuse_copyattr(iocb_fuse->ki_filp, iocb->ki_filp); + } + + iocb_fuse->ki_pos = iocb->ki_pos; + kfree(aio_req); +} + +static void fuse_aio_rw_complete(struct kiocb *iocb, long res, long res2) +{ + struct fuse_aio_req *aio_req = + container_of(iocb, struct fuse_aio_req, iocb); + struct kiocb *iocb_fuse = aio_req->iocb_fuse; + + fuse_aio_cleanup_handler(aio_req); + iocb_fuse->ki_complete(iocb_fuse, res, res2); +} + ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, struct iov_iter *iter) { @@ -28,9 +59,24 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, if (!iov_iter_count(iter)) return 0; - ret = vfs_iter_read(passthrough_filp, iter, &iocb_fuse->ki_pos, - iocb_to_rw_flags(iocb_fuse->ki_flags, - PASSTHROUGH_IOCB_MASK)); + if (is_sync_kiocb(iocb_fuse)) { + ret = vfs_iter_read(passthrough_filp, iter, &iocb_fuse->ki_pos, + iocb_to_rw_flags(iocb_fuse->ki_flags, + PASSTHROUGH_IOCB_MASK)); + } else { + struct fuse_aio_req *aio_req; + + aio_req = kmalloc(sizeof(struct fuse_aio_req), GFP_KERNEL); + if (!aio_req) + return -ENOMEM; + + aio_req->iocb_fuse = iocb_fuse; + kiocb_clone(&aio_req->iocb, iocb_fuse, passthrough_filp); + aio_req->iocb.ki_complete = fuse_aio_rw_complete; + ret = call_read_iter(passthrough_filp, &aio_req->iocb, iter); + if (ret != -EIOCBQUEUED) + fuse_aio_cleanup_handler(aio_req); + } return ret; } @@ -43,20 +89,41 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse, struct fuse_file *ff = fuse_filp->private_data; struct inode *fuse_inode = file_inode(fuse_filp); struct file *passthrough_filp = ff->passthrough.filp; + struct inode *passthrough_inode = file_inode(passthrough_filp); if (!iov_iter_count(iter)) return 0; inode_lock(fuse_inode); - file_start_write(passthrough_filp); - ret = vfs_iter_write(passthrough_filp, iter, &iocb_fuse->ki_pos, - iocb_to_rw_flags(iocb_fuse->ki_flags, - PASSTHROUGH_IOCB_MASK)); - file_end_write(passthrough_filp); - if (ret > 0) - fuse_copyattr(fuse_filp, passthrough_filp); - + if (is_sync_kiocb(iocb_fuse)) { + file_start_write(passthrough_filp); + ret = vfs_iter_write(passthrough_filp, iter, &iocb_fuse->ki_pos, + iocb_to_rw_flags(iocb_fuse->ki_flags, + PASSTHROUGH_IOCB_MASK)); + file_end_write(passthrough_filp); + if (ret > 0) + fuse_copyattr(fuse_filp, passthrough_filp); + } else { + struct fuse_aio_req *aio_req; + + aio_req = kmalloc(sizeof(struct fuse_aio_req), GFP_KERNEL); + if (!aio_req) { + ret = -ENOMEM; + goto out; + } + + file_start_write(passthrough_filp); + __sb_writers_release(passthrough_inode->i_sb, SB_FREEZE_WRITE); + + aio_req->iocb_fuse = iocb_fuse; + kiocb_clone(&aio_req->iocb, iocb_fuse, passthrough_filp); + aio_req->iocb.ki_complete = fuse_aio_rw_complete; + ret = call_write_iter(passthrough_filp, &aio_req->iocb, iter); + if (ret != -EIOCBQUEUED) + fuse_aio_cleanup_handler(aio_req); + } +out: inode_unlock(fuse_inode); return ret; From patchwork Mon Jan 25 15:30:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alessio Balsini X-Patchwork-Id: 12045345 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8EAFFC433DB for ; Tue, 26 Jan 2021 05:25:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 51A0322795 for ; Tue, 26 Jan 2021 05:25:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732663AbhAZFZd (ORCPT ); Tue, 26 Jan 2021 00:25:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60110 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730266AbhAYPmq (ORCPT ); Mon, 25 Jan 2021 10:42:46 -0500 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7508FC061D7E for ; Mon, 25 Jan 2021 07:31:15 -0800 (PST) Received: by mail-wr1-x435.google.com with SMTP id h9so2809225wrr.9 for ; Mon, 25 Jan 2021 07:31:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=android.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fjrWiiLqh1edssFer2OS0Teapj2NvPcckWh8WDNLyEA=; b=oWhB5L/esqbMhycrrJdQL9iT1JQ1LTp9tEFL9i0ANq+EXRgfDiNBLX54aDkOyztVbg 4U0dI7CKNJrA+W/2t8R1AoeykfReDwQyz3mSIoCqHph+up7SeoRoXE+3RAPM/P3BtKrx TH19YLqbzOyZo6O1DD7XZDqeMcBbBrUoebZiXPJtggJV5zBcp6Oo0+Bio3oWPGZWScPE G281PuwBKJSnXRug1of5u8oxG2GMe052y2zFbex8UmpLcM7WVm4HvEb+ScdyUAkW+dqN dKt+BgdTzIcFjm0OyM/eP3fDtiLnYeiuMKU59QplWiBri2X9OdlcYs+mTUmMBHehBR25 RRkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fjrWiiLqh1edssFer2OS0Teapj2NvPcckWh8WDNLyEA=; b=EU5T1sX3/SH3fXQUglBK/AfcLUaqxiNsPf0ZP3n3L+lFNY0cyo4md7jyy/Y9VkTgTl 4Nz0hN7BdWBPF8QZyjpKDS6BOe/x7iG75SrzlHmoudBtUqHQ823eGL3772rNxYjEUqWi FePP4pBIganxPsOI6KEkWYhomGh9/8+0IaMjZtEUwSKSSAxewVuHryyHQh2BBuWwemVe hOrEcVIlDdy8GcWkQEsJYOTrRm3FF4YgTw5H9wZAEfnaYLTDyo8R6/QxVRMeftBVI1iU OaGvyotsVQ7mnwPOBFNTdDCdY6mUgaMeft0tbiQcHm3v9C1D44S/oekR5PgpFN8r3cwP cCxA== X-Gm-Message-State: AOAM533767BEzMMAwSld4D/bD4rn0Esycn7LGclrnsCcEFppw1i0mg0X ECH1xNZ4bIiuf/EZ5UFa4ekt6Q== X-Google-Smtp-Source: ABdhPJycAAEu1hVQ5yB8I2AHNQ9SxcNftCjKV/yAs02OFI9vi+qkpX8D+AfUjFCLxLW6PR8Gku5G7Q== X-Received: by 2002:adf:ecc1:: with SMTP id s1mr1692764wro.146.1611588674162; Mon, 25 Jan 2021 07:31:14 -0800 (PST) Received: from balsini.lon.corp.google.com ([2a00:79e0:d:210:4cd4:5994:40fe:253d]) by smtp.gmail.com with ESMTPSA id o14sm22611965wri.48.2021.01.25.07.31.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 07:31:13 -0800 (PST) From: Alessio Balsini To: Miklos Szeredi Cc: Akilesh Kailash , Amir Goldstein , Antonio SJ Musumeci , David Anderson , Giuseppe Scrivano , Jann Horn , Jens Axboe , Martijn Coenen , Palmer Dabbelt , Paul Lawrence , Peng Tao , Stefano Duo , Zimuzo Ezeozue , wuyan , fuse-devel@lists.sourceforge.net, kernel-team@android.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH RESEND V12 7/8] fuse: Use daemon creds in passthrough mode Date: Mon, 25 Jan 2021 15:30:56 +0000 Message-Id: <20210125153057.3623715-8-balsini@android.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog In-Reply-To: <20210125153057.3623715-1-balsini@android.com> References: <20210125153057.3623715-1-balsini@android.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org When using FUSE passthrough, read/write operations are directly forwarded to the lower file system file through VFS, but there is no guarantee that the process that is triggering the request has the right permissions to access the lower file system. This would cause the read/write access to fail. In passthrough file systems, where the FUSE daemon is responsible for the enforcement of the lower file system access policies, often happens that the process dealing with the FUSE file system doesn't have access to the lower file system. Being the FUSE daemon in charge of implementing the FUSE file operations, that in the case of read/write operations usually simply results in the copy of memory buffers from/to the lower file system respectively, these operations are executed with the FUSE daemon privileges. This patch adds a reference to the FUSE daemon credentials, referenced at FUSE_DEV_IOC_PASSTHROUGH_OPEN ioctl() time so that they can be used to temporarily raise the user credentials when accessing lower file system files in passthrough. The process accessing the FUSE file with passthrough enabled temporarily receives the privileges of the FUSE daemon while performing read/write operations. Similar behavior is implemented in overlayfs. These privileges will be reverted as soon as the IO operation completes. This feature does not provide any higher security privileges to those processes accessing the FUSE file system with passthrough enabled. This is because it is still the FUSE daemon responsible for enabling or not the passthrough feature at file open time, and should enable the feature only after appropriate access policy checks. Signed-off-by: Alessio Balsini Signed-off-by: Alessio Balsini --- fs/fuse/fuse_i.h | 5 ++++- fs/fuse/passthrough.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index c4730d893324..815af1845b16 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -182,10 +182,13 @@ struct fuse_release_args; /** * Reference to lower filesystem file for read/write operations handled in - * passthrough mode + * passthrough mode. + * This struct also tracks the credentials to be used for handling read/write + * operations. */ struct fuse_passthrough { struct file *filp; + struct cred *cred; }; /** FUSE specific file data */ diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index c7fa1eeb7639..24866c5fe7e2 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -52,6 +52,7 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, struct iov_iter *iter) { ssize_t ret; + const struct cred *old_cred; struct file *fuse_filp = iocb_fuse->ki_filp; struct fuse_file *ff = fuse_filp->private_data; struct file *passthrough_filp = ff->passthrough.filp; @@ -59,6 +60,7 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, if (!iov_iter_count(iter)) return 0; + old_cred = override_creds(ff->passthrough.cred); if (is_sync_kiocb(iocb_fuse)) { ret = vfs_iter_read(passthrough_filp, iter, &iocb_fuse->ki_pos, iocb_to_rw_flags(iocb_fuse->ki_flags, @@ -77,6 +79,7 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, if (ret != -EIOCBQUEUED) fuse_aio_cleanup_handler(aio_req); } + revert_creds(old_cred); return ret; } @@ -85,6 +88,7 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse, struct iov_iter *iter) { ssize_t ret; + const struct cred *old_cred; struct file *fuse_filp = iocb_fuse->ki_filp; struct fuse_file *ff = fuse_filp->private_data; struct inode *fuse_inode = file_inode(fuse_filp); @@ -96,6 +100,7 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse, inode_lock(fuse_inode); + old_cred = override_creds(ff->passthrough.cred); if (is_sync_kiocb(iocb_fuse)) { file_start_write(passthrough_filp); ret = vfs_iter_write(passthrough_filp, iter, &iocb_fuse->ki_pos, @@ -124,6 +129,7 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse, fuse_aio_cleanup_handler(aio_req); } out: + revert_creds(old_cred); inode_unlock(fuse_inode); return ret; @@ -174,6 +180,7 @@ int fuse_passthrough_open(struct fuse_dev *fud, } passthrough->filp = passthrough_filp; + passthrough->cred = prepare_creds(); idr_preload(GFP_KERNEL); spin_lock(&fc->passthrough_req_lock); @@ -225,4 +232,8 @@ void fuse_passthrough_release(struct fuse_passthrough *passthrough) fput(passthrough->filp); passthrough->filp = NULL; } + if (passthrough->cred) { + put_cred(passthrough->cred); + passthrough->cred = NULL; + } } From patchwork Mon Jan 25 15:30:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alessio Balsini X-Patchwork-Id: 12043643 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B6EA1C433E9 for ; Mon, 25 Jan 2021 15:43:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7EE6222A84 for ; Mon, 25 Jan 2021 15:43:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730309AbhAYPna (ORCPT ); Mon, 25 Jan 2021 10:43:30 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60656 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730273AbhAYPnB (ORCPT ); Mon, 25 Jan 2021 10:43:01 -0500 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 668F3C061D7F for ; Mon, 25 Jan 2021 07:31:16 -0800 (PST) Received: by mail-wr1-x431.google.com with SMTP id a1so13062504wrq.6 for ; Mon, 25 Jan 2021 07:31:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=android.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bO1o95yEacxJCi6anL6VGLU0D9m8E1qC04Zr1YukLIY=; b=ZTJkmBtNvj+HaYd99yGGaGslCoSskPBt4H7l7Hk5qHb2OnXsuo+Dhoo+EFFsfD6JRu JTmgHLcpu21RVZAAYl3fnJF3ueXF+96EV/yA3ocS784tVf2+2daHcyNs8fLEeEG3OfPP TS6oFJAoYqmjxoPh/KNH5UN7r87b9yUMjxcnv2Z+JuvmysnIhIYKj99Sao0k3p709nIw b/3vldccwOQED9RavZ+r4Ip6qeV14H43+xB2oI2RjnTAhg3sbulT8odCQBX2BENwidl8 JrPx8Y7YyYrBUivhBUdFamIUb7KcT4AavuKxnMJ4V687huqvVsyESxpTfeJOaTrczksv AMlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bO1o95yEacxJCi6anL6VGLU0D9m8E1qC04Zr1YukLIY=; b=GR27UpzZMMHC2PMnHWBDbKp+rcGISu4I+u36B45T3PQiKATmJyDyIcNNSHeobRgABA AzxLod1j0njykjQ7PJFmm/CBPFnIPk6yBMirroK5gyDan5Rd3Fjp/EQ3S7XFQl0oHarS R7uEudcd64cqInQ93Nshr0Uki6PviRtGbvvtciiyFYyBV38Cc8eVwIziechxwXDjFc9K dxvOEeFD790tcD7xS9o5EPH55G2oLIPhLJjOQQ6w9/rTRwaxfnF0zmuNa1eTID4MW36j jJMJ1f0KKSOCUQx+eRQrmaICDiIcdbYUxgtwvRmy37Y/45az9DBqu6y8D+8gxR9hNMDH nMuA== X-Gm-Message-State: AOAM530DrSjL+K7Jwrry07x3NhWEXMX4jfVBD0/2IkraVobk8UjYd7vD lTPWCg9HowmVeHYAmvdRBcIe9w== X-Google-Smtp-Source: ABdhPJyg30IKJU9/J4/I2YRuP1Ce3mIuk2elXW5qp0wKyXt4pQb1HkUGdhTt0pKKcDa8nSqNfdxxxg== X-Received: by 2002:adf:f606:: with SMTP id t6mr1611833wrp.360.1611588675183; Mon, 25 Jan 2021 07:31:15 -0800 (PST) Received: from balsini.lon.corp.google.com ([2a00:79e0:d:210:4cd4:5994:40fe:253d]) by smtp.gmail.com with ESMTPSA id o14sm22611965wri.48.2021.01.25.07.31.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Jan 2021 07:31:14 -0800 (PST) From: Alessio Balsini To: Miklos Szeredi Cc: Akilesh Kailash , Amir Goldstein , Antonio SJ Musumeci , David Anderson , Giuseppe Scrivano , Jann Horn , Jens Axboe , Martijn Coenen , Palmer Dabbelt , Paul Lawrence , Peng Tao , Stefano Duo , Zimuzo Ezeozue , wuyan , fuse-devel@lists.sourceforge.net, kernel-team@android.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH RESEND V12 8/8] fuse: Introduce passthrough for mmap Date: Mon, 25 Jan 2021 15:30:57 +0000 Message-Id: <20210125153057.3623715-9-balsini@android.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog In-Reply-To: <20210125153057.3623715-1-balsini@android.com> References: <20210125153057.3623715-1-balsini@android.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Enabling FUSE passthrough for mmap-ed operations not only affects performance, but has also been shown as mandatory for the correct functioning of FUSE passthrough. yanwu noticed [1] that a FUSE file with passthrough enabled may suffer data inconsistencies if the same file is also accessed with mmap. What happens is that read/write operations are directly applied to the lower file system (and its cache), while mmap-ed operations are affecting the FUSE cache. Extend the FUSE passthrough implementation to also handle memory-mapped FUSE file, to both fix the cache inconsistencies and extend the passthrough performance benefits to mmap-ed operations. [1] https://lore.kernel.org/lkml/20210119110654.11817-1-wu-yan@tcl.com/ Signed-off-by: Alessio Balsini --- fs/fuse/file.c | 3 +++ fs/fuse/fuse_i.h | 1 + fs/fuse/passthrough.c | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index cddada1e8bd9..e3741a94c1f9 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -2370,6 +2370,9 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) if (FUSE_IS_DAX(file_inode(file))) return fuse_dax_mmap(file, vma); + if (ff->passthrough.filp) + return fuse_passthrough_mmap(file, vma); + if (ff->open_flags & FOPEN_DIRECT_IO) { /* Can't provide the coherency needed for MAP_SHARED */ if (vma->vm_flags & VM_MAYSHARE) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 815af1845b16..7b0d65984608 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1244,5 +1244,6 @@ int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, void fuse_passthrough_release(struct fuse_passthrough *passthrough); ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *to); ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, struct iov_iter *from); +ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma); #endif /* _FS_FUSE_I_H */ diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index 24866c5fe7e2..284979f87747 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -135,6 +135,47 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse, return ret; } +ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma) +{ + int ret; + const struct cred *old_cred; + struct fuse_file *ff = file->private_data; + struct inode *fuse_inode = file_inode(file); + struct file *passthrough_filp = ff->passthrough.filp; + struct inode *passthrough_inode = file_inode(passthrough_filp); + + if (!passthrough_filp->f_op->mmap) + return -ENODEV; + + if (WARN_ON(file != vma->vm_file)) + return -EIO; + + vma->vm_file = get_file(passthrough_filp); + + old_cred = override_creds(ff->passthrough.cred); + ret = call_mmap(vma->vm_file, vma); + revert_creds(old_cred); + + if (ret) + fput(passthrough_filp); + else + fput(file); + + if (file->f_flags & O_NOATIME) + return ret; + + if ((!timespec64_equal(&fuse_inode->i_mtime, + &passthrough_inode->i_mtime) || + !timespec64_equal(&fuse_inode->i_ctime, + &passthrough_inode->i_ctime))) { + fuse_inode->i_mtime = passthrough_inode->i_mtime; + fuse_inode->i_ctime = passthrough_inode->i_ctime; + } + touch_atime(&file->f_path); + + return ret; +} + int fuse_passthrough_open(struct fuse_dev *fud, struct fuse_passthrough_out *pto) {