Exemple #1
0
/* main function */
int main(int argc, char *argv[])
{
	IDLE_TIME *it;
	int have_logfile = 0;
	int min_idle_time;
	int sleep_time;
	int opt;

	/* create default idle-time parameter entry */
	if ((it = malloc(sizeof(*it))) == NULL)
	{
		fprintf(stderr, "out of memory\n");
		exit(1);
	}
	it->next = NULL;
	it->name = NULL;
	it->idle_time = DEFAULT_IDLE_TIME;
	it_root = it;

	/* process command line options */
	while ((opt = getopt(argc, argv, "t:a:i:l:dh")) != -1)
	{
		switch (opt)
		{

			case 't':
				/* just spin-down the specified disk and exit */
				spindown_disk(optarg);
				return (0);

			case 'a':
				/* add a new set of idle-time parameters for this particular disk */
				if ((it = malloc(sizeof(*it))) == NULL)
				{
					fprintf(stderr, "out of memory\n");
					return (2);
				}
				it->name = disk_name(optarg);
				it->idle_time = DEFAULT_IDLE_TIME;
				it->next = it_root;
				it_root = it;
				break;

			case 'i':
				/* set idle-time parameters for current (or default) disk */
				it->idle_time = atoi(optarg);
				break;

			case 'l':
				logfile = optarg;
				have_logfile = 1;
				break;

			case 'd':
				debug = 1;
				break;

			case 'h':
				printf("usage: hd-idle [-t <disk>] [-a <name>] [-i <idle_time>] [-l <logfile>] [-d] [-h]\n");
				return (0);

			case ':':
				fprintf(stderr, "error: option -%c requires an argument\n", optopt);
				return (1);

			case '?':
				fprintf(stderr, "error: unknown option -%c\n", optopt);
				return (1);
		}
	}

	/* set sleep time to 1/10th of the shortest idle time */
	min_idle_time = 1 << 30;
	for (it = it_root; it != NULL; it = it->next)
	{
		if (it->idle_time != 0 && it->idle_time < min_idle_time)
		{
			min_idle_time = it->idle_time;
		}
	}
	if ((sleep_time = min_idle_time / 10) == 0)
	{
		sleep_time = 1;
	}

	/* daemonize unless we're running in debug mode */
	if (!debug)
	{
		daemonize();
	}

	/* main loop: probe for idle disks and stop them */
	for (;;)
	{
		DISKSTATS tmp;
		FILE *fp;
		char buf[200];

		if ((fp = fopen(STAT_FILE, "r")) == NULL)
		{
			perror(STAT_FILE);
			return (2);
		}

		memset(&tmp, 0x00, sizeof(tmp));

		while (fgets(buf, sizeof(buf), fp) != NULL)
		{
			if (sscanf(buf, "%*d %*d %s %*u %*u %u %*u %*u %*u %u %*u %*u %*u %*u",
					tmp.name, &tmp.reads, &tmp.writes) == 3)
			{
				DISKSTATS *ds;
				time_t now = time(NULL);

				/* make sure this is a SCSI disk (sd[a-z]) */
				if (tmp.name[0] != 's' ||
						tmp.name[1] != 'd' ||
						!isalpha(tmp.name[2]) ||
						tmp.name[3] != '\0')
				{
					continue;
				}

				dprintf("probing %s: reads: %u, writes: %u\n", tmp.name, tmp.reads, tmp.writes);

				/* get previous statistics for this disk */
				ds = get_diskstats(tmp.name);

				if (ds == NULL)
				{
					/* new disk; just add it to the linked list */
					if ((ds = malloc(sizeof(*ds))) == NULL)
					{
						fprintf(stderr, "out of memory\n");
						return (2);
					}
					memcpy(ds, &tmp, sizeof(*ds));
					ds->last_io = now;
					ds->spinup = ds->last_io;
					ds->next = ds_root;
					ds_root = ds;

					/* find idle time for this disk (falling-back to default; default means
					 * 'it->name == NULL' and this entry will always be the last due to the
					 * way this single-linked list is built when parsing command line
					 * arguments)
					 */
					for (it = it_root; it != NULL; it = it->next)
					{
						if (it->name == NULL || !strcmp(ds->name, it->name))
						{
							ds->idle_time = it->idle_time;
							break;
						}
					}

				}
				else if (ds->reads == tmp.reads && ds->writes == tmp.writes)
				{
					if (!ds->spun_down)
					{
						/* no activity on this disk and still running */
						if (ds->idle_time != 0 && now - ds->last_io >= ds->idle_time)
						{
							spindown_disk(ds->name);
							ds->spindown = now;
							ds->spun_down = 1;
						}
					}

				}
				else
				{
					/* disk had some activity */
					if (ds->spun_down)
					{
						/* disk was spun down, thus it has just spun up */
						if (have_logfile)
						{
							log_spinup(ds);
						}
						ds->spinup = now;
					}
					ds->reads = tmp.reads;
					ds->writes = tmp.writes;
					ds->last_io = now;
					ds->spun_down = 0;
				}
			}
		}

		fclose(fp);
		sleep(sleep_time);
	}

	return (0);
}
Exemple #2
0
int main(int argc, char *argv[])
{
	IDLE_TIME *it;
	int min_idle_time;
	int sleep_time;
	int opt;

	if ((it = malloc(sizeof(*it))) == NULL) {
		fprintf(stderr, "out of memory\n");
		exit(1);
	}
	it->next = NULL;
	it->name = NULL;
	it->idle_time = DEFAULT_IDLE_TIME;
	it_root = it;

	while ((opt = getopt(argc, argv, "t:a:i:l:dnhI")) != -1) {
		switch (opt) {

		case 't':
			spindown_disk(optarg);
			return(0);

		case 'a':
			if ((it = malloc(sizeof(*it))) == NULL) {
			fprintf(stderr, "out of memory\n");
			return(2);
			}
			it->name = disk_name(optarg);
			it->idle_time = DEFAULT_IDLE_TIME;
			it->next = it_root;
			it_root = it;
			break;

		case 'i':
			it->idle_time = atoi(optarg);
			break;

		case 'd':
			loglevel = LOG_DEBUG;
			break;

		case 'n':
			asdaemon = 0;
			break;

		case 'I':
			loglevel = LOG_DEBUG;
			usesyslog = 0;
			break;

		case 'h':
			printf("usage: hd-idle [-t <disk>] [-a <name>] [-i <idle_time>] [-d (debug) ]\n"
			       "               [-n (no daemon)] [-I (interactive)] [-h]\n");
			return(0);

		case ':':
			fprintf(stderr, "error: option -%c requires an argument\n", optopt);
			return(1);

		case '?':
			fprintf(stderr, "error: unknown option -%c\n", optopt);
			return(1);
		}
	}

	/* set sleep time to 1/10th of the shortest idle time */
	min_idle_time = 1 << 30;
	for (it = it_root; it != NULL; it = it->next) {
		if (it->idle_time != 0 && it->idle_time < min_idle_time) {
			min_idle_time = it->idle_time;
		}
	}
	if ((sleep_time = min_idle_time / 10) == 0) {
		sleep_time = 1;
	}

	if (asdaemon)
		daemonize();

	if (usesyslog)
		openlog("hdidle", LOG_PID, LOG_DAEMON);

	for (;;) {
		DISKSTATS tmp;
		char buf[200];
		FILE *fp;

		if ((fp = fopen(STAT_FILE, "r")) == NULL) {
			perror(STAT_FILE);
			return(2);
		}

		memset(&tmp, 0x00, sizeof(tmp));

		while (fgets(buf, sizeof(buf), fp) != NULL) {
			if (!(sscanf(buf, "%*d %*d %s %*u %*u %u %*u %*u %*u %u %*u %*u %*u %*u",
					tmp.name, &tmp.reads, &tmp.writes) == 3))
				continue;

			DISKSTATS *ds;
			time_t now = time(NULL);

			/* make sure this is a SCSI disk (sd[a-z]) */
			if (tmp.name[0] != 's' || tmp.name[1] != 'd' ||
				!isalpha(tmp.name[2]) || tmp.name[3] != '\0')
				continue;

			write_log(LOG_DEBUG, "probing %s: reads: %u, writes: %u",
					tmp.name, tmp.reads, tmp.writes);

			/* get previous statistics for this disk */
			ds = get_diskstats(tmp.name);

			if (ds == NULL) {
			/* new disk; just add it to the linked list */
				if ((ds = malloc(sizeof(*ds))) == NULL) {
					fprintf(stderr, "out of memory\n");
					return(2);
				}
				memcpy(ds, &tmp, sizeof(*ds));
				ds->last_io = now;
				ds->spinup = ds->last_io;
				ds->next = ds_root;
				ds_root = ds;

				/* find idle time for this disk (falling-back to default; default means
				* 'it->name == NULL' and this entry will always be the last due to the
				* way this single-linked list is built when parsing command line
				* arguments)
				*/
				for (it = it_root; it != NULL; it = it->next)
					if (it->name == NULL || !strcmp(ds->name, it->name)) {
						ds->idle_time = it->idle_time;
						write_log(LOG_INFO, "disk %s: standby timeout %u seconds",
									ds->name, ds->idle_time);
						break;
					}
				continue;
			}

			/* no activity */
			if (ds->reads == tmp.reads && ds->writes == tmp.writes) {
				if (ds->spun_down)
					continue;

				/* no activity on this disk and still running */
				if (ds->idle_time != 0 && now - ds->last_io >= ds->idle_time) {
					spindown_disk(ds->name);
					ds->spindown = now;
					ds->spun_down = 1;
				}
				continue;
			}


			ds->reads = tmp.reads;
			ds->writes = tmp.writes;
			ds->last_io = now;
			ds->spun_down = 0;
			if (!ds->spun_down)
				continue;

			/* disk was spun down, thus it has just spun up */
			write_log(LOG_INFO, "disk %s: spinup (running: %ld, stopped: %ld)",
			ds->name,
			(long) ds->spindown - (long) ds->spinup,
			(long) time(NULL) - (long) ds->spindown);
			ds->spinup = now;
		}

		fclose(fp);
		sleep(sleep_time);
	}

	return(0);
}