1 /* Copyright (c) 2007 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>
10 #include <linux/delay.h>
13 static void dummy_timer(ulong);
14 static void aoedev_freedev(struct aoedev *);
15 static void freetgt(struct aoedev *d, struct aoetgt *t);
16 static void skbpoolfree(struct aoedev *d);
18 static struct aoedev *devlist;
19 static DEFINE_SPINLOCK(devlist_lock);
22 aoedev_isbusy(struct aoedev *d)
24 struct aoetgt **t, **te;
29 for (; t < te && *t; t++) {
31 e = f + (*t)->nframes;
33 if (f->tag != FREETAG)
40 aoedev_by_aoeaddr(int maj, int min)
45 spin_lock_irqsave(&devlist_lock, flags);
47 for (d=devlist; d; d=d->next)
48 if (d->aoemajor == maj && d->aoeminor == min)
51 spin_unlock_irqrestore(&devlist_lock, flags);
60 d = (struct aoedev *)vp;
61 if (d->flags & DEVFL_TKILL)
63 d->timer.expires = jiffies + HZ;
68 aoedev_downdev(struct aoedev *d)
70 struct aoetgt **t, **te;
77 for (; t < te && *t; t++) {
79 e = f + (*t)->nframes;
80 for (; f < e; f->tag = FREETAG, f->buf = NULL, f++) {
81 if (f->tag == FREETAG || f->buf == NULL)
85 if (--buf->nframesout == 0
86 && buf != d->inprocess) {
87 mempool_free(buf, d->bufpool);
91 (*t)->maxout = (*t)->nframes;
97 mempool_free(buf, d->bufpool);
103 while (!list_empty(&d->bufq)) {
104 buf = container_of(d->bufq.next, struct buf, bufs);
105 list_del(d->bufq.next);
107 mempool_free(buf, d->bufpool);
108 bio_endio(bio, -EIO);
114 d->flags &= ~DEVFL_UP;
118 aoedev_freedev(struct aoedev *d)
120 struct aoetgt **t, **e;
129 for (; t < e && *t; t++)
132 mempool_destroy(d->bufpool);
138 aoedev_flush(const char __user *str, size_t cnt)
141 struct aoedev *d, **dd;
142 struct aoedev *rmd = NULL;
147 if (cnt > sizeof buf)
149 if (copy_from_user(buf, str, cnt))
151 all = !strncmp(buf, "all", 3);
154 flush_scheduled_work();
155 spin_lock_irqsave(&devlist_lock, flags);
159 if ((!all && (d->flags & DEVFL_UP))
160 || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
162 spin_unlock(&d->lock);
168 d->flags |= DEVFL_TKILL;
169 spin_unlock(&d->lock);
173 spin_unlock_irqrestore(&devlist_lock, flags);
176 del_timer_sync(&d->timer);
177 aoedev_freedev(d); /* must be able to sleep */
182 /* I'm not really sure that this is a realistic problem, but if the
183 network driver goes gonzo let's just leak memory after complaining. */
185 skbfree(struct sk_buff *skb)
187 enum { Sms = 100, Tms = 3*1000};
192 while (atomic_read(&skb_shinfo(skb)->dataref) != 1 && i-- > 0)
196 "aoe: %s holds ref: %s\n",
197 skb->dev ? skb->dev->name : "netif",
198 "cannot free skb -- memory leaked.");
201 skb_shinfo(skb)->nr_frags = skb->data_len = 0;
207 skbpoolfree(struct aoedev *d)
211 while ((skb = d->skbpool_hd)) {
212 d->skbpool_hd = skb->next;
216 d->skbpool_tl = NULL;
219 /* find it or malloc it */
221 aoedev_by_sysminor_m(ulong sysminor)
226 spin_lock_irqsave(&devlist_lock, flags);
228 for (d=devlist; d; d=d->next)
229 if (d->sysminor == sysminor)
233 d = kcalloc(1, sizeof *d, GFP_ATOMIC);
236 INIT_WORK(&d->work, aoecmd_sleepwork);
237 spin_lock_init(&d->lock);
238 init_timer(&d->timer);
239 d->timer.data = (ulong) d;
240 d->timer.function = dummy_timer;
241 d->timer.expires = jiffies + HZ;
242 add_timer(&d->timer);
243 d->bufpool = NULL; /* defer to aoeblk_gdalloc */
245 INIT_LIST_HEAD(&d->bufq);
246 d->sysminor = sysminor;
247 d->aoemajor = AOEMAJOR(sysminor);
248 d->aoeminor = AOEMINOR(sysminor);
249 d->mintimer = MINTIMER;
253 spin_unlock_irqrestore(&devlist_lock, flags);
258 freetgt(struct aoedev *d, struct aoetgt *t)
276 flush_scheduled_work();
278 while ((d = devlist)) {
281 spin_lock_irqsave(&d->lock, flags);
283 d->flags |= DEVFL_TKILL;
284 spin_unlock_irqrestore(&d->lock, flags);
286 del_timer_sync(&d->timer);