int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value, FDSet *fds) {
        _cleanup_(exec_runtime_freep) ExecRuntime *rt_create = NULL;
        ExecRuntime *rt;
        int r;

        /* This is for the migration from old (v237 or earlier) deserialization text.
         * Due to the bug #7790, this may not work with the units that use JoinsNamespaceOf=.
         * Even if the ExecRuntime object originally created by the other unit, we cannot judge
         * so or not from the serialized text, then we always creates a new object owned by this. */

        assert(u);
        assert(key);
        assert(value);

        /* Manager manages ExecRuntime objects by the unit id.
         * So, we omit the serialized text when the unit does not have id (yet?)... */
        if (isempty(u->id)) {
                log_unit_debug(u, "Invocation ID not found. Dropping runtime parameter.");
                return 0;
        }

        r = hashmap_ensure_allocated(&u->manager->exec_runtime_by_id, &string_hash_ops);
        if (r < 0) {
                log_unit_debug_errno(u, r, "Failed to allocate storage for runtime parameter: %m");
                return 0;
        }

        rt = hashmap_get(u->manager->exec_runtime_by_id, u->id);
        if (!rt) {
                r = exec_runtime_allocate(&rt_create);
                if (r < 0)
                        return log_oom();

                rt_create->id = strdup(u->id);
                if (!rt_create->id)
                        return log_oom();

                rt = rt_create;
        }

        if (streq(key, "tmp-dir")) {
                char *copy;

                copy = strdup(value);
                if (!copy)
                        return log_oom();

                free_and_replace(rt->tmp_dir, copy);

        } else if (streq(key, "var-tmp-dir")) {
                char *copy;

                copy = strdup(value);
                if (!copy)
                        return log_oom();

                free_and_replace(rt->var_tmp_dir, copy);

        } else if (streq(key, "netns-socket-0")) {
                int fd;

                if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) {
                        log_unit_debug(u, "Failed to parse netns socket value: %s", value);
                        return 0;
                }

                safe_close(rt->netns_storage_socket[0]);
                rt->netns_storage_socket[0] = fdset_remove(fds, fd);

        } else if (streq(key, "netns-socket-1")) {
                int fd;

                if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) {
                        log_unit_debug(u, "Failed to parse netns socket value: %s", value);
                        return 0;
                }

                safe_close(rt->netns_storage_socket[1]);
                rt->netns_storage_socket[1] = fdset_remove(fds, fd);
        } else
                return 0;

        /* If the object is newly created, then put it to the hashmap which manages ExecRuntime objects. */
        if (rt_create) {
                r = hashmap_put(u->manager->exec_runtime_by_id, rt_create->id, rt_create);
                if (r < 0) {
                        log_unit_debug_errno(u, r, "Failed to put runtime parameter to manager's storage: %m");
                        return 0;
                }

                rt_create->manager = u->manager;

                /* Avoid cleanup */
                rt_create = NULL;
        }

        return 1;
}