/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <limits.h>
#include <linux/fs.h>
#include <time.h>
#include <fs_mgr.h>
#include <pthread.h>
#define LOG_TAG "fstrim"
#include "cutils/log.h"
#include "hardware_legacy/power.h"

/* These numbers must match what the MountService specified in
 * frameworks/base/services/java/com/android/server/EventLogTags.logtags
 */
#define LOG_FSTRIM_START  2755
#define LOG_FSTRIM_FINISH 2756

#define FSTRIM_WAKELOCK "dofstrim"

static unsigned long long get_boot_time_ms(void)
{
    struct timespec t;
    unsigned long long time_ms;

    t.tv_sec = 0;
    t.tv_nsec = 0;
    clock_gettime(CLOCK_BOOTTIME, &t);
    time_ms = (t.tv_sec * 1000LL) + (t.tv_nsec / 1000000);

    return time_ms;
}

static void *do_fstrim_filesystems(void *ignored)
{
    int i;
    int fd;
    int ret = 0;
    struct fstrim_range range = { 0 };
    struct stat sb;
    extern struct fstab *fstab;

    SLOGI("Starting fstrim work...\n");

    /* Log the start time in the event log */
    LOG_EVENT_LONG(LOG_FSTRIM_START, get_boot_time_ms());

    for (i = 0; i < fstab->num_entries; i++) {
        /* Skip raw partitions */
        if (!strcmp(fstab->recs[i].fs_type, "emmc") ||
            !strcmp(fstab->recs[i].fs_type, "mtd")) {
            continue;
        }
        /* Skip read-only filesystems */
        if (fstab->recs[i].flags & MS_RDONLY) {
            continue;
        }
        if (fs_mgr_is_voldmanaged(&fstab->recs[i])) {
            continue; /* Should we trim fat32 filesystems? */
        }

        if (stat(fstab->recs[i].mount_point, &sb) == -1) {
            SLOGE("Cannot stat mount point %s\n", fstab->recs[i].mount_point);
            ret = -1;
            continue;
        }
        if (!S_ISDIR(sb.st_mode)) {
            SLOGE("%s is not a directory\n", fstab->recs[i].mount_point);
            ret = -1;
            continue;
        }

        fd = open(fstab->recs[i].mount_point, O_RDONLY);
        if (fd < 0) {
            SLOGE("Cannot open %s for FITRIM\n", fstab->recs[i].mount_point);
            ret = -1;
            continue;
        }

        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);
            ret = -1;
        } else {
            SLOGI("Trimmed %llu bytes on %s\n", range.len, fstab->recs[i].mount_point);
        }
        close(fd);
    }

    /* Log the finish time in the event log */
    LOG_EVENT_LONG(LOG_FSTRIM_FINISH, get_boot_time_ms());

    SLOGI("Finished fstrim work.\n");

    /* Release the wakelock that let us work */
    release_wake_lock(FSTRIM_WAKELOCK);

    return (void *)ret;
}

int fstrim_filesystems(void)
{
    pthread_t t;
    int ret;

    /* Get a wakelock as this may take a while, and we don't want the
     * device to sleep on us.
     */
    acquire_wake_lock(PARTIAL_WAKE_LOCK, FSTRIM_WAKELOCK);

    /* Depending on the emmc chip and size, this can take upwards
     * of a few minutes.  If done in the same thread as the caller
     * of this function, that would block vold from accepting any
     * commands until the trim is finished.  So start another thread
     * to do the work, and return immediately.
     *
     * This function should not be called more than once per day, but
     * even if it is called a second time before the first one finishes,
     * 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);
    if (ret) {
        SLOGE("Cannot create thread to do fstrim");
        return ret;
    }

    ret = pthread_detach(t);
    if (ret) {
        SLOGE("Cannot detach thread doing fstrim");
        return ret;
    }

    return 0;
}
