linux/tools/laptop/dslm/dslm.c
<<
>>
Prefs
   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
  18#ifdef DEBUG
  19#define D(x) x
  20#else
  21#define D(x)
  22#endif
  23
  24int endit = 0;
  25
  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 */
  29static int check_powermode(int fd)
  30{
  31    unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0};
  32    int state;
  33
  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"; */
  39        } else
  40            state = 0; /* "sleeping"; */
  41    } else {
  42        state = (args[2] == 255) ? 1 : 0;
  43    }
  44    D(printf(" drive state is:  %d\n", state));
  45
  46    return state;
  47}
  48
  49static char *state_name(int i)
  50{
  51    if (i == -1) return "unknown";
  52    if (i == 0) return "sleeping";
  53    if (i == 1) return "active";
  54
  55    return "internal error";
  56}
  57
  58static char *myctime(time_t time)
  59{
  60    char *ts = ctime(&time);
  61    ts[strlen(ts) - 1] = 0;
  62
  63    return ts;
  64}
  65
  66static void measure(int fd)
  67{
  68    time_t start_time;
  69    int last_state;
  70    time_t last_time;
  71    int curr_state;
  72    time_t curr_time = 0;
  73    time_t time_diff;
  74    time_t active_time = 0;
  75    time_t sleep_time = 0;
  76    time_t unknown_time = 0;
  77    time_t total_time = 0;
  78    int changes = 0;
  79    float tmp;
  80
  81    printf("Starting measurements\n");
  82
  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));
  86
  87    while(!endit) {
  88        sleep(1);
  89        curr_state = check_powermode(fd);
  90
  91        if (curr_state != last_state || endit) {
  92            changes++;
  93            curr_time = time(0);
  94            time_diff = curr_time - last_time;
  95
  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;
  99
 100            last_state = curr_state;
 101            last_time = curr_time;
 102
 103            printf("%s: State-change to %s\n", myctime(curr_time),
 104                   state_name(curr_state));
 105        }
 106    }
 107    changes--; /* Compensate for SIGINT */
 108
 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);
 112
 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);
 119}
 120
 121static void ender(int s)
 122{
 123    endit = 1;
 124}
 125
 126static void usage(void)
 127{
 128    puts("usage: dslm [-w <time>] <disk>");
 129    exit(0);
 130}
 131
 132int main(int argc, char **argv)
 133{
 134    int fd;
 135    char *disk = 0;
 136    int settle_time = 60;
 137
 138    /* Parse the simple command-line */
 139    if (argc == 2)
 140        disk = argv[1];
 141    else if (argc == 4) {
 142        settle_time = atoi(argv[2]);
 143        disk = argv[3];
 144    } else
 145        usage();
 146
 147    if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) {
 148        printf("Can't open %s, because: %s\n", disk, strerror(errno));
 149        exit(-1);
 150    }
 151
 152    if (settle_time) {
 153        printf("Waiting %d seconds for the system to settle down to "
 154               "'normal'\n", settle_time);
 155        sleep(settle_time);
 156    } else
 157        puts("Not waiting for system to settle down");
 158
 159    signal(SIGINT, ender);
 160
 161    measure(fd);
 162
 163    close(fd);
 164
 165    return 0;
 166}
 167