Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b920cb44 authored by Paul Lawrence's avatar Paul Lawrence
Browse files

Handle retry count correctly

Test: vdc startCheckpoint 2 then reboot 3 times checking state

Change-Id: I4eeda7f73d82a7c8b2469571fa558df2fac47354
parent 380d3192
Loading
Loading
Loading
Loading
+108 −60
Original line number Diff line number Diff line
@@ -850,7 +850,61 @@ bool fs_mgr_update_logical_partition(struct fstab_rec* rec) {
    return true;
}

bool fs_mgr_update_checkpoint_partition(struct fstab_rec* rec) {
class CheckpointManager {
  public:
    CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {}

    bool Update(struct fstab_rec* rec) {
        if (!fs_mgr_is_checkpoint(rec)) {
            return true;
        }

        if (fs_mgr_is_checkpoint_blk(rec)) {
            call_vdc({"checkpoint", "restoreCheckpoint", rec->blk_device});
        }

        if (needs_checkpoint_ == UNKNOWN &&
            !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &needs_checkpoint_)) {
            LERROR << "Failed to find if checkpointing is needed. Assuming no.";
            needs_checkpoint_ = NO;
        }

        if (needs_checkpoint_ != YES) {
            return true;
        }

        if (!UpdateCheckpointPartition(rec)) {
            LERROR << "Could not set up checkpoint partition, skipping!";
            return false;
        }

        return true;
    }

    bool Revert(struct fstab_rec* rec) {
        if (!fs_mgr_is_checkpoint(rec)) {
            return true;
        }

        if (device_map_.find(rec->blk_device) == device_map_.end()) {
            return true;
        }

        std::string bow_device = rec->blk_device;
        free(rec->blk_device);
        rec->blk_device = strdup(device_map_[bow_device].c_str());
        device_map_.erase(bow_device);

        DeviceMapper& dm = DeviceMapper::Instance();
        if (!dm.DeleteDevice("bow")) {
            PERROR << "Failed to remove bow device";
        }

        return true;
    }

  private:
    bool UpdateCheckpointPartition(struct fstab_rec* rec) {
        if (fs_mgr_is_checkpoint_fs(rec)) {
            if (!strcmp(rec->fs_type, "f2fs")) {
                std::string opts(rec->fs_options);
@@ -862,8 +916,6 @@ bool fs_mgr_update_checkpoint_partition(struct fstab_rec* rec) {
                LERROR << rec->fs_type << " does not implement checkpoints.";
            }
        } else if (fs_mgr_is_checkpoint_blk(rec)) {
        call_vdc({"checkpoint", "restoreCheckpoint", rec->blk_device});

            android::base::unique_fd fd(
                    TEMP_FAILURE_RETRY(open(rec->blk_device, O_RDONLY | O_CLOEXEC)));
            if (!fd) {
@@ -880,7 +932,7 @@ bool fs_mgr_update_checkpoint_partition(struct fstab_rec* rec) {
            android::dm::DmTable table;
            if (!table.AddTarget(
                        std::make_unique<android::dm::DmTargetBow>(0, size, rec->blk_device))) {
            LERROR << "Failed to add Bow target";
                LERROR << "Failed to add bow target";
                return false;
            }

@@ -896,11 +948,18 @@ bool fs_mgr_update_checkpoint_partition(struct fstab_rec* rec) {
                return false;
            }

            device_map_[name] = rec->blk_device;
            free(rec->blk_device);
            rec->blk_device = strdup(name.c_str());
        }
        return true;
    }

    enum { UNKNOWN = -1, NO = 0, YES = 1 };
    int needs_checkpoint_;
    std::map<std::string, std::string> device_map_;
};

/* 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.
@@ -913,7 +972,7 @@ int fs_mgr_mount_all(fstab* fstab, int mount_mode) {
    int mret = -1;
    int mount_errno = 0;
    int attempted_idx = -1;
    int need_checkpoint = -1;
    CheckpointManager checkpoint_manager;
    FsManagerAvbUniquePtr avb_handle(nullptr);

    if (!fstab) {
@@ -960,17 +1019,9 @@ int fs_mgr_mount_all(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!";
        if (!checkpoint_manager.Update(&fstab->recs[i])) {
            continue;
        }
        }

        if (fstab->recs[i].fs_mgr_flags & MF_WAIT &&
            !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) {
@@ -1052,6 +1103,9 @@ int fs_mgr_mount_all(fstab* fstab, int mount_mode) {
                   << " is wiped and " << fstab->recs[top_idx].mount_point
                   << " " << fstab->recs[top_idx].fs_type
                   << " is formattable. Format it.";

            checkpoint_manager.Revert(&fstab->recs[top_idx]);

            if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
                strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
                int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY);
@@ -1172,11 +1226,12 @@ int fs_mgr_do_mount_one(struct fstab_rec *rec)
 * in turn, and stop on 1st success, or no more match.
 */
static int fs_mgr_do_mount_helper(fstab* fstab, const char* n_name, char* n_blk_device,
                                  char* tmp_mount_point, int need_checkpoint) {
                                  char* tmp_mount_point, int needs_checkpoint) {
    int i = 0;
    int mount_errors = 0;
    int first_mount_errno = 0;
    char* mount_point;
    CheckpointManager checkpoint_manager(needs_checkpoint);
    FsManagerAvbUniquePtr avb_handle(nullptr);

    if (!fstab) {
@@ -1205,17 +1260,10 @@ static int fs_mgr_do_mount_helper(fstab* fstab, const char* n_name, char* n_blk_
            }
        }

        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])) {
        if (!checkpoint_manager.Update(&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)) {
@@ -1291,8 +1339,8 @@ int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char*
}

int fs_mgr_do_mount(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);
                    bool needs_checkpoint) {
    return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_checkpoint);
}

/*
+4 −2
Original line number Diff line number Diff line
@@ -398,6 +398,10 @@ on late-fs
    class_start early_hal

on post-fs-data
    # Start checkpoint before we touch data
    start vold
    exec - system system -- /system/bin/vdc checkpoint prepareCheckpoint

    # We chown/chmod /data again so because mount is run as root + defaults
    chown system system /data
    chmod 0771 /data
@@ -405,8 +409,6 @@ on post-fs-data
    restorecon /data

    # Make sure we have the device encryption key.
    start vold
    exec - system system -- /system/bin/vdc checkpoint prepareDriveForCheckpoint /data
    installkey /data

    # Start bootcharting as soon as possible after the data partition is