summaryrefslogtreecommitdiff
path: root/fs/exfat/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exfat/file.c')
-rw-r--r--fs/exfat/file.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/fs/exfat/file.c b/fs/exfat/file.c
index f783cf38dd8e..6af0191b648f 100644
--- a/fs/exfat/file.c
+++ b/fs/exfat/file.c
@@ -4,6 +4,7 @@
*/
#include <linux/slab.h>
+#include <linux/compat.h>
#include <linux/cred.h>
#include <linux/buffer_head.h>
#include <linux/blkdev.h>
@@ -350,6 +351,54 @@ out:
return error;
}
+static int exfat_ioctl_fitrim(struct inode *inode, unsigned long arg)
+{
+ struct request_queue *q = bdev_get_queue(inode->i_sb->s_bdev);
+ struct fstrim_range range;
+ int ret = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (!blk_queue_discard(q))
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&range, (struct fstrim_range __user *)arg, sizeof(range)))
+ return -EFAULT;
+
+ range.minlen = max_t(unsigned int, range.minlen,
+ q->limits.discard_granularity);
+
+ ret = exfat_trim_fs(inode, &range);
+ if (ret < 0)
+ return ret;
+
+ if (copy_to_user((struct fstrim_range __user *)arg, &range, sizeof(range)))
+ return -EFAULT;
+
+ return 0;
+}
+
+long exfat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ struct inode *inode = file_inode(filp);
+
+ switch (cmd) {
+ case FITRIM:
+ return exfat_ioctl_fitrim(inode, arg);
+ default:
+ return -ENOTTY;
+ }
+}
+
+#ifdef CONFIG_COMPAT
+long exfat_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ return exfat_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
+
int exfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
{
struct inode *inode = filp->f_mapping->host;
@@ -370,6 +419,10 @@ const struct file_operations exfat_file_operations = {
.llseek = generic_file_llseek,
.read_iter = generic_file_read_iter,
.write_iter = generic_file_write_iter,
+ .unlocked_ioctl = exfat_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = exfat_compat_ioctl,
+#endif
.mmap = generic_file_mmap,
.fsync = exfat_file_fsync,
.splice_read = generic_file_splice_read,