diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-03-30 23:58:05 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-04-09 14:13:14 -0400 |
commit | 0ffddfbb834557b8babc7f050b83d11dbcbb1008 (patch) | |
tree | 620afe52d29443b4ad10f805afe6b22d43349e5f | |
parent | b6cdc7310338e204224f865918f774eb6db0b75d (diff) |
scsi: saner replacements for ->proc_info()
It's still an obsolete interface; don't introduce those in new drivers.
However, it's saner than the ->proc_info() and commits after this one
will convert the existing ->proc_info() users to it.
The read side is ->show_info(seq_file *, struct Scsi_Host *); use
seq_... for generating contents.
The write side is ->write_info(struct Scsi_Host *, char *, int).
Again, this is driven by procfs needs; we are going to kill ->write_proc()
and ->read_proc() and this is the main obstacle to burying that piece of
shit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | drivers/scsi/scsi_proc.c | 68 | ||||
-rw-r--r-- | include/scsi/scsi_host.h | 5 |
2 files changed, 63 insertions, 10 deletions
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index ad747dc337da..6f4c3cff03bb 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c | |||
@@ -97,6 +97,49 @@ out: | |||
97 | return ret; | 97 | return ret; |
98 | } | 98 | } |
99 | 99 | ||
100 | static ssize_t proc_scsi_host_write(struct file *file, const char __user *buf, | ||
101 | size_t count, loff_t *ppos) | ||
102 | { | ||
103 | struct Scsi_Host *shost = PDE(file_inode(file))->data; | ||
104 | ssize_t ret = -ENOMEM; | ||
105 | char *page; | ||
106 | |||
107 | if (count > PROC_BLOCK_SIZE) | ||
108 | return -EOVERFLOW; | ||
109 | |||
110 | if (!shost->hostt->write_info) | ||
111 | return -EINVAL; | ||
112 | |||
113 | page = (char *)__get_free_page(GFP_KERNEL); | ||
114 | if (page) { | ||
115 | ret = -EFAULT; | ||
116 | if (copy_from_user(page, buf, count)) | ||
117 | goto out; | ||
118 | ret = shost->hostt->write_info(shost, page, count); | ||
119 | } | ||
120 | out: | ||
121 | free_page((unsigned long)page); | ||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static int proc_scsi_show(struct seq_file *m, void *v) | ||
126 | { | ||
127 | struct Scsi_Host *shost = m->private; | ||
128 | return shost->hostt->show_info(m, shost); | ||
129 | } | ||
130 | |||
131 | static int proc_scsi_host_open(struct inode *inode, struct file *file) | ||
132 | { | ||
133 | return single_open(file, proc_scsi_show, PDE(inode)->data); | ||
134 | } | ||
135 | |||
136 | static const struct file_operations proc_scsi_fops = { | ||
137 | .open = proc_scsi_host_open, | ||
138 | .read = seq_read, | ||
139 | .llseek = seq_lseek, | ||
140 | .write = proc_scsi_host_write | ||
141 | }; | ||
142 | |||
100 | /** | 143 | /** |
101 | * scsi_proc_hostdir_add - Create directory in /proc for a scsi host | 144 | * scsi_proc_hostdir_add - Create directory in /proc for a scsi host |
102 | * @sht: owner of this directory | 145 | * @sht: owner of this directory |
@@ -106,7 +149,7 @@ out: | |||
106 | 149 | ||
107 | void scsi_proc_hostdir_add(struct scsi_host_template *sht) | 150 | void scsi_proc_hostdir_add(struct scsi_host_template *sht) |
108 | { | 151 | { |
109 | if (!sht->proc_info) | 152 | if (!sht->proc_info && !sht->show_info) |
110 | return; | 153 | return; |
111 | 154 | ||
112 | mutex_lock(&global_host_template_mutex); | 155 | mutex_lock(&global_host_template_mutex); |
@@ -125,7 +168,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht) | |||
125 | */ | 168 | */ |
126 | void scsi_proc_hostdir_rm(struct scsi_host_template *sht) | 169 | void scsi_proc_hostdir_rm(struct scsi_host_template *sht) |
127 | { | 170 | { |
128 | if (!sht->proc_info) | 171 | if (!sht->proc_info && !sht->show_info) |
129 | return; | 172 | return; |
130 | 173 | ||
131 | mutex_lock(&global_host_template_mutex); | 174 | mutex_lock(&global_host_template_mutex); |
@@ -151,16 +194,23 @@ void scsi_proc_host_add(struct Scsi_Host *shost) | |||
151 | return; | 194 | return; |
152 | 195 | ||
153 | sprintf(name,"%d", shost->host_no); | 196 | sprintf(name,"%d", shost->host_no); |
197 | if (sht->show_info) { | ||
198 | p = proc_create_data(name, S_IRUGO | S_IWUSR, | ||
199 | sht->proc_dir, &proc_scsi_fops, shost); | ||
200 | if (!p) | ||
201 | goto Fail; | ||
202 | return; | ||
203 | } | ||
154 | p = create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR, | 204 | p = create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR, |
155 | sht->proc_dir, proc_scsi_read, shost); | 205 | sht->proc_dir, proc_scsi_read, shost); |
156 | if (!p) { | 206 | if (p) { |
157 | printk(KERN_ERR "%s: Failed to register host %d in" | 207 | p->write_proc = proc_scsi_write_proc; |
158 | "%s\n", __func__, shost->host_no, | ||
159 | sht->proc_name); | ||
160 | return; | 208 | return; |
161 | } | 209 | } |
162 | 210 | Fail: | |
163 | p->write_proc = proc_scsi_write_proc; | 211 | printk(KERN_ERR "%s: Failed to register host %d in" |
212 | "%s\n", __func__, shost->host_no, | ||
213 | sht->proc_name); | ||
164 | } | 214 | } |
165 | 215 | ||
166 | /** | 216 | /** |
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 2b6956e9853d..70e08e442bfc 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
7 | #include <linux/workqueue.h> | 7 | #include <linux/workqueue.h> |
8 | #include <linux/mutex.h> | 8 | #include <linux/mutex.h> |
9 | #include <linux/seq_file.h> | ||
9 | #include <scsi/scsi.h> | 10 | #include <scsi/scsi.h> |
10 | 11 | ||
11 | struct request_queue; | 12 | struct request_queue; |
@@ -341,6 +342,8 @@ struct scsi_host_template { | |||
341 | * Status: OBSOLETE | 342 | * Status: OBSOLETE |
342 | */ | 343 | */ |
343 | int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int); | 344 | int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int); |
345 | int (*show_info)(struct seq_file *, struct Scsi_Host *); | ||
346 | int (*write_info)(struct Scsi_Host *, char *, int); | ||
344 | 347 | ||
345 | /* | 348 | /* |
346 | * This is an optional routine that allows the transport to become | 349 | * This is an optional routine that allows the transport to become |
@@ -375,7 +378,7 @@ struct scsi_host_template { | |||
375 | 378 | ||
376 | /* | 379 | /* |
377 | * Used to store the procfs directory if a driver implements the | 380 | * Used to store the procfs directory if a driver implements the |
378 | * proc_info method. | 381 | * proc_info or show_info method. |
379 | */ | 382 | */ |
380 | struct proc_dir_entry *proc_dir; | 383 | struct proc_dir_entry *proc_dir; |
381 | 384 | ||