diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index f56043cd5..10cd9e7f0 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -805,6 +805,23 @@ static bool call_vdc(const std::vector& args) { return true; } +static bool call_vdc_ret(const std::vector& args, int* ret) { + std::vector argv; + argv.emplace_back("/system/bin/vdc"); + for (auto& arg : args) { + argv.emplace_back(arg.c_str()); + } + LOG(INFO) << "Calling: " << android::base::Join(argv, ' '); + int err = android_fork_execvp(argv.size(), const_cast(argv.data()), ret, false, true); + if (err != 0) { + LOG(ERROR) << "vdc call failed with error code: " << err; + return false; + } + LOG(DEBUG) << "vdc finished successfully"; + *ret = WEXITSTATUS(*ret); + return true; +} + bool fs_mgr_update_logical_partition(struct fstab_rec* rec) { // Logical partitions are specified with a named partition rather than a // block device, so if the block device is a path, then it has already @@ -823,6 +840,24 @@ bool fs_mgr_update_logical_partition(struct fstab_rec* rec) { return true; } +bool fs_mgr_update_checkpoint_partition(struct fstab_rec* rec) { + if (fs_mgr_is_checkpoint(rec)) { + if (!strcmp(rec->fs_type, "f2fs")) { + std::string opts(rec->fs_options); + + opts += ",checkpoint=disable"; + free(rec->fs_options); + rec->fs_options = strdup(opts.c_str()); + } else { + LERROR << rec->fs_type << " does not implement checkpoints."; + } + } else if (rec->fs_mgr_flags & MF_CHECKPOINT_BLK) { + LERROR << "Block based checkpoint not implemented."; + return false; + } + return true; +} + /* When multiple fstab records share the same mount_point, it will * try to mount each one in turn, and ignore any duplicates after a * first successful mount. @@ -836,6 +871,7 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) int mret = -1; int mount_errno = 0; int attempted_idx = -1; + int need_checkpoint = -1; FsManagerAvbUniquePtr avb_handle(nullptr); if (!fstab) { @@ -882,6 +918,18 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) } } + if (fs_mgr_is_checkpoint(&fstab->recs[i])) { + if (need_checkpoint == -1 && + !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &need_checkpoint)) { + LERROR << "Failed to find if checkpointing is needed. Assuming no."; + need_checkpoint = 0; + } + if (need_checkpoint == 1 && !fs_mgr_update_checkpoint_partition(&fstab->recs[i])) { + LERROR << "Could not set up checkpoint partition, skipping!"; + continue; + } + } + if (fstab->recs[i].fs_mgr_flags & MF_WAIT && !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) { LERROR << "Skipping '" << fstab->recs[i].blk_device << "' during mount_all"; @@ -1081,9 +1129,8 @@ int fs_mgr_do_mount_one(struct fstab_rec *rec) * If multiple fstab entries are to be mounted on "n_name", it will try to mount each one * in turn, and stop on 1st success, or no more match. */ -int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, - char *tmp_mount_point) -{ +static int fs_mgr_do_mount_helper(struct fstab* fstab, const char* n_name, char* n_blk_device, + char* tmp_mount_point, int need_checkpoint) { int i = 0; int mount_errors = 0; int first_mount_errno = 0; @@ -1116,6 +1163,18 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, } } + if (fs_mgr_is_checkpoint(&fstab->recs[i])) { + if (need_checkpoint == -1 && + !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &need_checkpoint)) { + LERROR << "Failed to find if checkpointing is needed. Assuming no."; + need_checkpoint = 0; + } + if (need_checkpoint == 1 && !fs_mgr_update_checkpoint_partition(&fstab->recs[i])) { + LERROR << "Could not set up checkpoint partition, skipping!"; + continue; + } + } + /* First check the filesystem if requested */ if (fstab->recs[i].fs_mgr_flags & MF_WAIT && !fs_mgr_wait_for_file(n_blk_device, 20s)) { LERROR << "Skipping mounting '" << n_blk_device << "'"; @@ -1185,6 +1244,16 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, return FS_MGR_DOMNT_FAILED; } +int fs_mgr_do_mount(struct fstab* fstab, const char* n_name, char* n_blk_device, + char* tmp_mount_point) { + return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, -1); +} + +int fs_mgr_do_mount(struct fstab* fstab, const char* n_name, char* n_blk_device, + char* tmp_mount_point, bool needs_cp) { + return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_cp); +} + /* * mount a tmpfs filesystem at the given point. * return 0 on success, non-zero on failure. diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index f87a3b148..250793abf 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -80,37 +80,39 @@ static struct flag_list mount_flags[] = { }; static struct flag_list fs_mgr_flags[] = { - {"wait", MF_WAIT}, - {"check", MF_CHECK}, - {"encryptable=", MF_CRYPT}, - {"forceencrypt=", MF_FORCECRYPT}, - {"fileencryption=", MF_FILEENCRYPTION}, - {"forcefdeorfbe=", MF_FORCEFDEORFBE}, - {"keydirectory=", MF_KEYDIRECTORY}, - {"nonremovable", MF_NONREMOVABLE}, - {"voldmanaged=", MF_VOLDMANAGED}, - {"length=", MF_LENGTH}, - {"recoveryonly", MF_RECOVERYONLY}, - {"swapprio=", MF_SWAPPRIO}, - {"zramsize=", MF_ZRAMSIZE}, - {"max_comp_streams=", MF_MAX_COMP_STREAMS}, - {"verifyatboot", MF_VERIFYATBOOT}, - {"verify", MF_VERIFY}, - {"avb", MF_AVB}, - {"noemulatedsd", MF_NOEMULATEDSD}, - {"notrim", MF_NOTRIM}, - {"formattable", MF_FORMATTABLE}, - {"slotselect", MF_SLOTSELECT}, - {"nofail", MF_NOFAIL}, - {"latemount", MF_LATEMOUNT}, - {"reservedsize=", MF_RESERVEDSIZE}, - {"quota", MF_QUOTA}, - {"eraseblk=", MF_ERASEBLKSIZE}, - {"logicalblk=", MF_LOGICALBLKSIZE}, - {"sysfs_path=", MF_SYSFS}, - {"defaults", 0}, - {"logical", MF_LOGICAL}, - {0, 0}, + {"wait", MF_WAIT}, + {"check", MF_CHECK}, + {"encryptable=", MF_CRYPT}, + {"forceencrypt=", MF_FORCECRYPT}, + {"fileencryption=", MF_FILEENCRYPTION}, + {"forcefdeorfbe=", MF_FORCEFDEORFBE}, + {"keydirectory=", MF_KEYDIRECTORY}, + {"nonremovable", MF_NONREMOVABLE}, + {"voldmanaged=", MF_VOLDMANAGED}, + {"length=", MF_LENGTH}, + {"recoveryonly", MF_RECOVERYONLY}, + {"swapprio=", MF_SWAPPRIO}, + {"zramsize=", MF_ZRAMSIZE}, + {"max_comp_streams=", MF_MAX_COMP_STREAMS}, + {"verifyatboot", MF_VERIFYATBOOT}, + {"verify", MF_VERIFY}, + {"avb", MF_AVB}, + {"noemulatedsd", MF_NOEMULATEDSD}, + {"notrim", MF_NOTRIM}, + {"formattable", MF_FORMATTABLE}, + {"slotselect", MF_SLOTSELECT}, + {"nofail", MF_NOFAIL}, + {"latemount", MF_LATEMOUNT}, + {"reservedsize=", MF_RESERVEDSIZE}, + {"quota", MF_QUOTA}, + {"eraseblk=", MF_ERASEBLKSIZE}, + {"logicalblk=", MF_LOGICALBLKSIZE}, + {"sysfs_path=", MF_SYSFS}, + {"defaults", 0}, + {"logical", MF_LOGICAL}, + {"checkpoint=block", MF_CHECKPOINT_BLK}, + {"checkpoint=fs", MF_CHECKPOINT_FS}, + {0, 0}, }; #define EM_AES_256_XTS 1 @@ -1004,3 +1006,15 @@ int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab) int fs_mgr_is_logical(const struct fstab_rec* fstab) { return fstab->fs_mgr_flags & MF_LOGICAL; } + +int fs_mgr_is_checkpoint(const struct fstab_rec* fstab) { + return fstab->fs_mgr_flags & (MF_CHECKPOINT_FS | MF_CHECKPOINT_BLK); +} + +int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab) { + return fstab->fs_mgr_flags & MF_CHECKPOINT_FS; +} + +int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab) { + return fstab->fs_mgr_flags & MF_CHECKPOINT_BLK; +} diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index ebc4a0f08..506e81d06 100644 --- a/fs_mgr/fs_mgr_priv.h +++ b/fs_mgr/fs_mgr_priv.h @@ -113,6 +113,8 @@ #define MF_KEYDIRECTORY 0X4000000 #define MF_SYSFS 0X8000000 #define MF_LOGICAL 0x10000000 +#define MF_CHECKPOINT_BLK 0x20000000 +#define MF_CHECKPOINT_FS 0x40000000 // clang-format on #define DM_BUF_SIZE 4096 diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index 1049fb6cc..cee069b3b 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -70,6 +70,8 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode); int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, char *tmp_mount_point); +int fs_mgr_do_mount(struct fstab* fstab, const char* n_name, char* n_blk_device, + char* tmp_mount_point, bool need_cp); int fs_mgr_do_mount_one(struct fstab_rec *rec); int fs_mgr_do_tmpfs_mount(const char *n_name); struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab); diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h index b1ee32885..bb4051148 100644 --- a/fs_mgr/include_fstab/fstab/fstab.h +++ b/fs_mgr/include_fstab/fstab/fstab.h @@ -86,6 +86,9 @@ int fs_mgr_is_nofail(const struct fstab_rec* fstab); int fs_mgr_is_latemount(const struct fstab_rec* fstab); int fs_mgr_is_quota(const struct fstab_rec* fstab); int fs_mgr_is_logical(const struct fstab_rec* fstab); +int fs_mgr_is_checkpoint(const struct fstab_rec* fstab); +int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab); +int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab); int fs_mgr_has_sysfs_path(const struct fstab_rec* fstab); std::string fs_mgr_get_slot_suffix();