+ return -EINVAL;
+}
+
+static int transaction_merge_jobs(Manager *m) {
+ Job *j;
+ Iterator i;
+ int r;
+
+ assert(m);
+
+ /* First step, check whether any of the jobs for one specific
+ * task conflict. If so, try to drop one of them. */
+ HASHMAP_FOREACH(j, m->transaction_jobs, i) {
+ JobType t;
+ Job *k;
+
+ t = j->type;
+ LIST_FOREACH(transaction, k, j->transaction_next) {
+ if ((r = job_type_merge(&t, k->type)) >= 0)
+ continue;
+
+ /* OK, we could not merge all jobs for this
+ * action. Let's see if we can get rid of one
+ * of them */
+
+ if ((r = delete_one_unmergeable_job(m, j)) >= 0)
+ /* Ok, we managed to drop one, now
+ * let's ask our callers to call us
+ * again after garbage collecting */
+ return -EAGAIN;
+
+ /* We couldn't merge anything. Failure */
+ return r;
+ }
+ }
+
+ /* Second step, merge the jobs. */
+ HASHMAP_FOREACH(j, m->transaction_jobs, i) {
+ JobType t = j->type;
+ Job *k;
+
+ /* Merge all transactions */
+ LIST_FOREACH(transaction, k, j->transaction_next)
+ assert_se(job_type_merge(&t, k->type) == 0);
+
+ /* If an active job is mergeable, merge it too */
+ if (j->unit->meta.job)
+ job_type_merge(&t, j->unit->meta.job->type); /* Might fail. Which is OK */
+
+ while ((k = j->transaction_next)) {
+ if (j->installed) {
+ transaction_merge_and_delete_job(m, k, j, t);
+ j = k;
+ } else
+ transaction_merge_and_delete_job(m, j, k, t);
+ }
+
+ assert(!j->transaction_next);
+ assert(!j->transaction_prev);
+ }
+
+ return 0;
+}
+
+static bool unit_matters_to_anchor(Unit *u, Job *j) {
+ assert(u);
+ assert(!j->transaction_prev);
+
+ /* Checks whether at least one of the jobs for this unit
+ * matters to the anchor. */
+
+ LIST_FOREACH(transaction, j, j)
+ if (j->matters_to_anchor)
+ return true;
+
+ return false;
+}
+
+static int transaction_verify_order_one(Manager *m, Job *j, Job *from, unsigned generation) {
+ Iterator i;
+ Unit *u;
+ int r;
+
+ assert(m);
+ assert(j);
+ assert(!j->transaction_prev);
+
+ /* Does a recursive sweep through the ordering graph, looking
+ * for a cycle. If we find cycle we try to break it. */
+
+ /* Did we find a cycle? */
+ if (j->marker && j->generation == generation) {
+ Job *k;
+
+ /* So, we already have been here. We have a
+ * cycle. Let's try to break it. We go backwards in
+ * our path and try to find a suitable job to
+ * remove. We use the marker to find our way back,
+ * since smart how we are we stored our way back in
+ * there. */
+
+ log_debug("Found cycle on %s/%s", unit_id(j->unit), job_type_to_string(j->type));
+
+ for (k = from; k; k = (k->generation == generation ? k->marker : NULL)) {
+
+ log_debug("Walked on cycle path to %s/%s", unit_id(j->unit), job_type_to_string(j->type));
+
+ if (!k->installed &&
+ !unit_matters_to_anchor(k->unit, k)) {
+ /* Ok, we can drop this one, so let's
+ * do so. */
+ log_debug("Breaking order cycle by deleting job %s/%s", unit_id(k->unit), job_type_to_string(k->type));
+ transaction_delete_unit(m, k->unit);
+ return -EAGAIN;
+ }
+
+ /* Check if this in fact was the beginning of
+ * the cycle */
+ if (k == j)
+ break;
+ }
+
+ log_debug("Unable to break cycle");
+
+ return -ENOEXEC;
+ }
+
+ /* Make the marker point to where we come from, so that we can
+ * find our way backwards if we want to break a cycle */
+ j->marker = from;
+ j->generation = generation;
+
+ /* We assume that the the dependencies are bidirectional, and
+ * hence can ignore UNIT_AFTER */
+ SET_FOREACH(u, j->unit->meta.dependencies[UNIT_BEFORE], i) {
+ Job *o;
+
+ /* Is there a job for this unit? */
+ if (!(o = hashmap_get(m->transaction_jobs, u)))
+
+ /* Ok, there is no job for this in the
+ * transaction, but maybe there is already one
+ * running? */
+ if (!(o = u->meta.job))
+ continue;
+
+ if ((r = transaction_verify_order_one(m, o, j, generation)) < 0)
+ return r;