Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1# SPDX-License-Identifier: GPL-2.0
2
3import os
4
5ksft_skip=4
6
7sysfs_root = None
8with open('/proc/mounts', 'r') as f:
9 for line in f:
10 dev_name, mount_point, dev_fs = line.split()[:3]
11 if dev_fs == 'sysfs':
12 sysfs_root = '%s/kernel/mm/damon/admin' % mount_point
13 break
14if sysfs_root is None:
15 print('Seems sysfs not mounted?')
16 exit(ksft_skip)
17
18if not os.path.exists(sysfs_root):
19 print('Seems DAMON disabled?')
20 exit(ksft_skip)
21
22def write_file(path, string):
23 "Returns error string if failed, or None otherwise"
24 string = '%s' % string
25 try:
26 with open(path, 'w') as f:
27 f.write(string)
28 except Exception as e:
29 return '%s' % e
30 return None
31
32def read_file(path):
33 '''Returns the read content and error string. The read content is None if
34 the reading failed'''
35 try:
36 with open(path, 'r') as f:
37 return f.read(), None
38 except Exception as e:
39 return None, '%s' % e
40
41class DamosAccessPattern:
42 size = None
43 nr_accesses = None
44 age = None
45 scheme = None
46
47 def __init__(self, size=None, nr_accesses=None, age=None):
48 self.size = size
49 self.nr_accesses = nr_accesses
50 self.age = age
51
52 if self.size is None:
53 self.size = [0, 2**64 - 1]
54 if self.nr_accesses is None:
55 self.nr_accesses = [0, 2**32 - 1]
56 if self.age is None:
57 self.age = [0, 2**32 - 1]
58
59 def sysfs_dir(self):
60 return os.path.join(self.scheme.sysfs_dir(), 'access_pattern')
61
62 def stage(self):
63 err = write_file(
64 os.path.join(self.sysfs_dir(), 'sz', 'min'), self.size[0])
65 if err is not None:
66 return err
67 err = write_file(
68 os.path.join(self.sysfs_dir(), 'sz', 'max'), self.size[1])
69 if err is not None:
70 return err
71 err = write_file(os.path.join(self.sysfs_dir(), 'nr_accesses', 'min'),
72 self.nr_accesses[0])
73 if err is not None:
74 return err
75 err = write_file(os.path.join(self.sysfs_dir(), 'nr_accesses', 'max'),
76 self.nr_accesses[1])
77 if err is not None:
78 return err
79 err = write_file(
80 os.path.join(self.sysfs_dir(), 'age', 'min'), self.age[0])
81 if err is not None:
82 return err
83 err = write_file(
84 os.path.join(self.sysfs_dir(), 'age', 'max'), self.age[1])
85 if err is not None:
86 return err
87
88qgoal_metric_user_input = 'user_input'
89qgoal_metric_some_mem_psi_us = 'some_mem_psi_us'
90qgoal_metrics = [qgoal_metric_user_input, qgoal_metric_some_mem_psi_us]
91
92class DamosQuotaGoal:
93 metric = None
94 target_value = None
95 current_value = None
96 nid = None
97 effective_bytes = None
98 quota = None # owner quota
99 idx = None
100
101 def __init__(self, metric, target_value=10000, current_value=0, nid=0):
102 self.metric = metric
103 self.target_value = target_value
104 self.current_value = current_value
105 self.nid = nid
106
107 def sysfs_dir(self):
108 return os.path.join(self.quota.sysfs_dir(), 'goals', '%d' % self.idx)
109
110 def stage(self):
111 err = write_file(os.path.join(self.sysfs_dir(), 'target_metric'),
112 self.metric)
113 if err is not None:
114 return err
115 err = write_file(os.path.join(self.sysfs_dir(), 'target_value'),
116 self.target_value)
117 if err is not None:
118 return err
119 err = write_file(os.path.join(self.sysfs_dir(), 'current_value'),
120 self.current_value)
121 if err is not None:
122 return err
123 err = write_file(os.path.join(self.sysfs_dir(), 'nid'), self.nid)
124 if err is not None:
125 return err
126
127 return None
128
129class DamosQuota:
130 sz = None # size quota, in bytes
131 ms = None # time quota
132 goals = None # quota goals
133 reset_interval_ms = None # quota reset interval
134 weight_sz_permil = None
135 weight_nr_accesses_permil = None
136 weight_age_permil = None
137 scheme = None # owner scheme
138
139 def __init__(self, sz=0, ms=0, goals=None, reset_interval_ms=0,
140 weight_sz_permil=0, weight_nr_accesses_permil=0,
141 weight_age_permil=0):
142 self.sz = sz
143 self.ms = ms
144 self.reset_interval_ms = reset_interval_ms
145 self.weight_sz_permil = weight_sz_permil
146 self.weight_nr_accesses_permil = weight_nr_accesses_permil
147 self.weight_age_permil = weight_age_permil
148 self.goals = goals if goals is not None else []
149 for idx, goal in enumerate(self.goals):
150 goal.idx = idx
151 goal.quota = self
152
153 def sysfs_dir(self):
154 return os.path.join(self.scheme.sysfs_dir(), 'quotas')
155
156 def stage(self):
157 err = write_file(os.path.join(self.sysfs_dir(), 'bytes'), self.sz)
158 if err is not None:
159 return err
160 err = write_file(os.path.join(self.sysfs_dir(), 'ms'), self.ms)
161 if err is not None:
162 return err
163 err = write_file(os.path.join(self.sysfs_dir(), 'reset_interval_ms'),
164 self.reset_interval_ms)
165 if err is not None:
166 return err
167
168 err = write_file(os.path.join(
169 self.sysfs_dir(), 'weights', 'sz_permil'), self.weight_sz_permil)
170 if err is not None:
171 return err
172 err = write_file(os.path.join(
173 self.sysfs_dir(), 'weights', 'nr_accesses_permil'),
174 self.weight_nr_accesses_permil)
175 if err is not None:
176 return err
177 err = write_file(os.path.join(
178 self.sysfs_dir(), 'weights', 'age_permil'), self.weight_age_permil)
179 if err is not None:
180 return err
181
182 nr_goals_file = os.path.join(self.sysfs_dir(), 'goals', 'nr_goals')
183 content, err = read_file(nr_goals_file)
184 if err is not None:
185 return err
186 if int(content) != len(self.goals):
187 err = write_file(nr_goals_file, len(self.goals))
188 if err is not None:
189 return err
190 for goal in self.goals:
191 err = goal.stage()
192 if err is not None:
193 return err
194 return None
195
196class DamosWatermarks:
197 metric = None
198 interval = None
199 high = None
200 mid = None
201 low = None
202 scheme = None # owner scheme
203
204 def __init__(self, metric='none', interval=0, high=0, mid=0, low=0):
205 self.metric = metric
206 self.interval = interval
207 self.high = high
208 self.mid = mid
209 self.low = low
210
211 def sysfs_dir(self):
212 return os.path.join(self.scheme.sysfs_dir(), 'watermarks')
213
214 def stage(self):
215 err = write_file(os.path.join(self.sysfs_dir(), 'metric'), self.metric)
216 if err is not None:
217 return err
218 err = write_file(os.path.join(self.sysfs_dir(), 'interval_us'),
219 self.interval)
220 if err is not None:
221 return err
222 err = write_file(os.path.join(self.sysfs_dir(), 'high'), self.high)
223 if err is not None:
224 return err
225 err = write_file(os.path.join(self.sysfs_dir(), 'mid'), self.mid)
226 if err is not None:
227 return err
228 err = write_file(os.path.join(self.sysfs_dir(), 'low'), self.low)
229 if err is not None:
230 return err
231
232class DamosFilter:
233 type_ = None
234 matching = None
235 allow = None
236 memcg_path = None
237 addr_start = None
238 addr_end = None
239 target_idx = None
240 min_ = None
241 max_ = None
242 idx = None
243 filters = None # owner filters
244
245 def __init__(self, type_='anon', matching=False, allow=False,
246 memcg_path='', addr_start=0, addr_end=0, target_idx=0, min_=0,
247 max_=0):
248 self.type_ = type_
249 self.matching = matching
250 self.allow = allow
251 self.memcg_path = memcg_path,
252 self.addr_start = addr_start
253 self.addr_end = addr_end
254 self.target_idx = target_idx
255 self.min_ = min_
256 self.max_ = max_
257
258 def sysfs_dir(self):
259 return os.path.join(self.filters.sysfs_dir(), '%d' % self.idx)
260
261 def stage(self):
262 err = write_file(os.path.join(self.sysfs_dir(), 'type'), self.type_)
263 if err is not None:
264 return err
265 err = write_file(os.path.join(self.sysfs_dir(), 'matching'),
266 self.matching)
267 if err is not None:
268 return err
269 err = write_file(os.path.join(self.sysfs_dir(), 'allow'), self.allow)
270 if err is not None:
271 return err
272 err = write_file(os.path.join(self.sysfs_dir(), 'memcg_path'),
273 self.memcg_path)
274 if err is not None:
275 return err
276 err = write_file(os.path.join(self.sysfs_dir(), 'addr_start'),
277 self.addr_start)
278 if err is not None:
279 return err
280 err = write_file(os.path.join(self.sysfs_dir(), 'addr_end'),
281 self.addr_end)
282 if err is not None:
283 return err
284 err = write_file(os.path.join(self.sysfs_dir(), 'damon_target_idx'),
285 self.target_idx)
286 if err is not None:
287 return err
288 err = write_file(os.path.join(self.sysfs_dir(), 'min'), self.min_)
289 if err is not None:
290 return err
291 err = write_file(os.path.join(self.sysfs_dir(), 'max'), self.max_)
292 if err is not None:
293 return err
294 return None
295
296class DamosFilters:
297 name = None
298 filters = None
299 scheme = None # owner scheme
300
301 def __init__(self, name, filters=[]):
302 self.name = name
303 self.filters = filters
304 for idx, filter_ in enumerate(self.filters):
305 filter_.idx = idx
306 filter_.filters = self
307
308 def sysfs_dir(self):
309 return os.path.join(self.scheme.sysfs_dir(), self.name)
310
311 def stage(self):
312 err = write_file(os.path.join(self.sysfs_dir(), 'nr_filters'),
313 len(self.filters))
314 if err is not None:
315 return err
316 for filter_ in self.filters:
317 err = filter_.stage()
318 if err is not None:
319 return err
320 return None
321
322class DamosDest:
323 id = None
324 weight = None
325 idx = None
326 dests = None # owner dests
327
328 def __init__(self, id=0, weight=0):
329 self.id = id
330 self.weight = weight
331
332 def sysfs_dir(self):
333 return os.path.join(self.dests.sysfs_dir(), '%d' % self.idx)
334
335 def stage(self):
336 err = write_file(os.path.join(self.sysfs_dir(), 'id'), self.id)
337 if err is not None:
338 return err
339 err = write_file(os.path.join(self.sysfs_dir(), 'weight'), self.weight)
340 if err is not None:
341 return err
342 return None
343
344class DamosDests:
345 dests = None
346 scheme = None # owner scheme
347
348 def __init__(self, dests=[]):
349 self.dests = dests
350 for idx, dest in enumerate(self.dests):
351 dest.idx = idx
352 dest.dests = self
353
354 def sysfs_dir(self):
355 return os.path.join(self.scheme.sysfs_dir(), 'dests')
356
357 def stage(self):
358 err = write_file(os.path.join(self.sysfs_dir(), 'nr_dests'),
359 len(self.dests))
360 if err is not None:
361 return err
362 for dest in self.dests:
363 err = dest.stage()
364 if err is not None:
365 return err
366 return None
367
368class DamosStats:
369 nr_tried = None
370 sz_tried = None
371 nr_applied = None
372 sz_applied = None
373 qt_exceeds = None
374
375 def __init__(self, nr_tried, sz_tried, nr_applied, sz_applied, qt_exceeds):
376 self.nr_tried = nr_tried
377 self.sz_tried = sz_tried
378 self.nr_applied = nr_applied
379 self.sz_applied = sz_applied
380 self.qt_exceeds = qt_exceeds
381
382class DamosTriedRegion:
383 def __init__(self, start, end, nr_accesses, age):
384 self.start = start
385 self.end = end
386 self.nr_accesses = nr_accesses
387 self.age = age
388
389class Damos:
390 action = None
391 access_pattern = None
392 quota = None
393 watermarks = None
394 core_filters = None
395 ops_filters = None
396 filters = None
397 apply_interval_us = None
398 target_nid = None
399 dests = None
400 idx = None
401 context = None
402 tried_bytes = None
403 stats = None
404 tried_regions = None
405
406 def __init__(self, action='stat', access_pattern=DamosAccessPattern(),
407 quota=DamosQuota(), watermarks=DamosWatermarks(),
408 core_filters=[], ops_filters=[], filters=[], target_nid=0,
409 dests=DamosDests(), apply_interval_us=0):
410 self.action = action
411 self.access_pattern = access_pattern
412 self.access_pattern.scheme = self
413 self.quota = quota
414 self.quota.scheme = self
415 self.watermarks = watermarks
416 self.watermarks.scheme = self
417
418 self.core_filters = DamosFilters(name='core_filters',
419 filters=core_filters)
420 self.core_filters.scheme = self
421 self.ops_filters = DamosFilters(name='ops_filters',
422 filters=ops_filters)
423 self.ops_filters.scheme = self
424 self.filters = DamosFilters(name='filters', filters=filters)
425 self.filters.scheme = self
426
427 self.target_nid = target_nid
428 self.dests = dests
429 self.dests.scheme = self
430
431 self.apply_interval_us = apply_interval_us
432
433 def sysfs_dir(self):
434 return os.path.join(
435 self.context.sysfs_dir(), 'schemes', '%d' % self.idx)
436
437 def stage(self):
438 err = write_file(os.path.join(self.sysfs_dir(), 'action'), self.action)
439 if err is not None:
440 return err
441 err = self.access_pattern.stage()
442 if err is not None:
443 return err
444 err = write_file(os.path.join(self.sysfs_dir(), 'apply_interval_us'),
445 '%d' % self.apply_interval_us)
446 if err is not None:
447 return err
448
449 err = self.quota.stage()
450 if err is not None:
451 return err
452
453 err = self.watermarks.stage()
454 if err is not None:
455 return err
456
457 err = self.core_filters.stage()
458 if err is not None:
459 return err
460 err = self.ops_filters.stage()
461 if err is not None:
462 return err
463 err = self.filters.stage()
464 if err is not None:
465 return err
466
467 err = write_file(os.path.join(self.sysfs_dir(), 'target_nid'), '%d' %
468 self.target_nid)
469 if err is not None:
470 return err
471
472 err = self.dests.stage()
473 if err is not None:
474 return err
475
476class DamonTarget:
477 pid = None
478 obsolete = None
479 # todo: Support target regions if test is made
480 idx = None
481 context = None
482
483 def __init__(self, pid, obsolete=False):
484 self.pid = pid
485 self.obsolete = obsolete
486
487 def sysfs_dir(self):
488 return os.path.join(
489 self.context.sysfs_dir(), 'targets', '%d' % self.idx)
490
491 def stage(self):
492 err = write_file(
493 os.path.join(self.sysfs_dir(), 'regions', 'nr_regions'), '0')
494 if err is not None:
495 return err
496 err = write_file(
497 os.path.join(self.sysfs_dir(), 'pid_target'), self.pid)
498 if err is not None:
499 return err
500 return write_file(
501 os.path.join(self.sysfs_dir(), 'obsolete_target'),
502 'Y' if self.obsolete else 'N')
503
504class IntervalsGoal:
505 access_bp = None
506 aggrs = None
507 min_sample_us = None
508 max_sample_us = None
509 attrs = None # owner DamonAttrs
510
511 def __init__(self, access_bp=0, aggrs=0, min_sample_us=0, max_sample_us=0):
512 self.access_bp = access_bp
513 self.aggrs = aggrs
514 self.min_sample_us = min_sample_us
515 self.max_sample_us = max_sample_us
516
517 def sysfs_dir(self):
518 return os.path.join(self.attrs.interval_sysfs_dir(), 'intervals_goal')
519
520 def stage(self):
521 err = write_file(
522 os.path.join(self.sysfs_dir(), 'access_bp'), self.access_bp)
523 if err is not None:
524 return err
525 err = write_file(os.path.join(self.sysfs_dir(), 'aggrs'), self.aggrs)
526 if err is not None:
527 return err
528 err = write_file(os.path.join(self.sysfs_dir(), 'min_sample_us'),
529 self.min_sample_us)
530 if err is not None:
531 return err
532 err = write_file(os.path.join(self.sysfs_dir(), 'max_sample_us'),
533 self.max_sample_us)
534 if err is not None:
535 return err
536 return None
537
538class DamonAttrs:
539 sample_us = None
540 aggr_us = None
541 intervals_goal = None
542 update_us = None
543 min_nr_regions = None
544 max_nr_regions = None
545 context = None
546
547 def __init__(self, sample_us=5000, aggr_us=100000,
548 intervals_goal=IntervalsGoal(), update_us=1000000,
549 min_nr_regions=10, max_nr_regions=1000):
550 self.sample_us = sample_us
551 self.aggr_us = aggr_us
552 self.intervals_goal = intervals_goal
553 self.intervals_goal.attrs = self
554 self.update_us = update_us
555 self.min_nr_regions = min_nr_regions
556 self.max_nr_regions = max_nr_regions
557
558 def interval_sysfs_dir(self):
559 return os.path.join(self.context.sysfs_dir(), 'monitoring_attrs',
560 'intervals')
561
562 def nr_regions_range_sysfs_dir(self):
563 return os.path.join(self.context.sysfs_dir(), 'monitoring_attrs',
564 'nr_regions')
565
566 def stage(self):
567 err = write_file(os.path.join(self.interval_sysfs_dir(), 'sample_us'),
568 self.sample_us)
569 if err is not None:
570 return err
571 err = write_file(os.path.join(self.interval_sysfs_dir(), 'aggr_us'),
572 self.aggr_us)
573 if err is not None:
574 return err
575 err = self.intervals_goal.stage()
576 if err is not None:
577 return err
578 err = write_file(os.path.join(self.interval_sysfs_dir(), 'update_us'),
579 self.update_us)
580 if err is not None:
581 return err
582
583 err = write_file(
584 os.path.join(self.nr_regions_range_sysfs_dir(), 'min'),
585 self.min_nr_regions)
586 if err is not None:
587 return err
588
589 err = write_file(
590 os.path.join(self.nr_regions_range_sysfs_dir(), 'max'),
591 self.max_nr_regions)
592 if err is not None:
593 return err
594
595class DamonCtx:
596 ops = None
597 monitoring_attrs = None
598 targets = None
599 schemes = None
600 kdamond = None
601 idx = None
602
603 def __init__(self, ops='paddr', monitoring_attrs=DamonAttrs(), targets=[],
604 schemes=[]):
605 self.ops = ops
606 self.monitoring_attrs = monitoring_attrs
607 self.monitoring_attrs.context = self
608
609 self.targets = targets
610 for idx, target in enumerate(self.targets):
611 target.idx = idx
612 target.context = self
613
614 self.schemes = schemes
615 for idx, scheme in enumerate(self.schemes):
616 scheme.idx = idx
617 scheme.context = self
618
619 def sysfs_dir(self):
620 return os.path.join(self.kdamond.sysfs_dir(), 'contexts',
621 '%d' % self.idx)
622
623 def stage(self):
624 err = write_file(
625 os.path.join(self.sysfs_dir(), 'operations'), self.ops)
626 if err is not None:
627 return err
628 err = self.monitoring_attrs.stage()
629 if err is not None:
630 return err
631
632 nr_targets_file = os.path.join(
633 self.sysfs_dir(), 'targets', 'nr_targets')
634 content, err = read_file(nr_targets_file)
635 if err is not None:
636 return err
637 if int(content) != len(self.targets):
638 err = write_file(nr_targets_file, '%d' % len(self.targets))
639 if err is not None:
640 return err
641 for target in self.targets:
642 err = target.stage()
643 if err is not None:
644 return err
645
646 nr_schemes_file = os.path.join(
647 self.sysfs_dir(), 'schemes', 'nr_schemes')
648 content, err = read_file(nr_schemes_file)
649 if err is not None:
650 return err
651 if int(content) != len(self.schemes):
652 err = write_file(nr_schemes_file, '%d' % len(self.schemes))
653 if err is not None:
654 return err
655 for scheme in self.schemes:
656 err = scheme.stage()
657 if err is not None:
658 return err
659 return None
660
661class Kdamond:
662 state = None
663 pid = None
664 contexts = None
665 idx = None # index of this kdamond between siblings
666 kdamonds = None # parent
667
668 def __init__(self, contexts=[]):
669 self.contexts = contexts
670 for idx, context in enumerate(self.contexts):
671 context.idx = idx
672 context.kdamond = self
673
674 def sysfs_dir(self):
675 return os.path.join(self.kdamonds.sysfs_dir(), '%d' % self.idx)
676
677 def start(self):
678 nr_contexts_file = os.path.join(self.sysfs_dir(),
679 'contexts', 'nr_contexts')
680 content, err = read_file(nr_contexts_file)
681 if err is not None:
682 return err
683 if int(content) != len(self.contexts):
684 err = write_file(nr_contexts_file, '%d' % len(self.contexts))
685 if err is not None:
686 return err
687
688 for context in self.contexts:
689 err = context.stage()
690 if err is not None:
691 return err
692 err = write_file(os.path.join(self.sysfs_dir(), 'state'), 'on')
693 if err is not None:
694 return err
695 self.pid, err = read_file(os.path.join(self.sysfs_dir(), 'pid'))
696 return err
697
698 def stop(self):
699 err = write_file(os.path.join(self.sysfs_dir(), 'state'), 'off')
700 return err
701
702 def update_schemes_tried_regions(self):
703 err = write_file(os.path.join(self.sysfs_dir(), 'state'),
704 'update_schemes_tried_regions')
705 if err is not None:
706 return err
707 for context in self.contexts:
708 for scheme in context.schemes:
709 tried_regions = []
710 tried_regions_dir = os.path.join(
711 scheme.sysfs_dir(), 'tried_regions')
712 region_indices = []
713 for filename in os.listdir(
714 os.path.join(scheme.sysfs_dir(), 'tried_regions')):
715 tried_region_dir = os.path.join(tried_regions_dir, filename)
716 if not os.path.isdir(tried_region_dir):
717 continue
718 region_indices.append(int(filename))
719 for region_idx in sorted(region_indices):
720 tried_region_dir = os.path.join(tried_regions_dir,
721 '%d' % region_idx)
722 region_values = []
723 for f in ['start', 'end', 'nr_accesses', 'age']:
724 content, err = read_file(
725 os.path.join(tried_region_dir, f))
726 if err is not None:
727 return err
728 region_values.append(int(content))
729 tried_regions.append(DamosTriedRegion(*region_values))
730 scheme.tried_regions = tried_regions
731
732 def update_schemes_tried_bytes(self):
733 err = write_file(os.path.join(self.sysfs_dir(), 'state'),
734 'update_schemes_tried_bytes')
735 if err is not None:
736 return err
737 for context in self.contexts:
738 for scheme in context.schemes:
739 content, err = read_file(os.path.join(scheme.sysfs_dir(),
740 'tried_regions', 'total_bytes'))
741 if err is not None:
742 return err
743 scheme.tried_bytes = int(content)
744
745 def update_schemes_stats(self):
746 err = write_file(os.path.join(self.sysfs_dir(), 'state'),
747 'update_schemes_stats')
748 if err is not None:
749 return err
750 for context in self.contexts:
751 for scheme in context.schemes:
752 stat_values = []
753 for stat in ['nr_tried', 'sz_tried', 'nr_applied',
754 'sz_applied', 'qt_exceeds']:
755 content, err = read_file(
756 os.path.join(scheme.sysfs_dir(), 'stats', stat))
757 if err is not None:
758 return err
759 stat_values.append(int(content))
760 scheme.stats = DamosStats(*stat_values)
761
762 def update_schemes_effective_quotas(self):
763 err = write_file(os.path.join(self.sysfs_dir(), 'state'),
764 'update_schemes_effective_quotas')
765 if err is not None:
766 return err
767 for context in self.contexts:
768 for scheme in context.schemes:
769 for goal in scheme.quota.goals:
770 content, err = read_file(
771 os.path.join(scheme.quota.sysfs_dir(),
772 'effective_bytes'))
773 if err is not None:
774 return err
775 goal.effective_bytes = int(content)
776 return None
777
778 def commit(self):
779 nr_contexts_file = os.path.join(self.sysfs_dir(),
780 'contexts', 'nr_contexts')
781 content, err = read_file(nr_contexts_file)
782 if err is not None:
783 return err
784 if int(content) != len(self.contexts):
785 err = write_file(nr_contexts_file, '%d' % len(self.contexts))
786 if err is not None:
787 return err
788
789 for context in self.contexts:
790 err = context.stage()
791 if err is not None:
792 return err
793 err = write_file(os.path.join(self.sysfs_dir(), 'state'), 'commit')
794 return err
795
796
797 def commit_schemes_quota_goals(self):
798 for context in self.contexts:
799 for scheme in context.schemes:
800 for goal in scheme.quota.goals:
801 err = goal.stage()
802 if err is not None:
803 print('commit_schemes_quota_goals failed stagign: %s'%
804 err)
805 exit(1)
806 return write_file(os.path.join(self.sysfs_dir(), 'state'),
807 'commit_schemes_quota_goals')
808
809class Kdamonds:
810 kdamonds = []
811
812 def __init__(self, kdamonds=[]):
813 self.kdamonds = kdamonds
814 for idx, kdamond in enumerate(self.kdamonds):
815 kdamond.idx = idx
816 kdamond.kdamonds = self
817
818 def sysfs_dir(self):
819 return os.path.join(sysfs_root, 'kdamonds')
820
821 def start(self):
822 err = write_file(os.path.join(self.sysfs_dir(), 'nr_kdamonds'),
823 '%s' % len(self.kdamonds))
824 if err is not None:
825 return err
826 for kdamond in self.kdamonds:
827 err = kdamond.start()
828 if err is not None:
829 return err
830 return None
831
832 def stop(self):
833 for kdamond in self.kdamonds:
834 err = kdamond.stop()
835 if err is not None:
836 return err
837 return None