| From 654540d453a03efc0fe7fc0e0d155981051b10c4 Mon Sep 17 00:00:00 2001 |
| From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Date: Sun, 24 May 2020 12:37:15 +0200 |
| Subject: [PATCH 1/4] readfile: implement readfile syscall |
| |
| It's a tiny syscall, meant to allow a user to do a single "open this |
| file, read into this buffer, and close the file" all in a single shot. |
| |
| Should be good for reading "tiny" files like sysfs, procfs, and other |
| "small" files. |
| |
| There is no restarting the syscall, this is a "simple" syscall, with the |
| attempt to make reading "simple" files easier with less syscall |
| overhead. |
| |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/open.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 50 insertions(+) |
| |
| --- a/fs/open.c |
| +++ b/fs/open.c |
| @@ -1370,3 +1370,53 @@ int stream_open(struct inode *inode, str |
| } |
| |
| EXPORT_SYMBOL(stream_open); |
| + |
| +static struct file *readfile_open(int dfd, const char __user *filename, |
| + struct open_flags *op) |
| +{ |
| + struct filename *tmp; |
| + struct file *f; |
| + |
| + tmp = getname(filename); |
| + if (IS_ERR(tmp)) |
| + return (struct file *)tmp; |
| + |
| + f = do_filp_open(dfd, tmp, op); |
| + if (!IS_ERR(f)) |
| + fsnotify_open(f); |
| + |
| + putname(tmp); |
| + return f; |
| +} |
| + |
| +SYSCALL_DEFINE5(readfile, int, dfd, const char __user *, filename, |
| + char __user *, buffer, size_t, bufsize, int, flags) |
| +{ |
| + struct open_flags op; |
| + struct open_how how; |
| + struct file *file; |
| + loff_t pos = 0; |
| + int retval; |
| + |
| + /* only accept a small subset of O_ flags that make sense */ |
| + if ((flags | O_NOFOLLOW | O_NOATIME) != flags) |
| + return -EINVAL; |
| + |
| + /* add some needed flags to be able to open the file properly */ |
| + flags |= O_RDONLY | O_LARGEFILE; |
| + |
| + how = build_open_how(flags, 0000); |
| + retval = build_open_flags(&how, &op); |
| + if (retval) |
| + return retval; |
| + |
| + file = readfile_open(dfd, filename, &op); |
| + if (IS_ERR(file)) |
| + return PTR_ERR(file); |
| + |
| + retval = vfs_read(file, buffer, bufsize, &pos); |
| + |
| + filp_close(file, NULL); |
| + |
| + return retval; |
| +} |