Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp3607907pxb; Mon, 25 Jan 2021 23:15:35 -0800 (PST) X-Google-Smtp-Source: ABdhPJyNFN/lUVltiO8u8+eyCmEFAn6nQQYYyZj3gMrAKZG2Ixg1nS0V2hJ7ViRDNmXLZxAHyYXV X-Received: by 2002:a17:906:1689:: with SMTP id s9mr2560728ejd.500.1611645335348; Mon, 25 Jan 2021 23:15:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1611645335; cv=none; d=google.com; s=arc-20160816; b=uMIMYScy/N7ih0IdtfS1QuRjs2NM30QT+F3qVGDdmLRtX5pSEsPtHxfMS1o27SfZWt Rgbz4dWyf1vb3RU+2lDSZLNQJaTPfuqRXR1LySXooEijk1PFje7d0NAgyLn/+THgQ2n3 bHGbfkcrIqG1kp0XqazCg+nru0OHX0xEnb4rHrTSUGHwaJNIGRgi7D2Sc5CLRvohG4UF KPoMxAYpZ+C7wlWygfPzQtjOnQmncJk3d3+H+Nr50QAVYJUcZQr5g0ewJSqqBAaJsDmE mk9DeJaYpVra/0vfjZ1zgJHSITSWuNp5CfNfDUIOHRUrRHEJbDjY8yYRIfXJkw3wOUGB xDig== 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=K33/kOxBcJ35u0ayW/ijJxNjK4mLraYNnDTliI6dnXg=; b=nHjsaqIL8eeFaaTnZhff4x+rHMLL7MDR4ZDDxwM7C/7ZhZA0NBi1rX7Bszm6sDwE0E ByHOQcQ+lR/9SQYwTH3d59EXP5rP7nDMTRG1jZZet7+rMqtdltVZxthdS5OLKbzOnVY2 kT7uHVnB33DY9a1VJXOi907yuns3mSVI5yLRIvHDREr+k418jKlKdd5cUE6XBqHDiYZr 93kZK6RI+BhyFKk0xAs6Dvu3MWt7rA98g/NhX1EylSCzK0/sZuCjXp5zrhuZwEcSUYj8 gSTWAZNjNJYbeuhMKGod3XZL+m5GwFh7a04cocVI2ITYmhbjFwmqfmAmRdRDcHdDYIqN 2rKA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@android.com header.s=20161025 header.b=kEj9BGL5; 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 gs10si6709127ejb.494.2021.01.25.23.15.11; Mon, 25 Jan 2021 23:15:35 -0800 (PST) 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=kEj9BGL5; 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 S2389474AbhAZHMN (ORCPT + 99 others); Tue, 26 Jan 2021 02:12:13 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60600 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730251AbhAYPmb (ORCPT ); Mon, 25 Jan 2021 10:42:31 -0500 Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 688EDC061A32 for ; Mon, 25 Jan 2021 07:31:12 -0800 (PST) Received: by mail-wm1-x32f.google.com with SMTP id 190so11304839wmz.0 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=NwF5Dyh/P0K2yzMWePHAom9t665dNEtyPUoIMcuxNj6Yh36lfD6YsBw4WlQ0iSb2WZ 2HcPhcWUXXyfhGutgqSB4OqltW1iZa8Hqn92yKcDVprTMuvXxissiFwUUJmAi2oCUDqI L1l/WpOpMdrzeYSePAUSmXDjgruCD2LgrBMmUf2mWnqm4JylmJB7asrVeWrL9qaE3u7x 8vsCyB3e7u+MLT00V/U2PACM5aqWgF0LUw5dVdfqmu5iLQQCILAA7u58xLQ59TPcKjF+ gCUR25F9MVVTVO1aVSAgN9OsJRKpqFGLsOXgxxPecUHKS6ZV/75jkTxQoQNmuBZ7LivJ kXFg== X-Gm-Message-State: AOAM533KNHcpSxN+oFYnFZMJnNZ5OBLc51Zqz9RdBNxMKU1+5kJRNGw4 dDA6Grq+S2jCQeFtw4hpRiKLLg== 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 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, 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; + } } -- 2.30.0.280.ga3ce27912f-goog