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 7027b180d7405f2b2df25e2a8b1b796b00f3773cfAndrew Morton#include <linux/kernel.h> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/hdreg.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h> 1043cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton#include <linux/backing-dev.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioctl.h> 135a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 14027b180d7405f2b2df25e2a8b1b796b00f3773cfAndrew Morton#include <linux/ratelimit.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/genhd.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 172a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann#include <linux/mutex.h> 18d5decd3b9512e35c87492312a72443192eebdda9Paul Gortmaker#include <linux/export.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "aoe.h" 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 212a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmannstatic DEFINE_MUTEX(aoeblk_mutex); 22e18b890bb0881bbab6f4f1a6cd20d9c60d66b003Christoph Lameterstatic struct kmem_cache *buf_pool_cache; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t aoedisk_show_state(struct device *dev, 25edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct device_attribute *attr, char *page) 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 27edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct gendisk *disk = dev_to_disk(dev); 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d = disk->private_data; 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return snprintf(page, PAGE_SIZE, 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%s%s\n", 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (d->flags & DEVFL_UP) ? "up" : "down", 3368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin (d->flags & DEVFL_KICKME) ? ",kickme" : 343ae1c24e395b2b65326439622223d88d92bfa03aEd L. Cashin (d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : ""); 353ae1c24e395b2b65326439622223d88d92bfa03aEd L. Cashin /* I'd rather see nopen exported so we can ditch closewait */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 37edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t aoedisk_show_mac(struct device *dev, 38edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct device_attribute *attr, char *page) 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 40edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct gendisk *disk = dev_to_disk(dev); 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d = disk->private_data; 4268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin struct aoetgt *t = d->targets[0]; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (t == NULL) 4568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return snprintf(page, PAGE_SIZE, "none\n"); 46411c41eea58bd3500cf897e2c27dd5330935a3a8Harvey Harrison return snprintf(page, PAGE_SIZE, "%pm\n", t->addr); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 48edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t aoedisk_show_netif(struct device *dev, 49edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct device_attribute *attr, char *page) 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 51edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct gendisk *disk = dev_to_disk(dev); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d = disk->private_data; 5368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin struct net_device *nds[8], **nd, **nnd, **ne; 5468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin struct aoetgt **t, **te; 5568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin struct aoeif *ifp, *e; 5668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin char *p; 5768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin 5868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin memset(nds, 0, sizeof nds); 5968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin nd = nds; 6068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin ne = nd + ARRAY_SIZE(nds); 6168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin t = d->targets; 6268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin te = t + NTARGETS; 6368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin for (; t < te && *t; t++) { 6468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin ifp = (*t)->ifs; 6568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin e = ifp + NAOEIFS; 6668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin for (; ifp < e && ifp->nd; ifp++) { 6768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin for (nnd = nds; nnd < nd; nnd++) 6868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (*nnd == ifp->nd) 6968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin break; 7068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (nnd == nd && nd != ne) 7168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin *nd++ = ifp->nd; 7268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } 7368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin ne = nd; 7668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin nd = nds; 7768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (*nd == NULL) 7868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return snprintf(page, PAGE_SIZE, "none\n"); 7968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin for (p = page; nd < ne; nd++) 8068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin p += snprintf(p, PAGE_SIZE - (p-page), "%s%s", 8168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin p == page ? "" : ",", (*nd)->name); 8268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin p += snprintf(p, PAGE_SIZE - (p-page), "\n"); 8368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin return p-page; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 854613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin/* firmware version */ 86edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t aoedisk_show_fwver(struct device *dev, 87edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct device_attribute *attr, char *page) 884613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin{ 89edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct gendisk *disk = dev_to_disk(dev); 904613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin struct aoedev *d = disk->private_data; 914613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin 924613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin return snprintf(page, PAGE_SIZE, "0x%04x\n", (unsigned int) d->fw_ver); 934613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin} 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 95edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL); 96edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL); 97edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic DEVICE_ATTR(netif, S_IRUGO, aoedisk_show_netif, NULL); 98edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic struct device_attribute dev_attr_firmware_version = { 9901e8ef11bc1a74e65678ed55795f59266d4add01Parag Warudkar .attr = { .name = "firmware-version", .mode = S_IRUGO }, 100edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers .show = aoedisk_show_fwver, 1014613ed277ab8a41640434181898ef4649cc7301eEd L. Cashin}; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1034ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartmanstatic struct attribute *aoe_attrs[] = { 104edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers &dev_attr_state.attr, 105edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers &dev_attr_mac.attr, 106edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers &dev_attr_netif.attr, 107edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers &dev_attr_firmware_version.attr, 108edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers NULL, 1094ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman}; 1104ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman 1114ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartmanstatic const struct attribute_group attr_group = { 1124ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman .attrs = aoe_attrs, 1134ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman}; 1144ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartman 1154ca5224f3ea4779054d96e885ca9b3980801ce13Greg Kroah-Hartmanstatic int 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoedisk_add_sysfs(struct aoedev *d) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 118ed9e1982347b36573cd622ee5f4e2a7ccd79b3fdTejun Heo return sysfs_create_group(&disk_to_dev(d->gd)->kobj, &attr_group); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoedisk_rm_sysfs(struct aoedev *d) 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 123ed9e1982347b36573cd622ee5f4e2a7ccd79b3fdTejun Heo sysfs_remove_group(&disk_to_dev(d->gd)->kobj, &attr_group); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 12794562c175113cf91204a77269eabeea32e1f38dbAl Viroaoeblk_open(struct block_device *bdev, fmode_t mode) 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12994562c175113cf91204a77269eabeea32e1f38dbAl Viro struct aoedev *d = bdev->bd_disk->private_data; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ulong flags; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1322a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_lock(&aoeblk_mutex); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&d->lock, flags); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (d->flags & DEVFL_UP) { 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->nopen++; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1372a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_unlock(&aoeblk_mutex); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1412a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann mutex_unlock(&aoeblk_mutex); 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 14694562c175113cf91204a77269eabeea32e1f38dbAl Viroaoeblk_release(struct gendisk *disk, fmode_t mode) 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14894562c175113cf91204a77269eabeea32e1f38dbAl Viro struct aoedev *d = disk->private_data; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ulong flags; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&d->lock, flags); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1535f7702fd737d14de3ed06a94a1655be9d43f7e35Ed L. Cashin if (--d->nopen == 0) { 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aoecmd_cfg(d->aoemajor, d->aoeminor); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1635a7bbad27a410350e64a2d7f5ec18fc73836c14fChristoph Hellwigstatic void 164165125e1e480f9510a5ffcfbfee4e3ee38c05f23Jens Axboeaoeblk_make_request(struct request_queue *q, struct bio *bio) 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 166e9bb8fb0b6d61a822201537b25206a0ca34b9d1dDavid S. Miller struct sk_buff_head queue; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buf *buf; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ulong flags; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds blk_queue_bounce(q, &bio); 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17368e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (bio == NULL) { 17468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin printk(KERN_ERR "aoe: bio is NULL\n"); 17568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin BUG(); 1765a7bbad27a410350e64a2d7f5ec18fc73836c14fChristoph Hellwig return; 17768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = bio->bi_bdev->bd_disk->private_data; 17968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin if (d == NULL) { 18068e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin printk(KERN_ERR "aoe: bd_disk->private_data is NULL\n"); 18168e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin BUG(); 18268e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin bio_endio(bio, -ENXIO); 1835a7bbad27a410350e64a2d7f5ec18fc73836c14fChristoph Hellwig return; 18468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } else if (bio->bi_io_vec == NULL) { 18568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin printk(KERN_ERR "aoe: bi_io_vec is NULL\n"); 18668e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin BUG(); 18768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin bio_endio(bio, -ENXIO); 1885a7bbad27a410350e64a2d7f5ec18fc73836c14fChristoph Hellwig return; 18968e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin } 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf = mempool_alloc(d->bufpool, GFP_NOIO); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buf == NULL) { 192a12c93f08b8fc83b7fcdabaf92b1adcea7489f5eEd L. Cashin printk(KERN_INFO "aoe: buf allocation failure\n"); 1936712ecf8f648118c3363c142196418f89a510b90NeilBrown bio_endio(bio, -ENOMEM); 1945a7bbad27a410350e64a2d7f5ec18fc73836c14fChristoph Hellwig return; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(buf, 0, sizeof(*buf)); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&buf->bufs); 19868e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin buf->stime = jiffies; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf->bio = bio; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf->resid = bio->bi_size; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf->sector = bio->bi_sector; 202392e4845f9728114f7ffa8d7612683397fd4d441Ed L. Cashin buf->bv = &bio->bi_io_vec[bio->bi_idx]; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf->bv_resid = buf->bv->bv_len; 20468e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin WARN_ON(buf->bv_resid == 0); 20568e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin buf->bv_off = buf->bv->bv_offset; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&d->lock, flags); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((d->flags & DEVFL_UP) == 0) { 210027b180d7405f2b2df25e2a8b1b796b00f3773cfAndrew Morton pr_info_ratelimited("aoe: device %ld.%d is not up\n", 211a12c93f08b8fc83b7fcdabaf92b1adcea7489f5eEd L. Cashin d->aoemajor, d->aoeminor); 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mempool_free(buf, d->bufpool); 2146712ecf8f648118c3363c142196418f89a510b90NeilBrown bio_endio(bio, -ENXIO); 2155a7bbad27a410350e64a2d7f5ec18fc73836c14fChristoph Hellwig return; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(&buf->bufs, &d->bufq); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2203ae1c24e395b2b65326439622223d88d92bfa03aEd L. Cashin aoecmd_work(d); 221e9bb8fb0b6d61a822201537b25206a0ca34b9d1dDavid S. Miller __skb_queue_head_init(&queue); 222e9bb8fb0b6d61a822201537b25206a0ca34b9d1dDavid S. Miller skb_queue_splice_init(&d->sendq, &queue); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 225e9bb8fb0b6d61a822201537b25206a0ca34b9d1dDavid S. Miller aoenet_xmit(&queue); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 229a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwigaoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 231a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig struct aoedev *d = bdev->bd_disk->private_data; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((d->flags & DEVFL_UP) == 0) { 234a12c93f08b8fc83b7fcdabaf92b1adcea7489f5eEd L. Cashin printk(KERN_ERR "aoe: disk not up\n"); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 238a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->cylinders = d->geo.cylinders; 239a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->heads = d->geo.heads; 240a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig geo->sectors = d->geo.sectors; 241a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig return 0; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24483d5cde47dedf01b6a4a4331882cbc0a7eea3c2eAlexey Dobriyanstatic const struct block_device_operations aoe_bdops = { 24594562c175113cf91204a77269eabeea32e1f38dbAl Viro .open = aoeblk_open, 24694562c175113cf91204a77269eabeea32e1f38dbAl Viro .release = aoeblk_release, 247a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig .getgeo = aoeblk_getgeo, 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* alloc_disk and add_disk can sleep */ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoeblk_gdalloc(void *vp) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aoedev *d = vp; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gendisk *gd; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ulong flags; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd = alloc_disk(AOE_PARTITIONS); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gd == NULL) { 2611d75981a8094e9f84fae65a6a83b361e3893b971Ed L. Cashin printk(KERN_ERR 2621d75981a8094e9f84fae65a6a83b361e3893b971Ed L. Cashin "aoe: cannot allocate disk structure for %ld.%d\n", 2636bb6285fdb948cedee586c6bebc9ebc5e32a5c35Ed L. Cashin d->aoemajor, d->aoeminor); 26443cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton goto err; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26793d2341c750cda0df48a6cc67b35fe25f1ec47dfMatthew Dobson d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (d->bufpool == NULL) { 2691d75981a8094e9f84fae65a6a83b361e3893b971Ed L. Cashin printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%d\n", 2706bb6285fdb948cedee586c6bebc9ebc5e32a5c35Ed L. Cashin d->aoemajor, d->aoeminor); 27143cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton goto err_disk; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2747135a71b19be1faf48b7148d77844d03bc0717d6Ed L. Cashin d->blkq = blk_alloc_queue(GFP_KERNEL); 2757135a71b19be1faf48b7148d77844d03bc0717d6Ed L. Cashin if (!d->blkq) 27643cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton goto err_mempool; 2777135a71b19be1faf48b7148d77844d03bc0717d6Ed L. Cashin blk_queue_make_request(d->blkq, aoeblk_make_request); 278d993831fa7ffeb89e994f046f93eeb09ec91df08Jens Axboe d->blkq->backing_dev_info.name = "aoe"; 2797135a71b19be1faf48b7148d77844d03bc0717d6Ed L. Cashin if (bdi_init(&d->blkq->backing_dev_info)) 2807135a71b19be1faf48b7148d77844d03bc0717d6Ed L. Cashin goto err_blkq; 28143cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton spin_lock_irqsave(&d->lock, flags); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd->major = AOE_MAJOR; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd->first_minor = d->sysminor * AOE_PARTITIONS; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd->fops = &aoe_bdops; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gd->private_data = d; 28680795aefb76d10c5d698e60c7e7750b5330787daTejun Heo set_capacity(gd, d->ssize); 28768e0d42f39d85b334d3867a4e5fc2e0e775c1a6cEd L. Cashin snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->aoemajor, d->aoeminor); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2907135a71b19be1faf48b7148d77844d03bc0717d6Ed L. Cashin gd->queue = d->blkq; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->gd = gd; 2923ae1c24e395b2b65326439622223d88d92bfa03aEd L. Cashin d->flags &= ~DEVFL_GDALLOC; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->flags |= DEVFL_UP; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&d->lock, flags); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_disk(gd); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aoedisk_add_sysfs(d); 29943cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton return; 30043cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton 3017135a71b19be1faf48b7148d77844d03bc0717d6Ed L. Cashinerr_blkq: 3027135a71b19be1faf48b7148d77844d03bc0717d6Ed L. Cashin blk_cleanup_queue(d->blkq); 3037135a71b19be1faf48b7148d77844d03bc0717d6Ed L. Cashin d->blkq = NULL; 30443cbe2cbdd5320f1ac785c6f016923609831effeAndrew Mortonerr_mempool: 30543cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton mempool_destroy(d->bufpool); 30643cbe2cbdd5320f1ac785c6f016923609831effeAndrew Mortonerr_disk: 30743cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton put_disk(gd); 30843cbe2cbdd5320f1ac785c6f016923609831effeAndrew Mortonerr: 30943cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton spin_lock_irqsave(&d->lock, flags); 31043cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton d->flags &= ~DEVFL_GDALLOC; 31143cbe2cbdd5320f1ac785c6f016923609831effeAndrew Morton spin_unlock_irqrestore(&d->lock, flags); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoeblk_exit(void) 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kmem_cache_destroy(buf_pool_cache); 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaoeblk_init(void) 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 32320c2df83d25c6a95affe6157a4c9cac4cf5ffaacPaul Mundt buf_pool_cache = kmem_cache_create("aoe_bufs", 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct buf), 32520c2df83d25c6a95affe6157a4c9cac4cf5ffaacPaul Mundt 0, 0, NULL); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buf_pool_cache == NULL) 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 332