aoeblk.c revision e9bb8fb0b6d61a822201537b25206a0ca34b9d1d
152e112b3ab6b2b35a144565c8ea3bdda1e2845f2Ed L. Cashin/* Copyright (c) 2007 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"); 401eb0da4cea28ae8f1bbe61822a2cc04e6d074e03Ed L. Cashin return snprintf(page, PAGE_SIZE, "%012llx\n", mac_addr(t->addr)); 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 42edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t aoedisk_show_netif(struct device *dev, 43edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct device_attribute *attr, char *page) 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 45edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct gendisk *disk = dev_to_disk(dev); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d = disk->private_data; 4768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin struct net_device *nds[8], **nd, **nnd, **ne; 4868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin struct aoetgt **t, **te; 4968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin struct aoeif *ifp, *e; 5068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin char *p; 5168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin 5268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin memset(nds, 0, sizeof nds); 5368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin nd = nds; 5468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin ne = nd + ARRAY_SIZE(nds); 5568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin t = d->targets; 5668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin te = t + NTARGETS; 5768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin for (; t < te && *t; t++) { 5868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin ifp = (*t)->ifs; 5968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin e = ifp + NAOEIFS; 6068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin for (; ifp < e && ifp->nd; ifp++) { 6168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin for (nnd = nds; nnd < nd; nnd++) 6268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (*nnd == ifp->nd) 6368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin break; 6468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (nnd == nd && nd != ne) 6568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin *nd++ = ifp->nd; 6668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } 6768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin ne = nd; 7068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin nd = nds; 7168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (*nd == NULL) 7268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return snprintf(page, PAGE_SIZE, "none\n"); 7368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin for (p = page; nd < ne; nd++) 7468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin p += snprintf(p, PAGE_SIZE - (p-page), "%s%s", 7568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin p == page ? "" : ",", (*nd)->name); 7668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin p += snprintf(p, PAGE_SIZE - (p-page), "\n"); 7768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return p-page; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 794613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin/* firmware version */ 80edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t aoedisk_show_fwver(struct device *dev, 81edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct device_attribute *attr, char *page) 824613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin{ 83edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct gendisk *disk = dev_to_disk(dev); 844613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin struct aoedev *d = disk->private_data; 854613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin 864613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin return snprintf(page, PAGE_SIZE, "0x%04x\n", (unsigned int) d->fw_ver); 874613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin} 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 89edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL); 90edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL); 91edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic DEVICE_ATTR(netif, S_IRUGO, aoedisk_show_netif, NULL); 92edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic struct device_attribute dev_attr_firmware_version = { 93edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers .attr = { .name = "firmware-version", .mode = S_IRUGO, .owner = THIS_MODULE }, 94edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers .show = aoedisk_show_fwver, 954613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin}; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 974ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartmanstatic struct attribute *aoe_attrs[] = { 98edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers &dev_attr_state.attr, 99edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers &dev_attr_mac.attr, 100edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers &dev_attr_netif.attr, 101edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers &dev_attr_firmware_version.attr, 102edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers NULL, 1034ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman}; 1044ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman 1054ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartmanstatic const struct attribute_group attr_group = { 1064ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman .attrs = aoe_attrs, 1074ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman}; 1084ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman 1094ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartmanstatic int 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoedisk_add_sysfs(struct aoedev *d) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 112edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers return sysfs_create_group(&d->gd->dev.kobj, &attr_group); 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoedisk_rm_sysfs(struct aoedev *d) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 117edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers sysfs_remove_group(&d->gd->dev.kobj, &attr_group); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoeblk_open(struct inode *inode, struct file *filp) 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ulong flags; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = inode->i_bdev->bd_disk->private_data; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&d->lock, flags); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (d->flags & DEVFL_UP) { 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->nopen++; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoeblk_release(struct inode *inode, struct file *filp) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ulong flags; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = inode->i_bdev->bd_disk->private_data; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&d->lock, flags); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1485f7702fd737d14de3ed06a94a1655be9d43f7e35Ed L. Cashin if (--d->nopen == 0) { 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aoecmd_cfg(d->aoemajor, d->aoeminor); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 159165125e1e480f9510a5ffcfbfee4e3ee38c05f23Jens Axboeaoeblk_make_request(struct request_queue *q, struct bio *bio) 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 161e9bb8fb0b6d61a822201537b25206a0ca34b9d1dDavid S. Miller struct sk_buff_head queue; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buf *buf; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ulong flags; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds blk_queue_bounce(q, &bio); 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (bio == NULL) { 16968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin printk(KERN_ERR "aoe: bio is NULL\n"); 17068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin BUG(); 17168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return 0; 17268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = bio->bi_bdev->bd_disk->private_data; 17468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (d == NULL) { 17568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin printk(KERN_ERR "aoe: bd_disk->private_data is NULL\n"); 17668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin BUG(); 17768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin bio_endio(bio, -ENXIO); 17868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return 0; 17968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } else if (bio->bi_io_vec == NULL) { 18068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin printk(KERN_ERR "aoe: bi_io_vec is NULL\n"); 18168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin BUG(); 18268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin bio_endio(bio, -ENXIO); 18368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return 0; 18468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf = mempool_alloc(d->bufpool, GFP_NOIO); 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buf == NULL) { 187a12c93f08b8fc83b7fcdabaf92b1adcea7489f5eEd L. Cashin printk(KERN_INFO "aoe: buf allocation failure\n"); 1886712ecf8f648118c3363c142196418f89a510b90NeilBrown bio_endio(bio, -ENOMEM); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(buf, 0, sizeof(*buf)); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&buf->bufs); 19368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin buf->stime = jiffies; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf->bio = bio; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf->resid = bio->bi_size; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf->sector = bio->bi_sector; 197392e4845f9728114f7ffa8d7612683397fd4d441Ed L. Cashin buf->bv = &bio->bi_io_vec[bio->bi_idx]; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf->bv_resid = buf->bv->bv_len; 19968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin WARN_ON(buf->bv_resid == 0); 20068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin buf->bv_off = buf->bv->bv_offset; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&d->lock, flags); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((d->flags & DEVFL_UP) == 0) { 2051d75981a8094e9f84fae65a6a83b361e3893b971Ed L. Cashin printk(KERN_INFO "aoe: device %ld.%d is not up\n", 206a12c93f08b8fc83b7fcdabaf92b1adcea7489f5eEd L. Cashin d->aoemajor, d->aoeminor); 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_free(buf, d->bufpool); 2096712ecf8f648118c3363c142196418f89a510b90NeilBrown bio_endio(bio, -ENXIO); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(&buf->bufs, &d->bufq); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2153ae1c24e395b2b65326439622223d88d92bfa03aEd L. Cashin aoecmd_work(d); 216e9bb8fb0b6d61a822201537b25206a0ca34b9d1dDavid S. Miller __skb_queue_head_init(&queue); 217e9bb8fb0b6d61a822201537b25206a0ca34b9d1dDavid S. Miller skb_queue_splice_init(&d->sendq, &queue); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 220e9bb8fb0b6d61a822201537b25206a0ca34b9d1dDavid S. Miller aoenet_xmit(&queue); 2213ae1c24e395b2b65326439622223d88d92bfa03aEd L. Cashin 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 226a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwigaoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 228a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig struct aoedev *d = bdev->bd_disk->private_data; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((d->flags & DEVFL_UP) == 0) { 231a12c93f08b8fc83b7fcdabaf92b1adcea7489f5eEd L. Cashin printk(KERN_ERR "aoe: disk not up\n"); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 235a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->cylinders = d->geo.cylinders; 236a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->heads = d->geo.heads; 237a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->sectors = d->geo.sectors; 238a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig return 0; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct block_device_operations aoe_bdops = { 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = aoeblk_open, 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = aoeblk_release, 244a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig .getgeo = aoeblk_getgeo, 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* alloc_disk and add_disk can sleep */ 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoeblk_gdalloc(void *vp) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d = vp; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gendisk *gd; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ulong flags; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd = alloc_disk(AOE_PARTITIONS); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gd == NULL) { 2581d75981a8094e9f84fae65a6a83b361e3893b971Ed L. Cashin printk(KERN_ERR 2591d75981a8094e9f84fae65a6a83b361e3893b971Ed L. Cashin "aoe: cannot allocate disk structure for %ld.%d\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) { 2661d75981a8094e9f84fae65a6a83b361e3893b971Ed L. Cashin printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%d\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