]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/block/aoe/aoeblk.c
aoe: provide file operations for debugfs files
[mirror_ubuntu-artful-kernel.git] / drivers / block / aoe / aoeblk.c
CommitLineData
fea05a26 1/* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */
1da177e4
LT
2/*
3 * aoeblk.c
4 * block device routines
5 */
6
027b180d 7#include <linux/kernel.h>
1da177e4
LT
8#include <linux/hdreg.h>
9#include <linux/blkdev.h>
43cbe2cb 10#include <linux/backing-dev.h>
1da177e4
LT
11#include <linux/fs.h>
12#include <linux/ioctl.h>
5a0e3ad6 13#include <linux/slab.h>
027b180d 14#include <linux/ratelimit.h>
1da177e4
LT
15#include <linux/genhd.h>
16#include <linux/netdevice.h>
2a48fc0a 17#include <linux/mutex.h>
d5decd3b 18#include <linux/export.h>
aa304fde 19#include <linux/moduleparam.h>
190519cd 20#include <linux/debugfs.h>
667be1e7 21#include <scsi/sg.h>
1da177e4
LT
22#include "aoe.h"
23
2a48fc0a 24static DEFINE_MUTEX(aoeblk_mutex);
e18b890b 25static struct kmem_cache *buf_pool_cache;
190519cd 26static struct dentry *aoe_debugfs_dir;
1da177e4 27
aa304fde
EC
28/* GPFS needs a larger value than the default. */
29static int aoe_maxsectors;
30module_param(aoe_maxsectors, int, 0644);
31MODULE_PARM_DESC(aoe_maxsectors,
32 "When nonzero, set the maximum number of sectors per I/O request");
33
edfaa7c3
KS
34static ssize_t aoedisk_show_state(struct device *dev,
35 struct device_attribute *attr, char *page)
1da177e4 36{
edfaa7c3 37 struct gendisk *disk = dev_to_disk(dev);
1da177e4
LT
38 struct aoedev *d = disk->private_data;
39
40 return snprintf(page, PAGE_SIZE,
41 "%s%s\n",
42 (d->flags & DEVFL_UP) ? "up" : "down",
68e0d42f 43 (d->flags & DEVFL_KICKME) ? ",kickme" :
3ae1c24e
EC
44 (d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : "");
45 /* I'd rather see nopen exported so we can ditch closewait */
1da177e4 46}
edfaa7c3
KS
47static ssize_t aoedisk_show_mac(struct device *dev,
48 struct device_attribute *attr, char *page)
1da177e4 49{
edfaa7c3 50 struct gendisk *disk = dev_to_disk(dev);
1da177e4 51 struct aoedev *d = disk->private_data;
68e0d42f 52 struct aoetgt *t = d->targets[0];
1da177e4 53
68e0d42f
EC
54 if (t == NULL)
55 return snprintf(page, PAGE_SIZE, "none\n");
411c41ee 56 return snprintf(page, PAGE_SIZE, "%pm\n", t->addr);
1da177e4 57}
edfaa7c3
KS
58static ssize_t aoedisk_show_netif(struct device *dev,
59 struct device_attribute *attr, char *page)
1da177e4 60{
edfaa7c3 61 struct gendisk *disk = dev_to_disk(dev);
1da177e4 62 struct aoedev *d = disk->private_data;
68e0d42f
EC
63 struct net_device *nds[8], **nd, **nnd, **ne;
64 struct aoetgt **t, **te;
65 struct aoeif *ifp, *e;
66 char *p;
67
68 memset(nds, 0, sizeof nds);
69 nd = nds;
70 ne = nd + ARRAY_SIZE(nds);
71 t = d->targets;
71114ec4 72 te = t + d->ntargets;
68e0d42f
EC
73 for (; t < te && *t; t++) {
74 ifp = (*t)->ifs;
75 e = ifp + NAOEIFS;
76 for (; ifp < e && ifp->nd; ifp++) {
77 for (nnd = nds; nnd < nd; nnd++)
78 if (*nnd == ifp->nd)
79 break;
80 if (nnd == nd && nd != ne)
81 *nd++ = ifp->nd;
82 }
83 }
1da177e4 84
68e0d42f
EC
85 ne = nd;
86 nd = nds;
87 if (*nd == NULL)
88 return snprintf(page, PAGE_SIZE, "none\n");
89 for (p = page; nd < ne; nd++)
90 p += snprintf(p, PAGE_SIZE - (p-page), "%s%s",
91 p == page ? "" : ",", (*nd)->name);
92 p += snprintf(p, PAGE_SIZE - (p-page), "\n");
93 return p-page;
1da177e4 94}
4613ed27 95/* firmware version */
edfaa7c3
KS
96static ssize_t aoedisk_show_fwver(struct device *dev,
97 struct device_attribute *attr, char *page)
4613ed27 98{
edfaa7c3 99 struct gendisk *disk = dev_to_disk(dev);
4613ed27
EC
100 struct aoedev *d = disk->private_data;
101
102 return snprintf(page, PAGE_SIZE, "0x%04x\n", (unsigned int) d->fw_ver);
103}
90a2508d
EC
104static ssize_t aoedisk_show_payload(struct device *dev,
105 struct device_attribute *attr, char *page)
106{
107 struct gendisk *disk = dev_to_disk(dev);
108 struct aoedev *d = disk->private_data;
109
110 return snprintf(page, PAGE_SIZE, "%lu\n", d->maxbcnt);
111}
1da177e4 112
1cf94797
EC
113static int aoedisk_debugfs_show(struct seq_file *s, void *ignored)
114{
115 struct aoedev *d;
116 unsigned long flags;
117
118 d = s->private;
119 spin_lock_irqsave(&d->lock, flags);
120 seq_printf(s, "%s\n", d->gd->disk_name); /* place holder */
121 spin_unlock_irqrestore(&d->lock, flags);
122
123 return 0;
124}
125
126static int aoe_debugfs_open(struct inode *inode, struct file *file)
127{
128 return single_open(file, aoedisk_debugfs_show, inode->i_private);
129}
130
edfaa7c3
KS
131static DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL);
132static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL);
133static DEVICE_ATTR(netif, S_IRUGO, aoedisk_show_netif, NULL);
134static struct device_attribute dev_attr_firmware_version = {
01e8ef11 135 .attr = { .name = "firmware-version", .mode = S_IRUGO },
edfaa7c3 136 .show = aoedisk_show_fwver,
4613ed27 137};
90a2508d 138static DEVICE_ATTR(payload, S_IRUGO, aoedisk_show_payload, NULL);
1da177e4 139
4ca5224f 140static struct attribute *aoe_attrs[] = {
edfaa7c3
KS
141 &dev_attr_state.attr,
142 &dev_attr_mac.attr,
143 &dev_attr_netif.attr,
144 &dev_attr_firmware_version.attr,
90a2508d 145 &dev_attr_payload.attr,
edfaa7c3 146 NULL,
4ca5224f
GKH
147};
148
149static const struct attribute_group attr_group = {
150 .attrs = aoe_attrs,
151};
152
1cf94797
EC
153static const struct file_operations aoe_debugfs_fops = {
154 .open = aoe_debugfs_open,
155 .read = seq_read,
156 .llseek = seq_lseek,
157 .release = single_release,
158};
e8866cf2
EC
159
160static void
161aoedisk_add_debugfs(struct aoedev *d)
162{
163 struct dentry *entry;
164 char *p;
165
166 if (aoe_debugfs_dir == NULL)
167 return;
168 p = strchr(d->gd->disk_name, '/');
169 if (p == NULL)
170 p = d->gd->disk_name;
171 else
172 p++;
173 BUG_ON(*p == '\0');
174 entry = debugfs_create_file(p, 0444, aoe_debugfs_dir, d,
175 &aoe_debugfs_fops);
176 if (IS_ERR_OR_NULL(entry)) {
177 pr_info("aoe: cannot create debugfs file for %s\n",
178 d->gd->disk_name);
179 return;
180 }
181 BUG_ON(d->debugfs);
182 d->debugfs = entry;
183}
184void
185aoedisk_rm_debugfs(struct aoedev *d)
186{
187 BUG_ON(d->debugfs == NULL);
188 debugfs_remove(d->debugfs);
189 d->debugfs = NULL;
190}
191
4ca5224f 192static int
1da177e4
LT
193aoedisk_add_sysfs(struct aoedev *d)
194{
ed9e1982 195 return sysfs_create_group(&disk_to_dev(d->gd)->kobj, &attr_group);
1da177e4
LT
196}
197void
198aoedisk_rm_sysfs(struct aoedev *d)
199{
ed9e1982 200 sysfs_remove_group(&disk_to_dev(d->gd)->kobj, &attr_group);
1da177e4
LT
201}
202
203static int
94562c17 204aoeblk_open(struct block_device *bdev, fmode_t mode)
1da177e4 205{
94562c17 206 struct aoedev *d = bdev->bd_disk->private_data;
1da177e4
LT
207 ulong flags;
208
e52a2932
EC
209 if (!virt_addr_valid(d)) {
210 pr_crit("aoe: invalid device pointer in %s\n",
211 __func__);
212 WARN_ON(1);
213 return -ENODEV;
214 }
215 if (!(d->flags & DEVFL_UP) || d->flags & DEVFL_TKILL)
216 return -ENODEV;
217
2a48fc0a 218 mutex_lock(&aoeblk_mutex);
1da177e4 219 spin_lock_irqsave(&d->lock, flags);
e52a2932 220 if (d->flags & DEVFL_UP && !(d->flags & DEVFL_TKILL)) {
1da177e4
LT
221 d->nopen++;
222 spin_unlock_irqrestore(&d->lock, flags);
2a48fc0a 223 mutex_unlock(&aoeblk_mutex);
1da177e4
LT
224 return 0;
225 }
226 spin_unlock_irqrestore(&d->lock, flags);
2a48fc0a 227 mutex_unlock(&aoeblk_mutex);
1da177e4
LT
228 return -ENODEV;
229}
230
db2a144b 231static void
94562c17 232aoeblk_release(struct gendisk *disk, fmode_t mode)
1da177e4 233{
94562c17 234 struct aoedev *d = disk->private_data;
1da177e4
LT
235 ulong flags;
236
1da177e4
LT
237 spin_lock_irqsave(&d->lock, flags);
238
5f7702fd 239 if (--d->nopen == 0) {
1da177e4
LT
240 spin_unlock_irqrestore(&d->lock, flags);
241 aoecmd_cfg(d->aoemajor, d->aoeminor);
db2a144b 242 return;
1da177e4
LT
243 }
244 spin_unlock_irqrestore(&d->lock, flags);
1da177e4
LT
245}
246
5a7bbad2 247static void
69cf2d85 248aoeblk_request(struct request_queue *q)
1da177e4
LT
249{
250 struct aoedev *d;
69cf2d85 251 struct request *rq;
1da177e4 252
69cf2d85 253 d = q->queuedata;
1da177e4 254 if ((d->flags & DEVFL_UP) == 0) {
027b180d 255 pr_info_ratelimited("aoe: device %ld.%d is not up\n",
a12c93f0 256 d->aoemajor, d->aoeminor);
69cf2d85
EC
257 while ((rq = blk_peek_request(q))) {
258 blk_start_request(rq);
259 aoe_end_request(d, rq, 1);
260 }
5a7bbad2 261 return;
1da177e4 262 }
3ae1c24e 263 aoecmd_work(d);
1da177e4
LT
264}
265
1da177e4 266static int
a885c8c4 267aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1da177e4 268{
a885c8c4 269 struct aoedev *d = bdev->bd_disk->private_data;
1da177e4 270
1da177e4 271 if ((d->flags & DEVFL_UP) == 0) {
a12c93f0 272 printk(KERN_ERR "aoe: disk not up\n");
1da177e4
LT
273 return -ENODEV;
274 }
275
a885c8c4
CH
276 geo->cylinders = d->geo.cylinders;
277 geo->heads = d->geo.heads;
278 geo->sectors = d->geo.sectors;
279 return 0;
1da177e4
LT
280}
281
667be1e7
EC
282static int
283aoeblk_ioctl(struct block_device *bdev, fmode_t mode, uint cmd, ulong arg)
284{
285 struct aoedev *d;
286
287 if (!arg)
288 return -EINVAL;
289
290 d = bdev->bd_disk->private_data;
291 if ((d->flags & DEVFL_UP) == 0) {
292 pr_err("aoe: disk not up\n");
293 return -ENODEV;
294 }
295
296 if (cmd == HDIO_GET_IDENTITY) {
297 if (!copy_to_user((void __user *) arg, &d->ident,
298 sizeof(d->ident)))
299 return 0;
300 return -EFAULT;
301 }
302
303 /* udev calls scsi_id, which uses SG_IO, resulting in noise */
304 if (cmd != SG_IO)
305 pr_info("aoe: unknown ioctl 0x%x\n", cmd);
306
307 return -ENOTTY;
308}
309
83d5cde4 310static const struct block_device_operations aoe_bdops = {
94562c17
AV
311 .open = aoeblk_open,
312 .release = aoeblk_release,
667be1e7 313 .ioctl = aoeblk_ioctl,
a885c8c4 314 .getgeo = aoeblk_getgeo,
1da177e4
LT
315 .owner = THIS_MODULE,
316};
317
318/* alloc_disk and add_disk can sleep */
319void
320aoeblk_gdalloc(void *vp)
321{
322 struct aoedev *d = vp;
323 struct gendisk *gd;
69cf2d85
EC
324 mempool_t *mp;
325 struct request_queue *q;
326 enum { KB = 1024, MB = KB * KB, READ_AHEAD = 2 * MB, };
1da177e4 327 ulong flags;
e52a2932
EC
328 int late = 0;
329
330 spin_lock_irqsave(&d->lock, flags);
331 if (d->flags & DEVFL_GDALLOC
332 && !(d->flags & DEVFL_TKILL)
333 && !(d->flags & DEVFL_GD_NOW))
334 d->flags |= DEVFL_GD_NOW;
335 else
336 late = 1;
337 spin_unlock_irqrestore(&d->lock, flags);
338 if (late)
339 return;
1da177e4
LT
340
341 gd = alloc_disk(AOE_PARTITIONS);
342 if (gd == NULL) {
69cf2d85 343 pr_err("aoe: cannot allocate disk structure for %ld.%d\n",
6bb6285f 344 d->aoemajor, d->aoeminor);
43cbe2cb 345 goto err;
1da177e4
LT
346 }
347
69cf2d85
EC
348 mp = mempool_create(MIN_BUFS, mempool_alloc_slab, mempool_free_slab,
349 buf_pool_cache);
350 if (mp == NULL) {
1d75981a 351 printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%d\n",
6bb6285f 352 d->aoemajor, d->aoeminor);
43cbe2cb 353 goto err_disk;
1da177e4 354 }
69cf2d85
EC
355 q = blk_init_queue(aoeblk_request, &d->lock);
356 if (q == NULL) {
357 pr_err("aoe: cannot allocate block queue for %ld.%d\n",
358 d->aoemajor, d->aoeminor);
0a41409c 359 goto err_mempool;
69cf2d85 360 }
1da177e4 361
43cbe2cb 362 spin_lock_irqsave(&d->lock, flags);
e52a2932
EC
363 WARN_ON(!(d->flags & DEVFL_GD_NOW));
364 WARN_ON(!(d->flags & DEVFL_GDALLOC));
365 WARN_ON(d->flags & DEVFL_TKILL);
366 WARN_ON(d->gd);
367 WARN_ON(d->flags & DEVFL_UP);
0a41409c
EC
368 blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS);
369 q->backing_dev_info.name = "aoe";
69cf2d85
EC
370 q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE;
371 d->bufpool = mp;
372 d->blkq = gd->queue = q;
373 q->queuedata = d;
374 d->gd = gd;
aa304fde
EC
375 if (aoe_maxsectors)
376 blk_queue_max_hw_sectors(q, aoe_maxsectors);
1da177e4 377 gd->major = AOE_MAJOR;
0c966214 378 gd->first_minor = d->sysminor;
1da177e4
LT
379 gd->fops = &aoe_bdops;
380 gd->private_data = d;
80795aef 381 set_capacity(gd, d->ssize);
68e0d42f 382 snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d",
1da177e4
LT
383 d->aoemajor, d->aoeminor);
384
3ae1c24e 385 d->flags &= ~DEVFL_GDALLOC;
1da177e4
LT
386 d->flags |= DEVFL_UP;
387
388 spin_unlock_irqrestore(&d->lock, flags);
389
390 add_disk(gd);
391 aoedisk_add_sysfs(d);
e8866cf2 392 aoedisk_add_debugfs(d);
e52a2932
EC
393
394 spin_lock_irqsave(&d->lock, flags);
395 WARN_ON(!(d->flags & DEVFL_GD_NOW));
396 d->flags &= ~DEVFL_GD_NOW;
397 spin_unlock_irqrestore(&d->lock, flags);
43cbe2cb
AM
398 return;
399
400err_mempool:
0a41409c 401 mempool_destroy(mp);
43cbe2cb
AM
402err_disk:
403 put_disk(gd);
404err:
405 spin_lock_irqsave(&d->lock, flags);
e52a2932
EC
406 d->flags &= ~DEVFL_GD_NOW;
407 schedule_work(&d->work);
43cbe2cb 408 spin_unlock_irqrestore(&d->lock, flags);
1da177e4
LT
409}
410
411void
412aoeblk_exit(void)
413{
190519cd
EC
414 debugfs_remove_recursive(aoe_debugfs_dir);
415 aoe_debugfs_dir = NULL;
1da177e4
LT
416 kmem_cache_destroy(buf_pool_cache);
417}
418
419int __init
420aoeblk_init(void)
421{
20c2df83 422 buf_pool_cache = kmem_cache_create("aoe_bufs",
1da177e4 423 sizeof(struct buf),
20c2df83 424 0, 0, NULL);
1da177e4
LT
425 if (buf_pool_cache == NULL)
426 return -ENOMEM;
190519cd
EC
427 aoe_debugfs_dir = debugfs_create_dir("aoe", NULL);
428 if (IS_ERR_OR_NULL(aoe_debugfs_dir)) {
429 pr_info("aoe: cannot create debugfs directory\n");
430 aoe_debugfs_dir = NULL;
431 }
1da177e4
LT
432 return 0;
433}
434