1 /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ 2 /* 3 * aoedev.c 4 * AoE device utility functions; maintains device list. 5 */ 6 7 #include <linux/hdreg.h> 8 #include <linux/blkdev.h> 9 #include <linux/netdevice.h> 10 #include <linux/delay.h> 11 #include "aoe.h" 12 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); 17 18 static struct aoedev *devlist; 19 static DEFINE_SPINLOCK(devlist_lock); 20 21 struct aoedev * 22 aoedev_by_aoeaddr(int maj, int min) 23 { 24 struct aoedev *d; 25 ulong flags; 26 27 spin_lock_irqsave(&devlist_lock, flags); 28 29 for (d=devlist; d; d=d->next) 30 if (d->aoemajor == maj && d->aoeminor == min) 31 break; 32 33 spin_unlock_irqrestore(&devlist_lock, flags); 34 return d; 35 } 36 37 static void 38 dummy_timer(ulong vp) 39 { 40 struct aoedev *d; 41 42 d = (struct aoedev *)vp; 43 if (d->flags & DEVFL_TKILL) 44 return; 45 d->timer.expires = jiffies + HZ; 46 add_timer(&d->timer); 47 } 48 49 void 50 aoedev_downdev(struct aoedev *d) 51 { 52 struct aoetgt **t, **te; 53 struct frame *f, *e; 54 struct buf *buf; 55 struct bio *bio; 56 57 t = d->targets; 58 te = t + NTARGETS; 59 for (; t < te && *t; t++) { 60 f = (*t)->frames; 61 e = f + (*t)->nframes; 62 for (; f < e; f->tag = FREETAG, f->buf = NULL, f++) { 63 if (f->tag == FREETAG || f->buf == NULL) 64 continue; 65 buf = f->buf; 66 bio = buf->bio; 67 if (--buf->nframesout == 0 68 && buf != d->inprocess) { 69 mempool_free(buf, d->bufpool); 70 bio_endio(bio, -EIO); 71 } 72 } 73 (*t)->maxout = (*t)->nframes; 74 (*t)->nout = 0; 75 } 76 buf = d->inprocess; 77 if (buf) { 78 bio = buf->bio; 79 mempool_free(buf, d->bufpool); 80 bio_endio(bio, -EIO); 81 } 82 d->inprocess = NULL; 83 d->htgt = NULL; 84 85 while (!list_empty(&d->bufq)) { 86 buf = container_of(d->bufq.next, struct buf, bufs); 87 list_del(d->bufq.next); 88 bio = buf->bio; 89 mempool_free(buf, d->bufpool); 90 bio_endio(bio, -EIO); 91 } 92 93 if (d->gd) 94 set_capacity(d->gd, 0); 95 96 d->flags &= ~DEVFL_UP; 97 } 98 99 static void 100 aoedev_freedev(struct aoedev *d) 101 { 102 struct aoetgt **t, **e; 103 104 if (d->gd) { 105 aoedisk_rm_sysfs(d); 106 del_gendisk(d->gd); 107 put_disk(d->gd); 108 } 109 t = d->targets; 110 e = t + NTARGETS; 111 for (; t < e && *t; t++) 112 freetgt(d, *t); 113 if (d->bufpool) 114 mempool_destroy(d->bufpool); 115 skbpoolfree(d); 116 blk_cleanup_queue(d->blkq); 117 kfree(d); 118 } 119 120 int 121 aoedev_flush(const char __user *str, size_t cnt) 122 { 123 ulong flags; 124 struct aoedev *d, **dd; 125 struct aoedev *rmd = NULL; 126 char buf[16]; 127 int all = 0; 128 129 if (cnt >= 3) { 130 if (cnt > sizeof buf) 131 cnt = sizeof buf; 132 if (copy_from_user(buf, str, cnt)) 133 return -EFAULT; 134 all = !strncmp(buf, "all", 3); 135 } 136 137 flush_scheduled_work(); 138 spin_lock_irqsave(&devlist_lock, flags); 139 dd = &devlist; 140 while ((d = *dd)) { 141 spin_lock(&d->lock); 142 if ((!all && (d->flags & DEVFL_UP)) 143 || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) 144 || d->nopen) { 145 spin_unlock(&d->lock); 146 dd = &d->next; 147 continue; 148 } 149 *dd = d->next; 150 aoedev_downdev(d); 151 d->flags |= DEVFL_TKILL; 152 spin_unlock(&d->lock); 153 d->next = rmd; 154 rmd = d; 155 } 156 spin_unlock_irqrestore(&devlist_lock, flags); 157 while ((d = rmd)) { 158 rmd = d->next; 159 del_timer_sync(&d->timer); 160 aoedev_freedev(d); /* must be able to sleep */ 161 } 162 return 0; 163 } 164 165 /* I'm not really sure that this is a realistic problem, but if the 166 network driver goes gonzo let's just leak memory after complaining. */ 167 static void 168 skbfree(struct sk_buff *skb) 169 { 170 enum { Sms = 100, Tms = 3*1000}; 171 int i = Tms / Sms; 172 173 if (skb == NULL) 174 return; 175 while (atomic_read(&skb_shinfo(skb)->dataref) != 1 && i-- > 0) 176 msleep(Sms); 177 if (i < 0) { 178 printk(KERN_ERR 179 "aoe: %s holds ref: %s\n", 180 skb->dev ? skb->dev->name : "netif", 181 "cannot free skb -- memory leaked."); 182 return; 183 } 184 skb_shinfo(skb)->nr_frags = skb->data_len = 0; 185 skb_trim(skb, 0); 186 dev_kfree_skb(skb); 187 } 188 189 static void 190 skbpoolfree(struct aoedev *d) 191 { 192 struct sk_buff *skb, *tmp; 193 194 skb_queue_walk_safe(&d->skbpool, skb, tmp) 195 skbfree(skb); 196 197 __skb_queue_head_init(&d->skbpool); 198 } 199 200 /* find it or malloc it */ 201 struct aoedev * 202 aoedev_by_sysminor_m(ulong sysminor) 203 { 204 struct aoedev *d; 205 ulong flags; 206 207 spin_lock_irqsave(&devlist_lock, flags); 208 209 for (d=devlist; d; d=d->next) 210 if (d->sysminor == sysminor) 211 break; 212 if (d) 213 goto out; 214 d = kcalloc(1, sizeof *d, GFP_ATOMIC); 215 if (!d) 216 goto out; 217 INIT_WORK(&d->work, aoecmd_sleepwork); 218 spin_lock_init(&d->lock); 219 skb_queue_head_init(&d->sendq); 220 skb_queue_head_init(&d->skbpool); 221 init_timer(&d->timer); 222 d->timer.data = (ulong) d; 223 d->timer.function = dummy_timer; 224 d->timer.expires = jiffies + HZ; 225 add_timer(&d->timer); 226 d->bufpool = NULL; /* defer to aoeblk_gdalloc */ 227 d->tgt = d->targets; 228 INIT_LIST_HEAD(&d->bufq); 229 d->sysminor = sysminor; 230 d->aoemajor = AOEMAJOR(sysminor); 231 d->aoeminor = AOEMINOR(sysminor); 232 d->mintimer = MINTIMER; 233 d->next = devlist; 234 devlist = d; 235 out: 236 spin_unlock_irqrestore(&devlist_lock, flags); 237 return d; 238 } 239 240 static void 241 freetgt(struct aoedev *d, struct aoetgt *t) 242 { 243 struct frame *f, *e; 244 245 f = t->frames; 246 e = f + t->nframes; 247 for (; f < e; f++) 248 skbfree(f->skb); 249 kfree(t->frames); 250 kfree(t); 251 } 252 253 void 254 aoedev_exit(void) 255 { 256 struct aoedev *d; 257 ulong flags; 258 259 flush_scheduled_work(); 260 261 while ((d = devlist)) { 262 devlist = d->next; 263 264 spin_lock_irqsave(&d->lock, flags); 265 aoedev_downdev(d); 266 d->flags |= DEVFL_TKILL; 267 spin_unlock_irqrestore(&d->lock, flags); 268 269 del_timer_sync(&d->timer); 270 aoedev_freedev(d); 271 } 272 } 273 274 int __init 275 aoedev_init(void) 276 { 277 return 0; 278 } 279