Exemplo n.º 1
0
static void unmount_and_fsck(const struct mntent *entry) {
    if (strcmp(entry->mnt_type, "f2fs") && strcmp(entry->mnt_type, "ext4"))
        return;

    /* First, lazily unmount the directory. This unmount request finishes when
     * all processes that open a file or directory in |entry->mnt_dir| exit.
     */
    TEMP_FAILURE_RETRY(umount2(entry->mnt_dir, MNT_DETACH));

    /* Next, kill all processes except init, kthreadd, and kthreadd's
     * children to finish the lazy unmount. Killing all processes here is okay
     * because this callback function is only called right before reboot().
     * It might be cleaner to selectively kill processes that actually use
     * |entry->mnt_dir| rather than killing all, probably by reusing a function
     * like killProcessesWithOpenFiles() in vold/, but the selinux policy does
     * not allow init to scan /proc/<pid> files which the utility function
     * heavily relies on. The policy does not allow the process to execute
     * killall/pkill binaries either. Note that some processes might
     * automatically restart after kill(), but that is not really a problem
     * because |entry->mnt_dir| is no longer visible to such new processes.
     */
    ServiceManager::GetInstance().ForEachService([] (Service* s) { s->Stop(); });
    TEMP_FAILURE_RETRY(kill(-1, SIGKILL));

    int count = 0;
    while (count++ < UNMOUNT_CHECK_TIMES) {
        int fd = TEMP_FAILURE_RETRY(open(entry->mnt_fsname, O_RDONLY | O_EXCL));
        if (fd >= 0) {
            /* |entry->mnt_dir| has sucessfully been unmounted. */
            close(fd);
            break;
        } else if (errno == EBUSY) {
            /* Some processes using |entry->mnt_dir| are still alive. Wait for a
             * while then retry.
             */
            TEMP_FAILURE_RETRY(
                usleep(UNMOUNT_CHECK_MS * 1000 / UNMOUNT_CHECK_TIMES));
            continue;
        } else {
            /* Cannot open the device. Give up. */
            return;
        }
    }

    int st;
    if (!strcmp(entry->mnt_type, "f2fs")) {
        const char *f2fs_argv[] = {
            "/system/bin/fsck.f2fs", "-f", entry->mnt_fsname,
        };
        android_fork_execvp_ext(ARRAY_SIZE(f2fs_argv), (char **)f2fs_argv,
                                &st, true, LOG_KLOG, true, NULL, NULL, 0);
    } else if (!strcmp(entry->mnt_type, "ext4")) {
        const char *ext4_argv[] = {
            "/system/bin/e2fsck", "-f", "-y", entry->mnt_fsname,
        };
        android_fork_execvp_ext(ARRAY_SIZE(ext4_argv), (char **)ext4_argv,
                                &st, true, LOG_KLOG, true, NULL, NULL, 0);
    }
}
int main(int argc, char* agrv[])
{
    struct resize_stats stats = {0, 0};
    int status;
    int ret;
    char *blk_device;
    char *key_loc;

    if(argc != 3) {
        ERROR("The number of argument must be 3.\n");
        ret = -1;
        goto error;
    }
    
    blk_device = agrv[1];
    key_loc =  agrv[2];
    
    if ((ret = get_resize_stats(&stats, key_loc, blk_device)) < 0) {
        ERROR("Failed to get resize status of %s.\n", blk_device);
        goto error;
    }

    if (STATS_RESIZED == stats.state) {
        ERROR("Partition has been resized,so nothing to do!\n");
    }else {

        char *num_kb;
        if (asprintf(&num_kb, "%lldK", (unsigned long long)(stats.size / 1024)) <= 0) {
            ERROR("failed to create command for %s\n", blk_device);
            ret = -1;
            goto error;
        }
        char *resize_ext4_argv[] = {
                RESIZE_EXT4,
                "-f",
                blk_device,
                num_kb
        };
        ERROR("Running %s on %s\n", RESIZE_EXT4, blk_device);

        ret = android_fork_execvp_ext(ARRAY_SIZE(resize_ext4_argv), resize_ext4_argv,
                &status, true, LOG_NONE,
                false, NULL);
        free(num_kb);
        if (ret < 0) {
            /* No need to check for error in fork, we can't really handle it now */
            ERROR("Failed trying to run %s\n", RESIZE_EXT4);
            goto error;
        }
    }
error:
    ERROR("Resize ext4 return %d\n", ret);
    return ret;
}
Exemplo n.º 3
0
int execute_cmd(char *cmd_argv[], int argc) {
      int status;
      int ret = 0;

      ret = android_fork_execvp_ext(argc, cmd_argv, &status, true, LOG_KLOG, false, NULL);
      if (ret != 0) {
          /* No need to check for error in fork, we can't really handle it now */
          ERROR("Failed trying to run %s\n", cmd_argv[0]);
          return -1;
      }
      else {
          NOTICE("Execute '%s', status(%d), WEXITSTATUS(%d) \n", cmd_argv[0], status, WEXITSTATUS(status));
          return WEXITSTATUS(ret);
      }
}
Exemplo n.º 4
0
int main(int argc, char* argv[]) {
    int seg_fault_on_exit = 0;
    int log_target = LOG_ALOG;
    bool abbreviated = false;
    int ch;
    int status = 0xAAAA;
    int rc;

    while ((ch = getopt(argc, argv, "adk")) != -1) {
        switch (ch) {
            case 'a':
                abbreviated = true;
                break;
            case 'd':
                seg_fault_on_exit = 1;
                break;
            case 'k':
                log_target = LOG_KLOG;
                klog_set_level(6);
                break;
            case '?':
            default:
              usage();
        }
    }
    argc -= optind;
    argv += optind;

    if (argc < 1) {
        usage();
    }

    rc = android_fork_execvp_ext(argc, &argv[0], &status, true,
                                 log_target, abbreviated, NULL, NULL, 0);
    if (!rc) {
        if (WIFEXITED(status))
            rc = WEXITSTATUS(status);
        else
            rc = -ECHILD;
    }

    if (seg_fault_on_exit) {
        uintptr_t fault_address = (uintptr_t) status;
        *(int *) fault_address = 0;  // causes SIGSEGV with fault_address = status
    }

    return rc;
}
Exemplo n.º 5
0
static void check_fs(char *blk_device, char *fs_type, char *target)
{
    int status;
    int ret;
    long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
    char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro";
    char *e2fsck_argv[] = {
        E2FSCK_BIN,
        "-y",
        blk_device
    };

    /* Check for the types of filesystems we know how to check */
    if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
        /*
         * First try to mount and unmount the filesystem.  We do this because
         * the kernel is more efficient than e2fsck in running the journal and
         * processing orphaned inodes, and on at least one device with a
         * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes
         * to do what the kernel does in about a second.
         *
         * After mounting and unmounting the filesystem, run e2fsck, and if an
         * error is recorded in the filesystem superblock, e2fsck will do a full
         * check.  Otherwise, it does nothing.  If the kernel cannot mount the
         * filesytsem due to an error, e2fsck is still run to do a full check
         * fix the filesystem.
         */
        ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);
        if (!ret) {
            umount(target);
        }

        INFO("Running %s on %s\n", E2FSCK_BIN, blk_device);

        ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv,
                                      &status, true, LOG_KLOG | LOG_FILE,
                                      true, FSCK_LOG_FILE);

        if (ret < 0) {
            /* No need to check for error in fork, we can't really handle it now */
            ERROR("Failed trying to run %s\n", E2FSCK_BIN);
        }
    }

    return;
}
Exemplo n.º 6
0
static void resize_fs(char *blk_device, char *key_loc)
{
    int status;
    int ret;

    char *resize_ext4_argv[] = {
            RESIZE_EXT4,
            blk_device,
            key_loc
    };
    INFO("Running %s on %s\n", RESIZE_EXT4, blk_device);

    ret = android_fork_execvp_ext(ARRAY_SIZE(resize_ext4_argv), resize_ext4_argv,
            &status, true, LOG_NONE,
            false, NULL);
    if (ret < 0) {
        /* No need to check for error in fork, we can't really handle it now */
        ERROR("Failed trying to run %s\n", RESIZE_EXT4);
    }
exit:
    ERROR("Resize ext4 return %d\n", ret);
}
Exemplo n.º 7
0
/* This must be called after mount_all, because the mkswap command needs to be
 * available.
 */
int fs_mgr_swapon_all(struct fstab *fstab)
{
    int i = 0;
    int flags = 0;
    int err = 0;
    int ret = 0;
    int status;
    char *mkswap_argv[2] = {
        MKSWAP_BIN,
        NULL
    };

    if (!fstab) {
        return -1;
    }

    for (i = 0; i < fstab->num_entries; i++) {
        /* Skip non-swap entries */
        if (strcmp(fstab->recs[i].fs_type, "swap")) {
            continue;
        }

        if (fstab->recs[i].zram_size > 0) {
            /* A zram_size was specified, so we need to configure the
             * device.  There is no point in having multiple zram devices
             * on a system (all the memory comes from the same pool) so
             * we can assume the device number is 0.
             */
            FILE *zram_fp;

            zram_fp = fopen(ZRAM_CONF_DEV, "r+");
            if (zram_fp == NULL) {
                ERROR("Unable to open zram conf device %s\n", ZRAM_CONF_DEV);
                ret = -1;
                continue;
            }
            fprintf(zram_fp, "%d\n", fstab->recs[i].zram_size);
            fclose(zram_fp);
        }

        if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
            wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
        }

        /* Initialize the swap area */
        mkswap_argv[1] = fstab->recs[i].blk_device;
        err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv,
                                      &status, true, LOG_KLOG, false, NULL);
        if (err) {
            ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device);
            ret = -1;
            continue;
        }

        /* If -1, then no priority was specified in fstab, so don't set
         * SWAP_FLAG_PREFER or encode the priority */
        if (fstab->recs[i].swap_prio >= 0) {
            flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) &
                    SWAP_FLAG_PRIO_MASK;
            flags |= SWAP_FLAG_PREFER;
        } else {
            flags = 0;
        }
        err = swapon(fstab->recs[i].blk_device, flags);
        if (err) {
            ERROR("swapon failed for %s\n", fstab->recs[i].blk_device);
            ret = -1;
        }
    }

    return ret;
}
Exemplo n.º 8
0
static void format_fs(char *blk_device, char *fs_type, char *target, long int length)
{
    int status;
    int ret;
    long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
    char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro";

    /* Try to mount and then format block device if mount return error */
    ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);
    if(!ret) {
        umount(target);
    } else if (errno == EINVAL){
        ERROR("failed to mount because there is no valid superblock, try to format.\n");
        if (strcmp(fs_type, "ext4") == 0) {
            char *len;
            if (asprintf(&len, "%ld", length) <= 0) {
                ERROR("failed to create %s command for %s\n", fs_type, blk_device);
                ret = -1;
                goto err;
            }
            char *make_ext4fs_argv[] = {
                    MAKE_EXT4FS,
                    "-l",
                    len,
                    blk_device,
            };
            INFO("Running %s on %s\n", MAKE_EXT4FS, blk_device);

            ret = android_fork_execvp_ext(ARRAY_SIZE(make_ext4fs_argv), make_ext4fs_argv,
                    &status, true, LOG_NONE,
                    false, NULL);
            free(len);
            if (ret < 0) {
                /* No need to check for error in fork, we can't really handle it now */
                ERROR("Failed trying to run %s\n", MAKE_EXT4FS);
            }
        } else if (strcmp(fs_type, "f2fs") == 0){
            if (length < 0) {
                ERROR("negative length (%ld) not supported on %s\n", length, fs_type);
                ret = -1;
                goto err;
            }
            char *num_sectors;
            if (asprintf(&num_sectors, "%ld", length / 512) <= 0) {
                ERROR("failed to create %s command for %s\n", fs_type, blk_device);
                ret = -1;
                goto err;
            }
            char *make_f2fs_argv[] = {
                    MAKE_F2FS,
                    "-t",
                    "-d1",
                    blk_device,
                    num_sectors
            };
            INFO("Running %s on %s\n", MAKE_F2FS, blk_device);

            ret = android_fork_execvp_ext(ARRAY_SIZE(make_f2fs_argv), make_f2fs_argv,
                    &status, true, LOG_NONE,
                    false, NULL);
            free(num_sectors);
            if (ret < 0) {
                /* No need to check for error in fork, we can't really handle it now */
                ERROR("Failed trying to run %s\n", MAKE_F2FS);
            }
        } else {
            ERROR("File system type:%s not supported now.\n", fs_type);
        }
    } else {
        ERROR("mount fail:errno = %d\n", errno);
    }
err:
    if (ret != 0) {
        ERROR(" make %s failed on %s with %d(%s)\n", fs_type, blk_device, ret, strerror(errno));
    } else {
        ERROR(" make %s success on %s \n", fs_type, blk_device);        
    }
}
Exemplo n.º 9
0
static void check_fs(char *blk_device, char *fs_type, char *target)
{
    int status;
    int ret;
    long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
    char tmpmnt_opts[64] = "errors=remount-ro";
    char *e2fsck_argv[] = {
        E2FSCK_BIN,
        "-f",
        "-y",
        blk_device
    };

    /* Check for the types of filesystems we know how to check */
    if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
        /*
         * First try to mount and unmount the filesystem.  We do this because
         * the kernel is more efficient than e2fsck in running the journal and
         * processing orphaned inodes, and on at least one device with a
         * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes
         * to do what the kernel does in about a second.
         *
         * After mounting and unmounting the filesystem, run e2fsck, and if an
         * error is recorded in the filesystem superblock, e2fsck will do a full
         * check.  Otherwise, it does nothing.  If the kernel cannot mount the
         * filesytsem due to an error, e2fsck is still run to do a full check
         * fix the filesystem.
         */
        errno = 0;
        if (!strcmp(fs_type, "ext4")) {
            // This option is only valid with ext4
            strlcat(tmpmnt_opts, ",nomblk_io_submit", sizeof(tmpmnt_opts));
        }
        ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);
        INFO("%s(): mount(%s,%s,%s)=%d: %s\n",
             __func__, blk_device, target, fs_type, ret, strerror(errno));
        if (!ret) {
            int i;
            for (i = 0; i < 5; i++) {
                // Try to umount 5 times before continuing on.
                // Should we try rebooting if all attempts fail?
                int result = umount(target);
                if (result == 0) {
                    INFO("%s(): unmount(%s) succeeded\n", __func__, target);
                    break;
                }
                ERROR("%s(): umount(%s)=%d: %s\n", __func__, target, result, strerror(errno));
                sleep(1);
            }
        }

        /*
         * Some system images do not have e2fsck for licensing reasons
         * (e.g. recent SDK system images). Detect these and skip the check.
         */
        if (access(E2FSCK_BIN, X_OK)) {
            INFO("Not running %s on %s (executable not in system image)\n",
                 E2FSCK_BIN, blk_device);
        } else {
            INFO("Running %s on %s\n", E2FSCK_BIN, blk_device);

            ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv,
                                          &status, true, LOG_KLOG | LOG_FILE,
                                          true, FSCK_LOG_FILE, NULL, 0);

            if (ret < 0) {
                /* No need to check for error in fork, we can't really handle it now */
                ERROR("Failed trying to run %s\n", E2FSCK_BIN);
            }
        }
    } else if (!strcmp(fs_type, "f2fs")) {
            char *f2fs_fsck_argv[] = {
                    F2FS_FSCK_BIN,
                    "-a",
                    blk_device
            };
        INFO("Running %s -a %s\n", F2FS_FSCK_BIN, blk_device);

        ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv,
                                      &status, true, LOG_KLOG | LOG_FILE,
                                      true, FSCK_LOG_FILE, NULL, 0);
        if (ret < 0) {
            /* No need to check for error in fork, we can't really handle it now */
            ERROR("Failed trying to run %s\n", F2FS_FSCK_BIN);
        }
    }

    return;
}
Exemplo n.º 10
0
static void do_reserved_size(char *blk_device, char *fs_type, struct fstab_rec *rec)
{
    /* Check for the types of filesystems we know how to check */
    if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
        /*
         * Some system images do not have tune2fs for licensing reasons
         * Detect these and skip reserve blocks.
         */
        if (access(TUNE2FS_BIN, X_OK)) {
            ERROR("Not running %s on %s (executable not in system image)\n",
                  TUNE2FS_BIN, blk_device);
        } else {
            INFO("Running %s on %s\n", TUNE2FS_BIN, blk_device);

            int status = 0;
            int ret = 0;
            unsigned long reserved_blocks = 0;
            int fd = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC));
            if (fd >= 0) {
                struct ext4_super_block sb;
                ret = read_super_block(fd, &sb);
                if (ret < 0) {
                    ERROR("Can't read '%s' super block: %s\n", blk_device, strerror(errno));
                    goto out;
                }
                reserved_blocks = rec->reserved_size / EXT4_BLOCK_SIZE(&sb);
                unsigned long reserved_threshold = ext4_blocks_count(&sb) * 0.02;
                if (reserved_threshold < reserved_blocks) {
                    WARNING("Reserved blocks %lu is too large\n", reserved_blocks);
                    reserved_blocks = reserved_threshold;
                }

                if (ext4_r_blocks_count(&sb) == reserved_blocks) {
                    INFO("Have reserved same blocks\n");
                    goto out;
                }
            } else {
                ERROR("Failed to open '%s': %s\n", blk_device, strerror(errno));
                return;
            }

            char buf[16] = {0};
            snprintf(buf, sizeof (buf), "-r %lu", reserved_blocks);
            char *tune2fs_argv[] = {
                TUNE2FS_BIN,
                buf,
                blk_device,
            };

            ret = android_fork_execvp_ext(ARRAY_SIZE(tune2fs_argv), tune2fs_argv,
                                          &status, true, LOG_KLOG | LOG_FILE,
                                          true, NULL, NULL, 0);

            if (ret < 0) {
                /* No need to check for error in fork, we can't really handle it now */
                ERROR("Failed trying to run %s\n", TUNE2FS_BIN);
            }
      out:
            close(fd);
        }
    }
}
Exemplo n.º 11
0
static int do_quota(char *blk_device, char *fs_type, struct fstab_rec *rec)
{
    int force_check = 0;
    if (!strcmp(fs_type, "ext4")) {
        /*
         * Some system images do not have tune2fs for licensing reasons
         * Detect these and skip reserve blocks.
         */
        if (access(TUNE2FS_BIN, X_OK)) {
            ERROR("Not running %s on %s (executable not in system image)\n",
                  TUNE2FS_BIN, blk_device);
        } else {
            char* arg1 = NULL;
            char* arg2 = NULL;
            int status = 0;
            int ret = 0;
            int fd = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC));
            if (fd >= 0) {
                struct ext4_super_block sb;
                ret = read_super_block(fd, &sb);
                if (ret < 0) {
                    ERROR("Can't read '%s' super block: %s\n", blk_device, strerror(errno));
                    goto out;
                }

                int has_quota = (sb.s_feature_ro_compat
                        & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_QUOTA)) != 0;
                int want_quota = fs_mgr_is_quota(rec) != 0;

                if (has_quota == want_quota) {
                    INFO("Requested quota status is match on %s\n", blk_device);
                    goto out;
                } else if (want_quota) {
                    INFO("Enabling quota on %s\n", blk_device);
                    arg1 = "-Oquota";
                    arg2 = "-Qusrquota,grpquota";
                    force_check = 1;
                } else {
                    INFO("Disabling quota on %s\n", blk_device);
                    arg1 = "-Q^usrquota,^grpquota";
                    arg2 = "-O^quota";
                }
            } else {
                ERROR("Failed to open '%s': %s\n", blk_device, strerror(errno));
                return force_check;
            }

            char *tune2fs_argv[] = {
                TUNE2FS_BIN,
                arg1,
                arg2,
                blk_device,
            };
            ret = android_fork_execvp_ext(ARRAY_SIZE(tune2fs_argv), tune2fs_argv,
                                          &status, true, LOG_KLOG | LOG_FILE,
                                          true, NULL, NULL, 0);
            if (ret < 0) {
                /* No need to check for error in fork, we can't really handle it now */
                ERROR("Failed trying to run %s\n", TUNE2FS_BIN);
            }
      out:
            close(fd);
        }
    }
    return force_check;
}
int main(int argc, char **argv)
{
    struct fstab *fstab;
    int ret=0, syspart, i, status;
    char filenamePatched[PATH_MAX], filenameSystem[PATH_MAX];

    // check arguments
    if(argc!=2) {
        ERROR("Invalid Arguments");
        return -EINVAL;
    }

    // get syspart from cmdline
    syspart = getDualbootSyspart();
    if(syspart<0) {
        ERROR("Cannot read system number");
        return -EINVAL;
    }

    // patch fstab
    sprintf(filenamePatched, "%s.patched", argv[1]);
    sprintf(filenameSystem, "%s.system", argv[1]);
    patch_fstab(argv[1], filenamePatched, filenameSystem, syspart);

    // mount system
    fstab = fs_mgr_read_fstab(filenameSystem);
    ret = fs_mgr_mount_all(fstab);
    fs_mgr_free_fstab(fstab);
    if (ret == -1) {
        ERROR("fs_mgr_mount_all returned an error\n");
    }

    // mount data
    fstab = fs_mgr_read_fstab(argv[1]);
    for (i = 0; i < fstab->num_entries; ++i) {
        struct fstab_rec* v = &fstab->recs[i];
        
        if(strcmp(PARTITION_USERDATA, v->blk_device))
            continue;

        if (v->fs_mgr_flags & MF_WAIT) {
            wait_for_file(v->blk_device, WAIT_TIMEOUT);
        }

        if (v->fs_mgr_flags & MF_CHECK) {
            check_fs(v->blk_device, v->fs_type, v->mount_point);
        }

        if(mountScriptExists()) {
            char *e2fsck_argv[] = {
                "/system/bin/mount_ext4.sh",
                v->blk_device,
                v->mount_point
            };
            ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, &status, true, LOG_KLOG, true, NULL);
        }
        else {
            ret = mount(v->blk_device, v->mount_point,  v->fs_type, v->flags, v->fs_options);
        }
    }
    fs_mgr_free_fstab(fstab);
    if (ret == -1) {
        ERROR("error mounting userdata\n");
    }
    
    return ret;
}
Exemplo n.º 13
0
static void check_fs(char *blk_device, char *fs_type, char *target, bool force_format, char *key_loc, bool is_crypttable)
{
    int status;
    int ret;
    long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
    char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro";
    char *e2fsck_argv[] = {
        E2FSCK_BIN,
        "-y",
        blk_device
    };
    //reserve 1M for crypted partintion key
    off64_t key_loc_reserve=1048576;
    //partintion key is saved in 32768 before SEEK_END
    off64_t key_loc_pos_to_end=-32768;

    /* Check for the types of filesystems we know how to check */
    if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
        /*
         * First try to mount and unmount the filesystem.  We do this because
         * the kernel is more efficient than e2fsck in running the journal and
         * processing orphaned inodes, and on at least one device with a
         * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes
         * to do what the kernel does in about a second.
         *
         * After mounting and unmounting the filesystem, run e2fsck, and if an
         * error is recorded in the filesystem superblock, e2fsck will do a full
         * check.  Otherwise, it does nothing.  If the kernel cannot mount the
         * filesytsem due to an error, e2fsck is still run to do a full check
         * fix the filesystem.
         */
        ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);

        if (! ret) {
            umount(target);
        }else{
            if (key_loc!=NULL && is_crypttable && !partition_wiped(blk_device))
            {
                bool is_crypted=true;
                char magicBuf[4]= {0};
                int databk=open(key_loc, O_RDONLY);
                if (databk<0)
                    is_crypted=false;
                if (is_crypted && lseek64(databk,key_loc_pos_to_end,SEEK_END)<0)
                    is_crypted=false;
                if (is_crypted && read(databk,magicBuf,4)<4)
                    is_crypted=false;
                close(databk);
                if (is_crypted && magicBuf[0]==0xC4 && magicBuf[1]==0xB1 && magicBuf[2]==0xB5 && magicBuf[3]==0xD0)
                {
                    // is cryptted
                     INFO("%s is crypted\n", blk_device);
                    goto out;
                }
                else
                    setup_ext4(blk_device,0);
            }
            else if (key_loc!=NULL && !strcmp(key_loc,blk_device))
            {
                setup_ext4(blk_device,key_loc_reserve);
            }
            else if (force_format)
            {
                setup_ext4(blk_device,0);
            }
		}

        INFO("Running %s on %s\n", E2FSCK_BIN, blk_device);

        ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv,
                                      &status, true, LOG_KLOG | LOG_FILE,
                                      true, FSCK_LOG_FILE);

        if (ret < 0) {
            /* No need to check for error in fork, we can't really handle it now */
            ERROR("Failed trying to run %s\n", E2FSCK_BIN);
        }
    }
out:
    return;
}