diff options
Diffstat (limited to 'drivers/block/aoe/aoedev.c')
-rw-r--r-- | drivers/block/aoe/aoedev.c | 168 |
1 files changed, 79 insertions, 89 deletions
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 51f50710e5fc..a4d625aefeaa 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -15,15 +15,18 @@ static spinlock_t devlist_lock; int aoedev_isbusy(struct aoedev *d) { + struct aoetgt **t, **te; struct frame *f, *e; - f = d->frames; - e = f + d->nframes; - do { - if (f->tag != FREETAG) - return 1; - } while (++f < e); - + t = d->targets; + te = t + NTARGETS; + for (; t < te && *t; t++) { + f = (*t)->frames; + e = f + (*t)->nframes; + for (; f < e; f++) + if (f->tag != FREETAG) + return 1; + } return 0; } @@ -55,75 +58,41 @@ dummy_timer(ulong vp) add_timer(&d->timer); } -/* called with devlist lock held */ -static struct aoedev * -aoedev_newdev(ulong nframes) -{ - struct aoedev *d; - struct frame *f, *e; - - d = kzalloc(sizeof *d, GFP_ATOMIC); - f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); - switch (!d || !f) { - case 0: - d->nframes = nframes; - d->frames = f; - e = f + nframes; - for (; f<e; f++) { - f->tag = FREETAG; - f->skb = new_skb(ETH_ZLEN); - if (!f->skb) - break; - } - if (f == e) - break; - while (f > d->frames) { - f--; - dev_kfree_skb(f->skb); - } - default: - if (f) - kfree(f); - if (d) - kfree(d); - return NULL; - } - INIT_WORK(&d->work, aoecmd_sleepwork); - 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; - devlist = d; - - return d; -} - void aoedev_downdev(struct aoedev *d) { + struct aoetgt **t, **te; struct frame *f, *e; struct buf *buf; struct bio *bio; - f = d->frames; - e = f + d->nframes; - for (; f<e; f->tag = FREETAG, f->buf = NULL, f++) { - if (f->tag == FREETAG || f->buf == NULL) - continue; - buf = f->buf; - bio = buf->bio; - if (--buf->nframesout == 0) { - mempool_free(buf, d->bufpool); - bio_endio(bio, -EIO); + t = d->targets; + te = t + NTARGETS; + for (; t < te && *t; t++) { + f = (*t)->frames; + e = f + (*t)->nframes; + for (; f < e; f->tag = FREETAG, f->buf = NULL, f++) { + if (f->tag == FREETAG || f->buf == NULL) + continue; + buf = f->buf; + bio = buf->bio; + if (--buf->nframesout == 0 + && buf != d->inprocess) { + mempool_free(buf, d->bufpool); + bio_endio(bio, -EIO); + } } - skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; + (*t)->maxout = (*t)->nframes; + (*t)->nout = 0; + } + buf = d->inprocess; + if (buf) { + bio = buf->bio; + mempool_free(buf, d->bufpool); + bio_endio(bio, -EIO); } d->inprocess = NULL; + d->htgt = NULL; while (!list_empty(&d->bufq)) { buf = container_of(d->bufq.next, struct buf, bufs); @@ -136,12 +105,12 @@ aoedev_downdev(struct aoedev *d) if (d->gd) d->gd->capacity = 0; - d->flags &= ~(DEVFL_UP | DEVFL_PAUSE); + d->flags &= ~DEVFL_UP; } /* find it or malloc it */ struct aoedev * -aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) +aoedev_by_sysminor_m(ulong sysminor) { struct aoedev *d; ulong flags; @@ -151,40 +120,61 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) for (d=devlist; d; d=d->next) if (d->sysminor == sysminor) break; - - if (d == NULL) { - d = aoedev_newdev(bufcnt); - if (d == NULL) { - spin_unlock_irqrestore(&devlist_lock, flags); - printk(KERN_INFO "aoe: aoedev_newdev failure.\n"); - return NULL; - } - d->sysminor = sysminor; - d->aoemajor = AOEMAJOR(sysminor); - d->aoeminor = AOEMINOR(sysminor); - } - + if (d) + goto out; + d = kcalloc(1, sizeof *d, GFP_ATOMIC); + if (!d) + goto out; + INIT_WORK(&d->work, aoecmd_sleepwork); + 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 */ + d->tgt = d->targets; + INIT_LIST_HEAD(&d->bufq); + d->sysminor = sysminor; + d->aoemajor = AOEMAJOR(sysminor); + d->aoeminor = AOEMINOR(sysminor); + d->mintimer = MINTIMER; + d->next = devlist; + devlist = d; + out: spin_unlock_irqrestore(&devlist_lock, flags); return d; } static void -aoedev_freedev(struct aoedev *d) +freetgt(struct aoetgt *t) { struct frame *f, *e; + f = t->frames; + e = f + t->nframes; + for (; f < e; f++) { + skb_shinfo(f->skb)->nr_frags = 0; + dev_kfree_skb(f->skb); + } + kfree(t->frames); + kfree(t); +} + +static void +aoedev_freedev(struct aoedev *d) +{ + struct aoetgt **t, **e; + if (d->gd) { aoedisk_rm_sysfs(d); del_gendisk(d->gd); put_disk(d->gd); } - f = d->frames; - e = f + d->nframes; - for (; f<e; f++) { - skb_shinfo(f->skb)->nr_frags = 0; - dev_kfree_skb(f->skb); - } - kfree(d->frames); + t = d->targets; + e = t + NTARGETS; + for (; t < e && *t; t++) + freetgt(*t); if (d->bufpool) mempool_destroy(d->bufpool); kfree(d); |