PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/s390/block/dasd_proc.c

https://bitbucket.org/zozo123/boeffla-kernel-jb-u6-s3
C | 341 lines | 279 code | 31 blank | 31 comment | 39 complexity | c0391039e7c55af424c85d8c07b5a02e MD5 | raw file
  1. /*
  2. * File...........: linux/drivers/s390/block/dasd_proc.c
  3. * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  4. * Horst Hummel <Horst.Hummel@de.ibm.com>
  5. * Carsten Otte <Cotte@de.ibm.com>
  6. * Martin Schwidefsky <schwidefsky@de.ibm.com>
  7. * Bugreports.to..: <Linux390@de.ibm.com>
  8. * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2002
  9. *
  10. * /proc interface for the dasd driver.
  11. *
  12. */
  13. #define KMSG_COMPONENT "dasd"
  14. #include <linux/ctype.h>
  15. #include <linux/slab.h>
  16. #include <linux/string.h>
  17. #include <linux/seq_file.h>
  18. #include <linux/vmalloc.h>
  19. #include <linux/proc_fs.h>
  20. #include <asm/debug.h>
  21. #include <asm/uaccess.h>
  22. /* This is ugly... */
  23. #define PRINTK_HEADER "dasd_proc:"
  24. #include "dasd_int.h"
  25. static struct proc_dir_entry *dasd_proc_root_entry = NULL;
  26. static struct proc_dir_entry *dasd_devices_entry = NULL;
  27. static struct proc_dir_entry *dasd_statistics_entry = NULL;
  28. #ifdef CONFIG_DASD_PROFILE
  29. static char *
  30. dasd_get_user_string(const char __user *user_buf, size_t user_len)
  31. {
  32. char *buffer;
  33. buffer = kmalloc(user_len + 1, GFP_KERNEL);
  34. if (buffer == NULL)
  35. return ERR_PTR(-ENOMEM);
  36. if (copy_from_user(buffer, user_buf, user_len) != 0) {
  37. kfree(buffer);
  38. return ERR_PTR(-EFAULT);
  39. }
  40. /* got the string, now strip linefeed. */
  41. if (buffer[user_len - 1] == '\n')
  42. buffer[user_len - 1] = 0;
  43. else
  44. buffer[user_len] = 0;
  45. return buffer;
  46. }
  47. #endif /* CONFIG_DASD_PROFILE */
  48. static int
  49. dasd_devices_show(struct seq_file *m, void *v)
  50. {
  51. struct dasd_device *device;
  52. struct dasd_block *block;
  53. char *substr;
  54. device = dasd_device_from_devindex((unsigned long) v - 1);
  55. if (IS_ERR(device))
  56. return 0;
  57. if (device->block)
  58. block = device->block;
  59. else {
  60. dasd_put_device(device);
  61. return 0;
  62. }
  63. /* Print device number. */
  64. seq_printf(m, "%s", dev_name(&device->cdev->dev));
  65. /* Print discipline string. */
  66. if (device->discipline != NULL)
  67. seq_printf(m, "(%s)", device->discipline->name);
  68. else
  69. seq_printf(m, "(none)");
  70. /* Print kdev. */
  71. if (block->gdp)
  72. seq_printf(m, " at (%3d:%6d)",
  73. MAJOR(disk_devt(block->gdp)),
  74. MINOR(disk_devt(block->gdp)));
  75. else
  76. seq_printf(m, " at (???:??????)");
  77. /* Print device name. */
  78. if (block->gdp)
  79. seq_printf(m, " is %-8s", block->gdp->disk_name);
  80. else
  81. seq_printf(m, " is ????????");
  82. /* Print devices features. */
  83. substr = (device->features & DASD_FEATURE_READONLY) ? "(ro)" : " ";
  84. seq_printf(m, "%4s: ", substr);
  85. /* Print device status information. */
  86. switch (device->state) {
  87. case DASD_STATE_NEW:
  88. seq_printf(m, "new");
  89. break;
  90. case DASD_STATE_KNOWN:
  91. seq_printf(m, "detected");
  92. break;
  93. case DASD_STATE_BASIC:
  94. seq_printf(m, "basic");
  95. break;
  96. case DASD_STATE_UNFMT:
  97. seq_printf(m, "unformatted");
  98. break;
  99. case DASD_STATE_READY:
  100. case DASD_STATE_ONLINE:
  101. seq_printf(m, "active ");
  102. if (dasd_check_blocksize(block->bp_block))
  103. seq_printf(m, "n/f ");
  104. else
  105. seq_printf(m,
  106. "at blocksize: %d, %lld blocks, %lld MB",
  107. block->bp_block, block->blocks,
  108. ((block->bp_block >> 9) *
  109. block->blocks) >> 11);
  110. break;
  111. default:
  112. seq_printf(m, "no stat");
  113. break;
  114. }
  115. dasd_put_device(device);
  116. if (dasd_probeonly)
  117. seq_printf(m, "(probeonly)");
  118. seq_printf(m, "\n");
  119. return 0;
  120. }
  121. static void *dasd_devices_start(struct seq_file *m, loff_t *pos)
  122. {
  123. if (*pos >= dasd_max_devindex)
  124. return NULL;
  125. return (void *)((unsigned long) *pos + 1);
  126. }
  127. static void *dasd_devices_next(struct seq_file *m, void *v, loff_t *pos)
  128. {
  129. ++*pos;
  130. return dasd_devices_start(m, pos);
  131. }
  132. static void dasd_devices_stop(struct seq_file *m, void *v)
  133. {
  134. }
  135. static const struct seq_operations dasd_devices_seq_ops = {
  136. .start = dasd_devices_start,
  137. .next = dasd_devices_next,
  138. .stop = dasd_devices_stop,
  139. .show = dasd_devices_show,
  140. };
  141. static int dasd_devices_open(struct inode *inode, struct file *file)
  142. {
  143. return seq_open(file, &dasd_devices_seq_ops);
  144. }
  145. static const struct file_operations dasd_devices_file_ops = {
  146. .owner = THIS_MODULE,
  147. .open = dasd_devices_open,
  148. .read = seq_read,
  149. .llseek = seq_lseek,
  150. .release = seq_release,
  151. };
  152. #ifdef CONFIG_DASD_PROFILE
  153. static void dasd_statistics_array(struct seq_file *m, unsigned int *array, int factor)
  154. {
  155. int i;
  156. for (i = 0; i < 32; i++) {
  157. seq_printf(m, "%7d ", array[i] / factor);
  158. if (i == 15)
  159. seq_putc(m, '\n');
  160. }
  161. seq_putc(m, '\n');
  162. }
  163. #endif /* CONFIG_DASD_PROFILE */
  164. static int dasd_stats_proc_show(struct seq_file *m, void *v)
  165. {
  166. #ifdef CONFIG_DASD_PROFILE
  167. struct dasd_profile_info_t *prof;
  168. int factor;
  169. /* check for active profiling */
  170. if (dasd_profile_level == DASD_PROFILE_OFF) {
  171. seq_printf(m, "Statistics are off - they might be "
  172. "switched on using 'echo set on > "
  173. "/proc/dasd/statistics'\n");
  174. return 0;
  175. }
  176. prof = &dasd_global_profile;
  177. /* prevent counter 'overflow' on output */
  178. for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999;
  179. factor *= 10);
  180. seq_printf(m, "%d dasd I/O requests\n", prof->dasd_io_reqs);
  181. seq_printf(m, "with %u sectors(512B each)\n",
  182. prof->dasd_io_sects);
  183. seq_printf(m, "Scale Factor is %d\n", factor);
  184. seq_printf(m,
  185. " __<4 ___8 __16 __32 __64 _128 "
  186. " _256 _512 __1k __2k __4k __8k "
  187. " _16k _32k _64k 128k\n");
  188. seq_printf(m,
  189. " _256 _512 __1M __2M __4M __8M "
  190. " _16M _32M _64M 128M 256M 512M "
  191. " __1G __2G __4G " " _>4G\n");
  192. seq_printf(m, "Histogram of sizes (512B secs)\n");
  193. dasd_statistics_array(m, prof->dasd_io_secs, factor);
  194. seq_printf(m, "Histogram of I/O times (microseconds)\n");
  195. dasd_statistics_array(m, prof->dasd_io_times, factor);
  196. seq_printf(m, "Histogram of I/O times per sector\n");
  197. dasd_statistics_array(m, prof->dasd_io_timps, factor);
  198. seq_printf(m, "Histogram of I/O time till ssch\n");
  199. dasd_statistics_array(m, prof->dasd_io_time1, factor);
  200. seq_printf(m, "Histogram of I/O time between ssch and irq\n");
  201. dasd_statistics_array(m, prof->dasd_io_time2, factor);
  202. seq_printf(m, "Histogram of I/O time between ssch "
  203. "and irq per sector\n");
  204. dasd_statistics_array(m, prof->dasd_io_time2ps, factor);
  205. seq_printf(m, "Histogram of I/O time between irq and end\n");
  206. dasd_statistics_array(m, prof->dasd_io_time3, factor);
  207. seq_printf(m, "# of req in chanq at enqueuing (1..32) \n");
  208. dasd_statistics_array(m, prof->dasd_io_nr_req, factor);
  209. #else
  210. seq_printf(m, "Statistics are not activated in this kernel\n");
  211. #endif
  212. return 0;
  213. }
  214. static int dasd_stats_proc_open(struct inode *inode, struct file *file)
  215. {
  216. return single_open(file, dasd_stats_proc_show, NULL);
  217. }
  218. static ssize_t dasd_stats_proc_write(struct file *file,
  219. const char __user *user_buf, size_t user_len, loff_t *pos)
  220. {
  221. #ifdef CONFIG_DASD_PROFILE
  222. char *buffer, *str;
  223. if (user_len > 65536)
  224. user_len = 65536;
  225. buffer = dasd_get_user_string(user_buf, user_len);
  226. if (IS_ERR(buffer))
  227. return PTR_ERR(buffer);
  228. /* check for valid verbs */
  229. str = skip_spaces(buffer);
  230. if (strncmp(str, "set", 3) == 0 && isspace(str[3])) {
  231. /* 'set xxx' was given */
  232. str = skip_spaces(str + 4);
  233. if (strcmp(str, "on") == 0) {
  234. /* switch on statistics profiling */
  235. dasd_profile_level = DASD_PROFILE_ON;
  236. pr_info("The statistics feature has been switched "
  237. "on\n");
  238. } else if (strcmp(str, "off") == 0) {
  239. /* switch off and reset statistics profiling */
  240. memset(&dasd_global_profile,
  241. 0, sizeof (struct dasd_profile_info_t));
  242. dasd_profile_level = DASD_PROFILE_OFF;
  243. pr_info("The statistics feature has been switched "
  244. "off\n");
  245. } else
  246. goto out_error;
  247. } else if (strncmp(str, "reset", 5) == 0) {
  248. /* reset the statistics */
  249. memset(&dasd_global_profile, 0,
  250. sizeof (struct dasd_profile_info_t));
  251. pr_info("The statistics have been reset\n");
  252. } else
  253. goto out_error;
  254. kfree(buffer);
  255. return user_len;
  256. out_error:
  257. pr_warning("%s is not a supported value for /proc/dasd/statistics\n",
  258. str);
  259. kfree(buffer);
  260. return -EINVAL;
  261. #else
  262. pr_warning("/proc/dasd/statistics: is not activated in this kernel\n");
  263. return user_len;
  264. #endif /* CONFIG_DASD_PROFILE */
  265. }
  266. static const struct file_operations dasd_stats_proc_fops = {
  267. .owner = THIS_MODULE,
  268. .open = dasd_stats_proc_open,
  269. .read = seq_read,
  270. .llseek = seq_lseek,
  271. .release = single_release,
  272. .write = dasd_stats_proc_write,
  273. };
  274. /*
  275. * Create dasd proc-fs entries.
  276. * In case creation failed, cleanup and return -ENOENT.
  277. */
  278. int
  279. dasd_proc_init(void)
  280. {
  281. dasd_proc_root_entry = proc_mkdir("dasd", NULL);
  282. if (!dasd_proc_root_entry)
  283. goto out_nodasd;
  284. dasd_devices_entry = proc_create("devices",
  285. S_IFREG | S_IRUGO | S_IWUSR,
  286. dasd_proc_root_entry,
  287. &dasd_devices_file_ops);
  288. if (!dasd_devices_entry)
  289. goto out_nodevices;
  290. dasd_statistics_entry = proc_create("statistics",
  291. S_IFREG | S_IRUGO | S_IWUSR,
  292. dasd_proc_root_entry,
  293. &dasd_stats_proc_fops);
  294. if (!dasd_statistics_entry)
  295. goto out_nostatistics;
  296. return 0;
  297. out_nostatistics:
  298. remove_proc_entry("devices", dasd_proc_root_entry);
  299. out_nodevices:
  300. remove_proc_entry("dasd", NULL);
  301. out_nodasd:
  302. return -ENOENT;
  303. }
  304. void
  305. dasd_proc_exit(void)
  306. {
  307. remove_proc_entry("devices", dasd_proc_root_entry);
  308. remove_proc_entry("statistics", dasd_proc_root_entry);
  309. remove_proc_entry("dasd", NULL);
  310. }