#pragma once
#include <filesystem>
+#include <string_view>
namespace fs = std::filesystem;
virtual fs::path AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const = 0;
virtual void AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path, int uid, int gid) const = 0;
virtual void AddSubsessionCleanupFailure (const fs::path& tmpdir_path, const fs::path& subsession_path) const = 0;
+ virtual std::string_view TemplateName() const = 0;
};
// Should be unique per-backend.
static const std::string TMP_NEW_PREFIX = ".tmpfixednew";
+std::string_view DirBackendAddFixedSize::TemplateName() const
+{
+ return "__template_fixed__"sv;
+}
+
fs::path DirBackendFixedSize::GetImagePathFromSubsessionPath(fs::path subsession_path)
{
subsession_path.replace_filename(".img."s + subsession_path.filename().native());
fs::path AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const override;
void AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path, int uid, int gid) const override;
void AddSubsessionCleanupFailure (const fs::path& tmpdir_path, const fs::path& subsession_path) const override;
+ std::string_view TemplateName() const override;
};
#include "dir_backend_regular_dir.hpp"
#include "os_ops.hpp"
-using namespace std::string_literals;
+using namespace std::literals;
+
+std::string_view DirBackendAddRegularDir::TemplateName() const
+{
+ /* Still has to be a valid subsession name (to be visible
+ * to external update scripts) so must fit in 20 chars. */
+ return "__template_reg__"sv;
+}
fs::path DirBackendAddRegularDir::AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const
{
fs::path AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const override;
void AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path, int uid, int gid) const override;
void AddSubsessionCleanupFailure (const fs::path& tmpdir_path, const fs::path& subsession_path) const override;
+ std::string_view TemplateName() const override;
};
}
// Create `$HOME/subsession` directory if it doesn't exist
-static void create_main_subdirectory(const int session_uid, const fs::path& main_dir)
+void create_main_subdirectory(const int session_uid, const fs::path& main_dir)
{
if (fs::exists(main_dir))
return;
std::filesystem::path get_main_dir_by_user_id(const int uid);
std::filesystem::path get_last_subsession_path_by_user_id(const int uid);
+void create_main_subdirectory(const int session_uid, const fs::path& main_dir);
bool subsession_exists(const int session_uid, const std::string_view subsession_id);
void add_user_subsession(const int session_uid, const std::string_view subsession_id, const DirBackendAdd& backend);
void add_user_subsession_inner(const std::filesystem::path &main_path, const int session_uid, const std::string_view subsession_id, const DirBackendAdd& backend, bool force);
int main(int argc, char **argv) try {
if (isRestoreOnly(argc, argv)) {
- restore_all_user_sessions();
+ restore_all_user_sessions(true);
} else {
g_sessiond_context = std::make_unique <sessiond_context> ();
- restore_all_user_sessions();
+ restore_all_user_sessions(false);
g_sessiond_context->run();
}
} catch (const std::exception &ex) {
using namespace std::string_literals;
+static constexpr auto TEMPLATE_IMAGE_SIZE_KB = 10240;
+
std::string get_restoration_lock_filename(int uid)
{
return "/run/sessiond-restore-"s + std::to_string(uid) + ".lock";
throw;
}
-void restore_all_user_sessions()
+static void regenerate_template_sessions(int uid) try
+{
+ const fs::path main_path = get_main_dir_by_user_id(uid);
+ create_main_subdirectory(uid, main_path);
+
+ const auto add_template_for_backend = [&] (const DirBackendAdd &backend) {
+ /* Don't regenerate templates and assume that whatever was left from
+ * a previous boot, if anything, is correct. Image-backed subsessions
+ * are remounted early on (including via an early `--restore-only`). */
+ if (subsession_exists(uid, backend.TemplateName()))
+ return;
+ add_user_subsession_inner(main_path, uid, backend.TemplateName(), backend, false);
+ };
+
+ add_template_for_backend(DirBackendAddFixedSize {TEMPLATE_IMAGE_SIZE_KB});
+ add_template_for_backend(DirBackendAddRegularDir {});
+} catch (const std::exception &ex) {
+ LOGE("Exception while regenerating template subsessions for uid %d: %s", uid, ex.what());
+ throw;
+}
+
+void restore_all_user_sessions(bool restore_only)
{
/* In theory this should live among OS or FS helpers, but
* this happens at early boot so we care about performance
LOGI("Restoring last session for user %s (uid %d)", username.c_str(), uid);
restore_user_session(username, uid);
+
+ if (!restore_only) {
+ /* Templates aren't supposed to be used directly,
+ * and we always get a "fresh" copy when regenerated,
+ * so we don't need to create them at this point and
+ * can save up on some boot-time performance. */
+ LOGI("Regenerating template sessions for user %s (uid %d)", username.c_str(), uid);
+ regenerate_template_sessions(uid);
+ }
}
}
#pragma once
-void restore_all_user_sessions();
+void restore_all_user_sessions(bool only_restore);
loop_run_for_test(callback_pending_ud<ud_get_user_t>,(gpointer*)&ud, ud.loop);
- summarize_results_for_get_user_list(std::get<get_user::get_user_list_0>(ud.t), std::array<std::string, 1>({""}));
- std::array<std::string, 3> arr{std::string(TestUserStr::user_0), std::string(TestUserStr::user_1), std::string(TestUserStr::user_2)};
-
- summarize_results_for_get_user_list<std::array<std::string, 3>>(std::get<get_user::get_user_list_1_2>(ud.t), arr);
- summarize_results_for_get_user_list<std::array<std::string, 3>>(std::get<get_user::get_user_list_mixed_1_2>(ud.t), arr);
- summarize_results_for_get_user_list<std::array<std::string, 3>>(std::get<get_user::get_user_list_fixed_size_1_2>(ud.t), arr);
- summarize_results_for_counted_only_get_user_list(std::get<get_user::get_user_list_1_2_count_only>(ud.t), 3);
- summarize_results_for_counted_only_get_user_list(std::get<get_user::get_user_list_mixed_1_2_count_only>(ud.t), 3);
- summarize_results_for_counted_only_get_user_list(std::get<get_user::get_user_list_fixed_size_1_2_count_only>(ud.t), 3);
+ summarize_results_for_get_user_list(std::get<get_user::get_user_list_0>(ud.t), std::array<std::string, 3>({"", "__template_fixed__", "__template_reg__"}));
+ std::array<std::string, 5> arr{std::string(TestUserStr::user_0), std::string(TestUserStr::user_1), std::string(TestUserStr::user_2)
+ , "__template_fixed__", "__template_reg__"};
+
+ summarize_results_for_get_user_list<std::array<std::string, 5>>(std::get<get_user::get_user_list_1_2>(ud.t), arr);
+ summarize_results_for_get_user_list<std::array<std::string, 5>>(std::get<get_user::get_user_list_mixed_1_2>(ud.t), arr);
+ summarize_results_for_get_user_list<std::array<std::string, 5>>(std::get<get_user::get_user_list_fixed_size_1_2>(ud.t), arr);
+ summarize_results_for_counted_only_get_user_list(std::get<get_user::get_user_list_1_2_count_only>(ud.t), 5);
+ summarize_results_for_counted_only_get_user_list(std::get<get_user::get_user_list_mixed_1_2_count_only>(ud.t), 5);
+ summarize_results_for_counted_only_get_user_list(std::get<get_user::get_user_list_fixed_size_1_2_count_only>(ud.t), 5);
summarize_results<get_user::action_items>(results);
}