core: rework how we deserialize jobs

Let's add a helper call unit_deserialize_job() for this purpose, and
let's move registration in the global jobs hash table into
job_install_deserialized() so that it it is done after all superficial
checks are done, and before transitioning into installed states, so that
rollback code is not necessary anymore.
This commit is contained in:
Lennart Poettering 2018-12-10 19:40:37 +01:00
parent 48235ad6b7
commit b17c9620c8
3 changed files with 40 additions and 30 deletions

View file

@ -244,19 +244,25 @@ Job* job_install(Job *j) {
int job_install_deserialized(Job *j) {
Job **pj;
int r;
assert(!j->installed);
if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION)
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
return log_unit_debug_errno(j->unit, SYNTHETIC_ERRNO(EINVAL),
"Invalid job type %s in deserialization.",
strna(job_type_to_string(j->type)));
pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
if (*pj) {
log_unit_debug(j->unit, "Unit already has a job installed. Not installing deserialized job.");
return -EEXIST;
}
if (*pj)
return log_unit_debug_errno(j->unit, SYNTHETIC_ERRNO(EEXIST),
"Unit already has a job installed. Not installing deserialized job.");
r = hashmap_put(j->manager->jobs, UINT32_TO_PTR(j->id), j);
if (r == -EEXIST)
return log_unit_debug_errno(j->unit, r, "Job ID %" PRIu32 " already used, cannot deserialize job.", j->id);
if (r < 0)
return log_unit_debug_errno(j->unit, r, "Failed to insert job into jobs hash table: %m");
*pj = j;
j->installed = true;

View file

@ -222,6 +222,8 @@ void job_add_to_gc_queue(Job *j);
int job_get_before(Job *j, Job*** ret);
int job_get_after(Job *j, Job*** ret);
DEFINE_TRIVIAL_CLEANUP_FUNC(Job*, job_free);
const char* job_type_to_string(JobType t) _const_;
JobType job_type_from_string(const char *s) _pure_;

View file

@ -3288,6 +3288,29 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
return 0;
}
static int unit_deserialize_job(Unit *u, FILE *f) {
_cleanup_(job_freep) Job *j = NULL;
int r;
assert(u);
assert(f);
j = job_new_raw(u);
if (!j)
return log_oom();
r = job_deserialize(j, f);
if (r < 0)
return r;
r = job_install_deserialized(j);
if (r < 0)
return r;
TAKE_PTR(j);
return 0;
}
int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
int r;
@ -3321,32 +3344,11 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
if (streq(l, "job")) {
if (v[0] == '\0') {
/* new-style serialized job */
Job *j;
j = job_new_raw(u);
if (!j)
return log_oom();
r = job_deserialize(j, f);
if (r < 0) {
job_free(j);
/* New-style serialized job */
r = unit_deserialize_job(u, f);
if (r < 0)
return r;
}
r = hashmap_put(u->manager->jobs, UINT32_TO_PTR(j->id), j);
if (r < 0) {
job_free(j);
return r;
}
r = job_install_deserialized(j);
if (r < 0) {
hashmap_remove(u->manager->jobs, UINT32_TO_PTR(j->id));
job_free(j);
return r;
}
} else /* legacy for pre-44 */
} else /* Legacy for pre-44 */
log_unit_warning(u, "Update from too old systemd versions are unsupported, cannot deserialize job: %s", v);
continue;
} else if (streq(l, "state-change-timestamp")) {