1 // Copyright 2024, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 use super::*;
16
17 use std::sync::LockResult;
18 use std::sync::MutexGuard;
19
20 use mockall::predicate::*;
21 use mockall::Sequence;
22
23 use crate::os::MockMeminfoApi;
24 use crate::os::MEMINFO_API_MTX;
25 use crate::zram::MockSysfsZramApi;
26 use crate::zram::ZRAM_API_MTX;
27
28 const DEFAULT_TOTAL_ZRAM_SIZE: u64 = 4 << 30;
29 const DEFAULT_ZRAM_WRITEBACK_SIZE: u64 = 1 << 30;
30 const DEFAULT_PAGE_SIZE: u64 = 4096;
31
32 struct MockContext<'a> {
33 read_backing_dev:
34 crate::zram::__mock_MockSysfsZramApi_SysfsZramApi::__read_backing_dev::Context,
35 writeback: crate::zram::__mock_MockSysfsZramApi_SysfsZramApi::__writeback::Context,
36 write_writeback_limit:
37 crate::zram::__mock_MockSysfsZramApi_SysfsZramApi::__write_writeback_limit::Context,
38 read_writeback_limit:
39 crate::zram::__mock_MockSysfsZramApi_SysfsZramApi::__read_writeback_limit::Context,
40 set_idle: crate::zram::__mock_MockSysfsZramApi_SysfsZramApi::__set_idle::Context,
41 read_meminfo: crate::os::__mock_MockMeminfoApi_MeminfoApi::__read_meminfo::Context,
42 // Lock will be released after mock contexts are dropped.
43 _meminfo_lock: LockResult<MutexGuard<'a, ()>>,
44 _zram_lock: LockResult<MutexGuard<'a, ()>>,
45 }
46
47 impl<'a> MockContext<'a> {
new() -> Self48 fn new() -> Self {
49 let _zram_lock = ZRAM_API_MTX.lock();
50 let _meminfo_lock = MEMINFO_API_MTX.lock();
51 Self {
52 read_backing_dev: MockSysfsZramApi::read_backing_dev_context(),
53 writeback: MockSysfsZramApi::writeback_context(),
54 write_writeback_limit: MockSysfsZramApi::write_writeback_limit_context(),
55 read_writeback_limit: MockSysfsZramApi::read_writeback_limit_context(),
56 set_idle: MockSysfsZramApi::set_idle_context(),
57 read_meminfo: MockMeminfoApi::read_meminfo_context(),
58 _meminfo_lock,
59 _zram_lock,
60 }
61 }
62
setup_default_meminfo(&self)63 fn setup_default_meminfo(&self) {
64 let meminfo = "MemTotal: 8144296 kB
65 MemAvailable: 346452 kB";
66 self.read_meminfo.expect().returning(|| Ok(meminfo.to_string()));
67 }
68
setup_default_writeback_limit_read(&self)69 fn setup_default_writeback_limit_read(&self) {
70 self.read_writeback_limit.expect().returning(|| Ok("100\n".to_string()));
71 }
72 }
73
74 #[test]
test_is_zram_writeback_activated()75 fn test_is_zram_writeback_activated() {
76 let mock = MockContext::new();
77 mock.read_backing_dev.expect().returning(|| Ok("/dev/dm-1".to_string()));
78
79 assert!(is_zram_writeback_activated::<MockSysfsZramApi>().unwrap());
80 }
81
82 #[test]
test_load_zram_writeback_disk_size_writeback_is_not_enabled()83 fn test_load_zram_writeback_disk_size_writeback_is_not_enabled() {
84 let mock = MockContext::new();
85 mock.read_backing_dev.expect().returning(|| Ok("none".to_string()));
86
87 assert!(!is_zram_writeback_activated::<MockSysfsZramApi>().unwrap());
88 }
89
90 #[test]
test_is_zram_writeback_activated_writeback_is_not_supported()91 fn test_is_zram_writeback_activated_writeback_is_not_supported() {
92 let mock = MockContext::new();
93 mock.read_backing_dev
94 .expect()
95 .returning(|| Err(std::io::Error::new(std::io::ErrorKind::NotFound, "not found")));
96
97 assert!(!is_zram_writeback_activated::<MockSysfsZramApi>().unwrap());
98 }
99
100 #[test]
test_is_zram_writeback_activated_failure()101 fn test_is_zram_writeback_activated_failure() {
102 let mock = MockContext::new();
103 mock.read_backing_dev.expect().returning(|| Err(std::io::Error::other("error")));
104
105 assert!(is_zram_writeback_activated::<MockSysfsZramApi>().is_err());
106 }
107
108 #[test]
mark_and_flush_pages()109 fn mark_and_flush_pages() {
110 let mock = MockContext::new();
111 let mut seq = Sequence::new();
112 mock.setup_default_meminfo();
113 mock.setup_default_writeback_limit_read();
114 let params = Params::default();
115 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
116 let mut zram_writeback =
117 ZramWriteback::new(DEFAULT_TOTAL_ZRAM_SIZE, DEFAULT_ZRAM_WRITEBACK_SIZE);
118
119 mock.write_writeback_limit.expect().times(1).in_sequence(&mut seq).returning(|_| Ok(()));
120 mock.set_idle.expect().times(1).in_sequence(&mut seq).returning(|_| Ok(()));
121 mock.writeback.expect().times(1).in_sequence(&mut seq).returning(|_| Ok(()));
122 mock.set_idle.expect().times(1).in_sequence(&mut seq).returning(|_| Ok(()));
123 mock.writeback.expect().times(1).in_sequence(&mut seq).returning(|_| Ok(()));
124 mock.writeback.expect().times(1).in_sequence(&mut seq).returning(|_| Ok(()));
125
126 assert!(zram_writeback
127 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, Instant::now())
128 .is_ok());
129 }
130
131 #[test]
mark_and_flush_pages_before_backoff()132 fn mark_and_flush_pages_before_backoff() {
133 let mock = MockContext::new();
134 mock.writeback.expect().returning(|_| Ok(()));
135 mock.write_writeback_limit.expect().returning(|_| Ok(()));
136 mock.set_idle.expect().returning(|_| Ok(()));
137 mock.setup_default_meminfo();
138 mock.setup_default_writeback_limit_read();
139 let params = Params { backoff_duration: Duration::from_secs(100), ..Default::default() };
140 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
141 let base_time = Instant::now();
142 let mut zram_writeback =
143 ZramWriteback::new(DEFAULT_TOTAL_ZRAM_SIZE, DEFAULT_ZRAM_WRITEBACK_SIZE);
144 assert!(zram_writeback
145 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, base_time)
146 .is_ok());
147 mock.writeback.checkpoint();
148
149 mock.writeback.expect().times(0);
150
151 assert!(matches!(
152 zram_writeback.mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(
153 ¶ms,
154 &stats,
155 base_time + Duration::from_secs(99)
156 ),
157 Err(Error::BackoffTime)
158 ));
159 }
160
161 #[test]
mark_and_flush_pages_after_backoff()162 fn mark_and_flush_pages_after_backoff() {
163 let mock = MockContext::new();
164 mock.writeback.expect().returning(|_| Ok(()));
165 mock.write_writeback_limit.expect().returning(|_| Ok(()));
166 mock.set_idle.expect().returning(|_| Ok(()));
167 mock.setup_default_meminfo();
168 mock.setup_default_writeback_limit_read();
169 let params = Params { backoff_duration: Duration::from_secs(100), ..Default::default() };
170 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
171 let base_time = Instant::now();
172 let mut zram_writeback =
173 ZramWriteback::new(DEFAULT_TOTAL_ZRAM_SIZE, DEFAULT_ZRAM_WRITEBACK_SIZE);
174 assert!(zram_writeback
175 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, base_time)
176 .is_ok());
177 mock.writeback.checkpoint();
178 mock.write_writeback_limit.expect().returning(|_| Ok(()));
179 mock.set_idle.expect().returning(|_| Ok(()));
180 mock.setup_default_meminfo();
181 mock.setup_default_writeback_limit_read();
182
183 mock.writeback.expect().times(3).returning(|_| Ok(()));
184
185 assert!(zram_writeback
186 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(
187 ¶ms,
188 &stats,
189 base_time + Duration::from_secs(100)
190 )
191 .is_ok());
192 }
193
194 #[test]
mark_and_flush_pages_idle_time()195 fn mark_and_flush_pages_idle_time() {
196 let mock = MockContext::new();
197 mock.write_writeback_limit.expect().returning(|_| Ok(()));
198 mock.writeback.expect().returning(|_| Ok(()));
199 let meminfo = "MemTotal: 10000 kB
200 MemAvailable: 8000 kB";
201 mock.read_meminfo.expect().returning(|| Ok(meminfo.to_string()));
202 mock.setup_default_writeback_limit_read();
203 let params = Params {
204 min_idle: Duration::from_secs(3600),
205 max_idle: Duration::from_secs(4000),
206 ..Default::default()
207 };
208 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
209 let mut zram_writeback =
210 ZramWriteback::new(DEFAULT_TOTAL_ZRAM_SIZE, DEFAULT_ZRAM_WRITEBACK_SIZE);
211
212 mock.set_idle.expect().with(eq("3747")).times(2).returning(|_| Ok(()));
213
214 assert!(zram_writeback
215 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, Instant::now())
216 .is_ok());
217 }
218
219 #[test]
mark_and_flush_pages_calculate_idle_failure()220 fn mark_and_flush_pages_calculate_idle_failure() {
221 let mock = MockContext::new();
222 mock.write_writeback_limit.expect().returning(|_| Ok(()));
223 mock.writeback.expect().returning(|_| Ok(()));
224 mock.setup_default_writeback_limit_read();
225 let params = Params {
226 min_idle: Duration::from_secs(4000),
227 max_idle: Duration::from_secs(3600),
228 ..Default::default()
229 };
230 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
231 let mut zram_writeback =
232 ZramWriteback::new(DEFAULT_TOTAL_ZRAM_SIZE, DEFAULT_ZRAM_WRITEBACK_SIZE);
233
234 assert!(matches!(
235 zram_writeback.mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(
236 ¶ms,
237 &stats,
238 Instant::now()
239 ),
240 Err(Error::CalculateIdle(_))
241 ));
242 }
243
244 #[test]
mark_and_flush_pages_mark_idle_failure()245 fn mark_and_flush_pages_mark_idle_failure() {
246 let mock = MockContext::new();
247 mock.write_writeback_limit.expect().returning(|_| Ok(()));
248 mock.writeback.expect().returning(|_| Ok(()));
249 mock.setup_default_meminfo();
250 mock.setup_default_writeback_limit_read();
251 let params = Params::default();
252 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
253 let mut zram_writeback =
254 ZramWriteback::new(DEFAULT_TOTAL_ZRAM_SIZE, DEFAULT_ZRAM_WRITEBACK_SIZE);
255
256 mock.set_idle.expect().returning(|_| Err(std::io::Error::other("error")));
257
258 assert!(matches!(
259 zram_writeback.mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(
260 ¶ms,
261 &stats,
262 Instant::now()
263 ),
264 Err(Error::MarkIdle(_))
265 ));
266 }
267
268 #[test]
mark_and_flush_pages_skip_huge_idle()269 fn mark_and_flush_pages_skip_huge_idle() {
270 let mock = MockContext::new();
271 mock.write_writeback_limit.expect().returning(|_| Ok(()));
272 mock.set_idle.expect().returning(|_| Ok(()));
273 mock.setup_default_meminfo();
274 mock.setup_default_writeback_limit_read();
275 let params = Params { huge_idle: false, ..Default::default() };
276 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
277 let mut zram_writeback =
278 ZramWriteback::new(DEFAULT_TOTAL_ZRAM_SIZE, DEFAULT_ZRAM_WRITEBACK_SIZE);
279
280 mock.writeback.expect().with(eq("huge_idle")).times(0).returning(|_| Ok(()));
281 mock.writeback.expect().with(eq("idle")).times(1).returning(|_| Ok(()));
282 mock.writeback.expect().with(eq("huge")).times(1).returning(|_| Ok(()));
283
284 assert!(zram_writeback
285 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, Instant::now())
286 .is_ok());
287 }
288
289 #[test]
mark_and_flush_pages_skip_idle()290 fn mark_and_flush_pages_skip_idle() {
291 let mock = MockContext::new();
292 mock.write_writeback_limit.expect().returning(|_| Ok(()));
293 mock.set_idle.expect().returning(|_| Ok(()));
294 mock.setup_default_meminfo();
295 mock.setup_default_writeback_limit_read();
296 let params = Params { idle: false, ..Default::default() };
297 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
298 let mut zram_writeback =
299 ZramWriteback::new(DEFAULT_TOTAL_ZRAM_SIZE, DEFAULT_ZRAM_WRITEBACK_SIZE);
300
301 mock.writeback.expect().with(eq("huge_idle")).times(1).returning(|_| Ok(()));
302 mock.writeback.expect().with(eq("idle")).times(0).returning(|_| Ok(()));
303 mock.writeback.expect().with(eq("huge")).times(1).returning(|_| Ok(()));
304
305 assert!(zram_writeback
306 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, Instant::now())
307 .is_ok());
308 }
309
310 #[test]
mark_and_flush_pages_skip_huge()311 fn mark_and_flush_pages_skip_huge() {
312 let mock = MockContext::new();
313 mock.write_writeback_limit.expect().returning(|_| Ok(()));
314 mock.set_idle.expect().returning(|_| Ok(()));
315 mock.setup_default_meminfo();
316 mock.setup_default_writeback_limit_read();
317 let params = Params { huge: false, ..Default::default() };
318 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
319 let mut zram_writeback =
320 ZramWriteback::new(DEFAULT_TOTAL_ZRAM_SIZE, DEFAULT_ZRAM_WRITEBACK_SIZE);
321
322 mock.writeback.expect().with(eq("huge_idle")).times(1).returning(|_| Ok(()));
323 mock.writeback.expect().with(eq("idle")).times(1).returning(|_| Ok(()));
324 mock.writeback.expect().with(eq("huge")).times(0).returning(|_| Ok(()));
325
326 assert!(zram_writeback
327 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, Instant::now())
328 .is_ok());
329 }
330
331 #[test]
mark_and_flush_pages_write_limit_from_orig_data_size()332 fn mark_and_flush_pages_write_limit_from_orig_data_size() {
333 let mock = MockContext::new();
334 mock.writeback.expect().returning(|_| Ok(()));
335 mock.set_idle.expect().returning(|_| Ok(()));
336 mock.setup_default_meminfo();
337 mock.setup_default_writeback_limit_read();
338 let params = Params {
339 max_bytes: 600 * DEFAULT_PAGE_SIZE,
340 min_bytes: 10 * DEFAULT_PAGE_SIZE,
341 ..Default::default()
342 };
343 // zram utilization is 25%
344 let stats = Stats { orig_data_size: 500 * DEFAULT_PAGE_SIZE, ..Default::default() };
345 let mut zram_writeback = ZramWriteback::new_with_page_size(
346 2000 * DEFAULT_PAGE_SIZE,
347 1000 * DEFAULT_PAGE_SIZE,
348 DEFAULT_PAGE_SIZE,
349 );
350
351 // Writeback limit is 25% of max_bytes.
352 mock.write_writeback_limit.expect().with(eq("150")).times(1).returning(|_| Ok(()));
353
354 assert!(zram_writeback
355 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, Instant::now())
356 .is_ok());
357 }
358
359 #[test]
mark_and_flush_pages_write_limit_from_orig_data_size_with_big_page_size()360 fn mark_and_flush_pages_write_limit_from_orig_data_size_with_big_page_size() {
361 let mock = MockContext::new();
362 mock.writeback.expect().returning(|_| Ok(()));
363 mock.set_idle.expect().returning(|_| Ok(()));
364 mock.setup_default_meminfo();
365 mock.setup_default_writeback_limit_read();
366 let page_size = 2 * DEFAULT_PAGE_SIZE;
367 let params =
368 Params { max_bytes: 600 * page_size, min_bytes: 10 * page_size, ..Default::default() };
369 // zram utilization is 25%
370 let stats = Stats { orig_data_size: 500 * page_size, ..Default::default() };
371 let mut zram_writeback =
372 ZramWriteback::new_with_page_size(2000 * page_size, 1000 * page_size, page_size);
373
374 // Writeback limit is 25% of maxPages.
375 mock.write_writeback_limit.expect().with(eq("150")).times(1).returning(|_| Ok(()));
376
377 assert!(zram_writeback
378 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, Instant::now())
379 .is_ok());
380 }
381
382 #[test]
mark_and_flush_pages_write_limit_capped_by_current_writeback_size()383 fn mark_and_flush_pages_write_limit_capped_by_current_writeback_size() {
384 let mock = MockContext::new();
385 mock.writeback.expect().returning(|_| Ok(()));
386 mock.set_idle.expect().returning(|_| Ok(()));
387 mock.setup_default_meminfo();
388 mock.setup_default_writeback_limit_read();
389 let params = Params {
390 max_bytes: 600 * DEFAULT_PAGE_SIZE,
391 min_bytes: 10 * DEFAULT_PAGE_SIZE,
392 ..Default::default()
393 };
394 // zram utilization is 25%
395 let stats =
396 Stats { orig_data_size: 500 * DEFAULT_PAGE_SIZE, current_writeback_pages: 1000 - 50 };
397 let mut zram_writeback = ZramWriteback::new_with_page_size(
398 2000 * DEFAULT_PAGE_SIZE,
399 1000 * DEFAULT_PAGE_SIZE,
400 DEFAULT_PAGE_SIZE,
401 );
402
403 // Writeback disk only has 50 pages left.
404 mock.write_writeback_limit.expect().with(eq("50")).times(1).returning(|_| Ok(()));
405
406 assert!(zram_writeback
407 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, Instant::now())
408 .is_ok());
409 }
410
411 #[test]
mark_and_flush_pages_write_limit_capped_by_min_pages()412 fn mark_and_flush_pages_write_limit_capped_by_min_pages() {
413 let mock = MockContext::new();
414 mock.writeback.expect().returning(|_| Ok(()));
415 mock.set_idle.expect().returning(|_| Ok(()));
416 mock.setup_default_meminfo();
417 mock.setup_default_writeback_limit_read();
418 let params = Params {
419 max_bytes: 500 * DEFAULT_PAGE_SIZE,
420 min_bytes: 6 * DEFAULT_PAGE_SIZE,
421 ..Default::default()
422 };
423 // zram utilization is 1%
424 let stats = Stats { orig_data_size: 20 * DEFAULT_PAGE_SIZE, ..Default::default() };
425 let mut zram_writeback = ZramWriteback::new_with_page_size(
426 2000 * DEFAULT_PAGE_SIZE,
427 1000 * DEFAULT_PAGE_SIZE,
428 DEFAULT_PAGE_SIZE,
429 );
430
431 // Writeback limit is 5 pages (= 1% of 500 pages). But it is lower than min pages.
432 mock.write_writeback_limit.expect().times(0);
433
434 assert!(matches!(
435 zram_writeback.mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(
436 ¶ms,
437 &stats,
438 Instant::now()
439 ),
440 Err(Error::Limit)
441 ));
442 }
443
444 #[test]
mark_and_flush_pages_write_limit_capped_by_daily_limit_with_no_log()445 fn mark_and_flush_pages_write_limit_capped_by_daily_limit_with_no_log() {
446 let mock = MockContext::new();
447 mock.writeback.expect().returning(|_| Ok(()));
448 mock.set_idle.expect().returning(|_| Ok(()));
449 mock.setup_default_meminfo();
450 mock.setup_default_writeback_limit_read();
451 let params = Params {
452 max_bytes: 600 * DEFAULT_PAGE_SIZE,
453 min_bytes: 10 * DEFAULT_PAGE_SIZE,
454 max_bytes_per_day: 100 * DEFAULT_PAGE_SIZE,
455 ..Default::default()
456 };
457 // zram utilization is 25%
458 let stats = Stats { orig_data_size: 500 * DEFAULT_PAGE_SIZE, current_writeback_pages: 0 };
459 let mut zram_writeback = ZramWriteback::new_with_page_size(
460 2000 * DEFAULT_PAGE_SIZE,
461 1000 * DEFAULT_PAGE_SIZE,
462 DEFAULT_PAGE_SIZE,
463 );
464
465 // Writeback limit is 25% of max_bytes. But use smaller maxPagesPerDay as the limit.
466 mock.write_writeback_limit.expect().with(eq("100")).times(1).returning(|_| Ok(()));
467
468 assert!(zram_writeback
469 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, Instant::now())
470 .is_ok());
471 }
472
473 #[test]
mark_and_flush_pages_write_limit_capped_by_daily_limit()474 fn mark_and_flush_pages_write_limit_capped_by_daily_limit() {
475 let mock = MockContext::new();
476 mock.writeback.expect().returning(|_| Ok(()));
477 mock.set_idle.expect().returning(|_| Ok(()));
478 mock.setup_default_meminfo();
479 let params = Params {
480 max_bytes: 600 * DEFAULT_PAGE_SIZE,
481 min_bytes: 10 * DEFAULT_PAGE_SIZE,
482 max_bytes_per_day: 100 * DEFAULT_PAGE_SIZE,
483 ..Default::default()
484 };
485 let stats = Stats { orig_data_size: 500 * DEFAULT_PAGE_SIZE, current_writeback_pages: 0 };
486 let mut zram_writeback = ZramWriteback::new_with_page_size(
487 2000 * DEFAULT_PAGE_SIZE,
488 1000 * DEFAULT_PAGE_SIZE,
489 DEFAULT_PAGE_SIZE,
490 );
491 let base_point = Instant::now();
492
493 // Sets 100 as the daily limit for the first time.
494 mock.write_writeback_limit.expect().with(eq("100")).times(1).returning(|_| Ok(()));
495 // Load updated writeback_limit as the initial value.
496 mock.read_writeback_limit.expect().times(1).returning(|| Ok("100".to_string()));
497 // On first writeback, 40 pages are written back.
498 mock.read_writeback_limit.expect().returning(|| Ok("60".to_string()));
499
500 assert!(zram_writeback
501 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, base_point)
502 .is_ok());
503
504 // Daily limit with the history is applied on second markAndFlushPages.
505 mock.write_writeback_limit.expect().with(eq("60")).times(1).returning(|_| Ok(()));
506
507 assert!(zram_writeback
508 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(
509 ¶ms,
510 &stats,
511 base_point + Duration::from_secs(3600)
512 )
513 .is_ok());
514 }
515
516 #[test]
mark_and_flush_pages_write_limit_capped_by_daily_limit_expired()517 fn mark_and_flush_pages_write_limit_capped_by_daily_limit_expired() {
518 let mock = MockContext::new();
519 mock.writeback.expect().returning(|_| Ok(()));
520 mock.set_idle.expect().returning(|_| Ok(()));
521 mock.setup_default_meminfo();
522 let params = Params {
523 max_bytes: 600 * DEFAULT_PAGE_SIZE,
524 min_bytes: 10 * DEFAULT_PAGE_SIZE,
525 max_bytes_per_day: 100 * DEFAULT_PAGE_SIZE,
526 ..Default::default()
527 };
528 let stats = Stats { orig_data_size: 500 * DEFAULT_PAGE_SIZE, current_writeback_pages: 0 };
529 let mut zram_writeback = ZramWriteback::new_with_page_size(
530 2000 * DEFAULT_PAGE_SIZE,
531 1000 * DEFAULT_PAGE_SIZE,
532 DEFAULT_PAGE_SIZE,
533 );
534 let base_point = Instant::now();
535
536 // Sets 100 as the daily limit for the first time.
537 mock.write_writeback_limit.expect().with(eq("100")).times(1).returning(|_| Ok(()));
538 // Load updated writeback_limit as the initial value.
539 mock.read_writeback_limit.expect().times(1).returning(|| Ok("100\n".to_string()));
540 // On first writeback, 40 pages are written back.
541 mock.read_writeback_limit.expect().returning(|| Ok("60\n".to_string()));
542
543 assert!(zram_writeback
544 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, base_point)
545 .is_ok());
546
547 // On second time, the history is expired after 24 hours.
548 mock.write_writeback_limit.expect().with(eq("100")).times(1).returning(|_| Ok(()));
549 assert!(zram_writeback
550 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(
551 ¶ms,
552 &stats,
553 base_point + Duration::from_secs(24 * 3600)
554 )
555 .is_ok());
556 }
557
558 #[test]
mark_and_flush_pages_skip_on_write_limit()559 fn mark_and_flush_pages_skip_on_write_limit() {
560 let mock = MockContext::new();
561 mock.write_writeback_limit.expect().returning(|_| Ok(()));
562 mock.set_idle.expect().returning(|_| Ok(()));
563 mock.setup_default_meminfo();
564 let params = Params::default();
565 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
566 let mut zram_writeback = ZramWriteback::new_with_page_size(
567 DEFAULT_TOTAL_ZRAM_SIZE,
568 DEFAULT_ZRAM_WRITEBACK_SIZE,
569 DEFAULT_PAGE_SIZE,
570 );
571
572 // Load updated writeback_limit as the initial value.
573 mock.read_writeback_limit.expect().times(1).returning(|| Ok("100\n".to_string()));
574 // On first writeback, writeback limit becomes zero and skip following writeback.
575 mock.read_writeback_limit.expect().returning(|| Ok("0\n".to_string()));
576 mock.writeback.expect().with(eq("huge_idle")).times(1).returning(|_| Ok(()));
577 mock.writeback.expect().with(eq("idle")).times(0);
578 mock.writeback.expect().with(eq("huge")).times(0);
579
580 assert!(zram_writeback
581 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, Instant::now())
582 .is_ok());
583 }
584
585 #[test]
mark_and_flush_pages_skip_next_by_daily_limit()586 fn mark_and_flush_pages_skip_next_by_daily_limit() {
587 let mock = MockContext::new();
588 mock.writeback.expect().returning(|_| Ok(()));
589 mock.write_writeback_limit.expect().returning(|_| Ok(()));
590 mock.set_idle.expect().returning(|_| Ok(()));
591 mock.setup_default_meminfo();
592 let params = Params { max_bytes_per_day: 100 * DEFAULT_PAGE_SIZE, ..Default::default() };
593 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
594 let mut zram_writeback = ZramWriteback::new_with_page_size(
595 DEFAULT_TOTAL_ZRAM_SIZE,
596 DEFAULT_ZRAM_WRITEBACK_SIZE,
597 DEFAULT_PAGE_SIZE,
598 );
599 let base_point = Instant::now();
600
601 // Load updated writeback_limit as the initial value.
602 mock.read_writeback_limit.expect().times(1).returning(|| Ok("100\n".to_string()));
603 // On first writeback, writeback limit becomes zero and skip following writeback.
604 mock.read_writeback_limit.expect().returning(|| Ok("0\n".to_string()));
605 assert!(zram_writeback
606 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, base_point)
607 .is_ok());
608
609 mock.write_writeback_limit.checkpoint();
610 mock.write_writeback_limit.expect().times(0);
611 assert!(matches!(
612 zram_writeback.mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(
613 ¶ms,
614 &stats,
615 base_point + params.backoff_duration
616 ),
617 Err(Error::Limit)
618 ));
619
620 mock.write_writeback_limit.checkpoint();
621 mock.writeback.expect().returning(|_| Ok(()));
622 mock.set_idle.expect().returning(|_| Ok(()));
623 mock.setup_default_meminfo();
624 mock.setup_default_writeback_limit_read();
625 mock.write_writeback_limit.expect().returning(|_| Ok(()));
626 // writeback succeeds 24 hours after.
627 assert!(zram_writeback
628 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(
629 ¶ms,
630 &stats,
631 base_point + Duration::from_secs(24 * 3600)
632 )
633 .is_ok());
634 }
635
636 #[test]
mark_and_flush_pages_fails_to_record_history_by_writeback_error()637 fn mark_and_flush_pages_fails_to_record_history_by_writeback_error() {
638 let mock = MockContext::new();
639 mock.write_writeback_limit.expect().returning(|_| Ok(()));
640 mock.set_idle.expect().returning(|_| Ok(()));
641 mock.setup_default_meminfo();
642 let params = Params { max_bytes_per_day: 100 * DEFAULT_PAGE_SIZE, ..Default::default() };
643 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
644 let mut zram_writeback = ZramWriteback::new_with_page_size(
645 DEFAULT_TOTAL_ZRAM_SIZE,
646 DEFAULT_ZRAM_WRITEBACK_SIZE,
647 DEFAULT_PAGE_SIZE,
648 );
649 let base_point = Instant::now();
650
651 // Load updated writeback_limit as the initial value.
652 mock.read_writeback_limit.expect().times(1).returning(|| Ok("100\n".to_string()));
653 mock.writeback.expect().returning(|_| Err(std::io::Error::other("error")));
654 assert!(zram_writeback
655 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, base_point)
656 .is_err());
657
658 mock.write_writeback_limit.checkpoint();
659 mock.write_writeback_limit.expect().times(0);
660 assert!(matches!(
661 zram_writeback.mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(
662 ¶ms,
663 &stats,
664 base_point + params.backoff_duration
665 ),
666 Err(Error::Limit)
667 ));
668 }
669
670 #[test]
mark_and_flush_pages_fails_to_record_history_by_limit_load_error()671 fn mark_and_flush_pages_fails_to_record_history_by_limit_load_error() {
672 let mock = MockContext::new();
673 mock.writeback.expect().returning(|_| Ok(()));
674 mock.write_writeback_limit.expect().returning(|_| Ok(()));
675 mock.set_idle.expect().returning(|_| Ok(()));
676 mock.setup_default_meminfo();
677 let params = Params { max_bytes_per_day: 100 * DEFAULT_PAGE_SIZE, ..Default::default() };
678 let stats = Stats { orig_data_size: params.max_bytes, ..Default::default() };
679 let mut zram_writeback = ZramWriteback::new_with_page_size(
680 DEFAULT_TOTAL_ZRAM_SIZE,
681 DEFAULT_ZRAM_WRITEBACK_SIZE,
682 DEFAULT_PAGE_SIZE,
683 );
684 let base_point = Instant::now();
685
686 mock.read_writeback_limit.expect().times(1).returning(|| Ok("100\n".to_string()));
687 // read writeback_limit fails just after writeback.
688 mock.read_writeback_limit.expect().returning(|| Err(std::io::Error::other("error")));
689 assert!(zram_writeback
690 .mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(¶ms, &stats, base_point)
691 .is_ok());
692
693 mock.write_writeback_limit.checkpoint();
694 mock.write_writeback_limit.expect().times(0);
695 assert!(matches!(
696 zram_writeback.mark_and_flush_pages::<MockSysfsZramApi, MockMeminfoApi>(
697 ¶ms,
698 &stats,
699 base_point + params.backoff_duration
700 ),
701 Err(Error::Limit)
702 ));
703 }
704