lkml.org 
[lkml]   [2021]   [Jun]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[RFC PATCH 1/6] fs: generic file operation for fstrim
Date
In order to factor out common parts of fstrim ioctl's, introduce a new
file_operation field for the file system specific parts.

The generic ioctl code (do_vfs_ioctl) calls an helper for doing the common
actions (eg. permission checks or buffer copying). If the file system
doesn't supply an fstrim function, the call will be passed down directly
to the file system, as it used to be.

This change also enables an easier way for possible future relaxing of
permissions, eg. allowing unprivileged users to trim their own files
sounds like an apelling idea.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
---
fs/ioctl.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/fs.h | 1 +
2 files changed, 49 insertions(+)

diff --git a/fs/ioctl.c b/fs/ioctl.c
index 1e2204fa9963..3a638f1eb0f5 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -961,6 +961,51 @@ static int ioctl_fssetxattr(struct file *file, void __user *argp)
return err;
}

+/*
+ * ioctl_fitrim() generic handling for FITRIM ioctl() via dedicated file
+ * operation. It does't common things like copying the arg from/to userland,
+ * permission check, etc.
+ *
+ * If the handler in file_operation is NULL, just pass the ioctl down to the
+ * generic ioctl() handler, as it used to be.
+ */
+static int ioctl_fitrim(struct file *filp, unsigned int fd, unsigned int cmd,
+ void __user *argp)
+{
+ struct fstrim_range;
+ int ret;
+
+
+ if (S_ISREG(inode->i_mode))
+ return file_ioctl(filp, cmd, argp);
+ break;
+
+ /* if the fs doesn't implement the fitrim operation, just pass it to
+ the fs's ioctl() operation, so remaining implementations are kept
+ intact. this can be removed when all fs'es are converted */
+ if (!filp->f_op->fitrim) {
+ if (S_ISREG(inode->i_mode))
+ return file_ioctl(filp, cmd, argp);
+
+ return -ENOIOCTLCMD;
+ }
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (copy_from_user(&range, (struct fstrim_range __user)*argp,
+ sizeof(range)))
+ return -EFAULT;
+
+ ret = filp->f_op->fitrim(filp, &range);
+
+ if (copy_to_user((struct fstrim_range __user)*argp, &range,
+ sizeof(range)))
+ return -EFAULT;
+
+ return ret;
+}
+
/*
* do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
* It's just a simple helper for sys_ioctl and compat_sys_ioctl.
@@ -1043,6 +1088,9 @@ static int do_vfs_ioctl(struct file *filp, unsigned int fd,
case FS_IOC_FSSETXATTR:
return ioctl_fssetxattr(filp, argp);

+ case FITRIM:
+ return ioctl_fitrim(filp, cmd, argp);
+
default:
if (S_ISREG(inode->i_mode))
return file_ioctl(filp, cmd, argp);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c3c88fdb9b2a..9e2f0cd5c787 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2059,6 +2059,7 @@ struct file_operations {
struct file *file_out, loff_t pos_out,
loff_t len, unsigned int remap_flags);
int (*fadvise)(struct file *, loff_t, loff_t, int);
+ long (*fstrim)(struct file *, struct fstrim_range *range);
} __randomize_layout;

struct inode_operations {
--
2.20.1
\
 
 \ /
  Last update: 2021-06-22 14:12    [W:0.046 / U:0.540 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site