xref: /OK3568_Linux_fs/kernel/drivers/block/aoe/aoedev.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* Copyright (c) 2013 Coraid, Inc.  See COPYING for GPL terms. */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * aoedev.c
4*4882a593Smuzhiyun  * AoE device utility functions; maintains device list.
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <linux/hdreg.h>
8*4882a593Smuzhiyun #include <linux/blk-mq.h>
9*4882a593Smuzhiyun #include <linux/netdevice.h>
10*4882a593Smuzhiyun #include <linux/delay.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/bitmap.h>
13*4882a593Smuzhiyun #include <linux/kdev_t.h>
14*4882a593Smuzhiyun #include <linux/moduleparam.h>
15*4882a593Smuzhiyun #include <linux/string.h>
16*4882a593Smuzhiyun #include "aoe.h"
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun static void freetgt(struct aoedev *d, struct aoetgt *t);
19*4882a593Smuzhiyun static void skbpoolfree(struct aoedev *d);
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun static int aoe_dyndevs = 1;
22*4882a593Smuzhiyun module_param(aoe_dyndevs, int, 0644);
23*4882a593Smuzhiyun MODULE_PARM_DESC(aoe_dyndevs, "Use dynamic minor numbers for devices.");
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun static struct aoedev *devlist;
26*4882a593Smuzhiyun static DEFINE_SPINLOCK(devlist_lock);
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /* Because some systems will have one, many, or no
29*4882a593Smuzhiyun  *   - partitions,
30*4882a593Smuzhiyun  *   - slots per shelf,
31*4882a593Smuzhiyun  *   - or shelves,
32*4882a593Smuzhiyun  * we need some flexibility in the way the minor numbers
33*4882a593Smuzhiyun  * are allocated.  So they are dynamic.
34*4882a593Smuzhiyun  */
35*4882a593Smuzhiyun #define N_DEVS ((1U<<MINORBITS)/AOE_PARTITIONS)
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun static DEFINE_SPINLOCK(used_minors_lock);
38*4882a593Smuzhiyun static DECLARE_BITMAP(used_minors, N_DEVS);
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun static int
minor_get_dyn(ulong * sysminor)41*4882a593Smuzhiyun minor_get_dyn(ulong *sysminor)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	ulong flags;
44*4882a593Smuzhiyun 	ulong n;
45*4882a593Smuzhiyun 	int error = 0;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	spin_lock_irqsave(&used_minors_lock, flags);
48*4882a593Smuzhiyun 	n = find_first_zero_bit(used_minors, N_DEVS);
49*4882a593Smuzhiyun 	if (n < N_DEVS)
50*4882a593Smuzhiyun 		set_bit(n, used_minors);
51*4882a593Smuzhiyun 	else
52*4882a593Smuzhiyun 		error = -1;
53*4882a593Smuzhiyun 	spin_unlock_irqrestore(&used_minors_lock, flags);
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	*sysminor = n * AOE_PARTITIONS;
56*4882a593Smuzhiyun 	return error;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun static int
minor_get_static(ulong * sysminor,ulong aoemaj,int aoemin)60*4882a593Smuzhiyun minor_get_static(ulong *sysminor, ulong aoemaj, int aoemin)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	ulong flags;
63*4882a593Smuzhiyun 	ulong n;
64*4882a593Smuzhiyun 	int error = 0;
65*4882a593Smuzhiyun 	enum {
66*4882a593Smuzhiyun 		/* for backwards compatibility when !aoe_dyndevs,
67*4882a593Smuzhiyun 		 * a static number of supported slots per shelf */
68*4882a593Smuzhiyun 		NPERSHELF = 16,
69*4882a593Smuzhiyun 	};
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	if (aoemin >= NPERSHELF) {
72*4882a593Smuzhiyun 		pr_err("aoe: %s %d slots per shelf\n",
73*4882a593Smuzhiyun 			"static minor device numbers support only",
74*4882a593Smuzhiyun 			NPERSHELF);
75*4882a593Smuzhiyun 		error = -1;
76*4882a593Smuzhiyun 		goto out;
77*4882a593Smuzhiyun 	}
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	n = aoemaj * NPERSHELF + aoemin;
80*4882a593Smuzhiyun 	if (n >= N_DEVS) {
81*4882a593Smuzhiyun 		pr_err("aoe: %s with e%ld.%d\n",
82*4882a593Smuzhiyun 			"cannot use static minor device numbers",
83*4882a593Smuzhiyun 			aoemaj, aoemin);
84*4882a593Smuzhiyun 		error = -1;
85*4882a593Smuzhiyun 		goto out;
86*4882a593Smuzhiyun 	}
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	spin_lock_irqsave(&used_minors_lock, flags);
89*4882a593Smuzhiyun 	if (test_bit(n, used_minors)) {
90*4882a593Smuzhiyun 		pr_err("aoe: %s %lu\n",
91*4882a593Smuzhiyun 			"existing device already has static minor number",
92*4882a593Smuzhiyun 			n);
93*4882a593Smuzhiyun 		error = -1;
94*4882a593Smuzhiyun 	} else
95*4882a593Smuzhiyun 		set_bit(n, used_minors);
96*4882a593Smuzhiyun 	spin_unlock_irqrestore(&used_minors_lock, flags);
97*4882a593Smuzhiyun 	*sysminor = n * AOE_PARTITIONS;
98*4882a593Smuzhiyun out:
99*4882a593Smuzhiyun 	return error;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun static int
minor_get(ulong * sysminor,ulong aoemaj,int aoemin)103*4882a593Smuzhiyun minor_get(ulong *sysminor, ulong aoemaj, int aoemin)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	if (aoe_dyndevs)
106*4882a593Smuzhiyun 		return minor_get_dyn(sysminor);
107*4882a593Smuzhiyun 	else
108*4882a593Smuzhiyun 		return minor_get_static(sysminor, aoemaj, aoemin);
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun static void
minor_free(ulong minor)112*4882a593Smuzhiyun minor_free(ulong minor)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	ulong flags;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	minor /= AOE_PARTITIONS;
117*4882a593Smuzhiyun 	BUG_ON(minor >= N_DEVS);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	spin_lock_irqsave(&used_minors_lock, flags);
120*4882a593Smuzhiyun 	BUG_ON(!test_bit(minor, used_minors));
121*4882a593Smuzhiyun 	clear_bit(minor, used_minors);
122*4882a593Smuzhiyun 	spin_unlock_irqrestore(&used_minors_lock, flags);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun /*
126*4882a593Smuzhiyun  * Users who grab a pointer to the device with aoedev_by_aoeaddr
127*4882a593Smuzhiyun  * automatically get a reference count and must be responsible
128*4882a593Smuzhiyun  * for performing a aoedev_put.  With the addition of async
129*4882a593Smuzhiyun  * kthread processing I'm no longer confident that we can
130*4882a593Smuzhiyun  * guarantee consistency in the face of device flushes.
131*4882a593Smuzhiyun  *
132*4882a593Smuzhiyun  * For the time being, we only bother to add extra references for
133*4882a593Smuzhiyun  * frames sitting on the iocq.  When the kthreads finish processing
134*4882a593Smuzhiyun  * these frames, they will aoedev_put the device.
135*4882a593Smuzhiyun  */
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun void
aoedev_put(struct aoedev * d)138*4882a593Smuzhiyun aoedev_put(struct aoedev *d)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun 	ulong flags;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	spin_lock_irqsave(&devlist_lock, flags);
143*4882a593Smuzhiyun 	d->ref--;
144*4882a593Smuzhiyun 	spin_unlock_irqrestore(&devlist_lock, flags);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun static void
dummy_timer(struct timer_list * t)148*4882a593Smuzhiyun dummy_timer(struct timer_list *t)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	struct aoedev *d;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	d = from_timer(d, t, timer);
153*4882a593Smuzhiyun 	if (d->flags & DEVFL_TKILL)
154*4882a593Smuzhiyun 		return;
155*4882a593Smuzhiyun 	d->timer.expires = jiffies + HZ;
156*4882a593Smuzhiyun 	add_timer(&d->timer);
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun static void
aoe_failip(struct aoedev * d)160*4882a593Smuzhiyun aoe_failip(struct aoedev *d)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun 	struct request *rq;
163*4882a593Smuzhiyun 	struct aoe_req *req;
164*4882a593Smuzhiyun 	struct bio *bio;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	aoe_failbuf(d, d->ip.buf);
167*4882a593Smuzhiyun 	rq = d->ip.rq;
168*4882a593Smuzhiyun 	if (rq == NULL)
169*4882a593Smuzhiyun 		return;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	req = blk_mq_rq_to_pdu(rq);
172*4882a593Smuzhiyun 	while ((bio = d->ip.nxbio)) {
173*4882a593Smuzhiyun 		bio->bi_status = BLK_STS_IOERR;
174*4882a593Smuzhiyun 		d->ip.nxbio = bio->bi_next;
175*4882a593Smuzhiyun 		req->nr_bios--;
176*4882a593Smuzhiyun 	}
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	if (!req->nr_bios)
179*4882a593Smuzhiyun 		aoe_end_request(d, rq, 0);
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun static void
downdev_frame(struct list_head * pos)183*4882a593Smuzhiyun downdev_frame(struct list_head *pos)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun 	struct frame *f;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	f = list_entry(pos, struct frame, head);
188*4882a593Smuzhiyun 	list_del(pos);
189*4882a593Smuzhiyun 	if (f->buf) {
190*4882a593Smuzhiyun 		f->buf->nframesout--;
191*4882a593Smuzhiyun 		aoe_failbuf(f->t->d, f->buf);
192*4882a593Smuzhiyun 	}
193*4882a593Smuzhiyun 	aoe_freetframe(f);
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun void
aoedev_downdev(struct aoedev * d)197*4882a593Smuzhiyun aoedev_downdev(struct aoedev *d)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	struct aoetgt *t, **tt, **te;
200*4882a593Smuzhiyun 	struct list_head *head, *pos, *nx;
201*4882a593Smuzhiyun 	int i;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	d->flags &= ~DEVFL_UP;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	/* clean out active and to-be-retransmitted buffers */
206*4882a593Smuzhiyun 	for (i = 0; i < NFACTIVE; i++) {
207*4882a593Smuzhiyun 		head = &d->factive[i];
208*4882a593Smuzhiyun 		list_for_each_safe(pos, nx, head)
209*4882a593Smuzhiyun 			downdev_frame(pos);
210*4882a593Smuzhiyun 	}
211*4882a593Smuzhiyun 	head = &d->rexmitq;
212*4882a593Smuzhiyun 	list_for_each_safe(pos, nx, head)
213*4882a593Smuzhiyun 		downdev_frame(pos);
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	/* reset window dressings */
216*4882a593Smuzhiyun 	tt = d->targets;
217*4882a593Smuzhiyun 	te = tt + d->ntargets;
218*4882a593Smuzhiyun 	for (; tt < te && (t = *tt); tt++) {
219*4882a593Smuzhiyun 		aoecmd_wreset(t);
220*4882a593Smuzhiyun 		t->nout = 0;
221*4882a593Smuzhiyun 	}
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	/* clean out the in-process request (if any) */
224*4882a593Smuzhiyun 	aoe_failip(d);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	/* fast fail all pending I/O */
227*4882a593Smuzhiyun 	if (d->blkq) {
228*4882a593Smuzhiyun 		/* UP is cleared, freeze+quiesce to insure all are errored */
229*4882a593Smuzhiyun 		blk_mq_freeze_queue(d->blkq);
230*4882a593Smuzhiyun 		blk_mq_quiesce_queue(d->blkq);
231*4882a593Smuzhiyun 		blk_mq_unquiesce_queue(d->blkq);
232*4882a593Smuzhiyun 		blk_mq_unfreeze_queue(d->blkq);
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	if (d->gd)
236*4882a593Smuzhiyun 		set_capacity(d->gd, 0);
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun /* return whether the user asked for this particular
240*4882a593Smuzhiyun  * device to be flushed
241*4882a593Smuzhiyun  */
242*4882a593Smuzhiyun static int
user_req(char * s,size_t slen,struct aoedev * d)243*4882a593Smuzhiyun user_req(char *s, size_t slen, struct aoedev *d)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun 	const char *p;
246*4882a593Smuzhiyun 	size_t lim;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	if (!d->gd)
249*4882a593Smuzhiyun 		return 0;
250*4882a593Smuzhiyun 	p = kbasename(d->gd->disk_name);
251*4882a593Smuzhiyun 	lim = sizeof(d->gd->disk_name);
252*4882a593Smuzhiyun 	lim -= p - d->gd->disk_name;
253*4882a593Smuzhiyun 	if (slen < lim)
254*4882a593Smuzhiyun 		lim = slen;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	return !strncmp(s, p, lim);
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun static void
freedev(struct aoedev * d)260*4882a593Smuzhiyun freedev(struct aoedev *d)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun 	struct aoetgt **t, **e;
263*4882a593Smuzhiyun 	int freeing = 0;
264*4882a593Smuzhiyun 	unsigned long flags;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	spin_lock_irqsave(&d->lock, flags);
267*4882a593Smuzhiyun 	if (d->flags & DEVFL_TKILL
268*4882a593Smuzhiyun 	&& !(d->flags & DEVFL_FREEING)) {
269*4882a593Smuzhiyun 		d->flags |= DEVFL_FREEING;
270*4882a593Smuzhiyun 		freeing = 1;
271*4882a593Smuzhiyun 	}
272*4882a593Smuzhiyun 	spin_unlock_irqrestore(&d->lock, flags);
273*4882a593Smuzhiyun 	if (!freeing)
274*4882a593Smuzhiyun 		return;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	del_timer_sync(&d->timer);
277*4882a593Smuzhiyun 	if (d->gd) {
278*4882a593Smuzhiyun 		aoedisk_rm_debugfs(d);
279*4882a593Smuzhiyun 		del_gendisk(d->gd);
280*4882a593Smuzhiyun 		put_disk(d->gd);
281*4882a593Smuzhiyun 		blk_mq_free_tag_set(&d->tag_set);
282*4882a593Smuzhiyun 		blk_cleanup_queue(d->blkq);
283*4882a593Smuzhiyun 	}
284*4882a593Smuzhiyun 	t = d->targets;
285*4882a593Smuzhiyun 	e = t + d->ntargets;
286*4882a593Smuzhiyun 	for (; t < e && *t; t++)
287*4882a593Smuzhiyun 		freetgt(d, *t);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	mempool_destroy(d->bufpool);
290*4882a593Smuzhiyun 	skbpoolfree(d);
291*4882a593Smuzhiyun 	minor_free(d->sysminor);
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	spin_lock_irqsave(&d->lock, flags);
294*4882a593Smuzhiyun 	d->flags |= DEVFL_FREED;
295*4882a593Smuzhiyun 	spin_unlock_irqrestore(&d->lock, flags);
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun enum flush_parms {
299*4882a593Smuzhiyun 	NOT_EXITING = 0,
300*4882a593Smuzhiyun 	EXITING = 1,
301*4882a593Smuzhiyun };
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun static int
flush(const char __user * str,size_t cnt,int exiting)304*4882a593Smuzhiyun flush(const char __user *str, size_t cnt, int exiting)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun 	ulong flags;
307*4882a593Smuzhiyun 	struct aoedev *d, **dd;
308*4882a593Smuzhiyun 	char buf[16];
309*4882a593Smuzhiyun 	int all = 0;
310*4882a593Smuzhiyun 	int specified = 0;	/* flush a specific device */
311*4882a593Smuzhiyun 	unsigned int skipflags;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	skipflags = DEVFL_GDALLOC | DEVFL_NEWSIZE | DEVFL_TKILL;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	if (!exiting && cnt >= 3) {
316*4882a593Smuzhiyun 		if (cnt > sizeof buf)
317*4882a593Smuzhiyun 			cnt = sizeof buf;
318*4882a593Smuzhiyun 		if (copy_from_user(buf, str, cnt))
319*4882a593Smuzhiyun 			return -EFAULT;
320*4882a593Smuzhiyun 		all = !strncmp(buf, "all", 3);
321*4882a593Smuzhiyun 		if (!all)
322*4882a593Smuzhiyun 			specified = 1;
323*4882a593Smuzhiyun 	}
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	flush_scheduled_work();
326*4882a593Smuzhiyun 	/* pass one: do aoedev_downdev, which might sleep */
327*4882a593Smuzhiyun restart1:
328*4882a593Smuzhiyun 	spin_lock_irqsave(&devlist_lock, flags);
329*4882a593Smuzhiyun 	for (d = devlist; d; d = d->next) {
330*4882a593Smuzhiyun 		spin_lock(&d->lock);
331*4882a593Smuzhiyun 		if (d->flags & DEVFL_TKILL)
332*4882a593Smuzhiyun 			goto cont;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 		if (exiting) {
335*4882a593Smuzhiyun 			/* unconditionally take each device down */
336*4882a593Smuzhiyun 		} else if (specified) {
337*4882a593Smuzhiyun 			if (!user_req(buf, cnt, d))
338*4882a593Smuzhiyun 				goto cont;
339*4882a593Smuzhiyun 		} else if ((!all && (d->flags & DEVFL_UP))
340*4882a593Smuzhiyun 		|| d->flags & skipflags
341*4882a593Smuzhiyun 		|| d->nopen
342*4882a593Smuzhiyun 		|| d->ref)
343*4882a593Smuzhiyun 			goto cont;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 		spin_unlock(&d->lock);
346*4882a593Smuzhiyun 		spin_unlock_irqrestore(&devlist_lock, flags);
347*4882a593Smuzhiyun 		aoedev_downdev(d);
348*4882a593Smuzhiyun 		d->flags |= DEVFL_TKILL;
349*4882a593Smuzhiyun 		goto restart1;
350*4882a593Smuzhiyun cont:
351*4882a593Smuzhiyun 		spin_unlock(&d->lock);
352*4882a593Smuzhiyun 	}
353*4882a593Smuzhiyun 	spin_unlock_irqrestore(&devlist_lock, flags);
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	/* pass two: call freedev, which might sleep,
356*4882a593Smuzhiyun 	 * for aoedevs marked with DEVFL_TKILL
357*4882a593Smuzhiyun 	 */
358*4882a593Smuzhiyun restart2:
359*4882a593Smuzhiyun 	spin_lock_irqsave(&devlist_lock, flags);
360*4882a593Smuzhiyun 	for (d = devlist; d; d = d->next) {
361*4882a593Smuzhiyun 		spin_lock(&d->lock);
362*4882a593Smuzhiyun 		if (d->flags & DEVFL_TKILL
363*4882a593Smuzhiyun 		&& !(d->flags & DEVFL_FREEING)) {
364*4882a593Smuzhiyun 			spin_unlock(&d->lock);
365*4882a593Smuzhiyun 			spin_unlock_irqrestore(&devlist_lock, flags);
366*4882a593Smuzhiyun 			freedev(d);
367*4882a593Smuzhiyun 			goto restart2;
368*4882a593Smuzhiyun 		}
369*4882a593Smuzhiyun 		spin_unlock(&d->lock);
370*4882a593Smuzhiyun 	}
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	/* pass three: remove aoedevs marked with DEVFL_FREED */
373*4882a593Smuzhiyun 	for (dd = &devlist, d = *dd; d; d = *dd) {
374*4882a593Smuzhiyun 		struct aoedev *doomed = NULL;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 		spin_lock(&d->lock);
377*4882a593Smuzhiyun 		if (d->flags & DEVFL_FREED) {
378*4882a593Smuzhiyun 			*dd = d->next;
379*4882a593Smuzhiyun 			doomed = d;
380*4882a593Smuzhiyun 		} else {
381*4882a593Smuzhiyun 			dd = &d->next;
382*4882a593Smuzhiyun 		}
383*4882a593Smuzhiyun 		spin_unlock(&d->lock);
384*4882a593Smuzhiyun 		if (doomed)
385*4882a593Smuzhiyun 			kfree(doomed->targets);
386*4882a593Smuzhiyun 		kfree(doomed);
387*4882a593Smuzhiyun 	}
388*4882a593Smuzhiyun 	spin_unlock_irqrestore(&devlist_lock, flags);
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	return 0;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun int
aoedev_flush(const char __user * str,size_t cnt)394*4882a593Smuzhiyun aoedev_flush(const char __user *str, size_t cnt)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun 	return flush(str, cnt, NOT_EXITING);
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun /* This has been confirmed to occur once with Tms=3*1000 due to the
400*4882a593Smuzhiyun  * driver changing link and not processing its transmit ring.  The
401*4882a593Smuzhiyun  * problem is hard enough to solve by returning an error that I'm
402*4882a593Smuzhiyun  * still punting on "solving" this.
403*4882a593Smuzhiyun  */
404*4882a593Smuzhiyun static void
skbfree(struct sk_buff * skb)405*4882a593Smuzhiyun skbfree(struct sk_buff *skb)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun 	enum { Sms = 250, Tms = 30 * 1000};
408*4882a593Smuzhiyun 	int i = Tms / Sms;
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	if (skb == NULL)
411*4882a593Smuzhiyun 		return;
412*4882a593Smuzhiyun 	while (atomic_read(&skb_shinfo(skb)->dataref) != 1 && i-- > 0)
413*4882a593Smuzhiyun 		msleep(Sms);
414*4882a593Smuzhiyun 	if (i < 0) {
415*4882a593Smuzhiyun 		printk(KERN_ERR
416*4882a593Smuzhiyun 			"aoe: %s holds ref: %s\n",
417*4882a593Smuzhiyun 			skb->dev ? skb->dev->name : "netif",
418*4882a593Smuzhiyun 			"cannot free skb -- memory leaked.");
419*4882a593Smuzhiyun 		return;
420*4882a593Smuzhiyun 	}
421*4882a593Smuzhiyun 	skb->truesize -= skb->data_len;
422*4882a593Smuzhiyun 	skb_shinfo(skb)->nr_frags = skb->data_len = 0;
423*4882a593Smuzhiyun 	skb_trim(skb, 0);
424*4882a593Smuzhiyun 	dev_kfree_skb(skb);
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun static void
skbpoolfree(struct aoedev * d)428*4882a593Smuzhiyun skbpoolfree(struct aoedev *d)
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun 	struct sk_buff *skb, *tmp;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	skb_queue_walk_safe(&d->skbpool, skb, tmp)
433*4882a593Smuzhiyun 		skbfree(skb);
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	__skb_queue_head_init(&d->skbpool);
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun /* find it or allocate it */
439*4882a593Smuzhiyun struct aoedev *
aoedev_by_aoeaddr(ulong maj,int min,int do_alloc)440*4882a593Smuzhiyun aoedev_by_aoeaddr(ulong maj, int min, int do_alloc)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun 	struct aoedev *d;
443*4882a593Smuzhiyun 	int i;
444*4882a593Smuzhiyun 	ulong flags;
445*4882a593Smuzhiyun 	ulong sysminor = 0;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	spin_lock_irqsave(&devlist_lock, flags);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	for (d=devlist; d; d=d->next)
450*4882a593Smuzhiyun 		if (d->aoemajor == maj && d->aoeminor == min) {
451*4882a593Smuzhiyun 			spin_lock(&d->lock);
452*4882a593Smuzhiyun 			if (d->flags & DEVFL_TKILL) {
453*4882a593Smuzhiyun 				spin_unlock(&d->lock);
454*4882a593Smuzhiyun 				d = NULL;
455*4882a593Smuzhiyun 				goto out;
456*4882a593Smuzhiyun 			}
457*4882a593Smuzhiyun 			d->ref++;
458*4882a593Smuzhiyun 			spin_unlock(&d->lock);
459*4882a593Smuzhiyun 			break;
460*4882a593Smuzhiyun 		}
461*4882a593Smuzhiyun 	if (d || !do_alloc || minor_get(&sysminor, maj, min) < 0)
462*4882a593Smuzhiyun 		goto out;
463*4882a593Smuzhiyun 	d = kcalloc(1, sizeof *d, GFP_ATOMIC);
464*4882a593Smuzhiyun 	if (!d)
465*4882a593Smuzhiyun 		goto out;
466*4882a593Smuzhiyun 	d->targets = kcalloc(NTARGETS, sizeof(*d->targets), GFP_ATOMIC);
467*4882a593Smuzhiyun 	if (!d->targets) {
468*4882a593Smuzhiyun 		kfree(d);
469*4882a593Smuzhiyun 		d = NULL;
470*4882a593Smuzhiyun 		goto out;
471*4882a593Smuzhiyun 	}
472*4882a593Smuzhiyun 	d->ntargets = NTARGETS;
473*4882a593Smuzhiyun 	INIT_WORK(&d->work, aoecmd_sleepwork);
474*4882a593Smuzhiyun 	spin_lock_init(&d->lock);
475*4882a593Smuzhiyun 	INIT_LIST_HEAD(&d->rq_list);
476*4882a593Smuzhiyun 	skb_queue_head_init(&d->skbpool);
477*4882a593Smuzhiyun 	timer_setup(&d->timer, dummy_timer, 0);
478*4882a593Smuzhiyun 	d->timer.expires = jiffies + HZ;
479*4882a593Smuzhiyun 	add_timer(&d->timer);
480*4882a593Smuzhiyun 	d->bufpool = NULL;	/* defer to aoeblk_gdalloc */
481*4882a593Smuzhiyun 	d->tgt = d->targets;
482*4882a593Smuzhiyun 	d->ref = 1;
483*4882a593Smuzhiyun 	for (i = 0; i < NFACTIVE; i++)
484*4882a593Smuzhiyun 		INIT_LIST_HEAD(&d->factive[i]);
485*4882a593Smuzhiyun 	INIT_LIST_HEAD(&d->rexmitq);
486*4882a593Smuzhiyun 	d->sysminor = sysminor;
487*4882a593Smuzhiyun 	d->aoemajor = maj;
488*4882a593Smuzhiyun 	d->aoeminor = min;
489*4882a593Smuzhiyun 	d->rttavg = RTTAVG_INIT;
490*4882a593Smuzhiyun 	d->rttdev = RTTDEV_INIT;
491*4882a593Smuzhiyun 	d->next = devlist;
492*4882a593Smuzhiyun 	devlist = d;
493*4882a593Smuzhiyun  out:
494*4882a593Smuzhiyun 	spin_unlock_irqrestore(&devlist_lock, flags);
495*4882a593Smuzhiyun 	return d;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun static void
freetgt(struct aoedev * d,struct aoetgt * t)499*4882a593Smuzhiyun freetgt(struct aoedev *d, struct aoetgt *t)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun 	struct frame *f;
502*4882a593Smuzhiyun 	struct list_head *pos, *nx, *head;
503*4882a593Smuzhiyun 	struct aoeif *ifp;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	for (ifp = t->ifs; ifp < &t->ifs[NAOEIFS]; ++ifp) {
506*4882a593Smuzhiyun 		if (!ifp->nd)
507*4882a593Smuzhiyun 			break;
508*4882a593Smuzhiyun 		dev_put(ifp->nd);
509*4882a593Smuzhiyun 	}
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	head = &t->ffree;
512*4882a593Smuzhiyun 	list_for_each_safe(pos, nx, head) {
513*4882a593Smuzhiyun 		list_del(pos);
514*4882a593Smuzhiyun 		f = list_entry(pos, struct frame, head);
515*4882a593Smuzhiyun 		skbfree(f->skb);
516*4882a593Smuzhiyun 		kfree(f);
517*4882a593Smuzhiyun 	}
518*4882a593Smuzhiyun 	kfree(t);
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun void
aoedev_exit(void)522*4882a593Smuzhiyun aoedev_exit(void)
523*4882a593Smuzhiyun {
524*4882a593Smuzhiyun 	flush_scheduled_work();
525*4882a593Smuzhiyun 	flush(NULL, 0, EXITING);
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun int __init
aoedev_init(void)529*4882a593Smuzhiyun aoedev_init(void)
530*4882a593Smuzhiyun {
531*4882a593Smuzhiyun 	return 0;
532*4882a593Smuzhiyun }
533