In most cases we're just reading from m.plan fields (Services,
DefaultServiceNames, and so on), so we can use m.Plan(), which holds
the plan lock only for the duration of fetch m.plan -- this is safe,
because we never mutate what's inside m.plan, we only replace it (in
updatePlan).
This also means that in functions like Services() we're only holding
either the plan lock or the services lock at once, not both -- avoiding
the 3-way deadlock described in #314.
For the cases we are updating the plan (AppendLayer, CombineLayer,
SetServiceArgs), we still need acquirePlan.
In ServiceManager.ServiceLogs, we don't need to acquire the plan lock
at all (m.plan isn't used).
In most cases we're just reading from m.plan fields (Services, DefaultServiceNames, and so on), so we can use m.Plan(), which holds the plan lock only for the duration of fetch m.plan -- this is safe, because we never mutate what's inside m.plan, we only replace it (in updatePlan).
This also means that in functions like Services() we're only holding either the plan lock or the services lock at once, not both -- avoiding the 3-way deadlock described in #314.
For the cases we are updating the plan (AppendLayer, CombineLayer, SetServiceArgs), we still need acquirePlan.
In ServiceManager.ServiceLogs, we don't need to acquire the plan lock at all (m.plan isn't used).
Fixes #314.