Conservative SmartOS global-zone memory pressure guard with dry-run-first policy and SMF integration.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

134 lignes
7.4 KiB

  1. /* Exercise the actual daemon selection/action path. Native backend NOT linked. */
  2. #define main guard_program_main
  3. #include "../src/main.c"
  4. #undef main
  5. static double fake_now = 100;
  6. static sample_t fake_sample;
  7. static process_t fixtures[8];
  8. static unsigned nfixtures, real_requests, validation_requests, checks;
  9. static int fail_validation, fail_sample, partial;
  10. #define CHECK(x) do { if (!(x)) { fprintf(stderr, "FAIL runtime line %d: %s\n", __LINE__, #x); exit(1); } checks++; } while (0)
  11. double monotime(void) { return fake_now; }
  12. int secure_file(const char *p, int flags, unsigned mode)
  13. { (void)p; (void)flags; (void)mode; errno = EPERM; return -1; }
  14. int secure_directory(const char *p) { (void)p; return -1; }
  15. int platform_init(void) { return 0; }
  16. void platform_fini(void) { }
  17. int platform_sample(sample_t *s)
  18. { *s = fake_sample; s->at = fake_now; return fail_sample ? -1 : 0; }
  19. int platform_walk(int (*fn)(const process_t *, void *), void *arg, unsigned budget)
  20. {
  21. unsigned j; (void)budget;
  22. for (j = 0; j < nfixtures; j++) if (fn(&fixtures[j], arg)) return -1;
  23. return partial ? -1 : 0;
  24. }
  25. int platform_signal(const config_t *c, const process_t *p, enum action action,
  26. int real, uint64_t ceiling)
  27. {
  28. CHECK(action == TERM || action == KILL);
  29. CHECK(!protected_process(c, p));
  30. if (real) { CHECK(c->armed && fake_sample.free < ceiling); real_requests++; }
  31. else validation_requests++;
  32. if (fail_validation) { errno = ESTALE; return -1; }
  33. return 0; /* This test backend cannot send any signal. */
  34. }
  35. static void reset(void)
  36. {
  37. defaults(&cfg); cfg.log_mib = 100;
  38. cfg.nzones = 2;
  39. strcpy(cfg.zones[0].uuid, "11111111-1111-4111-8111-111111111111");
  40. strcpy(cfg.zones[0].alias, "web-a"); cfg.zones[0].policy = ALLOW;
  41. strcpy(cfg.zones[1].uuid, "22222222-2222-4222-8222-222222222222");
  42. strcpy(cfg.zones[1].alias, "web-b"); cfg.zones[1].policy = ALLOW;
  43. memset(processes, 0, sizeof (processes)); memset(zone_stats, 0, sizeof (zone_stats));
  44. memset(metrics, 0, sizeof (metrics));
  45. memset(&controller, 0, sizeof (controller)); memset(fixtures, 0, sizeof (fixtures));
  46. engine_init(&engine); engine.state = CRITICAL; engine.danger = 1;
  47. stopping = 0; started = 0; log_ok = 1; log_bytes = 0;
  48. scan_generation = 0; fake_now = 100; partial = fail_sample = fail_validation = 0;
  49. real_requests = validation_requests = 0;
  50. memset(&fake_sample, 0, sizeof (fake_sample)); fake_sample.at = fake_now;
  51. fake_sample.free = 60000; fake_sample.lots = 130875;
  52. fake_sample.des = 65437; fake_sample.min = 49077;
  53. fixtures[0].pid = 123; fixtures[0].ppid = 100; fixtures[0].zid = 9;
  54. fixtures[0].initpid = 99; fixtures[0].nlwp = 1; fixtures[0].start_sec = 1000;
  55. fixtures[0].zone_generation = 20; fixtures[0].rss_kib = 100000;
  56. strcpy(fixtures[0].uuid, cfg.zones[0].uuid); strcpy(fixtures[0].name, "php-fpm");
  57. nfixtures = 1;
  58. scan_processes(0);
  59. }
  60. int main(void)
  61. {
  62. FILE *log = tmpfile(); char contents[65536]; size_t n;
  63. const process_t *chosen;
  64. unsigned second;
  65. CHECK(log != NULL); logfd = fileno(log);
  66. reset(); act(&fake_sample);
  67. CHECK(real_requests == 0 && validation_requests == 1 && controller.has_pending);
  68. fake_now += 5; scan_processes(0); act(&fake_sample);
  69. CHECK(real_requests == 0 && !controller.has_pending);
  70. rewind(log); n = fread(contents, 1, sizeof (contents) - 1, log); contents[n] = 0;
  71. CHECK(strstr(contents, "WOULD_ACTION=SIGTERM") != NULL);
  72. CHECK(strstr(contents, "WOULD_ACTION=SIGKILL") != NULL);
  73. CHECK(strstr(contents, "ACTION_INTENT=") == NULL);
  74. CHECK(fseek(log, 0, SEEK_END) == 0);
  75. puts("PASS actual daemon dry-run path records WOULD_ACTION=SIGTERM/SIGKILL; zero real requests");
  76. reset();
  77. fake_sample.arc_ok = 1;
  78. fake_sample.swap_virtual_ok = fake_sample.swap_physical_ok = fake_sample.pageout_ok = 1;
  79. for (second = 0; second <= 60; second++) {
  80. fake_sample.at = 100 + second;
  81. fake_sample.arc = UINT64_C(6000000000) + 1000 * second;
  82. fake_sample.swap_alloc = 7000000 + 3 * second;
  83. fake_sample.swap_reserved = 480000 + 2 * second;
  84. fake_sample.swap_available = 6200000 - second;
  85. fake_sample.swap_physical_used_bytes = UINT64_C(4143648768) + 4096 * second;
  86. fake_sample.anon_pageout_pages = 1000 + 2 * second;
  87. record_metrics(&fake_sample);
  88. }
  89. log_sample(&fake_sample);
  90. CHECK(fflush(log) == 0 && fseek(log, 0, SEEK_SET) == 0);
  91. n = fread(contents, 1, sizeof (contents) - 1, log); contents[n] = 0;
  92. CHECK(strstr(contents, "swap_committed_ok=1 swap_committed_pages=7480300") != NULL);
  93. CHECK(strstr(contents, "swap_physical_used_ok=1 swap_physical_used_bytes=4143894528") != NULL);
  94. CHECK(strstr(contents, "anon_pageout_ok=1 anon_pageout_pages=1120") != NULL);
  95. CHECK(strstr(contents, "swap_alloc_pages=7000180 swap_reserved_pages=480120 swap_available_pages=6199940") != NULL);
  96. CHECK(strstr(contents, "metric=swap_committed_pages d5=+25@5.00s d15=+75@15.00s d60=+300@60.00s") != NULL);
  97. CHECK(strstr(contents, "metric=swap_physical_used_bytes d5=+20480@5.00s d15=+61440@15.00s d60=+245760@60.00s") != NULL);
  98. CHECK(strstr(contents, "metric=anon_pageout_pages d5=+10@5.00s d15=+30@15.00s d60=+120@60.00s") != NULL);
  99. CHECK(strstr(contents, "swap_used_pages") == NULL);
  100. CHECK(fseek(log, 0, SEEK_END) == 0);
  101. puts("PASS continuous sample contract and 5/15/60 deltas for commitment, physical swap and pageout");
  102. reset(); cfg.armed = 1; act(&fake_sample);
  103. CHECK(real_requests == 1);
  104. fake_now += 5; scan_processes(0); act(&fake_sample); CHECK(real_requests == 2);
  105. reset(); cfg.armed = 1; started = 80; act(&fake_sample); CHECK(real_requests == 0);
  106. reset(); cfg.armed = 1; log_ok = 0; act(&fake_sample); CHECK(real_requests == 0);
  107. reset(); cfg.armed = 1; partial = 1; scan_processes(0); act(&fake_sample); CHECK(real_requests == 0);
  108. reset(); cfg.armed = 1; fail_sample = 1; act(&fake_sample); CHECK(real_requests == 0);
  109. reset(); cfg.armed = 1; fail_validation = 1; act(&fake_sample); CHECK(real_requests == 0);
  110. reset(); cfg.armed = 1; fake_sample.free = 150000; act(&fake_sample); CHECK(real_requests == 0);
  111. reset(); cfg.armed = 1; fake_now += 3; act(&fake_sample); CHECK(real_requests == 0);
  112. reset(); cfg.armed = 1; stopping = 1; act(&fake_sample); CHECK(real_requests == 0);
  113. reset(); fake_sample.free = 20000; act(&fake_sample);
  114. CHECK(!controller.has_pending && controller.nvictims == 1);
  115. puts("PASS armed-path mock requests, warmup, stale cache, logging/sampling failures, stop and fresh floor");
  116. reset(); fixtures[1] = fixtures[0]; fixtures[1].pid = 124;
  117. fixtures[1].rss_kib = 900000; fixtures[1].zid = 10;
  118. strcpy(fixtures[1].uuid, cfg.zones[1].uuid); nfixtures = 2;
  119. fake_now = 101; scan_processes(0); chosen = candidate(); CHECK(chosen && chosen->pid == 124);
  120. /* Small zone grows fast enough to outweigh a larger steady zone. */
  121. fixtures[0].rss_kib = 600000; fake_now = 161; scan_processes(0);
  122. chosen = candidate(); CHECK(chosen && chosen->pid == 123);
  123. cfg.zones[0].policy = PROTECT; fake_now = 162; scan_processes(0);
  124. chosen = candidate(); CHECK(chosen && chosen->pid == 124);
  125. fixtures[1].zid = 0; fake_now = 163; scan_processes(0); CHECK(candidate() == NULL);
  126. puts("PASS actual daemon ranking by zone/PID RSS and growth; protected zones and global zone excluded");
  127. fclose(log);
  128. printf("PASS %u runtime checks; all platform calls mocked, no signals sent\n", checks);
  129. return 0;
  130. }