1 /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */
4 * AoE device utility functions; maintains device list.
7 #include <linux/hdreg.h>
8 #include <linux/blkdev.h>
9 #include <linux/netdevice.h>
12 static void dummy_timer(ulong);
13 static void aoedev_freedev(struct aoedev *);
14 static void freetgt(struct aoetgt *t);
16 static struct aoedev *devlist;
17 static spinlock_t devlist_lock;
20 aoedev_isbusy(struct aoedev *d)
22 struct aoetgt **t, **te;
27 for (; t < te && *t; t++) {
29 e = f + (*t)->nframes;
31 if (f->tag != FREETAG)
38 aoedev_by_aoeaddr(int maj, int min)
43 spin_lock_irqsave(&devlist_lock, flags);
45 for (d=devlist; d; d=d->next)
46 if (d->aoemajor == maj && d->aoeminor == min)
49 spin_unlock_irqrestore(&devlist_lock, flags);
58 d = (struct aoedev *)vp;
59 if (d->flags & DEVFL_TKILL)
61 d->timer.expires = jiffies + HZ;
66 aoedev_downdev(struct aoedev *d)
68 struct aoetgt **t, **te;
75 for (; t < te && *t; t++) {
77 e = f + (*t)->nframes;
78 for (; f < e; f->tag = FREETAG, f->buf = NULL, f++) {
79 if (f->tag == FREETAG || f->buf == NULL)
83 if (--buf->nframesout == 0
84 && buf != d->inprocess) {
85 mempool_free(buf, d->bufpool);
89 (*t)->maxout = (*t)->nframes;
95 mempool_free(buf, d->bufpool);
101 while (!list_empty(&d->bufq)) {
102 buf = container_of(d->bufq.next, struct buf, bufs);
103 list_del(d->bufq.next);
105 mempool_free(buf, d->bufpool);
106 bio_endio(bio, -EIO);
112 d->flags &= ~DEVFL_UP;
116 aoedev_freedev(struct aoedev *d)
118 struct aoetgt **t, **e;
127 for (; t < e && *t; t++)
130 mempool_destroy(d->bufpool);
135 aoedev_flush(const char __user *str, size_t cnt)
138 struct aoedev *d, **dd;
139 struct aoedev *rmd = NULL;
144 if (cnt > sizeof buf)
146 if (copy_from_user(buf, str, cnt))
148 all = !strncmp(buf, "all", 3);
151 flush_scheduled_work();
152 spin_lock_irqsave(&devlist_lock, flags);
156 if ((!all && (d->flags & DEVFL_UP))
157 || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
159 spin_unlock(&d->lock);
165 d->flags |= DEVFL_TKILL;
166 spin_unlock(&d->lock);
170 spin_unlock_irqrestore(&devlist_lock, flags);
173 del_timer_sync(&d->timer);
174 aoedev_freedev(d); /* must be able to sleep */
179 /* find it or malloc it */
181 aoedev_by_sysminor_m(ulong sysminor)
186 spin_lock_irqsave(&devlist_lock, flags);
188 for (d=devlist; d; d=d->next)
189 if (d->sysminor == sysminor)
193 d = kcalloc(1, sizeof *d, GFP_ATOMIC);
196 INIT_WORK(&d->work, aoecmd_sleepwork);
197 spin_lock_init(&d->lock);
198 init_timer(&d->timer);
199 d->timer.data = (ulong) d;
200 d->timer.function = dummy_timer;
201 d->timer.expires = jiffies + HZ;
202 add_timer(&d->timer);
203 d->bufpool = NULL; /* defer to aoeblk_gdalloc */
205 INIT_LIST_HEAD(&d->bufq);
206 d->sysminor = sysminor;
207 d->aoemajor = AOEMAJOR(sysminor);
208 d->aoeminor = AOEMINOR(sysminor);
209 d->mintimer = MINTIMER;
213 spin_unlock_irqrestore(&devlist_lock, flags);
218 freetgt(struct aoetgt *t)
225 skb_shinfo(f->skb)->nr_frags = 0;
226 dev_kfree_skb(f->skb);
238 flush_scheduled_work();
240 while ((d = devlist)) {
243 spin_lock_irqsave(&d->lock, flags);
245 d->flags |= DEVFL_TKILL;
246 spin_unlock_irqrestore(&d->lock, flags);
248 del_timer_sync(&d->timer);
256 spin_lock_init(&devlist_lock);