return thaw_super(sb);
}
+static int ioctl_fstrim(struct file *filp, void __user *argp)
+{
+ struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
+ struct fstrim_range range;
+ int ret = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ /* If filesystem doesn't support trim feature, return. */
+ if (sb->s_op->trim_fs == NULL)
+ return -EOPNOTSUPP;
+
+ /* If a blockdevice-backed filesystem isn't specified, return EINVAL. */
+ if (sb->s_bdev == NULL)
+ return -EINVAL;
+
+ if (argp == NULL) {
+ range.start = 0;
+ range.len = ULLONG_MAX;
+ range.minlen = 0;
+ } else if (copy_from_user(&range, argp, sizeof(range)))
+ return -EFAULT;
+
+ ret = sb->s_op->trim_fs(sb, &range);
+ if (ret < 0)
+ return ret;
+
+ if ((argp != NULL) &&
+ (copy_to_user(argp, &range, sizeof(range))))
+ return -EFAULT;
+
+ return 0;
+}
+
/*
* When you add any new common ioctls to the switches above and below
* please update compat_sys_ioctl() too.
error = ioctl_fsthaw(filp);
break;
+ case FITRIM:
+ error = ioctl_fstrim(filp, argp);
+ break;
+
case FS_IOC_FIEMAP:
return ioctl_fiemap(filp, arg);
#define SEEK_END 2 /* seek relative to end of file */
#define SEEK_MAX SEEK_END
+struct fstrim_range {
+ uint64_t start;
+ uint64_t len;
+ uint64_t minlen;
+};
+
/* And dynamically-tunable limits and defaults: */
struct files_stat_struct {
int nr_files; /* read only */
#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */
#define FIFREEZE _IOWR('X', 119, int) /* Freeze */
#define FITHAW _IOWR('X', 120, int) /* Thaw */
+#define FITRIM _IOWR('X', 121, struct fstrim_range) /* Trim */
#define FS_IOC_GETFLAGS _IOR('f', 1, long)
#define FS_IOC_SETFLAGS _IOW('f', 2, long)
ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
#endif
int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
+ int (*trim_fs) (struct super_block *, struct fstrim_range *);
};
/*