cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

aoeblk.c (11219B)


      1/* Copyright (c) 2013 Coraid, Inc.  See COPYING for GPL terms. */
      2/*
      3 * aoeblk.c
      4 * block device routines
      5 */
      6
      7#include <linux/kernel.h>
      8#include <linux/hdreg.h>
      9#include <linux/blk-mq.h>
     10#include <linux/backing-dev.h>
     11#include <linux/fs.h>
     12#include <linux/ioctl.h>
     13#include <linux/slab.h>
     14#include <linux/ratelimit.h>
     15#include <linux/netdevice.h>
     16#include <linux/mutex.h>
     17#include <linux/export.h>
     18#include <linux/moduleparam.h>
     19#include <linux/debugfs.h>
     20#include <scsi/sg.h>
     21#include "aoe.h"
     22
     23static DEFINE_MUTEX(aoeblk_mutex);
     24static struct kmem_cache *buf_pool_cache;
     25static struct dentry *aoe_debugfs_dir;
     26
     27/* GPFS needs a larger value than the default. */
     28static int aoe_maxsectors;
     29module_param(aoe_maxsectors, int, 0644);
     30MODULE_PARM_DESC(aoe_maxsectors,
     31	"When nonzero, set the maximum number of sectors per I/O request");
     32
     33static ssize_t aoedisk_show_state(struct device *dev,
     34				  struct device_attribute *attr, char *page)
     35{
     36	struct gendisk *disk = dev_to_disk(dev);
     37	struct aoedev *d = disk->private_data;
     38
     39	return sysfs_emit(page, "%s%s\n",
     40			(d->flags & DEVFL_UP) ? "up" : "down",
     41			(d->flags & DEVFL_KICKME) ? ",kickme" :
     42			(d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : "");
     43	/* I'd rather see nopen exported so we can ditch closewait */
     44}
     45static ssize_t aoedisk_show_mac(struct device *dev,
     46				struct device_attribute *attr, char *page)
     47{
     48	struct gendisk *disk = dev_to_disk(dev);
     49	struct aoedev *d = disk->private_data;
     50	struct aoetgt *t = d->targets[0];
     51
     52	if (t == NULL)
     53		return sysfs_emit(page, "none\n");
     54	return sysfs_emit(page, "%pm\n", t->addr);
     55}
     56static ssize_t aoedisk_show_netif(struct device *dev,
     57				  struct device_attribute *attr, char *page)
     58{
     59	struct gendisk *disk = dev_to_disk(dev);
     60	struct aoedev *d = disk->private_data;
     61	struct net_device *nds[8], **nd, **nnd, **ne;
     62	struct aoetgt **t, **te;
     63	struct aoeif *ifp, *e;
     64	char *p;
     65
     66	memset(nds, 0, sizeof nds);
     67	nd = nds;
     68	ne = nd + ARRAY_SIZE(nds);
     69	t = d->targets;
     70	te = t + d->ntargets;
     71	for (; t < te && *t; t++) {
     72		ifp = (*t)->ifs;
     73		e = ifp + NAOEIFS;
     74		for (; ifp < e && ifp->nd; ifp++) {
     75			for (nnd = nds; nnd < nd; nnd++)
     76				if (*nnd == ifp->nd)
     77					break;
     78			if (nnd == nd && nd != ne)
     79				*nd++ = ifp->nd;
     80		}
     81	}
     82
     83	ne = nd;
     84	nd = nds;
     85	if (*nd == NULL)
     86		return sysfs_emit(page, "none\n");
     87	for (p = page; nd < ne; nd++)
     88		p += scnprintf(p, PAGE_SIZE - (p-page), "%s%s",
     89			p == page ? "" : ",", (*nd)->name);
     90	p += scnprintf(p, PAGE_SIZE - (p-page), "\n");
     91	return p-page;
     92}
     93/* firmware version */
     94static ssize_t aoedisk_show_fwver(struct device *dev,
     95				  struct device_attribute *attr, char *page)
     96{
     97	struct gendisk *disk = dev_to_disk(dev);
     98	struct aoedev *d = disk->private_data;
     99
    100	return sysfs_emit(page, "0x%04x\n", (unsigned int) d->fw_ver);
    101}
    102static ssize_t aoedisk_show_payload(struct device *dev,
    103				    struct device_attribute *attr, char *page)
    104{
    105	struct gendisk *disk = dev_to_disk(dev);
    106	struct aoedev *d = disk->private_data;
    107
    108	return sysfs_emit(page, "%lu\n", d->maxbcnt);
    109}
    110
    111static int aoedisk_debugfs_show(struct seq_file *s, void *ignored)
    112{
    113	struct aoedev *d;
    114	struct aoetgt **t, **te;
    115	struct aoeif *ifp, *ife;
    116	unsigned long flags;
    117	char c;
    118
    119	d = s->private;
    120	seq_printf(s, "rttavg: %d rttdev: %d\n",
    121		d->rttavg >> RTTSCALE,
    122		d->rttdev >> RTTDSCALE);
    123	seq_printf(s, "nskbpool: %d\n", skb_queue_len(&d->skbpool));
    124	seq_printf(s, "kicked: %ld\n", d->kicked);
    125	seq_printf(s, "maxbcnt: %ld\n", d->maxbcnt);
    126	seq_printf(s, "ref: %ld\n", d->ref);
    127
    128	spin_lock_irqsave(&d->lock, flags);
    129	t = d->targets;
    130	te = t + d->ntargets;
    131	for (; t < te && *t; t++) {
    132		c = '\t';
    133		seq_printf(s, "falloc: %ld\n", (*t)->falloc);
    134		seq_printf(s, "ffree: %p\n",
    135			list_empty(&(*t)->ffree) ? NULL : (*t)->ffree.next);
    136		seq_printf(s, "%pm:%d:%d:%d\n", (*t)->addr, (*t)->nout,
    137			(*t)->maxout, (*t)->nframes);
    138		seq_printf(s, "\tssthresh:%d\n", (*t)->ssthresh);
    139		seq_printf(s, "\ttaint:%d\n", (*t)->taint);
    140		seq_printf(s, "\tr:%d\n", (*t)->rpkts);
    141		seq_printf(s, "\tw:%d\n", (*t)->wpkts);
    142		ifp = (*t)->ifs;
    143		ife = ifp + ARRAY_SIZE((*t)->ifs);
    144		for (; ifp->nd && ifp < ife; ifp++) {
    145			seq_printf(s, "%c%s", c, ifp->nd->name);
    146			c = ',';
    147		}
    148		seq_puts(s, "\n");
    149	}
    150	spin_unlock_irqrestore(&d->lock, flags);
    151
    152	return 0;
    153}
    154
    155static int aoe_debugfs_open(struct inode *inode, struct file *file)
    156{
    157	return single_open(file, aoedisk_debugfs_show, inode->i_private);
    158}
    159
    160static DEVICE_ATTR(state, 0444, aoedisk_show_state, NULL);
    161static DEVICE_ATTR(mac, 0444, aoedisk_show_mac, NULL);
    162static DEVICE_ATTR(netif, 0444, aoedisk_show_netif, NULL);
    163static struct device_attribute dev_attr_firmware_version = {
    164	.attr = { .name = "firmware-version", .mode = 0444 },
    165	.show = aoedisk_show_fwver,
    166};
    167static DEVICE_ATTR(payload, 0444, aoedisk_show_payload, NULL);
    168
    169static struct attribute *aoe_attrs[] = {
    170	&dev_attr_state.attr,
    171	&dev_attr_mac.attr,
    172	&dev_attr_netif.attr,
    173	&dev_attr_firmware_version.attr,
    174	&dev_attr_payload.attr,
    175	NULL,
    176};
    177
    178static const struct attribute_group aoe_attr_group = {
    179	.attrs = aoe_attrs,
    180};
    181
    182static const struct attribute_group *aoe_attr_groups[] = {
    183	&aoe_attr_group,
    184	NULL,
    185};
    186
    187static const struct file_operations aoe_debugfs_fops = {
    188	.open = aoe_debugfs_open,
    189	.read = seq_read,
    190	.llseek = seq_lseek,
    191	.release = single_release,
    192};
    193
    194static void
    195aoedisk_add_debugfs(struct aoedev *d)
    196{
    197	char *p;
    198
    199	if (aoe_debugfs_dir == NULL)
    200		return;
    201	p = strchr(d->gd->disk_name, '/');
    202	if (p == NULL)
    203		p = d->gd->disk_name;
    204	else
    205		p++;
    206	BUG_ON(*p == '\0');
    207	d->debugfs = debugfs_create_file(p, 0444, aoe_debugfs_dir, d,
    208					 &aoe_debugfs_fops);
    209}
    210void
    211aoedisk_rm_debugfs(struct aoedev *d)
    212{
    213	debugfs_remove(d->debugfs);
    214	d->debugfs = NULL;
    215}
    216
    217static int
    218aoeblk_open(struct block_device *bdev, fmode_t mode)
    219{
    220	struct aoedev *d = bdev->bd_disk->private_data;
    221	ulong flags;
    222
    223	if (!virt_addr_valid(d)) {
    224		pr_crit("aoe: invalid device pointer in %s\n",
    225			__func__);
    226		WARN_ON(1);
    227		return -ENODEV;
    228	}
    229	if (!(d->flags & DEVFL_UP) || d->flags & DEVFL_TKILL)
    230		return -ENODEV;
    231
    232	mutex_lock(&aoeblk_mutex);
    233	spin_lock_irqsave(&d->lock, flags);
    234	if (d->flags & DEVFL_UP && !(d->flags & DEVFL_TKILL)) {
    235		d->nopen++;
    236		spin_unlock_irqrestore(&d->lock, flags);
    237		mutex_unlock(&aoeblk_mutex);
    238		return 0;
    239	}
    240	spin_unlock_irqrestore(&d->lock, flags);
    241	mutex_unlock(&aoeblk_mutex);
    242	return -ENODEV;
    243}
    244
    245static void
    246aoeblk_release(struct gendisk *disk, fmode_t mode)
    247{
    248	struct aoedev *d = disk->private_data;
    249	ulong flags;
    250
    251	spin_lock_irqsave(&d->lock, flags);
    252
    253	if (--d->nopen == 0) {
    254		spin_unlock_irqrestore(&d->lock, flags);
    255		aoecmd_cfg(d->aoemajor, d->aoeminor);
    256		return;
    257	}
    258	spin_unlock_irqrestore(&d->lock, flags);
    259}
    260
    261static blk_status_t aoeblk_queue_rq(struct blk_mq_hw_ctx *hctx,
    262				    const struct blk_mq_queue_data *bd)
    263{
    264	struct aoedev *d = hctx->queue->queuedata;
    265
    266	spin_lock_irq(&d->lock);
    267
    268	if ((d->flags & DEVFL_UP) == 0) {
    269		pr_info_ratelimited("aoe: device %ld.%d is not up\n",
    270			d->aoemajor, d->aoeminor);
    271		spin_unlock_irq(&d->lock);
    272		blk_mq_start_request(bd->rq);
    273		return BLK_STS_IOERR;
    274	}
    275
    276	list_add_tail(&bd->rq->queuelist, &d->rq_list);
    277	aoecmd_work(d);
    278	spin_unlock_irq(&d->lock);
    279	return BLK_STS_OK;
    280}
    281
    282static int
    283aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
    284{
    285	struct aoedev *d = bdev->bd_disk->private_data;
    286
    287	if ((d->flags & DEVFL_UP) == 0) {
    288		printk(KERN_ERR "aoe: disk not up\n");
    289		return -ENODEV;
    290	}
    291
    292	geo->cylinders = d->geo.cylinders;
    293	geo->heads = d->geo.heads;
    294	geo->sectors = d->geo.sectors;
    295	return 0;
    296}
    297
    298static int
    299aoeblk_ioctl(struct block_device *bdev, fmode_t mode, uint cmd, ulong arg)
    300{
    301	struct aoedev *d;
    302
    303	if (!arg)
    304		return -EINVAL;
    305
    306	d = bdev->bd_disk->private_data;
    307	if ((d->flags & DEVFL_UP) == 0) {
    308		pr_err("aoe: disk not up\n");
    309		return -ENODEV;
    310	}
    311
    312	if (cmd == HDIO_GET_IDENTITY) {
    313		if (!copy_to_user((void __user *) arg, &d->ident,
    314			sizeof(d->ident)))
    315			return 0;
    316		return -EFAULT;
    317	}
    318
    319	/* udev calls scsi_id, which uses SG_IO, resulting in noise */
    320	if (cmd != SG_IO)
    321		pr_info("aoe: unknown ioctl 0x%x\n", cmd);
    322
    323	return -ENOTTY;
    324}
    325
    326static const struct block_device_operations aoe_bdops = {
    327	.open = aoeblk_open,
    328	.release = aoeblk_release,
    329	.ioctl = aoeblk_ioctl,
    330	.compat_ioctl = blkdev_compat_ptr_ioctl,
    331	.getgeo = aoeblk_getgeo,
    332	.owner = THIS_MODULE,
    333};
    334
    335static const struct blk_mq_ops aoeblk_mq_ops = {
    336	.queue_rq	= aoeblk_queue_rq,
    337};
    338
    339/* blk_mq_alloc_disk and add_disk can sleep */
    340void
    341aoeblk_gdalloc(void *vp)
    342{
    343	struct aoedev *d = vp;
    344	struct gendisk *gd;
    345	mempool_t *mp;
    346	struct blk_mq_tag_set *set;
    347	ulong flags;
    348	int late = 0;
    349	int err;
    350
    351	spin_lock_irqsave(&d->lock, flags);
    352	if (d->flags & DEVFL_GDALLOC
    353	&& !(d->flags & DEVFL_TKILL)
    354	&& !(d->flags & DEVFL_GD_NOW))
    355		d->flags |= DEVFL_GD_NOW;
    356	else
    357		late = 1;
    358	spin_unlock_irqrestore(&d->lock, flags);
    359	if (late)
    360		return;
    361
    362	mp = mempool_create(MIN_BUFS, mempool_alloc_slab, mempool_free_slab,
    363		buf_pool_cache);
    364	if (mp == NULL) {
    365		printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%d\n",
    366			d->aoemajor, d->aoeminor);
    367		goto err;
    368	}
    369
    370	set = &d->tag_set;
    371	set->ops = &aoeblk_mq_ops;
    372	set->cmd_size = sizeof(struct aoe_req);
    373	set->nr_hw_queues = 1;
    374	set->queue_depth = 128;
    375	set->numa_node = NUMA_NO_NODE;
    376	set->flags = BLK_MQ_F_SHOULD_MERGE;
    377	err = blk_mq_alloc_tag_set(set);
    378	if (err) {
    379		pr_err("aoe: cannot allocate tag set for %ld.%d\n",
    380			d->aoemajor, d->aoeminor);
    381		goto err_mempool;
    382	}
    383
    384	gd = blk_mq_alloc_disk(set, d);
    385	if (IS_ERR(gd)) {
    386		pr_err("aoe: cannot allocate block queue for %ld.%d\n",
    387			d->aoemajor, d->aoeminor);
    388		goto err_tagset;
    389	}
    390
    391	spin_lock_irqsave(&d->lock, flags);
    392	WARN_ON(!(d->flags & DEVFL_GD_NOW));
    393	WARN_ON(!(d->flags & DEVFL_GDALLOC));
    394	WARN_ON(d->flags & DEVFL_TKILL);
    395	WARN_ON(d->gd);
    396	WARN_ON(d->flags & DEVFL_UP);
    397	blk_queue_max_hw_sectors(gd->queue, BLK_DEF_MAX_SECTORS);
    398	blk_queue_io_opt(gd->queue, SZ_2M);
    399	d->bufpool = mp;
    400	d->blkq = gd->queue;
    401	d->gd = gd;
    402	if (aoe_maxsectors)
    403		blk_queue_max_hw_sectors(gd->queue, aoe_maxsectors);
    404	gd->major = AOE_MAJOR;
    405	gd->first_minor = d->sysminor;
    406	gd->minors = AOE_PARTITIONS;
    407	gd->fops = &aoe_bdops;
    408	gd->private_data = d;
    409	set_capacity(gd, d->ssize);
    410	snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d",
    411		d->aoemajor, d->aoeminor);
    412
    413	d->flags &= ~DEVFL_GDALLOC;
    414	d->flags |= DEVFL_UP;
    415
    416	spin_unlock_irqrestore(&d->lock, flags);
    417
    418	err = device_add_disk(NULL, gd, aoe_attr_groups);
    419	if (err)
    420		goto out_disk_cleanup;
    421	aoedisk_add_debugfs(d);
    422
    423	spin_lock_irqsave(&d->lock, flags);
    424	WARN_ON(!(d->flags & DEVFL_GD_NOW));
    425	d->flags &= ~DEVFL_GD_NOW;
    426	spin_unlock_irqrestore(&d->lock, flags);
    427	return;
    428
    429out_disk_cleanup:
    430	blk_cleanup_disk(gd);
    431err_tagset:
    432	blk_mq_free_tag_set(set);
    433err_mempool:
    434	mempool_destroy(mp);
    435err:
    436	spin_lock_irqsave(&d->lock, flags);
    437	d->flags &= ~DEVFL_GD_NOW;
    438	queue_work(aoe_wq, &d->work);
    439	spin_unlock_irqrestore(&d->lock, flags);
    440}
    441
    442void
    443aoeblk_exit(void)
    444{
    445	debugfs_remove_recursive(aoe_debugfs_dir);
    446	aoe_debugfs_dir = NULL;
    447	kmem_cache_destroy(buf_pool_cache);
    448}
    449
    450int __init
    451aoeblk_init(void)
    452{
    453	buf_pool_cache = kmem_cache_create("aoe_bufs",
    454					   sizeof(struct buf),
    455					   0, 0, NULL);
    456	if (buf_pool_cache == NULL)
    457		return -ENOMEM;
    458	aoe_debugfs_dir = debugfs_create_dir("aoe", NULL);
    459	return 0;
    460}
    461