summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorLukas Czerner <lczerner@redhat.com>2010-11-19 21:47:07 -0500
committerTheodore Ts'o <tytso@mit.edu>2010-11-19 21:47:07 -0500
commite681c047e47c0abe67bf95857f23814372793cb0 (patch)
treeb82d1e75d2b7774c05e0c224464286c570d5d624 /fs
parent93bb41f4f8b89ac8b4d0a734bc59634cb0a29a89 (diff)
downloadlinux-3.10-e681c047e47c0abe67bf95857f23814372793cb0.tar.gz
linux-3.10-e681c047e47c0abe67bf95857f23814372793cb0.tar.bz2
linux-3.10-e681c047e47c0abe67bf95857f23814372793cb0.zip
ext4: Add EXT4_IOC_TRIM ioctl to handle batched discard
Filesystem independent ioctl was rejected as not common enough to be in core vfs ioctl. Since we still need to access to this functionality this commit adds ext4 specific ioctl EXT4_IOC_TRIM to dispatch ext4_trim_fs(). It takes fstrim_range structure as an argument. fstrim_range is definec in the include/linux/fs.h and its definition is as follows. struct fstrim_range { __u64 start; __u64 len; __u64 minlen; } start - first Byte to trim len - number of Bytes to trim from start minlen - minimum extent length to trim, free extents shorter than this number of Bytes will be ignored. This will be rounded up to fs block size. After the FITRIM is done, the number of actually discarded Bytes is stored in fstrim_range.len to give the user better insight on how much storage space has been really released for wear-leveling. Signed-off-by: Lukas Czerner <lczerner@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/ioctl.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index bf5ae883b1b..eb3bc2fe647 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -331,6 +331,30 @@ mext_out:
return err;
}
+ case FITRIM:
+ {
+ struct super_block *sb = inode->i_sb;
+ struct fstrim_range range;
+ int ret = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (copy_from_user(&range, (struct fstrim_range *)arg,
+ sizeof(range)))
+ return -EFAULT;
+
+ ret = ext4_trim_fs(sb, &range);
+ if (ret < 0)
+ return ret;
+
+ if (copy_to_user((struct fstrim_range *)arg, &range,
+ sizeof(range)))
+ return -EFAULT;
+
+ return 0;
+ }
+
default:
return -ENOTTY;
}