Пример #1
0
/*
 ***************************************************************************
 * Allocate and init structures, according to system state.
 ***************************************************************************
 */
void io_sys_init(void)
{
	/* Allocate and init stat common counters */
	init_stats();

	/* How many processors on this machine? */
	cpu_nr = get_cpu_nr(~0, FALSE);

	/* Get number of block devices and partitions in /proc/diskstats */
	if ((iodev_nr = get_diskstats_dev_nr(CNT_PART, CNT_ALL_DEV)) > 0) {
		flags |= I_F_HAS_DISKSTATS;
		iodev_nr += NR_DEV_PREALLOC;
	}

	if (!HAS_DISKSTATS(flags) ||
	    (DISPLAY_PARTITIONS(flags) && !DISPLAY_PART_ALL(flags))) {
		/*
		 * If /proc/diskstats exists but we also want stats for the partitions
		 * of a particular device, stats will have to be found in /sys. So we
		 * need to know if /sys is mounted or not, and set flags accordingly.
		 */

		/* Get number of block devices (and partitions) in sysfs */
		if ((iodev_nr = get_sysfs_dev_nr(DISPLAY_PARTITIONS(flags))) > 0) {
			flags |= I_F_HAS_SYSFS;
			iodev_nr += NR_DEV_PREALLOC;
		}
		else {
			fprintf(stderr, _("Cannot find disk data\n"));
			exit(2);
		}
	}

	/* Also allocate stat structures for "group" devices */
	iodev_nr += group_nr;

	/*
	 * Allocate structures for number of disks found, but also
	 * for groups of devices if option -g has been entered on the command line.
	 * iodev_nr must be <> 0.
	 */
	salloc_device(iodev_nr);
}
Пример #2
0
/*
 ***************************************************************************
 * Read stats from /proc/stat file...
 * Useful at least for CPU utilization.
 * May be useful to get disk stats if /sys not available.
 ***************************************************************************
 */
void read_proc_stat(int curr, int flags)
{
   FILE *fp;
   char line[8192];
   int pos, i;
   unsigned long v_tmp[4];
   unsigned int v_major, v_index;
   struct io_stats *st_iodev_tmp[4];
   unsigned long long cc_idle, cc_iowait, cc_steal;
   unsigned long long cc_user, cc_nice, cc_system, cc_hardirq, cc_softirq;


   /*
    * Prepare pointers on the 4 disk structures in case we have a
    * /proc/stat file with "disk_rblk", etc. entries.
    */
   for (i = 0; i < 4; i++)
      st_iodev_tmp[i] = st_iodev[curr] + i;

   if ((fp = fopen(STAT, "r")) == NULL) {
      perror("fopen");
      exit(2);
   }

   while (fgets(line, 8192, fp) != NULL) {

      if (!strncmp(line, "cpu ", 4)) {
	 /*
	  * Read the number of jiffies spent in the different modes,
	  * and compute system uptime in jiffies (1/100ths of a second
	  * if HZ=100).
	  * Some fields are only present in 2.6 kernels.
	  */
	 comm_stats[curr].cpu_iowait = 0;	/* For pre 2.6 kernels */
	 comm_stats[curr].cpu_steal = 0;
	 cc_hardirq = cc_softirq = 0;
	 /* CPU counters became unsigned long long with kernel 2.6.5 */
	 sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu",
	        &(comm_stats[curr].cpu_user), &(comm_stats[curr].cpu_nice),
		&(comm_stats[curr].cpu_system), &(comm_stats[curr].cpu_idle),
		&(comm_stats[curr].cpu_iowait), &cc_hardirq, &cc_softirq,
		&(comm_stats[curr].cpu_steal));

	 /*
	  * Time spent in system mode also includes time spent servicing
	  * hard interrupts and softirqs.
	  */
	 comm_stats[curr].cpu_system += cc_hardirq + cc_softirq;
	
	 /*
	  * Compute system uptime in jiffies.
	  * Uptime is multiplied by the number of processors.
	  */
	 comm_stats[curr].uptime = comm_stats[curr].cpu_user +
	                           comm_stats[curr].cpu_nice +
	                           comm_stats[curr].cpu_system +
	                           comm_stats[curr].cpu_idle +
	                           comm_stats[curr].cpu_iowait +
	    			   comm_stats[curr].cpu_steal;
      }

      else if ((!strncmp(line, "cpu0", 4)) && (cpu_nr > 1)) {
	 /*
	  * Read CPU line for proc#0 (if available).
	  * This is necessary to compute time interval since
	  * processors may be disabled (offline) sometimes.
	  * (Assume that proc#0 can never be offline).
	  */
	 cc_iowait = cc_hardirq = cc_softirq = cc_steal = 0;
	 sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu",
		&cc_user, &cc_nice, &cc_system, &cc_idle, &cc_iowait,
		&cc_hardirq, &cc_softirq, &cc_steal);
	 comm_stats[curr].uptime0 = cc_user + cc_nice + cc_system +
	    			    cc_idle + cc_iowait +
	    			    cc_hardirq + cc_softirq + cc_steal;
      }

      else if (DISPLAY_EXTENDED(flags) || HAS_DISKSTATS(flags) ||
	       HAS_PPARTITIONS(flags) || HAS_SYSFS(flags))
	 /*
	  * When displaying extended statistics, or if /proc/diskstats or
	  * /proc/partitions exists, or /sys is mounted,
	  * we just need to get CPU info from /proc/stat.
	  */
	 continue;

      else if (!strncmp(line, "disk_rblk ", 10)) {
	 /*
	  * Read the number of blocks read from disk.
	  * A block is of indeterminate size.
	  * The size may vary depending on the device type.
	  */
	 sscanf(line + 10, "%lu %lu %lu %lu",
		&v_tmp[0], &v_tmp[1], &v_tmp[2], &v_tmp[3]);

	 st_iodev_tmp[0]->dk_drive_rblk = v_tmp[0];
	 st_iodev_tmp[1]->dk_drive_rblk = v_tmp[1];
	 st_iodev_tmp[2]->dk_drive_rblk = v_tmp[2];
	 st_iodev_tmp[3]->dk_drive_rblk = v_tmp[3];
      }

      else if (!strncmp(line, "disk_wblk ", 10)) {
	 /* Read the number of blocks written to disk */
	 sscanf(line + 10, "%lu %lu %lu %lu",
		&v_tmp[0], &v_tmp[1], &v_tmp[2], &v_tmp[3]);
	
	 st_iodev_tmp[0]->dk_drive_wblk = v_tmp[0];
	 st_iodev_tmp[1]->dk_drive_wblk = v_tmp[1];
	 st_iodev_tmp[2]->dk_drive_wblk = v_tmp[2];
	 st_iodev_tmp[3]->dk_drive_wblk = v_tmp[3];
      }

      else if (!strncmp(line, "disk ", 5)) {
	 /* Read the number of I/O done since the last reboot */
	 sscanf(line + 5, "%lu %lu %lu %lu",
		&v_tmp[0], &v_tmp[1], &v_tmp[2], &v_tmp[3]);
	
	 st_iodev_tmp[0]->dk_drive = v_tmp[0];
	 st_iodev_tmp[1]->dk_drive = v_tmp[1];
	 st_iodev_tmp[2]->dk_drive = v_tmp[2];
	 st_iodev_tmp[3]->dk_drive = v_tmp[3];
      }

      else if (!strncmp(line, "disk_io: ", 9)) {
	 struct io_stats sdev;
	 char dev_name[MAX_NAME_LEN];
	
	 pos = 9;

	 /* Every disk_io entry is potentially unregistered */
	 set_entries_inactive(iodev_nr);
	
	 /* Read disks I/O statistics (for 2.4 kernels) */
	 while (pos < strlen(line) - 1) {
	    /* Beware: a CR is already included in the line */
	    sscanf(line + pos, "(%u,%u):(%lu,%*u,%lu,%*u,%lu) ",
		   &v_major, &v_index, &v_tmp[0], &v_tmp[1], &v_tmp[2]);

	    sprintf(dev_name, "dev%d-%d", v_major, v_index);
	    sdev.dk_drive      = v_tmp[0];
	    sdev.dk_drive_rblk = v_tmp[1];
	    sdev.dk_drive_wblk = v_tmp[2];
	    save_dev_stats(dev_name, curr, &sdev);

	    pos += strcspn(line + pos, " ") + 1;
	 }

	 /* Free structures corresponding to unregistered disks */
	 free_inactive_entries(iodev_nr);
      }
   }

   fclose(fp);
}
Пример #3
0
/*
 ***************************************************************************
 * Main loop: Read I/O stats from the relevant sources and display them.
 *
 * IN:
 * @count	Number of lines of stats to print.
 * @rectime	Current date and time.
 ***************************************************************************
 */
void rw_io_stat_loop(long int count, struct tm *rectime)
{
	int curr = 1;
	int skip = 0;

	/* Should we skip first report? */
	if (DISPLAY_OMIT_SINCE_BOOT(flags) && interval > 0) {
		skip = 1;
	}

	/* Don't buffer data if redirected to a pipe */
	setbuf(stdout, NULL);

	do {
		if (cpu_nr > 1) {
			/*
			 * Read system uptime (only for SMP machines).
			 * Init uptime0. So if /proc/uptime cannot fill it,
			 * this will be done by /proc/stat.
			 */
			uptime0[curr] = 0;
			read_uptime(&(uptime0[curr]));
		}

		/*
		 * Read stats for CPU "all" and 0.
		 * Note that stats for CPU 0 are not used per se. It only makes
		 * read_stat_cpu() fill uptime0.
		 */
		read_stat_cpu(st_cpu[curr], 2, &(uptime[curr]), &(uptime0[curr]));

		if (dlist_idx) {
			/*
			 * A device or partition name was explicitly entered
			 * on the command line, with or without -p option
			 * (but not -p ALL).
			 */
			if (HAS_DISKSTATS(flags) && !DISPLAY_PARTITIONS(flags)) {
				read_diskstats_stat(curr);
			}
			else if (HAS_SYSFS(flags)) {
				read_sysfs_dlist_stat(curr);
			}
		}
		else {
			/*
			 * No devices nor partitions entered on the command line
			 * (for example if -p ALL was used).
			 */
			if (HAS_DISKSTATS(flags)) {
				read_diskstats_stat(curr);
			}
			else if (HAS_SYSFS(flags)) {
				read_sysfs_stat(curr);
			}
		}

		/* Compute device groups stats */
		if (group_nr > 0) {
			compute_device_groups_stats(curr);
		}

		/* Get time */
		get_localtime(rectime, 0);

		/* Check whether we should skip first report */
		if (!skip) {
			/* Print results */
			write_stats(curr, rectime);

			if (count > 0) {
				count--;
			}
		}
		else {
			skip = 0;
		}

		if (count) {
			curr ^= 1;
			pause();
		}
	}
	while (count);
}
Пример #4
0
/*
 ***************************************************************************
 * Allocate and init structures, according to system state
 ***************************************************************************
 */
void io_sys_init(int *flags)
{
   int i;

   /* Init stat common counters */
   init_stats();

   /* How many processors on this machine ? */
   cpu_nr = get_cpu_nr(~0);

   /* Get number of block devices and partitions in /proc/diskstats */
   if ((iodev_nr = get_diskstats_dev_nr(CNT_PART, CNT_ALL_DEV)) > 0) {
      *flags |= I_F_HAS_DISKSTATS;
      iodev_nr += NR_DEV_PREALLOC;
   }

   if (!HAS_DISKSTATS(*flags) ||
       (DISPLAY_PARTITIONS(*flags) && !DISPLAY_PART_ALL(*flags))) {
      /*
       * If /proc/diskstats exists but we also want stats for the partitions
       * of a particular device, stats will have to be found in /sys. So we
       * need to know if /sys is mounted or not, and set *flags accordingly.
       */

      /* Get number of block devices (and partitions) in sysfs */
      if ((iodev_nr = get_sysfs_dev_nr(DISPLAY_PARTITIONS(*flags))) > 0) {
	 *flags |= I_F_HAS_SYSFS;
	 iodev_nr += NR_DEV_PREALLOC;
      }
      /*
       * Get number of block devices and partitions in /proc/partitions,
       * those with statistics...
       */
      else if ((iodev_nr = get_ppartitions_dev_nr(CNT_PART)) > 0) {
	 *flags |= I_F_HAS_PPARTITIONS;
	 iodev_nr += NR_DEV_PREALLOC;
      }
      /* Get number of "disk_io:" entries in /proc/stat */
      else if ((iodev_nr = get_disk_io_nr()) > 0) {
	 *flags |= I_F_PLAIN_KERNEL24;
	 iodev_nr += NR_DISK_PREALLOC;
      }
      else {
	 /* Assume we have an old kernel: stats for 4 disks are in /proc/stat */
	 iodev_nr = 4;
	 *flags |= I_F_OLD_KERNEL;
      }
   }
   /*
    * Allocate structures for number of disks found.
    * iodev_nr must be <> 0.
    */
   salloc_device(iodev_nr);

   if (HAS_OLD_KERNEL(*flags)) {
      struct io_hdr_stats *shi = st_hdr_iodev;
      /*
       * If we have an old kernel with the stats for the first four disks
       * in /proc/stat, then set the devices names to hdisk[0..3].
       */
      for (i = 0; i < 4; i++, shi++) {
	 shi->used = TRUE;
	 sprintf(shi->name, "%s%d", K_HDISK, i);
      }
   }
}