aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/aoe/aoedev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/aoe/aoedev.c')
-rw-r--r--drivers/block/aoe/aoedev.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index e26f6f4a28a2..839a964906ce 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -7,11 +7,13 @@
7#include <linux/hdreg.h> 7#include <linux/hdreg.h>
8#include <linux/blkdev.h> 8#include <linux/blkdev.h>
9#include <linux/netdevice.h> 9#include <linux/netdevice.h>
10#include <linux/delay.h>
10#include "aoe.h" 11#include "aoe.h"
11 12
12static void dummy_timer(ulong); 13static void dummy_timer(ulong);
13static void aoedev_freedev(struct aoedev *); 14static void aoedev_freedev(struct aoedev *);
14static void freetgt(struct aoetgt *t); 15static void freetgt(struct aoedev *d, struct aoetgt *t);
16static void skbpoolfree(struct aoedev *d);
15 17
16static struct aoedev *devlist; 18static struct aoedev *devlist;
17static spinlock_t devlist_lock; 19static spinlock_t devlist_lock;
@@ -125,9 +127,10 @@ aoedev_freedev(struct aoedev *d)
125 t = d->targets; 127 t = d->targets;
126 e = t + NTARGETS; 128 e = t + NTARGETS;
127 for (; t < e && *t; t++) 129 for (; t < e && *t; t++)
128 freetgt(*t); 130 freetgt(d, *t);
129 if (d->bufpool) 131 if (d->bufpool)
130 mempool_destroy(d->bufpool); 132 mempool_destroy(d->bufpool);
133 skbpoolfree(d);
131 kfree(d); 134 kfree(d);
132} 135}
133 136
@@ -176,6 +179,43 @@ aoedev_flush(const char __user *str, size_t cnt)
176 return 0; 179 return 0;
177} 180}
178 181
182/* I'm not really sure that this is a realistic problem, but if the
183network driver goes gonzo let's just leak memory after complaining. */
184static void
185skbfree(struct sk_buff *skb)
186{
187 enum { Sms = 100, Tms = 3*1000};
188 int i = Tms / Sms;
189
190 if (skb == NULL)
191 return;
192 while (atomic_read(&skb_shinfo(skb)->dataref) != 1 && i-- > 0)
193 msleep(Sms);
194 if (i <= 0) {
195 printk(KERN_ERR
196 "aoe: %s holds ref: %s\n",
197 skb->dev ? skb->dev->name : "netif",
198 "cannot free skb -- memory leaked.");
199 return;
200 }
201 skb_shinfo(skb)->nr_frags = skb->data_len = 0;
202 skb_trim(skb, 0);
203 dev_kfree_skb(skb);
204}
205
206static void
207skbpoolfree(struct aoedev *d)
208{
209 struct sk_buff *skb;
210
211 while ((skb = d->skbpool_hd)) {
212 d->skbpool_hd = skb->next;
213 skb->next = NULL;
214 skbfree(skb);
215 }
216 d->skbpool_tl = NULL;
217}
218
179/* find it or malloc it */ 219/* find it or malloc it */
180struct aoedev * 220struct aoedev *
181aoedev_by_sysminor_m(ulong sysminor) 221aoedev_by_sysminor_m(ulong sysminor)
@@ -215,16 +255,14 @@ aoedev_by_sysminor_m(ulong sysminor)
215} 255}
216 256
217static void 257static void
218freetgt(struct aoetgt *t) 258freetgt(struct aoedev *d, struct aoetgt *t)
219{ 259{
220 struct frame *f, *e; 260 struct frame *f, *e;
221 261
222 f = t->frames; 262 f = t->frames;
223 e = f + t->nframes; 263 e = f + t->nframes;
224 for (; f < e; f++) { 264 for (; f < e; f++)
225 skb_shinfo(f->skb)->nr_frags = 0; 265 skbfree(f->skb);
226 dev_kfree_skb(f->skb);
227 }
228 kfree(t->frames); 266 kfree(t->frames);
229 kfree(t); 267 kfree(t);
230} 268}