Back to home page

OSCL-LXR

 
 

    


0001 /* Copyright (c) 2013 Coraid, Inc.  See COPYING for GPL terms. */
0002 /*
0003  * aoeblk.c
0004  * block device routines
0005  */
0006 
0007 #include <linux/kernel.h>
0008 #include <linux/hdreg.h>
0009 #include <linux/blk-mq.h>
0010 #include <linux/backing-dev.h>
0011 #include <linux/fs.h>
0012 #include <linux/ioctl.h>
0013 #include <linux/slab.h>
0014 #include <linux/ratelimit.h>
0015 #include <linux/netdevice.h>
0016 #include <linux/mutex.h>
0017 #include <linux/export.h>
0018 #include <linux/moduleparam.h>
0019 #include <linux/debugfs.h>
0020 #include <scsi/sg.h>
0021 #include "aoe.h"
0022 
0023 static DEFINE_MUTEX(aoeblk_mutex);
0024 static struct kmem_cache *buf_pool_cache;
0025 static struct dentry *aoe_debugfs_dir;
0026 
0027 /* GPFS needs a larger value than the default. */
0028 static int aoe_maxsectors;
0029 module_param(aoe_maxsectors, int, 0644);
0030 MODULE_PARM_DESC(aoe_maxsectors,
0031     "When nonzero, set the maximum number of sectors per I/O request");
0032 
0033 static ssize_t aoedisk_show_state(struct device *dev,
0034                   struct device_attribute *attr, char *page)
0035 {
0036     struct gendisk *disk = dev_to_disk(dev);
0037     struct aoedev *d = disk->private_data;
0038 
0039     return sysfs_emit(page, "%s%s\n",
0040             (d->flags & DEVFL_UP) ? "up" : "down",
0041             (d->flags & DEVFL_KICKME) ? ",kickme" :
0042             (d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : "");
0043     /* I'd rather see nopen exported so we can ditch closewait */
0044 }
0045 static ssize_t aoedisk_show_mac(struct device *dev,
0046                 struct device_attribute *attr, char *page)
0047 {
0048     struct gendisk *disk = dev_to_disk(dev);
0049     struct aoedev *d = disk->private_data;
0050     struct aoetgt *t = d->targets[0];
0051 
0052     if (t == NULL)
0053         return sysfs_emit(page, "none\n");
0054     return sysfs_emit(page, "%pm\n", t->addr);
0055 }
0056 static ssize_t aoedisk_show_netif(struct device *dev,
0057                   struct device_attribute *attr, char *page)
0058 {
0059     struct gendisk *disk = dev_to_disk(dev);
0060     struct aoedev *d = disk->private_data;
0061     struct net_device *nds[8], **nd, **nnd, **ne;
0062     struct aoetgt **t, **te;
0063     struct aoeif *ifp, *e;
0064     char *p;
0065 
0066     memset(nds, 0, sizeof nds);
0067     nd = nds;
0068     ne = nd + ARRAY_SIZE(nds);
0069     t = d->targets;
0070     te = t + d->ntargets;
0071     for (; t < te && *t; t++) {
0072         ifp = (*t)->ifs;
0073         e = ifp + NAOEIFS;
0074         for (; ifp < e && ifp->nd; ifp++) {
0075             for (nnd = nds; nnd < nd; nnd++)
0076                 if (*nnd == ifp->nd)
0077                     break;
0078             if (nnd == nd && nd != ne)
0079                 *nd++ = ifp->nd;
0080         }
0081     }
0082 
0083     ne = nd;
0084     nd = nds;
0085     if (*nd == NULL)
0086         return sysfs_emit(page, "none\n");
0087     for (p = page; nd < ne; nd++)
0088         p += scnprintf(p, PAGE_SIZE - (p-page), "%s%s",
0089             p == page ? "" : ",", (*nd)->name);
0090     p += scnprintf(p, PAGE_SIZE - (p-page), "\n");
0091     return p-page;
0092 }
0093 /* firmware version */
0094 static ssize_t aoedisk_show_fwver(struct device *dev,
0095                   struct device_attribute *attr, char *page)
0096 {
0097     struct gendisk *disk = dev_to_disk(dev);
0098     struct aoedev *d = disk->private_data;
0099 
0100     return sysfs_emit(page, "0x%04x\n", (unsigned int) d->fw_ver);
0101 }
0102 static ssize_t aoedisk_show_payload(struct device *dev,
0103                     struct device_attribute *attr, char *page)
0104 {
0105     struct gendisk *disk = dev_to_disk(dev);
0106     struct aoedev *d = disk->private_data;
0107 
0108     return sysfs_emit(page, "%lu\n", d->maxbcnt);
0109 }
0110 
0111 static int aoedisk_debugfs_show(struct seq_file *s, void *ignored)
0112 {
0113     struct aoedev *d;
0114     struct aoetgt **t, **te;
0115     struct aoeif *ifp, *ife;
0116     unsigned long flags;
0117     char c;
0118 
0119     d = s->private;
0120     seq_printf(s, "rttavg: %d rttdev: %d\n",
0121         d->rttavg >> RTTSCALE,
0122         d->rttdev >> RTTDSCALE);
0123     seq_printf(s, "nskbpool: %d\n", skb_queue_len(&d->skbpool));
0124     seq_printf(s, "kicked: %ld\n", d->kicked);
0125     seq_printf(s, "maxbcnt: %ld\n", d->maxbcnt);
0126     seq_printf(s, "ref: %ld\n", d->ref);
0127 
0128     spin_lock_irqsave(&d->lock, flags);
0129     t = d->targets;
0130     te = t + d->ntargets;
0131     for (; t < te && *t; t++) {
0132         c = '\t';
0133         seq_printf(s, "falloc: %ld\n", (*t)->falloc);
0134         seq_printf(s, "ffree: %p\n",
0135             list_empty(&(*t)->ffree) ? NULL : (*t)->ffree.next);
0136         seq_printf(s, "%pm:%d:%d:%d\n", (*t)->addr, (*t)->nout,
0137             (*t)->maxout, (*t)->nframes);
0138         seq_printf(s, "\tssthresh:%d\n", (*t)->ssthresh);
0139         seq_printf(s, "\ttaint:%d\n", (*t)->taint);
0140         seq_printf(s, "\tr:%d\n", (*t)->rpkts);
0141         seq_printf(s, "\tw:%d\n", (*t)->wpkts);
0142         ifp = (*t)->ifs;
0143         ife = ifp + ARRAY_SIZE((*t)->ifs);
0144         for (; ifp->nd && ifp < ife; ifp++) {
0145             seq_printf(s, "%c%s", c, ifp->nd->name);
0146             c = ',';
0147         }
0148         seq_puts(s, "\n");
0149     }
0150     spin_unlock_irqrestore(&d->lock, flags);
0151 
0152     return 0;
0153 }
0154 
0155 static int aoe_debugfs_open(struct inode *inode, struct file *file)
0156 {
0157     return single_open(file, aoedisk_debugfs_show, inode->i_private);
0158 }
0159 
0160 static DEVICE_ATTR(state, 0444, aoedisk_show_state, NULL);
0161 static DEVICE_ATTR(mac, 0444, aoedisk_show_mac, NULL);
0162 static DEVICE_ATTR(netif, 0444, aoedisk_show_netif, NULL);
0163 static struct device_attribute dev_attr_firmware_version = {
0164     .attr = { .name = "firmware-version", .mode = 0444 },
0165     .show = aoedisk_show_fwver,
0166 };
0167 static DEVICE_ATTR(payload, 0444, aoedisk_show_payload, NULL);
0168 
0169 static struct attribute *aoe_attrs[] = {
0170     &dev_attr_state.attr,
0171     &dev_attr_mac.attr,
0172     &dev_attr_netif.attr,
0173     &dev_attr_firmware_version.attr,
0174     &dev_attr_payload.attr,
0175     NULL,
0176 };
0177 
0178 static const struct attribute_group aoe_attr_group = {
0179     .attrs = aoe_attrs,
0180 };
0181 
0182 static const struct attribute_group *aoe_attr_groups[] = {
0183     &aoe_attr_group,
0184     NULL,
0185 };
0186 
0187 static const struct file_operations aoe_debugfs_fops = {
0188     .open = aoe_debugfs_open,
0189     .read = seq_read,
0190     .llseek = seq_lseek,
0191     .release = single_release,
0192 };
0193 
0194 static void
0195 aoedisk_add_debugfs(struct aoedev *d)
0196 {
0197     char *p;
0198 
0199     if (aoe_debugfs_dir == NULL)
0200         return;
0201     p = strchr(d->gd->disk_name, '/');
0202     if (p == NULL)
0203         p = d->gd->disk_name;
0204     else
0205         p++;
0206     BUG_ON(*p == '\0');
0207     d->debugfs = debugfs_create_file(p, 0444, aoe_debugfs_dir, d,
0208                      &aoe_debugfs_fops);
0209 }
0210 void
0211 aoedisk_rm_debugfs(struct aoedev *d)
0212 {
0213     debugfs_remove(d->debugfs);
0214     d->debugfs = NULL;
0215 }
0216 
0217 static int
0218 aoeblk_open(struct block_device *bdev, fmode_t mode)
0219 {
0220     struct aoedev *d = bdev->bd_disk->private_data;
0221     ulong flags;
0222 
0223     if (!virt_addr_valid(d)) {
0224         pr_crit("aoe: invalid device pointer in %s\n",
0225             __func__);
0226         WARN_ON(1);
0227         return -ENODEV;
0228     }
0229     if (!(d->flags & DEVFL_UP) || d->flags & DEVFL_TKILL)
0230         return -ENODEV;
0231 
0232     mutex_lock(&aoeblk_mutex);
0233     spin_lock_irqsave(&d->lock, flags);
0234     if (d->flags & DEVFL_UP && !(d->flags & DEVFL_TKILL)) {
0235         d->nopen++;
0236         spin_unlock_irqrestore(&d->lock, flags);
0237         mutex_unlock(&aoeblk_mutex);
0238         return 0;
0239     }
0240     spin_unlock_irqrestore(&d->lock, flags);
0241     mutex_unlock(&aoeblk_mutex);
0242     return -ENODEV;
0243 }
0244 
0245 static void
0246 aoeblk_release(struct gendisk *disk, fmode_t mode)
0247 {
0248     struct aoedev *d = disk->private_data;
0249     ulong flags;
0250 
0251     spin_lock_irqsave(&d->lock, flags);
0252 
0253     if (--d->nopen == 0) {
0254         spin_unlock_irqrestore(&d->lock, flags);
0255         aoecmd_cfg(d->aoemajor, d->aoeminor);
0256         return;
0257     }
0258     spin_unlock_irqrestore(&d->lock, flags);
0259 }
0260 
0261 static blk_status_t aoeblk_queue_rq(struct blk_mq_hw_ctx *hctx,
0262                     const struct blk_mq_queue_data *bd)
0263 {
0264     struct aoedev *d = hctx->queue->queuedata;
0265 
0266     spin_lock_irq(&d->lock);
0267 
0268     if ((d->flags & DEVFL_UP) == 0) {
0269         pr_info_ratelimited("aoe: device %ld.%d is not up\n",
0270             d->aoemajor, d->aoeminor);
0271         spin_unlock_irq(&d->lock);
0272         blk_mq_start_request(bd->rq);
0273         return BLK_STS_IOERR;
0274     }
0275 
0276     list_add_tail(&bd->rq->queuelist, &d->rq_list);
0277     aoecmd_work(d);
0278     spin_unlock_irq(&d->lock);
0279     return BLK_STS_OK;
0280 }
0281 
0282 static int
0283 aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
0284 {
0285     struct aoedev *d = bdev->bd_disk->private_data;
0286 
0287     if ((d->flags & DEVFL_UP) == 0) {
0288         printk(KERN_ERR "aoe: disk not up\n");
0289         return -ENODEV;
0290     }
0291 
0292     geo->cylinders = d->geo.cylinders;
0293     geo->heads = d->geo.heads;
0294     geo->sectors = d->geo.sectors;
0295     return 0;
0296 }
0297 
0298 static int
0299 aoeblk_ioctl(struct block_device *bdev, fmode_t mode, uint cmd, ulong arg)
0300 {
0301     struct aoedev *d;
0302 
0303     if (!arg)
0304         return -EINVAL;
0305 
0306     d = bdev->bd_disk->private_data;
0307     if ((d->flags & DEVFL_UP) == 0) {
0308         pr_err("aoe: disk not up\n");
0309         return -ENODEV;
0310     }
0311 
0312     if (cmd == HDIO_GET_IDENTITY) {
0313         if (!copy_to_user((void __user *) arg, &d->ident,
0314             sizeof(d->ident)))
0315             return 0;
0316         return -EFAULT;
0317     }
0318 
0319     /* udev calls scsi_id, which uses SG_IO, resulting in noise */
0320     if (cmd != SG_IO)
0321         pr_info("aoe: unknown ioctl 0x%x\n", cmd);
0322 
0323     return -ENOTTY;
0324 }
0325 
0326 static const struct block_device_operations aoe_bdops = {
0327     .open = aoeblk_open,
0328     .release = aoeblk_release,
0329     .ioctl = aoeblk_ioctl,
0330     .compat_ioctl = blkdev_compat_ptr_ioctl,
0331     .getgeo = aoeblk_getgeo,
0332     .owner = THIS_MODULE,
0333 };
0334 
0335 static const struct blk_mq_ops aoeblk_mq_ops = {
0336     .queue_rq   = aoeblk_queue_rq,
0337 };
0338 
0339 /* blk_mq_alloc_disk and add_disk can sleep */
0340 void
0341 aoeblk_gdalloc(void *vp)
0342 {
0343     struct aoedev *d = vp;
0344     struct gendisk *gd;
0345     mempool_t *mp;
0346     struct blk_mq_tag_set *set;
0347     ulong flags;
0348     int late = 0;
0349     int err;
0350 
0351     spin_lock_irqsave(&d->lock, flags);
0352     if (d->flags & DEVFL_GDALLOC
0353     && !(d->flags & DEVFL_TKILL)
0354     && !(d->flags & DEVFL_GD_NOW))
0355         d->flags |= DEVFL_GD_NOW;
0356     else
0357         late = 1;
0358     spin_unlock_irqrestore(&d->lock, flags);
0359     if (late)
0360         return;
0361 
0362     mp = mempool_create(MIN_BUFS, mempool_alloc_slab, mempool_free_slab,
0363         buf_pool_cache);
0364     if (mp == NULL) {
0365         printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%d\n",
0366             d->aoemajor, d->aoeminor);
0367         goto err;
0368     }
0369 
0370     set = &d->tag_set;
0371     set->ops = &aoeblk_mq_ops;
0372     set->cmd_size = sizeof(struct aoe_req);
0373     set->nr_hw_queues = 1;
0374     set->queue_depth = 128;
0375     set->numa_node = NUMA_NO_NODE;
0376     set->flags = BLK_MQ_F_SHOULD_MERGE;
0377     err = blk_mq_alloc_tag_set(set);
0378     if (err) {
0379         pr_err("aoe: cannot allocate tag set for %ld.%d\n",
0380             d->aoemajor, d->aoeminor);
0381         goto err_mempool;
0382     }
0383 
0384     gd = blk_mq_alloc_disk(set, d);
0385     if (IS_ERR(gd)) {
0386         pr_err("aoe: cannot allocate block queue for %ld.%d\n",
0387             d->aoemajor, d->aoeminor);
0388         goto err_tagset;
0389     }
0390 
0391     spin_lock_irqsave(&d->lock, flags);
0392     WARN_ON(!(d->flags & DEVFL_GD_NOW));
0393     WARN_ON(!(d->flags & DEVFL_GDALLOC));
0394     WARN_ON(d->flags & DEVFL_TKILL);
0395     WARN_ON(d->gd);
0396     WARN_ON(d->flags & DEVFL_UP);
0397     blk_queue_max_hw_sectors(gd->queue, BLK_DEF_MAX_SECTORS);
0398     blk_queue_io_opt(gd->queue, SZ_2M);
0399     d->bufpool = mp;
0400     d->blkq = gd->queue;
0401     d->gd = gd;
0402     if (aoe_maxsectors)
0403         blk_queue_max_hw_sectors(gd->queue, aoe_maxsectors);
0404     gd->major = AOE_MAJOR;
0405     gd->first_minor = d->sysminor;
0406     gd->minors = AOE_PARTITIONS;
0407     gd->fops = &aoe_bdops;
0408     gd->private_data = d;
0409     set_capacity(gd, d->ssize);
0410     snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d",
0411         d->aoemajor, d->aoeminor);
0412 
0413     d->flags &= ~DEVFL_GDALLOC;
0414     d->flags |= DEVFL_UP;
0415 
0416     spin_unlock_irqrestore(&d->lock, flags);
0417 
0418     err = device_add_disk(NULL, gd, aoe_attr_groups);
0419     if (err)
0420         goto out_disk_cleanup;
0421     aoedisk_add_debugfs(d);
0422 
0423     spin_lock_irqsave(&d->lock, flags);
0424     WARN_ON(!(d->flags & DEVFL_GD_NOW));
0425     d->flags &= ~DEVFL_GD_NOW;
0426     spin_unlock_irqrestore(&d->lock, flags);
0427     return;
0428 
0429 out_disk_cleanup:
0430     put_disk(gd);
0431 err_tagset:
0432     blk_mq_free_tag_set(set);
0433 err_mempool:
0434     mempool_destroy(mp);
0435 err:
0436     spin_lock_irqsave(&d->lock, flags);
0437     d->flags &= ~DEVFL_GD_NOW;
0438     queue_work(aoe_wq, &d->work);
0439     spin_unlock_irqrestore(&d->lock, flags);
0440 }
0441 
0442 void
0443 aoeblk_exit(void)
0444 {
0445     debugfs_remove_recursive(aoe_debugfs_dir);
0446     aoe_debugfs_dir = NULL;
0447     kmem_cache_destroy(buf_pool_cache);
0448 }
0449 
0450 int __init
0451 aoeblk_init(void)
0452 {
0453     buf_pool_cache = kmem_cache_create("aoe_bufs",
0454                        sizeof(struct buf),
0455                        0, 0, NULL);
0456     if (buf_pool_cache == NULL)
0457         return -ENOMEM;
0458     aoe_debugfs_dir = debugfs_create_dir("aoe", NULL);
0459     return 0;
0460 }
0461