Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | // SPDX-License-Identifier: GPL-2.0 /* * tape device driver for S/390 and zSeries tapes. * * S390 and zSeries version * Copyright IBM Corp. 2001 * Author(s): Carsten Otte <cotte@de.ibm.com> * Michael Holzheu <holzheu@de.ibm.com> * Tuan Ngo-Anh <ngoanh@de.ibm.com> * * PROCFS Functions */ #define KMSG_COMPONENT "tape" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include <linux/module.h> #include <linux/vmalloc.h> #include <linux/seq_file.h> #include <linux/proc_fs.h> #define TAPE_DBF_AREA tape_core_dbf #include "tape.h" static const char *tape_med_st_verbose[MS_SIZE] = { [MS_UNKNOWN] = "UNKNOWN ", [MS_LOADED] = "LOADED ", [MS_UNLOADED] = "UNLOADED" }; /* our proc tapedevices entry */ static struct proc_dir_entry *tape_proc_devices; /* * Show function for /proc/tapedevices */ static int tape_proc_show(struct seq_file *m, void *v) { struct tape_device *device; struct tape_request *request; const char *str; unsigned long n; n = (unsigned long) v - 1; if (!n) { seq_printf(m, "TapeNo\tBusID CuType/Model\t" "DevType/Model\tBlkSize\tState\tOp\tMedState\n"); } device = tape_find_device(n); if (IS_ERR(device)) return 0; spin_lock_irq(get_ccwdev_lock(device->cdev)); seq_printf(m, "%d\t", (int) n); seq_printf(m, "%-10.10s ", dev_name(&device->cdev->dev)); seq_printf(m, "%04X/", device->cdev->id.cu_type); seq_printf(m, "%02X\t", device->cdev->id.cu_model); seq_printf(m, "%04X/", device->cdev->id.dev_type); seq_printf(m, "%02X\t\t", device->cdev->id.dev_model); if (device->char_data.block_size == 0) seq_printf(m, "auto\t"); else seq_printf(m, "%i\t", device->char_data.block_size); if (device->tape_state >= 0 && device->tape_state < TS_SIZE) str = tape_state_verbose[device->tape_state]; else str = "UNKNOWN"; seq_printf(m, "%s\t", str); if (!list_empty(&device->req_queue)) { request = list_entry(device->req_queue.next, struct tape_request, list); str = tape_op_verbose[request->op]; } else str = "---"; seq_printf(m, "%s\t", str); seq_printf(m, "%s\n", tape_med_st_verbose[device->medium_state]); spin_unlock_irq(get_ccwdev_lock(device->cdev)); tape_put_device(device); return 0; } static void *tape_proc_start(struct seq_file *m, loff_t *pos) { if (*pos >= 256 / TAPE_MINORS_PER_DEV) return NULL; return (void *)((unsigned long) *pos + 1); } static void *tape_proc_next(struct seq_file *m, void *v, loff_t *pos) { ++*pos; return tape_proc_start(m, pos); } static void tape_proc_stop(struct seq_file *m, void *v) { } static const struct seq_operations tape_proc_seq = { .start = tape_proc_start, .next = tape_proc_next, .stop = tape_proc_stop, .show = tape_proc_show, }; static int tape_proc_open(struct inode *inode, struct file *file) { return seq_open(file, &tape_proc_seq); } static const struct file_operations tape_proc_ops = { .owner = THIS_MODULE, .open = tape_proc_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, }; /* * Initialize procfs stuff on startup */ void tape_proc_init(void) { tape_proc_devices = proc_create("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, NULL, &tape_proc_ops); if (tape_proc_devices == NULL) { return; } } /* * Cleanup all stuff registered to the procfs */ void tape_proc_cleanup(void) { if (tape_proc_devices != NULL) remove_proc_entry ("tapedevices", NULL); } |