18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> 48c2ecf20Sopenharmony_ci * Horst Hummel <Horst.Hummel@de.ibm.com> 58c2ecf20Sopenharmony_ci * Carsten Otte <Cotte@de.ibm.com> 68c2ecf20Sopenharmony_ci * Martin Schwidefsky <schwidefsky@de.ibm.com> 78c2ecf20Sopenharmony_ci * Bugreports.to..: <Linux390@de.ibm.com> 88c2ecf20Sopenharmony_ci * Copyright IBM Corp. 1999, 2002 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * /proc interface for the dasd driver. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define KMSG_COMPONENT "dasd" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/ctype.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/string.h> 198c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 208c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 218c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <asm/debug.h> 248c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* This is ugly... */ 278c2ecf20Sopenharmony_ci#define PRINTK_HEADER "dasd_proc:" 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include "dasd_int.h" 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic struct proc_dir_entry *dasd_proc_root_entry = NULL; 328c2ecf20Sopenharmony_cistatic struct proc_dir_entry *dasd_devices_entry = NULL; 338c2ecf20Sopenharmony_cistatic struct proc_dir_entry *dasd_statistics_entry = NULL; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic int 368c2ecf20Sopenharmony_cidasd_devices_show(struct seq_file *m, void *v) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci struct dasd_device *device; 398c2ecf20Sopenharmony_ci struct dasd_block *block; 408c2ecf20Sopenharmony_ci char *substr; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci device = dasd_device_from_devindex((unsigned long) v - 1); 438c2ecf20Sopenharmony_ci if (IS_ERR(device)) 448c2ecf20Sopenharmony_ci return 0; 458c2ecf20Sopenharmony_ci if (device->block) 468c2ecf20Sopenharmony_ci block = device->block; 478c2ecf20Sopenharmony_ci else { 488c2ecf20Sopenharmony_ci dasd_put_device(device); 498c2ecf20Sopenharmony_ci return 0; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci /* Print device number. */ 528c2ecf20Sopenharmony_ci seq_printf(m, "%s", dev_name(&device->cdev->dev)); 538c2ecf20Sopenharmony_ci /* Print discipline string. */ 548c2ecf20Sopenharmony_ci if (device->discipline != NULL) 558c2ecf20Sopenharmony_ci seq_printf(m, "(%s)", device->discipline->name); 568c2ecf20Sopenharmony_ci else 578c2ecf20Sopenharmony_ci seq_printf(m, "(none)"); 588c2ecf20Sopenharmony_ci /* Print kdev. */ 598c2ecf20Sopenharmony_ci if (block->gdp) 608c2ecf20Sopenharmony_ci seq_printf(m, " at (%3d:%6d)", 618c2ecf20Sopenharmony_ci MAJOR(disk_devt(block->gdp)), 628c2ecf20Sopenharmony_ci MINOR(disk_devt(block->gdp))); 638c2ecf20Sopenharmony_ci else 648c2ecf20Sopenharmony_ci seq_printf(m, " at (???:??????)"); 658c2ecf20Sopenharmony_ci /* Print device name. */ 668c2ecf20Sopenharmony_ci if (block->gdp) 678c2ecf20Sopenharmony_ci seq_printf(m, " is %-8s", block->gdp->disk_name); 688c2ecf20Sopenharmony_ci else 698c2ecf20Sopenharmony_ci seq_printf(m, " is ????????"); 708c2ecf20Sopenharmony_ci /* Print devices features. */ 718c2ecf20Sopenharmony_ci substr = (device->features & DASD_FEATURE_READONLY) ? "(ro)" : " "; 728c2ecf20Sopenharmony_ci seq_printf(m, "%4s: ", substr); 738c2ecf20Sopenharmony_ci /* Print device status information. */ 748c2ecf20Sopenharmony_ci switch (device->state) { 758c2ecf20Sopenharmony_ci case DASD_STATE_NEW: 768c2ecf20Sopenharmony_ci seq_printf(m, "new"); 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci case DASD_STATE_KNOWN: 798c2ecf20Sopenharmony_ci seq_printf(m, "detected"); 808c2ecf20Sopenharmony_ci break; 818c2ecf20Sopenharmony_ci case DASD_STATE_BASIC: 828c2ecf20Sopenharmony_ci seq_printf(m, "basic"); 838c2ecf20Sopenharmony_ci break; 848c2ecf20Sopenharmony_ci case DASD_STATE_UNFMT: 858c2ecf20Sopenharmony_ci seq_printf(m, "unformatted"); 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci case DASD_STATE_READY: 888c2ecf20Sopenharmony_ci case DASD_STATE_ONLINE: 898c2ecf20Sopenharmony_ci seq_printf(m, "active "); 908c2ecf20Sopenharmony_ci if (dasd_check_blocksize(block->bp_block)) 918c2ecf20Sopenharmony_ci seq_printf(m, "n/f "); 928c2ecf20Sopenharmony_ci else 938c2ecf20Sopenharmony_ci seq_printf(m, 948c2ecf20Sopenharmony_ci "at blocksize: %u, %lu blocks, %lu MB", 958c2ecf20Sopenharmony_ci block->bp_block, block->blocks, 968c2ecf20Sopenharmony_ci ((block->bp_block >> 9) * 978c2ecf20Sopenharmony_ci block->blocks) >> 11); 988c2ecf20Sopenharmony_ci break; 998c2ecf20Sopenharmony_ci default: 1008c2ecf20Sopenharmony_ci seq_printf(m, "no stat"); 1018c2ecf20Sopenharmony_ci break; 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci dasd_put_device(device); 1048c2ecf20Sopenharmony_ci if (dasd_probeonly) 1058c2ecf20Sopenharmony_ci seq_printf(m, "(probeonly)"); 1068c2ecf20Sopenharmony_ci seq_printf(m, "\n"); 1078c2ecf20Sopenharmony_ci return 0; 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic void *dasd_devices_start(struct seq_file *m, loff_t *pos) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci if (*pos >= dasd_max_devindex) 1138c2ecf20Sopenharmony_ci return NULL; 1148c2ecf20Sopenharmony_ci return (void *)((unsigned long) *pos + 1); 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic void *dasd_devices_next(struct seq_file *m, void *v, loff_t *pos) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci ++*pos; 1208c2ecf20Sopenharmony_ci return dasd_devices_start(m, pos); 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic void dasd_devices_stop(struct seq_file *m, void *v) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic const struct seq_operations dasd_devices_seq_ops = { 1288c2ecf20Sopenharmony_ci .start = dasd_devices_start, 1298c2ecf20Sopenharmony_ci .next = dasd_devices_next, 1308c2ecf20Sopenharmony_ci .stop = dasd_devices_stop, 1318c2ecf20Sopenharmony_ci .show = dasd_devices_show, 1328c2ecf20Sopenharmony_ci}; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci#ifdef CONFIG_DASD_PROFILE 1358c2ecf20Sopenharmony_cistatic int dasd_stats_all_block_on(void) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci int i, rc; 1388c2ecf20Sopenharmony_ci struct dasd_device *device; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci rc = 0; 1418c2ecf20Sopenharmony_ci for (i = 0; i < dasd_max_devindex; ++i) { 1428c2ecf20Sopenharmony_ci device = dasd_device_from_devindex(i); 1438c2ecf20Sopenharmony_ci if (IS_ERR(device)) 1448c2ecf20Sopenharmony_ci continue; 1458c2ecf20Sopenharmony_ci if (device->block) 1468c2ecf20Sopenharmony_ci rc = dasd_profile_on(&device->block->profile); 1478c2ecf20Sopenharmony_ci dasd_put_device(device); 1488c2ecf20Sopenharmony_ci if (rc) 1498c2ecf20Sopenharmony_ci return rc; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci return 0; 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic void dasd_stats_all_block_off(void) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci int i; 1578c2ecf20Sopenharmony_ci struct dasd_device *device; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci for (i = 0; i < dasd_max_devindex; ++i) { 1608c2ecf20Sopenharmony_ci device = dasd_device_from_devindex(i); 1618c2ecf20Sopenharmony_ci if (IS_ERR(device)) 1628c2ecf20Sopenharmony_ci continue; 1638c2ecf20Sopenharmony_ci if (device->block) 1648c2ecf20Sopenharmony_ci dasd_profile_off(&device->block->profile); 1658c2ecf20Sopenharmony_ci dasd_put_device(device); 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic void dasd_stats_all_block_reset(void) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci int i; 1728c2ecf20Sopenharmony_ci struct dasd_device *device; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci for (i = 0; i < dasd_max_devindex; ++i) { 1758c2ecf20Sopenharmony_ci device = dasd_device_from_devindex(i); 1768c2ecf20Sopenharmony_ci if (IS_ERR(device)) 1778c2ecf20Sopenharmony_ci continue; 1788c2ecf20Sopenharmony_ci if (device->block) 1798c2ecf20Sopenharmony_ci dasd_profile_reset(&device->block->profile); 1808c2ecf20Sopenharmony_ci dasd_put_device(device); 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci} 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cistatic void dasd_statistics_array(struct seq_file *m, unsigned int *array, int factor) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci int i; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) { 1898c2ecf20Sopenharmony_ci seq_printf(m, "%7d ", array[i] / factor); 1908c2ecf20Sopenharmony_ci if (i == 15) 1918c2ecf20Sopenharmony_ci seq_putc(m, '\n'); 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci seq_putc(m, '\n'); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci#endif /* CONFIG_DASD_PROFILE */ 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int dasd_stats_proc_show(struct seq_file *m, void *v) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci#ifdef CONFIG_DASD_PROFILE 2008c2ecf20Sopenharmony_ci struct dasd_profile_info *prof; 2018c2ecf20Sopenharmony_ci int factor; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci spin_lock_bh(&dasd_global_profile.lock); 2048c2ecf20Sopenharmony_ci prof = dasd_global_profile.data; 2058c2ecf20Sopenharmony_ci if (!prof) { 2068c2ecf20Sopenharmony_ci spin_unlock_bh(&dasd_global_profile.lock); 2078c2ecf20Sopenharmony_ci seq_printf(m, "Statistics are off - they might be " 2088c2ecf20Sopenharmony_ci "switched on using 'echo set on > " 2098c2ecf20Sopenharmony_ci "/proc/dasd/statistics'\n"); 2108c2ecf20Sopenharmony_ci return 0; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci /* prevent counter 'overflow' on output */ 2148c2ecf20Sopenharmony_ci for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999; 2158c2ecf20Sopenharmony_ci factor *= 10); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci seq_printf(m, "%d dasd I/O requests\n", prof->dasd_io_reqs); 2188c2ecf20Sopenharmony_ci seq_printf(m, "with %u sectors(512B each)\n", 2198c2ecf20Sopenharmony_ci prof->dasd_io_sects); 2208c2ecf20Sopenharmony_ci seq_printf(m, "Scale Factor is %d\n", factor); 2218c2ecf20Sopenharmony_ci seq_printf(m, 2228c2ecf20Sopenharmony_ci " __<4 ___8 __16 __32 __64 _128 " 2238c2ecf20Sopenharmony_ci " _256 _512 __1k __2k __4k __8k " 2248c2ecf20Sopenharmony_ci " _16k _32k _64k 128k\n"); 2258c2ecf20Sopenharmony_ci seq_printf(m, 2268c2ecf20Sopenharmony_ci " _256 _512 __1M __2M __4M __8M " 2278c2ecf20Sopenharmony_ci " _16M _32M _64M 128M 256M 512M " 2288c2ecf20Sopenharmony_ci " __1G __2G __4G " " _>4G\n"); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci seq_printf(m, "Histogram of sizes (512B secs)\n"); 2318c2ecf20Sopenharmony_ci dasd_statistics_array(m, prof->dasd_io_secs, factor); 2328c2ecf20Sopenharmony_ci seq_printf(m, "Histogram of I/O times (microseconds)\n"); 2338c2ecf20Sopenharmony_ci dasd_statistics_array(m, prof->dasd_io_times, factor); 2348c2ecf20Sopenharmony_ci seq_printf(m, "Histogram of I/O times per sector\n"); 2358c2ecf20Sopenharmony_ci dasd_statistics_array(m, prof->dasd_io_timps, factor); 2368c2ecf20Sopenharmony_ci seq_printf(m, "Histogram of I/O time till ssch\n"); 2378c2ecf20Sopenharmony_ci dasd_statistics_array(m, prof->dasd_io_time1, factor); 2388c2ecf20Sopenharmony_ci seq_printf(m, "Histogram of I/O time between ssch and irq\n"); 2398c2ecf20Sopenharmony_ci dasd_statistics_array(m, prof->dasd_io_time2, factor); 2408c2ecf20Sopenharmony_ci seq_printf(m, "Histogram of I/O time between ssch " 2418c2ecf20Sopenharmony_ci "and irq per sector\n"); 2428c2ecf20Sopenharmony_ci dasd_statistics_array(m, prof->dasd_io_time2ps, factor); 2438c2ecf20Sopenharmony_ci seq_printf(m, "Histogram of I/O time between irq and end\n"); 2448c2ecf20Sopenharmony_ci dasd_statistics_array(m, prof->dasd_io_time3, factor); 2458c2ecf20Sopenharmony_ci seq_printf(m, "# of req in chanq at enqueuing (1..32) \n"); 2468c2ecf20Sopenharmony_ci dasd_statistics_array(m, prof->dasd_io_nr_req, factor); 2478c2ecf20Sopenharmony_ci spin_unlock_bh(&dasd_global_profile.lock); 2488c2ecf20Sopenharmony_ci#else 2498c2ecf20Sopenharmony_ci seq_printf(m, "Statistics are not activated in this kernel\n"); 2508c2ecf20Sopenharmony_ci#endif 2518c2ecf20Sopenharmony_ci return 0; 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic int dasd_stats_proc_open(struct inode *inode, struct file *file) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci return single_open(file, dasd_stats_proc_show, NULL); 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_cistatic ssize_t dasd_stats_proc_write(struct file *file, 2608c2ecf20Sopenharmony_ci const char __user *user_buf, size_t user_len, loff_t *pos) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci#ifdef CONFIG_DASD_PROFILE 2638c2ecf20Sopenharmony_ci char *buffer, *str; 2648c2ecf20Sopenharmony_ci int rc; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci if (user_len > 65536) 2678c2ecf20Sopenharmony_ci user_len = 65536; 2688c2ecf20Sopenharmony_ci buffer = dasd_get_user_string(user_buf, user_len); 2698c2ecf20Sopenharmony_ci if (IS_ERR(buffer)) 2708c2ecf20Sopenharmony_ci return PTR_ERR(buffer); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci /* check for valid verbs */ 2738c2ecf20Sopenharmony_ci str = skip_spaces(buffer); 2748c2ecf20Sopenharmony_ci if (strncmp(str, "set", 3) == 0 && isspace(str[3])) { 2758c2ecf20Sopenharmony_ci /* 'set xxx' was given */ 2768c2ecf20Sopenharmony_ci str = skip_spaces(str + 4); 2778c2ecf20Sopenharmony_ci if (strcmp(str, "on") == 0) { 2788c2ecf20Sopenharmony_ci /* switch on statistics profiling */ 2798c2ecf20Sopenharmony_ci rc = dasd_stats_all_block_on(); 2808c2ecf20Sopenharmony_ci if (rc) { 2818c2ecf20Sopenharmony_ci dasd_stats_all_block_off(); 2828c2ecf20Sopenharmony_ci goto out_error; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci rc = dasd_profile_on(&dasd_global_profile); 2858c2ecf20Sopenharmony_ci if (rc) { 2868c2ecf20Sopenharmony_ci dasd_stats_all_block_off(); 2878c2ecf20Sopenharmony_ci goto out_error; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci dasd_profile_reset(&dasd_global_profile); 2908c2ecf20Sopenharmony_ci dasd_global_profile_level = DASD_PROFILE_ON; 2918c2ecf20Sopenharmony_ci pr_info("The statistics feature has been switched " 2928c2ecf20Sopenharmony_ci "on\n"); 2938c2ecf20Sopenharmony_ci } else if (strcmp(str, "off") == 0) { 2948c2ecf20Sopenharmony_ci /* switch off statistics profiling */ 2958c2ecf20Sopenharmony_ci dasd_global_profile_level = DASD_PROFILE_OFF; 2968c2ecf20Sopenharmony_ci dasd_profile_off(&dasd_global_profile); 2978c2ecf20Sopenharmony_ci dasd_stats_all_block_off(); 2988c2ecf20Sopenharmony_ci pr_info("The statistics feature has been switched " 2998c2ecf20Sopenharmony_ci "off\n"); 3008c2ecf20Sopenharmony_ci } else 3018c2ecf20Sopenharmony_ci goto out_parse_error; 3028c2ecf20Sopenharmony_ci } else if (strncmp(str, "reset", 5) == 0) { 3038c2ecf20Sopenharmony_ci /* reset the statistics */ 3048c2ecf20Sopenharmony_ci dasd_profile_reset(&dasd_global_profile); 3058c2ecf20Sopenharmony_ci dasd_stats_all_block_reset(); 3068c2ecf20Sopenharmony_ci pr_info("The statistics have been reset\n"); 3078c2ecf20Sopenharmony_ci } else 3088c2ecf20Sopenharmony_ci goto out_parse_error; 3098c2ecf20Sopenharmony_ci vfree(buffer); 3108c2ecf20Sopenharmony_ci return user_len; 3118c2ecf20Sopenharmony_ciout_parse_error: 3128c2ecf20Sopenharmony_ci rc = -EINVAL; 3138c2ecf20Sopenharmony_ci pr_warn("%s is not a supported value for /proc/dasd/statistics\n", str); 3148c2ecf20Sopenharmony_ciout_error: 3158c2ecf20Sopenharmony_ci vfree(buffer); 3168c2ecf20Sopenharmony_ci return rc; 3178c2ecf20Sopenharmony_ci#else 3188c2ecf20Sopenharmony_ci pr_warn("/proc/dasd/statistics: is not activated in this kernel\n"); 3198c2ecf20Sopenharmony_ci return user_len; 3208c2ecf20Sopenharmony_ci#endif /* CONFIG_DASD_PROFILE */ 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic const struct proc_ops dasd_stats_proc_ops = { 3248c2ecf20Sopenharmony_ci .proc_open = dasd_stats_proc_open, 3258c2ecf20Sopenharmony_ci .proc_read = seq_read, 3268c2ecf20Sopenharmony_ci .proc_lseek = seq_lseek, 3278c2ecf20Sopenharmony_ci .proc_release = single_release, 3288c2ecf20Sopenharmony_ci .proc_write = dasd_stats_proc_write, 3298c2ecf20Sopenharmony_ci}; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci/* 3328c2ecf20Sopenharmony_ci * Create dasd proc-fs entries. 3338c2ecf20Sopenharmony_ci * In case creation failed, cleanup and return -ENOENT. 3348c2ecf20Sopenharmony_ci */ 3358c2ecf20Sopenharmony_ciint 3368c2ecf20Sopenharmony_cidasd_proc_init(void) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci dasd_proc_root_entry = proc_mkdir("dasd", NULL); 3398c2ecf20Sopenharmony_ci if (!dasd_proc_root_entry) 3408c2ecf20Sopenharmony_ci goto out_nodasd; 3418c2ecf20Sopenharmony_ci dasd_devices_entry = proc_create_seq("devices", 0444, 3428c2ecf20Sopenharmony_ci dasd_proc_root_entry, 3438c2ecf20Sopenharmony_ci &dasd_devices_seq_ops); 3448c2ecf20Sopenharmony_ci if (!dasd_devices_entry) 3458c2ecf20Sopenharmony_ci goto out_nodevices; 3468c2ecf20Sopenharmony_ci dasd_statistics_entry = proc_create("statistics", 3478c2ecf20Sopenharmony_ci S_IFREG | S_IRUGO | S_IWUSR, 3488c2ecf20Sopenharmony_ci dasd_proc_root_entry, 3498c2ecf20Sopenharmony_ci &dasd_stats_proc_ops); 3508c2ecf20Sopenharmony_ci if (!dasd_statistics_entry) 3518c2ecf20Sopenharmony_ci goto out_nostatistics; 3528c2ecf20Sopenharmony_ci return 0; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci out_nostatistics: 3558c2ecf20Sopenharmony_ci remove_proc_entry("devices", dasd_proc_root_entry); 3568c2ecf20Sopenharmony_ci out_nodevices: 3578c2ecf20Sopenharmony_ci remove_proc_entry("dasd", NULL); 3588c2ecf20Sopenharmony_ci out_nodasd: 3598c2ecf20Sopenharmony_ci return -ENOENT; 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_civoid 3638c2ecf20Sopenharmony_cidasd_proc_exit(void) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci remove_proc_entry("devices", dasd_proc_root_entry); 3668c2ecf20Sopenharmony_ci remove_proc_entry("statistics", dasd_proc_root_entry); 3678c2ecf20Sopenharmony_ci remove_proc_entry("dasd", NULL); 3688c2ecf20Sopenharmony_ci} 369