blob: 995874094d661c4b968e8f3b4495e03d26017bf8 [file] [log] [blame]
From 583753fa8f68f1490098d1b6c2d0ed4286b7d1bb Mon Sep 17 00:00:00 2001
From: Chirantan Ekbote <chirantan@chromium.org>
Date: Thu, 5 Nov 2020 19:15:44 +0900
Subject: [PATCH] CHROMIUM: fuse: Implement CHROMEOS_TMPFILE
This is a chrome os extension for fuse implemented in a way that will
hopefully not conflict with rebases. The upstream maintainer was not
happy with this approach because it uses 2 round-trips instead of one.
However, his proposed mechanism requires changes to the VFS layer but
the VFS maintainer was non-committal.
At this point, I think the patch is non-intrusive enough that we can
just maintain it ourselves and if upstream ever gains support for
O_TMPFILE we can drop it at that time.
BUG=b:160932094
TEST=Successfully open a file with O_TMPFILE on virtio-fs
Change-Id: I600abd2d7604f8e167b6be65f5194e18bbf1b554
Signed-off-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2520740
Reviewed-by: Suleiman Souhlal <suleiman@chromium.org>
Conflicts: fs/fuse/file.c
[rebase510(groeck):
no init_security in v5.10
1st argument to create_new_entry() changed
]
Signed-off-by: Guenter Roeck <groeck@chromium.org>
---
fs/fuse/dir.c | 22 ++++++++++++++++++++++
fs/fuse/file.c | 2 +-
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 1b6c001a7dd1..16ebb05ff25d 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -767,6 +767,27 @@ static int fuse_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
return create_new_entry(fm, &args, dir, entry, S_IFDIR);
}
+static int fuse_chromeos_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
+ struct dentry *entry, umode_t mode)
+{
+ struct fuse_chromeos_tmpfile_in inarg;
+ struct fuse_mount *fm = get_fuse_mount(dir);
+ FUSE_ARGS(args);
+
+ if (!fm->fc->dont_mask)
+ mode &= ~current_umask();
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.mode = mode;
+ inarg.umask = current_umask();
+ args.opcode = FUSE_CHROMEOS_TMPFILE;
+ args.in_numargs = 1;
+ args.in_args[0].size = sizeof(inarg);
+ args.in_args[0].value = &inarg;
+
+ return create_new_entry(fm, &args, dir, entry, S_IFREG);
+}
+
static int fuse_symlink(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *entry, const char *link)
{
@@ -1868,6 +1889,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
.set_acl = fuse_set_acl,
.fileattr_get = fuse_fileattr_get,
.fileattr_set = fuse_fileattr_set,
+ .tmpfile = fuse_chromeos_tmpfile,
};
static const struct file_operations fuse_dir_operations = {
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 09ef2a4d25ed..6d0c74160e9a 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -27,7 +27,7 @@ static int fuse_send_open(struct fuse_mount *fm, u64 nodeid,
FUSE_ARGS(args);
memset(&inarg, 0, sizeof(inarg));
- inarg.flags = open_flags & ~(O_CREAT | O_EXCL | O_NOCTTY);
+ inarg.flags = open_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TMPFILE);
if (!fm->fc->atomic_o_trunc)
inarg.flags &= ~O_TRUNC;
--
2.17.1