enum {
        DEFAULTBCNT = 2 * 512,  /* 2 sectors */
        MIN_BUFS = 16,
-       NTARGETS = 8,
+       NTARGETS = 4,
        NAOEIFS = 8,
        NSKBPOOLMAX = 256,
        NFACTIVE = 61,
        ulong maxbcnt;
        struct list_head factive[NFACTIVE];     /* hash of active frames */
        struct list_head rexmitq; /* deferred retransmissions */
-       struct aoetgt *targets[NTARGETS];
+       struct aoetgt **targets;
+       ulong ntargets;         /* number of allocated aoetgt pointers */
        struct aoetgt **tgt;    /* target in use when working */
-       ulong ntargets;
        ulong kicked;
        char ident[512];
 };
 
        int use_tainted;
        int has_untainted;
 
-       if (d->targets[0] == NULL) {    /* shouldn't happen, but I'm paranoid */
+       if (!d->targets || !d->targets[0]) {
                printk(KERN_ERR "aoe: NULL TARGETS!\n");
                return NULL;
        }
        tt = d->tgt;    /* last used target */
        for (use_tainted = 0, has_untainted = 0;;) {
                tt++;
-               if (tt >= &d->targets[NTARGETS] || !*tt)
+               if (tt >= &d->targets[d->ntargets] || !*tt)
                        tt = d->targets;
                t = *tt;
                if (!t->taint) {
        struct aoetgt **t, **e;
 
        t = d->targets;
-       e = t + NTARGETS;
+       e = t + d->ntargets;
        for (; t < e && *t; t++)
                if (memcmp((*t)->addr, addr, sizeof((*t)->addr)) == 0)
                        return *t;
        return skb;
 }
 
+static struct aoetgt **
+grow_targets(struct aoedev *d)
+{
+       ulong oldn, newn;
+       struct aoetgt **tt;
+
+       oldn = d->ntargets;
+       newn = oldn * 2;
+       tt = kcalloc(newn, sizeof(*d->targets), GFP_ATOMIC);
+       if (!tt)
+               return NULL;
+       memmove(tt, d->targets, sizeof(*d->targets) * oldn);
+       d->tgt = tt + (d->tgt - d->targets);
+       kfree(d->targets);
+       d->targets = tt;
+       d->ntargets = newn;
+
+       return &d->targets[oldn];
+}
+
 static struct aoetgt *
 addtgt(struct aoedev *d, char *addr, ulong nframes)
 {
        struct aoetgt *t, **tt, **te;
 
        tt = d->targets;
-       te = tt + NTARGETS;
+       te = tt + d->ntargets;
        for (; tt < te && *tt; tt++)
                ;
 
        if (tt == te) {
-               printk(KERN_INFO
-                       "aoe: device addtgt failure; too many targets\n");
-               return NULL;
+               tt = grow_targets(d);
+               if (!tt)
+                       goto nomem;
        }
        t = kzalloc(sizeof(*t), GFP_ATOMIC);
-       if (!t) {
-               printk(KERN_INFO "aoe: cannot allocate memory to add target\n");
-               return NULL;
-       }
-
-       d->ntargets++;
+       if (!t)
+               goto nomem;
        t->nframes = nframes;
        t->d = d;
        memcpy(t->addr, addr, sizeof t->addr);
        t->maxout = t->nframes / 2;
        INIT_LIST_HEAD(&t->ffree);
        return *tt = t;
+
+ nomem:
+       pr_info("aoe: cannot allocate memory to add target\n");
+       return NULL;
 }
 
 static void
        int bcnt = 0;
 
        t = d->targets;
-       e = t + NTARGETS;
+       e = t + d->ntargets;
        for (; t < e && *t; t++)
                if (bcnt == 0 || bcnt > (*t)->minbcnt)
                        bcnt = (*t)->minbcnt;
        d->maxbcnt = 0;
 
        t = d->targets;
-       te = t + NTARGETS;
+       te = t + d->ntargets;
        for (; t < te && *t; t++)
                aoecmd_wreset(*t);
 }
 
 
        /* reset window dressings */
        tt = d->targets;
-       te = tt + NTARGETS;
+       te = tt + d->ntargets;
        for (; tt < te && (t = *tt); tt++) {
                aoecmd_wreset(t);
                t->nout = 0;
                blk_cleanup_queue(d->blkq);
        }
        t = d->targets;
-       e = t + NTARGETS;
+       e = t + d->ntargets;
        for (; t < e && *t; t++)
                freetgt(d, *t);
        if (d->bufpool)
                        dd = &d->next;
                }
                spin_unlock(&d->lock);
+               if (doomed)
+                       kfree(doomed->targets);
                kfree(doomed);
        }
        spin_unlock_irqrestore(&devlist_lock, flags);
        d = kcalloc(1, sizeof *d, GFP_ATOMIC);
        if (!d)
                goto out;
+       d->targets = kcalloc(NTARGETS, sizeof(*d->targets), GFP_ATOMIC);
+       if (!d->targets) {
+               kfree(d);
+               goto out;
+       }
+       d->ntargets = NTARGETS;
        INIT_WORK(&d->work, aoecmd_sleepwork);
        spin_lock_init(&d->lock);
        skb_queue_head_init(&d->skbpool);