3 * Simple Disk Sleep Monitor
5 * Licensed under the GPL
15 #include <sys/ioctl.h>
16 #include <linux/hdreg.h>
26 /* Check if the disk is in powersave-mode
27 * Most of the code is stolen from hdparm.
28 * 1 = active, 0 = standby/sleep, -1 = unknown */
29 static int check_powermode(int fd
)
31 unsigned char args
[4] = {WIN_CHECKPOWERMODE1
,0,0,0};
34 if (ioctl(fd
, HDIO_DRIVE_CMD
, &args
)
35 && (args
[0] = WIN_CHECKPOWERMODE2
) /* try again with 0x98 */
36 && ioctl(fd
, HDIO_DRIVE_CMD
, &args
)) {
37 if (errno
!= EIO
|| args
[0] != 0 || args
[1] != 0) {
38 state
= -1; /* "unknown"; */
40 state
= 0; /* "sleeping"; */
42 state
= (args
[2] == 255) ? 1 : 0;
44 D(printf(" drive state is: %d\n", state
));
49 static char *state_name(int i
)
51 if (i
== -1) return "unknown";
52 if (i
== 0) return "sleeping";
53 if (i
== 1) return "active";
55 return "internal error";
58 static char *myctime(time_t time
)
60 char *ts
= ctime(&time
);
61 ts
[strlen(ts
) - 1] = 0;
66 static void measure(int fd
)
74 time_t active_time
= 0;
75 time_t sleep_time
= 0;
76 time_t unknown_time
= 0;
77 time_t total_time
= 0;
81 printf("Starting measurements\n");
83 last_state
= check_powermode(fd
);
84 start_time
= last_time
= time(0);
85 printf(" System is in state %s\n\n", state_name(last_state
));
89 curr_state
= check_powermode(fd
);
91 if (curr_state
!= last_state
|| endit
) {
94 time_diff
= curr_time
- last_time
;
96 if (last_state
== 1) active_time
+= time_diff
;
97 else if (last_state
== 0) sleep_time
+= time_diff
;
98 else unknown_time
+= time_diff
;
100 last_state
= curr_state
;
101 last_time
= curr_time
;
103 printf("%s: State-change to %s\n", myctime(curr_time
),
104 state_name(curr_state
));
107 changes
--; /* Compensate for SIGINT */
109 total_time
= time(0) - start_time
;
110 printf("\nTotal running time: %lus\n", curr_time
- start_time
);
111 printf(" State changed %d times\n", changes
);
113 tmp
= (float)sleep_time
/ (float)total_time
* 100;
114 printf(" Time in sleep state: %lus (%.2f%%)\n", sleep_time
, tmp
);
115 tmp
= (float)active_time
/ (float)total_time
* 100;
116 printf(" Time in active state: %lus (%.2f%%)\n", active_time
, tmp
);
117 tmp
= (float)unknown_time
/ (float)total_time
* 100;
118 printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time
, tmp
);
121 static void ender(int s
)
126 static void usage(void)
128 puts("usage: dslm [-w <time>] <disk>");
132 int main(int argc
, char **argv
)
136 int settle_time
= 60;
138 /* Parse the simple command-line */
141 else if (argc
== 4) {
142 settle_time
= atoi(argv
[2]);
147 if (!(fd
= open(disk
, O_RDONLY
|O_NONBLOCK
))) {
148 printf("Can't open %s, because: %s\n", disk
, strerror(errno
));
153 printf("Waiting %d seconds for the system to settle down to "
154 "'normal'\n", settle_time
);
157 puts("Not waiting for system to settle down");
159 signal(SIGINT
, ender
);