1/* 2 * Unix SMB/CIFS implementation. 3 * Performance Counter Daemon 4 * 5 * Copyright (C) Marcin Krzysztof Porwit 2005 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21#include "perf.h" 22 23void init_diskdata_desc(PERF_DATA_BLOCK *data) 24{ 25 init_perf_counter(&(data->diskInfo.diskObjDesc), 26 &(data->diskInfo.diskObjDesc), 27 get_counter_id(data), 28 "Logical Disk", 29 "The Logical Disk object consists of counters that show information about disks.", 30 0, 31 PERF_OBJECT); 32 init_perf_counter(&(data->diskInfo.freeMegs), 33 &(data->diskInfo.diskObjDesc), 34 get_counter_id(data), 35 "Megabytes Free", 36 "The amount of available disk space, in megabytes.", 37 PERF_SIZE_LARGE | PERF_TYPE_NUMBER | PERF_NUMBER_DECIMAL | PERF_DISPLAY_NO_SUFFIX, 38 PERF_COUNTER); 39 init_perf_counter(&(data->diskInfo.writesPerSec), 40 &(data->diskInfo.diskObjDesc), 41 get_counter_id(data), 42 "Writes/sec", 43 "The number of writes per second to that disk.", 44 PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_DELTA_COUNTER | PERF_DISPLAY_PER_SEC, 45 PERF_COUNTER); 46 init_perf_counter(&(data->diskInfo.readsPerSec), 47 &(data->diskInfo.diskObjDesc), 48 get_counter_id(data), 49 "Reads/sec", 50 "The number of reads of that disk per second.", 51 PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_DELTA_COUNTER | PERF_DISPLAY_PER_SEC, 52 PERF_COUNTER); 53 54 return; 55} 56void init_num_disks(PERF_DATA_BLOCK *data) 57{ 58 FILE *mtab; 59 char buf[PROC_BUF]; 60 char *start, *stop; 61 int i = 0, num; 62 63 if(!(mtab = fopen("/etc/mtab", "r"))) 64 { 65 perror("init_disk_names: fopen"); 66 exit(1); 67 } 68 69 rewind(mtab); 70 fflush(mtab); 71 72 while(fgets(buf, sizeof(buf), mtab)) 73 { 74 if(start = strstr(buf, "/dev/")) 75 { 76 if(start = strstr(start, "da")) 77 { 78 i++; 79 } 80 } 81 } 82 83 data->diskInfo.numDisks = i; 84 fclose(mtab); 85 86 return; 87} 88 89void init_disk_names(PERF_DATA_BLOCK *data) 90{ 91 FILE *mtab; 92 char buf[PROC_BUF]; 93 char *start, *stop; 94 int i = 0, num; 95 96 if(!(mtab = fopen("/etc/mtab", "r"))) 97 { 98 perror("init_disk_names: fopen"); 99 exit(1); 100 } 101 102 rewind(mtab); 103 fflush(mtab); 104 105 while(fgets(buf, sizeof(buf), mtab)) 106 { 107 if(start = strstr(buf, "/dev/")) 108 { 109 if(start = strstr(start, "da")) 110 { 111 start -=1; 112 stop = strstr(start, " "); 113 memcpy(data->diskInfo.mdata[i].name, start, stop - start); 114 start = stop +1; 115 stop = strstr(start, " "); 116 memcpy(data->diskInfo.mdata[i].mountpoint, start, stop - start); 117 i++; 118 } 119 } 120 } 121 122 fclose(mtab); 123 124 return; 125} 126 127void get_diskinfo(PERF_DATA_BLOCK *data) 128{ 129 int i; 130 DiskData *p; 131 struct statfs statfsbuf; 132 int status, num; 133 char buf[LARGE_BUF], *start; 134 FILE *diskstats; 135 long reads, writes, discard; 136 137 diskstats = fopen("/proc/diskstats", "r"); 138 rewind(diskstats); 139 fflush(diskstats); 140 status = fread(buf, sizeof(char), LARGE_BUF, diskstats); 141 fclose(diskstats); 142 143 for(i = 0; i < data->diskInfo.numDisks; i++) 144 { 145 p = &(data->diskInfo.data[i]); 146 status = statfs(data->diskInfo.mdata[i].mountpoint, &statfsbuf); 147 p->freeMegs = (statfsbuf.f_bfree*statfsbuf.f_bsize)/1048576; 148 start = strstr(buf, data->diskInfo.mdata[i].name); 149 start += strlen(data->diskInfo.mdata[i].name) + 1; 150 num = sscanf(start, "%u %u %u %u", 151 &reads, 152 &discard, 153 &writes, 154 &discard); 155 p->writesPerSec = writes; 156 p->readsPerSec = reads; 157 fprintf(stderr, "%s:\t%u\t%u\n", 158 data->diskInfo.mdata[i].mountpoint, 159 reads, writes); 160 } 161 return; 162} 163void init_disk_data(PERF_DATA_BLOCK *data) 164{ 165 init_diskdata_desc(data); 166 167 init_num_disks(data); 168 169 data->diskInfo.mdata = calloc(data->diskInfo.numDisks, sizeof(DiskMetaData)); 170 if(!data->diskInfo.mdata) 171 { 172 fatal("init_disk_data: out of memory"); 173 } 174 175 init_disk_names(data); 176 177 data->diskInfo.data = calloc(data->diskInfo.numDisks, sizeof(DiskData)); 178 if(!data->diskInfo.data) 179 { 180 fatal("init_disk_data: out of memory"); 181 } 182 183 get_diskinfo(data); 184 185 return; 186} 187 188void output_disk_desc(PERF_DATA_BLOCK *data, RuntimeSettings rt) 189{ 190 output_perf_desc(data->diskInfo.diskObjDesc, rt); 191 output_perf_desc(data->diskInfo.freeMegs, rt); 192 output_perf_desc(data->diskInfo.writesPerSec, rt); 193 output_perf_desc(data->diskInfo.readsPerSec, rt); 194 output_num_instances(data->diskInfo.diskObjDesc, data->diskInfo.numDisks, rt); 195 196 return; 197} 198 199void output_diskinfo(PERF_DATA_BLOCK *data, RuntimeSettings rt, int tdb_flags) 200{ 201 int i; 202 203 output_perf_counter(data->diskInfo.freeMegs, 204 data->diskInfo.data[0].freeMegs, 205 rt, tdb_flags); 206 output_perf_counter(data->diskInfo.writesPerSec, 207 (unsigned long long)data->diskInfo.data[0].writesPerSec, 208 rt, tdb_flags); 209 output_perf_counter(data->diskInfo.readsPerSec, 210 (unsigned long long)data->diskInfo.data[0].readsPerSec, 211 rt, tdb_flags); 212 213 for(i = 0; i < data->diskInfo.numDisks; i++) 214 { 215 output_perf_instance(data->diskInfo.diskObjDesc.index, 216 i, 217 (void *)&(data->diskInfo.data[i]), 218 sizeof(DiskData), 219 data->diskInfo.mdata[i].mountpoint, 220 rt, tdb_flags); 221 } 222 223 return; 224} 225