dslm.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * dslm.c
  3. * Simple Disk Sleep Monitor
  4. * by Bartek Kania
  5. * Licensed under the GPL
  6. */
  7. #include <unistd.h>
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <fcntl.h>
  11. #include <errno.h>
  12. #include <time.h>
  13. #include <string.h>
  14. #include <signal.h>
  15. #include <sys/ioctl.h>
  16. #include <linux/hdreg.h>
  17. #ifdef DEBUG
  18. #define D(x) x
  19. #else
  20. #define D(x)
  21. #endif
  22. int endit = 0;
  23. /* Check if the disk is in powersave-mode
  24. * Most of the code is stolen from hdparm.
  25. * 1 = active, 0 = standby/sleep, -1 = unknown */
  26. static int check_powermode(int fd)
  27. {
  28. unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0};
  29. int state;
  30. if (ioctl(fd, HDIO_DRIVE_CMD, &args)
  31. && (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */
  32. && ioctl(fd, HDIO_DRIVE_CMD, &args)) {
  33. if (errno != EIO || args[0] != 0 || args[1] != 0) {
  34. state = -1; /* "unknown"; */
  35. } else
  36. state = 0; /* "sleeping"; */
  37. } else {
  38. state = (args[2] == 255) ? 1 : 0;
  39. }
  40. D(printf(" drive state is: %d\n", state));
  41. return state;
  42. }
  43. static char *state_name(int i)
  44. {
  45. if (i == -1) return "unknown";
  46. if (i == 0) return "sleeping";
  47. if (i == 1) return "active";
  48. return "internal error";
  49. }
  50. static char *myctime(time_t time)
  51. {
  52. char *ts = ctime(&time);
  53. ts[strlen(ts) - 1] = 0;
  54. return ts;
  55. }
  56. static void measure(int fd)
  57. {
  58. time_t start_time;
  59. int last_state;
  60. time_t last_time;
  61. int curr_state;
  62. time_t curr_time = 0;
  63. time_t time_diff;
  64. time_t active_time = 0;
  65. time_t sleep_time = 0;
  66. time_t unknown_time = 0;
  67. time_t total_time = 0;
  68. int changes = 0;
  69. float tmp;
  70. printf("Starting measurements\n");
  71. last_state = check_powermode(fd);
  72. start_time = last_time = time(0);
  73. printf(" System is in state %s\n\n", state_name(last_state));
  74. while(!endit) {
  75. sleep(1);
  76. curr_state = check_powermode(fd);
  77. if (curr_state != last_state || endit) {
  78. changes++;
  79. curr_time = time(0);
  80. time_diff = curr_time - last_time;
  81. if (last_state == 1) active_time += time_diff;
  82. else if (last_state == 0) sleep_time += time_diff;
  83. else unknown_time += time_diff;
  84. last_state = curr_state;
  85. last_time = curr_time;
  86. printf("%s: State-change to %s\n", myctime(curr_time),
  87. state_name(curr_state));
  88. }
  89. }
  90. changes--; /* Compensate for SIGINT */
  91. total_time = time(0) - start_time;
  92. printf("\nTotal running time: %lus\n", curr_time - start_time);
  93. printf(" State changed %d times\n", changes);
  94. tmp = (float)sleep_time / (float)total_time * 100;
  95. printf(" Time in sleep state: %lus (%.2f%%)\n", sleep_time, tmp);
  96. tmp = (float)active_time / (float)total_time * 100;
  97. printf(" Time in active state: %lus (%.2f%%)\n", active_time, tmp);
  98. tmp = (float)unknown_time / (float)total_time * 100;
  99. printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp);
  100. }
  101. static void ender(int s)
  102. {
  103. endit = 1;
  104. }
  105. static void usage(void)
  106. {
  107. puts("usage: dslm [-w <time>] <disk>");
  108. exit(0);
  109. }
  110. int main(int argc, char **argv)
  111. {
  112. int fd;
  113. char *disk = 0;
  114. int settle_time = 60;
  115. /* Parse the simple command-line */
  116. if (argc == 2)
  117. disk = argv[1];
  118. else if (argc == 4) {
  119. settle_time = atoi(argv[2]);
  120. disk = argv[3];
  121. } else
  122. usage();
  123. if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) {
  124. printf("Can't open %s, because: %s\n", disk, strerror(errno));
  125. exit(-1);
  126. }
  127. if (settle_time) {
  128. printf("Waiting %d seconds for the system to settle down to "
  129. "'normal'\n", settle_time);
  130. sleep(settle_time);
  131. } else
  132. puts("Not waiting for system to settle down");
  133. signal(SIGINT, ender);
  134. measure(fd);
  135. close(fd);
  136. return 0;
  137. }