]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/scope.c
core: unify call we use to synthesize cgroup empty events when we stopped watching...
[thirdparty/systemd.git] / src / core / scope.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
6c12b52e
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
21#include <errno.h>
6c12b52e
LP
22#include <unistd.h>
23
b5efdb8a 24#include "alloc-util.h"
07630cea
LP
25#include "dbus-scope.h"
26#include "load-dropin.h"
6c12b52e 27#include "log.h"
b5efdb8a 28#include "scope.h"
6c12b52e 29#include "special.h"
8b43440b 30#include "string-table.h"
07630cea
LP
31#include "string-util.h"
32#include "strv.h"
6c12b52e 33#include "unit-name.h"
efdb0237 34#include "unit.h"
6c12b52e
LP
35
36static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
37 [SCOPE_DEAD] = UNIT_INACTIVE,
38 [SCOPE_RUNNING] = UNIT_ACTIVE,
a911bb9a 39 [SCOPE_ABANDONED] = UNIT_ACTIVE,
6c12b52e
LP
40 [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING,
41 [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING,
42 [SCOPE_FAILED] = UNIT_FAILED
43};
44
718db961
LP
45static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
46
6c12b52e
LP
47static void scope_init(Unit *u) {
48 Scope *s = SCOPE(u);
49
50 assert(u);
51 assert(u->load_state == UNIT_STUB);
52
1f19a534 53 s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
1b4cd0cf 54 u->ignore_on_isolate = true;
6c12b52e
LP
55}
56
57static void scope_done(Unit *u) {
58 Scope *s = SCOPE(u);
59
60 assert(u);
61
371c0b79
LP
62 s->controller = mfree(s->controller);
63 s->controller_track = sd_bus_track_unref(s->controller_track);
2d4a39e7 64
718db961
LP
65 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
66}
67
36c16a7c 68static int scope_arm_timer(Scope *s, usec_t usec) {
718db961
LP
69 int r;
70
71 assert(s);
72
718db961 73 if (s->timer_event_source) {
36c16a7c 74 r = sd_event_source_set_time(s->timer_event_source, usec);
718db961
LP
75 if (r < 0)
76 return r;
77
78 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
79 }
80
36c16a7c
LP
81 if (usec == USEC_INFINITY)
82 return 0;
83
cbf60d0a 84 r = sd_event_add_time(
6a0f1f6d
LP
85 UNIT(s)->manager->event,
86 &s->timer_event_source,
87 CLOCK_MONOTONIC,
36c16a7c 88 usec, 0,
6a0f1f6d 89 scope_dispatch_timer, s);
7dfbe2e3
TG
90 if (r < 0)
91 return r;
92
93 (void) sd_event_source_set_description(s->timer_event_source, "scope-timer");
94
95 return 0;
6c12b52e
LP
96}
97
98static void scope_set_state(Scope *s, ScopeState state) {
99 ScopeState old_state;
100 assert(s);
101
102 old_state = s->state;
103 s->state = state;
104
a911bb9a 105 if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
718db961 106 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
6c12b52e 107
a911bb9a
LP
108 if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED))
109 unit_unwatch_all_pids(UNIT(s));
110
6c12b52e 111 if (state != old_state)
a911bb9a 112 log_debug("%s changed %s -> %s", UNIT(s)->id, scope_state_to_string(old_state), scope_state_to_string(state));
6c12b52e
LP
113
114 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
115}
116
117static int scope_add_default_dependencies(Scope *s) {
118 int r;
119
120 assert(s);
121
4c9ea260
LP
122 if (!UNIT(s)->default_dependencies)
123 return 0;
124
6c12b52e
LP
125 /* Make sure scopes are unloaded on shutdown */
126 r = unit_add_two_dependencies_by_name(
127 UNIT(s),
128 UNIT_BEFORE, UNIT_CONFLICTS,
eef85c4a
LP
129 SPECIAL_SHUTDOWN_TARGET, NULL, true,
130 UNIT_DEPENDENCY_DEFAULT);
6c12b52e
LP
131 if (r < 0)
132 return r;
133
134 return 0;
135}
136
137static int scope_verify(Scope *s) {
138 assert(s);
139
140 if (UNIT(s)->load_state != UNIT_LOADED)
141 return 0;
142
efdb0237 143 if (set_isempty(UNIT(s)->pids) &&
2c289ea8 144 !MANAGER_IS_RELOADING(UNIT(s)->manager) &&
efdb0237 145 !unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) {
f2341e0a 146 log_unit_error(UNIT(s), "Scope has no PIDs. Refusing.");
6c12b52e
LP
147 return -EINVAL;
148 }
149
150 return 0;
151}
152
8e4e851f
LP
153static int scope_load_init_scope(Unit *u) {
154 assert(u);
155
156 if (!unit_has_name(u, SPECIAL_INIT_SCOPE))
157 return 0;
158
159 u->transient = true;
f5869324 160 u->perpetual = true;
8e4e851f
LP
161
162 /* init.scope is a bit special, as it has to stick around forever. Because of its special semantics we
163 * synthesize it here, instead of relying on the unit file on disk. */
164
165 u->default_dependencies = false;
166 u->ignore_on_isolate = true;
8e4e851f
LP
167
168 SCOPE(u)->kill_context.kill_signal = SIGRTMIN+14;
169
170 /* Prettify things, if we can. */
171 if (!u->description)
172 u->description = strdup("System and Service Manager");
173 if (!u->documentation)
174 (void) strv_extend(&u->documentation, "man:systemd(1)");
175
176 return 1;
177}
178
6c12b52e
LP
179static int scope_load(Unit *u) {
180 Scope *s = SCOPE(u);
181 int r;
182
183 assert(s);
184 assert(u->load_state == UNIT_STUB);
185
2c289ea8 186 if (!u->transient && !MANAGER_IS_RELOADING(u->manager))
4f4afc88 187 /* Refuse to load non-transient scope units, but allow them while reloading. */
6c12b52e
LP
188 return -ENOENT;
189
8e4e851f
LP
190 r = scope_load_init_scope(u);
191 if (r < 0)
192 return r;
4f4afc88 193 r = unit_load_fragment_and_dropin_optional(u);
6c12b52e
LP
194 if (r < 0)
195 return r;
196
4f4afc88
LP
197 if (u->load_state == UNIT_LOADED) {
198 r = unit_patch_contexts(u);
199 if (r < 0)
200 return r;
598459ce 201
4f4afc88
LP
202 r = unit_set_default_slice(u);
203 if (r < 0)
204 return r;
6c12b52e 205
4f4afc88
LP
206 r = scope_add_default_dependencies(s);
207 if (r < 0)
208 return r;
209 }
6c12b52e
LP
210
211 return scope_verify(s);
212}
213
be847e82 214static int scope_coldplug(Unit *u) {
6c12b52e
LP
215 Scope *s = SCOPE(u);
216 int r;
217
218 assert(s);
219 assert(s->state == SCOPE_DEAD);
220
36c16a7c
LP
221 if (s->deserialized_state == s->state)
222 return 0;
a911bb9a 223
36c16a7c
LP
224 if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
225 r = scope_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_stop_usec));
226 if (r < 0)
227 return r;
6c12b52e
LP
228 }
229
36c16a7c
LP
230 if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
231 unit_watch_all_pids(UNIT(s));
232
371c0b79
LP
233 bus_scope_track_controller(s);
234
36c16a7c 235 scope_set_state(s, s->deserialized_state);
6c12b52e
LP
236 return 0;
237}
238
239static void scope_dump(Unit *u, FILE *f, const char *prefix) {
240 Scope *s = SCOPE(u);
241
242 assert(s);
243 assert(f);
244
245 fprintf(f,
246 "%sScope State: %s\n"
247 "%sResult: %s\n",
248 prefix, scope_state_to_string(s->state),
249 prefix, scope_result_to_string(s->result));
250
251 cgroup_context_dump(&s->cgroup_context, f, prefix);
252 kill_context_dump(&s->kill_context, f, prefix);
253}
254
255static void scope_enter_dead(Scope *s, ScopeResult f) {
256 assert(s);
257
a0fef983 258 if (s->result == SCOPE_SUCCESS)
6c12b52e
LP
259 s->result = f;
260
ed77d407
LP
261 if (s->result != SCOPE_SUCCESS)
262 log_unit_warning(UNIT(s), "Failed with result '%s'.", scope_result_to_string(s->result));
263
6c12b52e
LP
264 scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
265}
266
267static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
2d4a39e7 268 bool skip_signal = false;
6c12b52e
LP
269 int r;
270
271 assert(s);
272
a0fef983 273 if (s->result == SCOPE_SUCCESS)
6c12b52e
LP
274 s->result = f;
275
a911bb9a
LP
276 unit_watch_all_pids(UNIT(s));
277
371c0b79
LP
278 /* If we have a controller set let's ask the controller nicely to terminate the scope, instead of us going
279 * directly into SIGTERM berserk mode */
2d4a39e7
LP
280 if (state == SCOPE_STOP_SIGTERM)
281 skip_signal = bus_scope_send_request_stop(s) > 0;
282
59ec09a8
ZJS
283 if (skip_signal)
284 r = 1; /* wait */
285 else {
2d4a39e7
LP
286 r = unit_kill_context(
287 UNIT(s),
288 &s->kill_context,
3862e809
LP
289 state != SCOPE_STOP_SIGTERM ? KILL_KILL :
290 s->was_abandoned ? KILL_TERMINATE_AND_LOG :
291 KILL_TERMINATE,
2d4a39e7
LP
292 -1, -1, false);
293 if (r < 0)
294 goto fail;
59ec09a8 295 }
6c12b52e
LP
296
297 if (r > 0) {
36c16a7c 298 r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec));
718db961
LP
299 if (r < 0)
300 goto fail;
6c12b52e
LP
301
302 scope_set_state(s, state);
ac84d1fb
LP
303 } else if (state == SCOPE_STOP_SIGTERM)
304 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
305 else
6c12b52e
LP
306 scope_enter_dead(s, SCOPE_SUCCESS);
307
308 return;
309
310fail:
f2341e0a 311 log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
6c12b52e
LP
312
313 scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
314}
315
316static int scope_start(Unit *u) {
317 Scope *s = SCOPE(u);
318 int r;
319
320 assert(s);
321
efdb0237
LP
322 if (unit_has_name(u, SPECIAL_INIT_SCOPE))
323 return -EPERM;
324
7b617155
LP
325 if (s->state == SCOPE_FAILED)
326 return -EPERM;
327
dd305ec9 328 /* We can't fulfill this right now, please try again later */
3742095b 329 if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
6c12b52e
LP
330 return -EAGAIN;
331
332 assert(s->state == SCOPE_DEAD);
333
2c289ea8 334 if (!u->transient && !MANAGER_IS_RELOADING(u->manager))
6c12b52e
LP
335 return -ENOENT;
336
371c0b79
LP
337 (void) bus_scope_track_controller(s);
338
4b58153d
LP
339 r = unit_acquire_invocation_id(u);
340 if (r < 0)
341 return r;
342
5ad096b3 343 (void) unit_realize_cgroup(u);
906c06f6
DM
344 (void) unit_reset_cpu_accounting(u);
345 (void) unit_reset_ip_accounting(u);
5ad096b3 346
d3070fbd
LP
347 unit_export_state_files(UNIT(s));
348
7b3fd631 349 r = unit_attach_pids_to_cgroup(u);
dd305ec9 350 if (r < 0) {
f2341e0a 351 log_unit_warning_errno(UNIT(s), r, "Failed to add PIDs to scope's control group: %m");
68a01fb6 352 scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
6c12b52e 353 return r;
dd305ec9 354 }
6c12b52e 355
6c12b52e
LP
356 s->result = SCOPE_SUCCESS;
357
358 scope_set_state(s, SCOPE_RUNNING);
82a2b6bb 359 return 1;
6c12b52e
LP
360}
361
362static int scope_stop(Unit *u) {
363 Scope *s = SCOPE(u);
364
365 assert(s);
6c12b52e 366
3742095b 367 if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
6c12b52e
LP
368 return 0;
369
3742095b 370 assert(IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED));
6c12b52e
LP
371
372 scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
82a2b6bb 373 return 1;
6c12b52e
LP
374}
375
8bcca7e2
LP
376static void scope_reset_failed(Unit *u) {
377 Scope *s = SCOPE(u);
378
379 assert(s);
380
381 if (s->state == SCOPE_FAILED)
382 scope_set_state(s, SCOPE_DEAD);
383
384 s->result = SCOPE_SUCCESS;
385}
386
718db961 387static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
6c12b52e
LP
388 return unit_kill_common(u, who, signo, -1, -1, error);
389}
390
7a7821c8 391static int scope_get_timeout(Unit *u, usec_t *timeout) {
68db7a3b 392 Scope *s = SCOPE(u);
7a7821c8 393 usec_t t;
68db7a3b
ZJS
394 int r;
395
396 if (!s->timer_event_source)
397 return 0;
398
7a7821c8 399 r = sd_event_source_get_time(s->timer_event_source, &t);
68db7a3b
ZJS
400 if (r < 0)
401 return r;
7a7821c8
LP
402 if (t == USEC_INFINITY)
403 return 0;
68db7a3b 404
7a7821c8 405 *timeout = t;
68db7a3b
ZJS
406 return 1;
407}
408
6c12b52e
LP
409static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
410 Scope *s = SCOPE(u);
411
412 assert(s);
413 assert(f);
414 assert(fds);
415
416 unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
3862e809 417 unit_serialize_item(u, f, "was-abandoned", yes_no(s->was_abandoned));
33fe0afe
LP
418
419 if (s->controller)
420 unit_serialize_item(u, f, "controller", s->controller);
421
6c12b52e
LP
422 return 0;
423}
424
425static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
426 Scope *s = SCOPE(u);
33fe0afe 427 int r;
6c12b52e
LP
428
429 assert(u);
430 assert(key);
431 assert(value);
432 assert(fds);
433
434 if (streq(key, "state")) {
435 ScopeState state;
436
437 state = scope_state_from_string(value);
438 if (state < 0)
f2341e0a 439 log_unit_debug(u, "Failed to parse state value: %s", value);
6c12b52e
LP
440 else
441 s->deserialized_state = state;
442
3862e809
LP
443 } else if (streq(key, "was-abandoned")) {
444 int k;
445
446 k = parse_boolean(value);
447 if (k < 0)
448 log_unit_debug(u, "Failed to parse boolean value: %s", value);
449 else
450 s->was_abandoned = k;
33fe0afe
LP
451 } else if (streq(key, "controller")) {
452
453 r = free_and_strdup(&s->controller, value);
454 if (r < 0)
455 log_oom();
456
6c12b52e 457 } else
f2341e0a 458 log_unit_debug(u, "Unknown serialization key: %s", key);
6c12b52e
LP
459
460 return 0;
461}
462
a911bb9a
LP
463static void scope_notify_cgroup_empty_event(Unit *u) {
464 Scope *s = SCOPE(u);
465 assert(u);
466
f2341e0a 467 log_unit_debug(u, "cgroup is empty");
a911bb9a
LP
468
469 if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
470 scope_enter_dead(s, SCOPE_SUCCESS);
471}
472
473static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
474
11aef522 475 assert(u);
a911bb9a 476
11aef522
LP
477 /* If we get a SIGCHLD event for one of the processes we were interested in, then we look for others to
478 * watch, under the assumption that we'll sooner or later get a SIGCHLD for them, as the original
479 * process we watched was probably the parent of them, and they are hence now our children. */
a911bb9a
LP
480 unit_tidy_watch_pids(u, 0, 0);
481 unit_watch_all_pids(u);
482
11aef522
LP
483 /* If the PID set is empty now, then let's finish this off. */
484 unit_synthesize_cgroup_empty_event(u);
a911bb9a
LP
485}
486
718db961
LP
487static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
488 Scope *s = SCOPE(userdata);
6c12b52e
LP
489
490 assert(s);
718db961 491 assert(s->timer_event_source == source);
6c12b52e
LP
492
493 switch (s->state) {
494
495 case SCOPE_STOP_SIGTERM:
496 if (s->kill_context.send_sigkill) {
f2341e0a 497 log_unit_warning(UNIT(s), "Stopping timed out. Killing.");
6c12b52e
LP
498 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
499 } else {
f2341e0a 500 log_unit_warning(UNIT(s), "Stopping timed out. Skipping SIGKILL.");
6c12b52e
LP
501 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
502 }
503
504 break;
505
506 case SCOPE_STOP_SIGKILL:
f2341e0a 507 log_unit_warning(UNIT(s), "Still around after SIGKILL. Ignoring.");
6c12b52e
LP
508 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
509 break;
510
511 default:
512 assert_not_reached("Timeout at wrong time.");
513 }
718db961
LP
514
515 return 0;
6c12b52e
LP
516}
517
a911bb9a
LP
518int scope_abandon(Scope *s) {
519 assert(s);
6c12b52e 520
efdb0237
LP
521 if (unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE))
522 return -EPERM;
523
a911bb9a
LP
524 if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED))
525 return -ESTALE;
6c12b52e 526
3862e809 527 s->was_abandoned = true;
371c0b79 528
a1e58e8e 529 s->controller = mfree(s->controller);
371c0b79
LP
530 s->controller_track = sd_bus_track_unref(s->controller_track);
531
8cb83266 532 scope_set_state(s, SCOPE_ABANDONED);
6c12b52e 533
a911bb9a
LP
534 /* The client is no longer watching the remaining processes,
535 * so let's step in here, under the assumption that the
536 * remaining processes will be sooner or later reassigned to
537 * us as parent. */
6c12b52e 538
a911bb9a
LP
539 unit_tidy_watch_pids(UNIT(s), 0, 0);
540 unit_watch_all_pids(UNIT(s));
6c12b52e 541
a911bb9a 542 return 0;
6c12b52e
LP
543}
544
545_pure_ static UnitActiveState scope_active_state(Unit *u) {
546 assert(u);
547
548 return state_translation_table[SCOPE(u)->state];
549}
550
551_pure_ static const char *scope_sub_state_to_string(Unit *u) {
552 assert(u);
553
554 return scope_state_to_string(SCOPE(u)->state);
555}
556
ba64af90 557static void scope_enumerate(Manager *m) {
efdb0237
LP
558 Unit *u;
559 int r;
560
561 assert(m);
562
563 /* Let's unconditionally add the "init.scope" special unit
564 * that encapsulates PID 1. Note that PID 1 already is in the
565 * cgroup for this, we hence just need to allocate the object
566 * for it and that's it. */
567
568 u = manager_get_unit(m, SPECIAL_INIT_SCOPE);
569 if (!u) {
a581e45a 570 r = unit_new_for_name(m, sizeof(Scope), SPECIAL_INIT_SCOPE, &u);
efdb0237 571 if (r < 0) {
a581e45a 572 log_error_errno(r, "Failed to allocate the special " SPECIAL_INIT_SCOPE " unit: %m");
ba64af90 573 return;
efdb0237
LP
574 }
575 }
576
577 u->transient = true;
f5869324 578 u->perpetual = true;
efdb0237 579 SCOPE(u)->deserialized_state = SCOPE_RUNNING;
efdb0237
LP
580
581 unit_add_to_load_queue(u);
582 unit_add_to_dbus_queue(u);
efdb0237
LP
583}
584
6c12b52e
LP
585static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
586 [SCOPE_SUCCESS] = "success",
587 [SCOPE_FAILURE_RESOURCES] = "resources",
588 [SCOPE_FAILURE_TIMEOUT] = "timeout",
589};
590
591DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
592
593const UnitVTable scope_vtable = {
594 .object_size = sizeof(Scope),
718db961
LP
595 .cgroup_context_offset = offsetof(Scope, cgroup_context),
596 .kill_context_offset = offsetof(Scope, kill_context),
597
6c12b52e
LP
598 .sections =
599 "Unit\0"
600 "Scope\0"
601 "Install\0",
6c12b52e 602 .private_section = "Scope",
6c12b52e 603
700e2d63 604 .can_transient = true,
6c12b52e
LP
605
606 .init = scope_init,
607 .load = scope_load,
608 .done = scope_done,
609
610 .coldplug = scope_coldplug,
611
612 .dump = scope_dump,
613
614 .start = scope_start,
615 .stop = scope_stop,
616
617 .kill = scope_kill,
618
68db7a3b
ZJS
619 .get_timeout = scope_get_timeout,
620
6c12b52e
LP
621 .serialize = scope_serialize,
622 .deserialize_item = scope_deserialize_item,
623
624 .active_state = scope_active_state,
625 .sub_state_to_string = scope_sub_state_to_string,
626
a911bb9a
LP
627 .sigchld_event = scope_sigchld_event,
628
8bcca7e2
LP
629 .reset_failed = scope_reset_failed,
630
6c12b52e
LP
631 .notify_cgroup_empty = scope_notify_cgroup_empty_event,
632
718db961 633 .bus_vtable = bus_scope_vtable,
6c12b52e
LP
634 .bus_set_property = bus_scope_set_property,
635 .bus_commit_properties = bus_scope_commit_properties,
636
efdb0237 637 .enumerate = scope_enumerate,
6c12b52e 638};