Received: by 2002:a05:6a10:9e8c:0:0:0:0 with SMTP id y12csp352562pxx; Mon, 26 Oct 2020 09:59:54 -0700 (PDT) X-Google-Smtp-Source: ABdhPJykgo63H3SizQKfc5z3umTJT7ovVKtEVqrPLD14sLnPJEFj3sYuaob7CYZdJd9XQ3+KnO/S X-Received: by 2002:a17:906:add3:: with SMTP id lb19mr11551313ejb.130.1603731594115; Mon, 26 Oct 2020 09:59:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1603731594; cv=none; d=google.com; s=arc-20160816; b=u6vNcf9sqIZDJssVA6aQoH9QdHitFfRj5I2oPPzwB5Ciuyg+5qJTfQovWh4sViM/nZ UxCE1VOT5gRfyIeam7eVvTxoYlhRqI+vxOz6Ts+e9Bx+EEFutHGn5Xrgcndx/xxkSMl8 xrgse0dy8fWWvnapuVH9fDm84U3PyXD5O0A9rdDBlqtZpBQHvQzTKEEaXqM4lpRwl9d0 2zUVwB3hWe2Pr25oa/IrJ/7XKOXlFVskaGKx1CiNbtDI8Y9vKua3a400c4EL6HKBBD6z F0eD+UHGX1cwr1BFe0hGiDgwxJY7P6cETGwvEUaYUS2F+QDt7g7lPwV28N+CshFUln7X 2Phg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=8U6Qxx953w4L4tpJflBCmGVShrqbgz4wqR0nsj2i66M=; b=Wyk7s6bpC8s32tvBNK4dZx6ZPHRGY9U7NfLQViZp6vDInEmUvZOdeYIyJDXPGpAgCC HFIfHau3ffn1JA1aNzdWXe301x+sGAM4m3/xTQ1Fe6bdzd4ajNT0EyH7INC/Qd8mKpi/ FnzUHx5bro3xkURJkDqA82FtomVCfd/nP2QLtN2LKAxJaXdGaUMw961Vwrl/fqQ1SgiU 1VDBthfwxJPorIVPJt/LSbfbB/lKj/ZSGzrY1fT8+LPeHKs1dZpxstVCUzF/Rm7um0qQ aGWVDn3TXgyMZsBOWHTCOoNPnCoXz1qEOKTmCJRCwY/plzYQfoyLrj31vQqHocTkoHy5 VjKA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@android.com header.s=20161025 header.b=k7bQnsf6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=android.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id dc11si6931440ejb.375.2020.10.26.09.59.31; Mon, 26 Oct 2020 09:59:54 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@android.com header.s=20161025 header.b=k7bQnsf6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=android.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1775585AbgJZMvc (ORCPT + 99 others); Mon, 26 Oct 2020 08:51:32 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:38522 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1775580AbgJZMvb (ORCPT ); Mon, 26 Oct 2020 08:51:31 -0400 Received: by mail-wr1-f65.google.com with SMTP id n18so12364404wrs.5 for ; Mon, 26 Oct 2020 05:51:29 -0700 (PDT) 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=8U6Qxx953w4L4tpJflBCmGVShrqbgz4wqR0nsj2i66M=; b=k7bQnsf63vkCKsp8Rvxr7QOrch0TfaeXCi6nD1OZg5KP7PnOCGqEYtVxrvjHPIJECi ikDfclmimdvLua7YBaaUzumilE+yGMsAKKo99Zbi33Y4OQoWQZS3BnEcMXHE1S+yIUKy tAbfSzQlJfUVBtiehjICl3umaBVwuQ89Pb/D3wfWOrDWi/C0plwRi9n7ot4fnnUH2qi4 hbzZk0VJ+KsbnquuJijziGPftFUsY2gIJnzzvPOL6/lTiatBoEL1+wZfsRfDtIMZd6JO 8dSM3ET/8MNL2HSvDgQFZ66I31+HGAH0oAkb0fb3nEps9/8mbKcZzde4dvmKYRVUd1et wlnw== 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=8U6Qxx953w4L4tpJflBCmGVShrqbgz4wqR0nsj2i66M=; b=BlrCRT3VxMaupx2HI/+SKmjT2M8C8utA+/SOAaQdeUFuNxMwDwq9CoSXE/hI5tkZKc rrGAHnpNZlZDQw39r9IZlhdNBE8o1UkeYa4bi36nScIfx+nf3eWuVOS4ApnCwQS2CrO7 6gAHlLLQIjNRuxbSwemqxj7gPLsPHj7sfYJcmMo7wXt/wf7CkV44Cao1jWlPOXUvrC1a 42cC693Ad6X4R6ErMdnos9sPy2ESzUJdOOoBFUqYYjGr/ufRQeogUBRBj1R+qW3toviF 9wQclOs01kC8PKklwhKPof4KiUx4WxGBbyBbooDDOPgZq2eVuKBgs2j288ESVeBprn13 3h1w== X-Gm-Message-State: AOAM531mwLoTBKfSOvb1JSIhlGraB4EigOjIqbb16Ax8VGAsLCBEHtSf hzYUgOUsxhXwOnO/ACX1j8sUuA== X-Received: by 2002:adf:ef06:: with SMTP id e6mr17579382wro.397.1603716688727; Mon, 26 Oct 2020 05:51:28 -0700 (PDT) Received: from balsini.lon.corp.google.com ([2a00:79e0:d:210:7220:84ff:fe09:7d5c]) by smtp.gmail.com with ESMTPSA id r1sm24423262wro.18.2020.10.26.05.51.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Oct 2020 05:51:28 -0700 (PDT) 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 , Stefano Duo , Zimuzo Ezeozue , fuse-devel@lists.sourceforge.net, kernel-team@android.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH V10 2/5] fuse: Passthrough initialization and release Date: Mon, 26 Oct 2020 12:50:13 +0000 Message-Id: <20201026125016.1905945-3-balsini@android.com> X-Mailer: git-send-email 2.29.0.rc1.297.gfa9743e501-goog In-Reply-To: <20201026125016.1905945-1-balsini@android.com> References: <20201026125016.1905945-1-balsini@android.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@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, userspace 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 userspace can be: - > 0: success, the identifier can be used as part of an open/create reply. - < 0: an error occurred. The value 0 has been left unused for 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, zero-initialized in the common libfuse implementation. Removing the 0 value fixes the ambiguity between the case in which 0 corresponds to a real passthrough_fh or a missing implementation, simplifying the userspace implementation. For the passthrough mode to be successfully activated, the lower file system file must implement both read_ 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 | 80 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 6738dd5ff5d2..1e94c54d1455 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -1034,6 +1034,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..a135c955cc33 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -3,19 +3,95 @@ #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 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"); + return -EBADF; + } + + passthrough = kmalloc(sizeof(struct fuse_passthrough), GFP_KERNEL); + if (!passthrough) + return -ENOMEM; + + 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) { + fuse_passthrough_release(passthrough); + kfree(passthrough); + } + + return res; } int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, struct fuse_open_out *openarg) { - return -EINVAL; + struct inode *passthrough_inode; + struct super_block *passthrough_sb; + 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; + + 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"); + fuse_passthrough_release(passthrough); + kfree(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; + } } -- 2.29.0.rc1.297.gfa9743e501-goog