aoeblk.c revision 68e0d42f39d85b334d3867a4e5fc2e0e775c1a6c
12611464d7f36685fb1990275d3de1e72e6aff9d9Ed L. Cashin/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * aoeblk.c 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * block device routines 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/hdreg.h> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h> 943cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton#include <linux/backing-dev.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioctl.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/genhd.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "aoe.h" 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16e18b890bb0881bbab6f4f1a6cd20d9c60d66b003Christoph Lameterstatic struct kmem_cache *buf_pool_cache; 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t aoedisk_show_state(struct device *dev, 19edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct device_attribute *attr, char *page) 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct gendisk *disk = dev_to_disk(dev); 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d = disk->private_data; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return snprintf(page, PAGE_SIZE, 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%s%s\n", 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (d->flags & DEVFL_UP) ? "up" : "down", 2768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin (d->flags & DEVFL_KICKME) ? ",kickme" : 283ae1c24e395b2b65326439622223d88d92bfa03aEd L. Cashin (d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : ""); 293ae1c24e395b2b65326439622223d88d92bfa03aEd L. Cashin /* I'd rather see nopen exported so we can ditch closewait */ 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 31edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t aoedisk_show_mac(struct device *dev, 32edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct device_attribute *attr, char *page) 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 34edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct gendisk *disk = dev_to_disk(dev); 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d = disk->private_data; 3668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin struct aoetgt *t = d->targets[0]; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (t == NULL) 3968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return snprintf(page, PAGE_SIZE, "none\n"); 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return snprintf(page, PAGE_SIZE, "%012llx\n", 4168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin (unsigned long long)mac_addr(t->addr)); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 43edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t aoedisk_show_netif(struct device *dev, 44edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct device_attribute *attr, char *page) 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 46edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct gendisk *disk = dev_to_disk(dev); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d = disk->private_data; 4868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin struct net_device *nds[8], **nd, **nnd, **ne; 4968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin struct aoetgt **t, **te; 5068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin struct aoeif *ifp, *e; 5168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin char *p; 5268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin 5368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin memset(nds, 0, sizeof nds); 5468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin nd = nds; 5568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin ne = nd + ARRAY_SIZE(nds); 5668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin t = d->targets; 5768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin te = t + NTARGETS; 5868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin for (; t < te && *t; t++) { 5968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin ifp = (*t)->ifs; 6068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin e = ifp + NAOEIFS; 6168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin for (; ifp < e && ifp->nd; ifp++) { 6268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin for (nnd = nds; nnd < nd; nnd++) 6368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (*nnd == ifp->nd) 6468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin break; 6568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (nnd == nd && nd != ne) 6668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin *nd++ = ifp->nd; 6768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } 6868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin ne = nd; 7168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin nd = nds; 7268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (*nd == NULL) 7368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return snprintf(page, PAGE_SIZE, "none\n"); 7468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin for (p = page; nd < ne; nd++) 7568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin p += snprintf(p, PAGE_SIZE - (p-page), "%s%s", 7668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin p == page ? "" : ",", (*nd)->name); 7768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin p += snprintf(p, PAGE_SIZE - (p-page), "\n"); 7868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return p-page; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 804613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin/* firmware version */ 81edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t aoedisk_show_fwver(struct device *dev, 82edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct device_attribute *attr, char *page) 834613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin{ 84edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct gendisk *disk = dev_to_disk(dev); 854613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin struct aoedev *d = disk->private_data; 864613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin 874613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin return snprintf(page, PAGE_SIZE, "0x%04x\n", (unsigned int) d->fw_ver); 884613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin} 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 90edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL); 91edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL); 92edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic DEVICE_ATTR(netif, S_IRUGO, aoedisk_show_netif, NULL); 93edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic struct device_attribute dev_attr_firmware_version = { 94edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers .attr = { .name = "firmware-version", .mode = S_IRUGO, .owner = THIS_MODULE }, 95edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers .show = aoedisk_show_fwver, 964613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin}; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 984ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartmanstatic struct attribute *aoe_attrs[] = { 99edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers &dev_attr_state.attr, 100edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers &dev_attr_mac.attr, 101edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers &dev_attr_netif.attr, 102edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers &dev_attr_firmware_version.attr, 103edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers NULL, 1044ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman}; 1054ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman 1064ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartmanstatic const struct attribute_group attr_group = { 1074ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman .attrs = aoe_attrs, 1084ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman}; 1094ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman 1104ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartmanstatic int 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoedisk_add_sysfs(struct aoedev *d) 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 113edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers return sysfs_create_group(&d->gd->dev.kobj, &attr_group); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoedisk_rm_sysfs(struct aoedev *d) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 118edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers sysfs_remove_group(&d->gd->dev.kobj, &attr_group); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoeblk_open(struct inode *inode, struct file *filp) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ulong flags; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = inode->i_bdev->bd_disk->private_data; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&d->lock, flags); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (d->flags & DEVFL_UP) { 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->nopen++; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoeblk_release(struct inode *inode, struct file *filp) 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ulong flags; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = inode->i_bdev->bd_disk->private_data; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&d->lock, flags); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1495f7702fd737d14de3ed06a94a1655be9d43f7e35Ed L. Cashin if (--d->nopen == 0) { 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aoecmd_cfg(d->aoemajor, d->aoeminor); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 160165125e1e480f9510a5ffcfbfee4e3ee38c05f23Jens Axboeaoeblk_make_request(struct request_queue *q, struct bio *bio) 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buf *buf; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *sl; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ulong flags; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds blk_queue_bounce(q, &bio); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (bio == NULL) { 17068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin printk(KERN_ERR "aoe: bio is NULL\n"); 17168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin BUG(); 17268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return 0; 17368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = bio->bi_bdev->bd_disk->private_data; 17568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (d == NULL) { 17668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin printk(KERN_ERR "aoe: bd_disk->private_data is NULL\n"); 17768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin BUG(); 17868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin bio_endio(bio, -ENXIO); 17968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return 0; 18068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } else if (bio->bi_io_vec == NULL) { 18168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin printk(KERN_ERR "aoe: bi_io_vec is NULL\n"); 18268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin BUG(); 18368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin bio_endio(bio, -ENXIO); 18468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return 0; 18568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf = mempool_alloc(d->bufpool, GFP_NOIO); 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buf == NULL) { 188a12c93f08b8fc83b7fcdabaf92b1adcea7489f5eEd L. Cashin printk(KERN_INFO "aoe: buf allocation failure\n"); 1896712ecf8f648118c3363c142196418f89a510b90NeilBrown bio_endio(bio, -ENOMEM); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(buf, 0, sizeof(*buf)); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&buf->bufs); 19468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin buf->stime = jiffies; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf->bio = bio; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf->resid = bio->bi_size; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf->sector = bio->bi_sector; 198392e4845f9728114f7ffa8d7612683397fd4d441Ed L. Cashin buf->bv = &bio->bi_io_vec[bio->bi_idx]; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf->bv_resid = buf->bv->bv_len; 20068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin WARN_ON(buf->bv_resid == 0); 20168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin buf->bv_off = buf->bv->bv_offset; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&d->lock, flags); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((d->flags & DEVFL_UP) == 0) { 206a12c93f08b8fc83b7fcdabaf92b1adcea7489f5eEd L. Cashin printk(KERN_INFO "aoe: device %ld.%ld is not up\n", 207a12c93f08b8fc83b7fcdabaf92b1adcea7489f5eEd L. Cashin d->aoemajor, d->aoeminor); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_free(buf, d->bufpool); 2106712ecf8f648118c3363c142196418f89a510b90NeilBrown bio_endio(bio, -ENXIO); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(&buf->bufs, &d->bufq); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2163ae1c24e395b2b65326439622223d88d92bfa03aEd L. Cashin aoecmd_work(d); 217a4b38364093bf2094ff858ad45f490521bb87984Ed L. Cashin sl = d->sendq_hd; 218a4b38364093bf2094ff858ad45f490521bb87984Ed L. Cashin d->sendq_hd = d->sendq_tl = NULL; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aoenet_xmit(sl); 2223ae1c24e395b2b65326439622223d88d92bfa03aEd L. Cashin 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 227a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwigaoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 229a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig struct aoedev *d = bdev->bd_disk->private_data; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((d->flags & DEVFL_UP) == 0) { 232a12c93f08b8fc83b7fcdabaf92b1adcea7489f5eEd L. Cashin printk(KERN_ERR "aoe: disk not up\n"); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 236a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->cylinders = d->geo.cylinders; 237a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->heads = d->geo.heads; 238a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->sectors = d->geo.sectors; 239a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig return 0; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct block_device_operations aoe_bdops = { 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = aoeblk_open, 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = aoeblk_release, 245a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig .getgeo = aoeblk_getgeo, 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* alloc_disk and add_disk can sleep */ 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoeblk_gdalloc(void *vp) 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d = vp; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gendisk *gd; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ulong flags; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd = alloc_disk(AOE_PARTITIONS); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gd == NULL) { 259a12c93f08b8fc83b7fcdabaf92b1adcea7489f5eEd L. Cashin printk(KERN_ERR "aoe: cannot allocate disk structure for %ld.%ld\n", 2606bb6285fdb948cedee586c6bebc9ebc5e32a5c35Ed L. Cashin d->aoemajor, d->aoeminor); 26143cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton goto err; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26493d2341c750cda0df48a6cc67b35fe25f1ec47dfMatthew Dobson d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (d->bufpool == NULL) { 266a12c93f08b8fc83b7fcdabaf92b1adcea7489f5eEd L. Cashin printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%ld\n", 2676bb6285fdb948cedee586c6bebc9ebc5e32a5c35Ed L. Cashin d->aoemajor, d->aoeminor); 26843cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton goto err_disk; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds blk_queue_make_request(&d->blkq, aoeblk_make_request); 27243cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton if (bdi_init(&d->blkq.backing_dev_info)) 27343cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton goto err_mempool; 27443cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton spin_lock_irqsave(&d->lock, flags); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd->major = AOE_MAJOR; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd->first_minor = d->sysminor * AOE_PARTITIONS; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd->fops = &aoe_bdops; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd->private_data = d; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd->capacity = d->ssize; 28068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->aoemajor, d->aoeminor); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd->queue = &d->blkq; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->gd = gd; 2853ae1c24e395b2b65326439622223d88d92bfa03aEd L. Cashin d->flags &= ~DEVFL_GDALLOC; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->flags |= DEVFL_UP; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_disk(gd); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aoedisk_add_sysfs(d); 29243cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton return; 29343cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton 29443cbe2cbdd5320f1ac785c6f016923609831effeAndrew Mortonerr_mempool: 29543cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton mempool_destroy(d->bufpool); 29643cbe2cbdd5320f1ac785c6f016923609831effeAndrew Mortonerr_disk: 29743cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton put_disk(gd); 29843cbe2cbdd5320f1ac785c6f016923609831effeAndrew Mortonerr: 29943cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton spin_lock_irqsave(&d->lock, flags); 30043cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton d->flags &= ~DEVFL_GDALLOC; 30143cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton spin_unlock_irqrestore(&d->lock, flags); 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoeblk_exit(void) 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kmem_cache_destroy(buf_pool_cache); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoeblk_init(void) 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 31320c2df83d25c6a95affe6157a4c9cac4cf5ffaacPaul Mundt buf_pool_cache = kmem_cache_create("aoe_bufs", 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct buf), 31520c2df83d25c6a95affe6157a4c9cac4cf5ffaacPaul Mundt 0, 0, NULL); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buf_pool_cache == NULL) 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 322