fuse: implement ->tmpfile()

JIRA: https://issues.redhat.com/browse/RHEL-33888
Status: Linus

Conflicts: Hunk #1 on include/uapi/linux/fuse.h was rejected because
	there are some differences, we have CentOS Stream commitis
	328cc1ffc2 ("fuse: support per inode DAX in fuse protocol")
	and c4ea092a2a ("fuse: add feature flag for expire-only")
	but we don't have upstream commit 98046f7486db7 ("fuse: support
	per inode DAX in fuse protocol"). Consequently the version
	changelog will not match upstream.
	Hunk #5 against fs/fuse/dir.c failed due out of order a patch
	pplication, in the context fuse_mkdir()	already has the idmap
	parameter, hunk applied manually.

commit 7d37539037c2fca70346fbedc219f655253d5cff
Author: Miklos Szeredi <mszeredi@redhat.com>
Date:   Sat Sep 24 07:00:00 2022 +0200

    fuse: implement ->tmpfile()

    This is basically equivalent to the FUSE_CREATE operation which creates and
    opens a regular file.

    Add a new FUSE_TMPFILE operation, otherwise just reuse the protocol and the
    code for FUSE_CREATE.

    Acked-by: Christian Brauner (Microsoft) <brauner@kernel.org>
    Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>

Signed-off-by: Ian Kent <ikent@redhat.com>
This commit is contained in:
Ian Kent 2024-05-22 13:06:26 +08:00 committed by Ian Kent
parent 956e3ad810
commit 3ad3f4ea76
3 changed files with 29 additions and 4 deletions

View File

@ -609,7 +609,7 @@ static void free_ext_value(struct fuse_args *args)
*/
static int fuse_create_open(struct inode *dir, struct dentry *entry,
struct file *file, unsigned int flags,
umode_t mode)
umode_t mode, u32 opcode)
{
int err;
struct inode *inode;
@ -651,7 +651,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
inarg.open_flags |= FUSE_OPEN_KILL_SUIDGID;
}
args.opcode = FUSE_CREATE;
args.opcode = opcode;
args.nodeid = get_node_id(dir);
args.in_numargs = 2;
args.in_args[0].size = sizeof(inarg);
@ -747,7 +747,7 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
if (fc->no_create)
goto mknod;
err = fuse_create_open(dir, entry, file, flags, mode);
err = fuse_create_open(dir, entry, file, flags, mode, FUSE_CREATE);
if (err == -ENOSYS) {
fc->no_create = 1;
goto mknod;
@ -864,6 +864,23 @@ static int fuse_create(struct mnt_idmap *idmap, struct inode *dir,
return fuse_mknod(&nop_mnt_idmap, dir, entry, mode, 0);
}
static int fuse_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
struct file *file, umode_t mode)
{
struct fuse_conn *fc = get_fuse_conn(dir);
int err;
if (fc->no_tmpfile)
return -EOPNOTSUPP;
err = fuse_create_open(dir, file->f_path.dentry, file, file->f_flags, mode, FUSE_TMPFILE);
if (err == -ENOSYS) {
fc->no_tmpfile = 1;
err = -EOPNOTSUPP;
}
return err;
}
static int fuse_mkdir(struct mnt_idmap *idmap, struct inode *dir,
struct dentry *entry, umode_t mode)
{
@ -1981,6 +1998,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
.setattr = fuse_setattr,
.create = fuse_create,
.atomic_open = fuse_atomic_open,
.tmpfile = fuse_tmpfile,
.mknod = fuse_mknod,
.permission = fuse_permission,
.getattr = fuse_getattr,

View File

@ -781,6 +781,9 @@ struct fuse_conn {
/* Add supplementary group info when creating a new inode */
unsigned int create_supp_group:1;
/* Is tmpfile not implemented by fs? */
unsigned int no_tmpfile:1;
/** The number of requests waiting for completion */
atomic_t num_waiting;

View File

@ -195,6 +195,9 @@
* - add security context to create, mkdir, symlink, and mknod requests
* - add FUSE_EXPIRE_ONLY flag to fuse_notify_inval_entry
* - add FUSE_HAS_EXPIRE_ONLY
*
* 7.37
* - add FUSE_TMPFILE
*/
#ifndef _LINUX_FUSE_H
@ -230,7 +233,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
#define FUSE_KERNEL_MINOR_VERSION 36
#define FUSE_KERNEL_MINOR_VERSION 37
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@ -558,6 +561,7 @@ enum fuse_opcode {
FUSE_SETUPMAPPING = 48,
FUSE_REMOVEMAPPING = 49,
FUSE_SYNCFS = 50,
FUSE_TMPFILE = 51,
/* CUSE specific operations */
CUSE_INIT = 4096,