fstrim: prep for supporting a deep trim ioctl
This adds an "fstrim dodtrim" command which will attempt to use
the FIDTRIM ioctl() if FIDTRIM is defined in the uapi/linux/fs.h.
If not, it will fail with EINVAL.
If no FIDTRIM is defined, it does not affect the "fstrim dotrim".
Change-Id: Icbfd621abb592b170db06f749e5eedfd1175f723
diff --git a/fstrim.c b/fstrim.c
index 9a6637d..7f83ff7 100644
--- a/fstrim.c
+++ b/fstrim.c
@@ -52,7 +52,7 @@
return time_ms;
}
-static void *do_fstrim_filesystems(void *ignored UNUSED)
+static void *do_fstrim_filesystems(void *thread_arg)
{
int i;
int fd;
@@ -60,6 +60,7 @@
struct fstrim_range range = { 0 };
struct stat sb;
extern struct fstab *fstab;
+ int deep_trim = !!thread_arg;
SLOGI("Starting fstrim work...\n");
@@ -100,9 +101,19 @@
memset(&range, 0, sizeof(range));
range.len = ULLONG_MAX;
- SLOGI("Invoking FITRIM ioctl on %s", fstab->recs[i].mount_point);
- if (ioctl(fd, FITRIM, &range)) {
- SLOGE("FITRIM ioctl failed on %s", fstab->recs[i].mount_point);
+ SLOGI("Invoking %s ioctl on %s", deep_trim ? "FIDTRIM" : "FITRIM", fstab->recs[i].mount_point);
+#if defined(FIDTRIM)
+ ret = ioctl(fd, deep_trim ? FIDTRIM : FITRIM, &range);
+#else
+ if (deep_trim) {
+ ret = -1;
+ errno = EINVAL;
+ } else {
+ ret = ioctl(fd, FITRIM, &range);
+ }
+#endif
+ if (ret) {
+ SLOGE("FIDTRIM ioctl failed on %s (error %d/%s)", fstab->recs[i].mount_point, errno, strerror(errno));
ret = -1;
} else {
SLOGI("Trimmed %llu bytes on %s\n", range.len, fstab->recs[i].mount_point);
@@ -121,7 +132,7 @@
return (void *)(uintptr_t)ret;
}
-int fstrim_filesystems(void)
+int fstrim_filesystems(int deep_trim)
{
pthread_t t;
int ret;
@@ -142,7 +153,7 @@
* the kernel will "do the right thing" and split the work between
* the two ioctls invoked in separate threads.
*/
- ret = pthread_create(&t, NULL, do_fstrim_filesystems, NULL);
+ ret = pthread_create(&t, NULL, do_fstrim_filesystems, (void *)(intptr_t)deep_trim);
if (ret) {
SLOGE("Cannot create thread to do fstrim");
return ret;