Commit 7d375390 authored by Miklos Szeredi's avatar Miklos Szeredi
Browse files

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: default avatarChristian Brauner (Microsoft) <brauner@kernel.org>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 863f144f
Loading
Loading
Loading
Loading
+21 −3
Original line number Diff line number Diff line
@@ -529,7 +529,7 @@ static int get_security_context(struct dentry *entry, umode_t mode,
 */
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;
@@ -573,7 +573,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);
@@ -676,7 +676,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;
@@ -802,6 +802,23 @@ static int fuse_create(struct user_namespace *mnt_userns, struct inode *dir,
	return fuse_mknod(&init_user_ns, 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 user_namespace *mnt_userns, struct inode *dir,
		      struct dentry *entry, umode_t mode)
{
@@ -1913,6 +1930,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,
+3 −0
Original line number Diff line number Diff line
@@ -784,6 +784,9 @@ struct fuse_conn {
	/* Does the filesystem support per inode DAX? */
	unsigned int inode_dax:1;

	/* Is tmpfile not implemented by fs? */
	unsigned int no_tmpfile:1;

	/** The number of requests waiting for completion */
	atomic_t num_waiting;

+5 −1
Original line number Diff line number Diff line
@@ -194,6 +194,9 @@
 *  - add FUSE_SECURITY_CTX init flag
 *  - add security context to create, mkdir, symlink, and mknod requests
 *  - add FUSE_HAS_INODE_DAX, FUSE_ATTR_DAX
 *
 *  7.37
 *  - add FUSE_TMPFILE
 */

#ifndef _LINUX_FUSE_H
@@ -229,7 +232,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
@@ -537,6 +540,7 @@ enum fuse_opcode {
	FUSE_SETUPMAPPING	= 48,
	FUSE_REMOVEMAPPING	= 49,
	FUSE_SYNCFS		= 50,
	FUSE_TMPFILE		= 51,

	/* CUSE specific operations */
	CUSE_INIT		= 4096,