Create templates at sessiond start 79/324679/3
authorMichal Bloch <m.bloch@samsung.com>
Thu, 22 May 2025 15:16:17 +0000 (17:16 +0200)
committerMichal Bloch <m.bloch@samsung.com>
Wed, 28 May 2025 15:29:57 +0000 (17:29 +0200)
Will be used for a fast route to add subsessions,
since renaming a dir/image is much faster than
copying the whole skel folder hierarchy.

Change-Id: I0ff51c4126f44675445d3337a5ab51463c0aec03

src/service/src/dir_backend.hpp
src/service/src/dir_backend_fixed_size.cpp
src/service/src/dir_backend_fixed_size.hpp
src/service/src/dir_backend_regular_dir.cpp
src/service/src/dir_backend_regular_dir.hpp
src/service/src/fs_helpers.cpp
src/service/src/fs_helpers.hpp
src/service/src/main.cpp
src/service/src/main_restore.cpp
src/service/src/main_restore.hpp
tests/api_tests/test_api_get_user_list.cpp

index d1c66c5cc41935fe4f1842639fda842a14e188a2..b451c2c0ce527ac7f80b118bfc2ca289e4499ac5 100644 (file)
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <filesystem>
+#include <string_view>
 
 namespace fs = std::filesystem;
 
@@ -14,4 +15,5 @@ struct DirBackendAdd {
        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;
 };
index bb7ae4083a53b3dfd76d1fbe1e36c1961c91d9c5..d4d1a529f7beb526dff2fa2af48217d18e375876 100644 (file)
@@ -38,6 +38,11 @@ using namespace std::literals;
 // 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());
index cd752921d35bd17d9583a1d6e082bab01be7b9df..c1a94e4c4f60dd3dccad57ca112a4ca06b02b04d 100644 (file)
@@ -19,4 +19,5 @@ struct DirBackendAddFixedSize : public DirBackendAdd {
        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;
 };
index 5f46a7f946fff456721f845f340ab77e014a2edc..de5e971b939f21814057ff9b8ea24add85610009 100644 (file)
 #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
 {
index ed4a9f612077af4db094b6254a8ac5e0da5fb63d..d9b0dcaa99b8eb00c129c1d8f719727b20d6bf26 100644 (file)
@@ -12,4 +12,5 @@ struct DirBackendAddRegularDir : public DirBackendAdd {
        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;
 };
index c0d04d8737bb1e22a02b7ac464ca410a0c192a7b..13f2aa8424437271e197a527c829cbe1fcf0995b 100644 (file)
@@ -63,7 +63,7 @@ static inline bool should_copy_perms_from_skel(Directory_Class type) {
 }
 
 // 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;
index 65a51693f59a7ac8f4266f235b44d58437591849..366d97ac9e2440800ae06a32387e6626f3de2a9e 100644 (file)
@@ -10,6 +10,7 @@
 
 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);
index 07a3ff92c571780a8f634511bdb05ca444f1154e..8eae03bf1d8bf6160fe72bbc80afbeb8ff60e280 100644 (file)
@@ -36,10 +36,10 @@ bool isRestoreOnly(int argc, char **argv)
 
 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) {
index 7b132513ecec5cc3f2f70b20c06ccf000dd9651b..ea94d5881e66bc9ad3f5e5cd87ea5b083470e666 100644 (file)
@@ -43,6 +43,8 @@
 
 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";
@@ -138,7 +140,28 @@ static void remount_image_sessions(int uid) try
        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
@@ -170,6 +193,15 @@ void restore_all_user_sessions()
 
                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);
+               }
        }
 }
 
index 146b4106cbb57afcba1afc639c858db4c2fe90f7..d458ddaa6c0c98417fcb0a01be09e7db8e980249 100644 (file)
@@ -22,4 +22,4 @@
 
 #pragma once
 
-void restore_all_user_sessions();
+void restore_all_user_sessions(bool only_restore);
index 522b58572a298215e7486f2270255ff2a6c1a661..4533ab16172ce51af993d3b33a1c6c567b005d31 100644 (file)
@@ -154,15 +154,16 @@ TEST(subsession_get_user_list, GetUserListOk) {
 
        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);
 }