[PATCH] aoe [2/8]: support dynamic resizing of AoE devices
Allow the driver to recognize AoE devices that have changed size.
Devices not in use are updated automatically, and devices that are in
use are updated at user request.
Signed-off-by: "Ed L. Cashin" <ecashin@coraid.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index ded33ba..ed4258a 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -12,6 +12,24 @@
static struct aoedev *devlist;
static spinlock_t devlist_lock;
+int
+aoedev_isbusy(struct aoedev *d)
+{
+ struct frame *f, *e;
+
+ f = d->frames;
+ e = f + d->nframes;
+ do {
+ if (f->tag != FREETAG) {
+ printk(KERN_DEBUG "aoe: %ld.%ld isbusy\n",
+ d->aoemajor, d->aoeminor);
+ return 1;
+ }
+ } while (++f < e);
+
+ return 0;
+}
+
struct aoedev *
aoedev_by_aoeaddr(int maj, int min)
{
@@ -28,6 +46,18 @@
return d;
}
+static void
+dummy_timer(ulong vp)
+{
+ struct aoedev *d;
+
+ d = (struct aoedev *)vp;
+ if (d->flags & DEVFL_TKILL)
+ return;
+ d->timer.expires = jiffies + HZ;
+ add_timer(&d->timer);
+}
+
/* called with devlist lock held */
static struct aoedev *
aoedev_newdev(ulong nframes)
@@ -44,6 +74,8 @@
return NULL;
}
+ INIT_WORK(&d->work, aoecmd_sleepwork, d);
+
d->nframes = nframes;
d->frames = f;
e = f + nframes;
@@ -52,6 +84,10 @@
spin_lock_init(&d->lock);
init_timer(&d->timer);
+ d->timer.data = (ulong) d;
+ d->timer.function = dummy_timer;
+ d->timer.expires = jiffies + HZ;
+ add_timer(&d->timer);
d->bufpool = NULL; /* defer to aoeblk_gdalloc */
INIT_LIST_HEAD(&d->bufq);
d->next = devlist;
@@ -67,9 +103,6 @@
struct buf *buf;
struct bio *bio;
- d->flags |= DEVFL_TKILL;
- del_timer(&d->timer);
-
f = d->frames;
e = f + d->nframes;
for (; f<e; f->tag = FREETAG, f->buf = NULL, f++) {
@@ -92,16 +125,15 @@
bio_endio(bio, bio->bi_size, -EIO);
}
- if (d->nopen)
- d->flags |= DEVFL_CLOSEWAIT;
if (d->gd)
d->gd->capacity = 0;
- d->flags &= ~DEVFL_UP;
+ d->flags &= ~(DEVFL_UP | DEVFL_PAUSE);
}
+/* find it or malloc it */
struct aoedev *
-aoedev_set(ulong sysminor, unsigned char *addr, struct net_device *ifp, ulong bufcnt)
+aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt)
{
struct aoedev *d;
ulong flags;
@@ -112,25 +144,19 @@
if (d->sysminor == sysminor)
break;
- if (d == NULL && (d = aoedev_newdev(bufcnt)) == NULL) {
- spin_unlock_irqrestore(&devlist_lock, flags);
- printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n");
- return NULL;
- } /* if newdev, (d->flags & DEVFL_UP) == 0 for below */
-
- spin_unlock_irqrestore(&devlist_lock, flags);
- spin_lock_irqsave(&d->lock, flags);
-
- d->ifp = ifp;
- memcpy(d->addr, addr, sizeof d->addr);
- if ((d->flags & DEVFL_UP) == 0) {
- aoedev_downdev(d); /* flushes outstanding frames */
+ if (d == NULL) {
+ d = aoedev_newdev(bufcnt);
+ if (d == NULL) {
+ spin_unlock_irqrestore(&devlist_lock, flags);
+ printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n");
+ return NULL;
+ }
d->sysminor = sysminor;
d->aoemajor = AOEMAJOR(sysminor);
d->aoeminor = AOEMINOR(sysminor);
}
- spin_unlock_irqrestore(&d->lock, flags);
+ spin_unlock_irqrestore(&devlist_lock, flags);
return d;
}
@@ -161,6 +187,7 @@
spin_lock_irqsave(&d->lock, flags);
aoedev_downdev(d);
+ d->flags |= DEVFL_TKILL;
spin_unlock_irqrestore(&d->lock, flags);
del_timer_sync(&d->timer);