aoedev.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */
  2. /*
  3. * aoedev.c
  4. * AoE device utility functions; maintains device list.
  5. */
  6. #include <linux/hdreg.h>
  7. #include <linux/blkdev.h>
  8. #include <linux/netdevice.h>
  9. #include "aoe.h"
  10. static void dummy_timer(ulong);
  11. static void aoedev_freedev(struct aoedev *);
  12. static void freetgt(struct aoetgt *t);
  13. static struct aoedev *devlist;
  14. static spinlock_t devlist_lock;
  15. int
  16. aoedev_isbusy(struct aoedev *d)
  17. {
  18. struct aoetgt **t, **te;
  19. struct frame *f, *e;
  20. t = d->targets;
  21. te = t + NTARGETS;
  22. for (; t < te && *t; t++) {
  23. f = (*t)->frames;
  24. e = f + (*t)->nframes;
  25. for (; f < e; f++)
  26. if (f->tag != FREETAG)
  27. return 1;
  28. }
  29. return 0;
  30. }
  31. struct aoedev *
  32. aoedev_by_aoeaddr(int maj, int min)
  33. {
  34. struct aoedev *d;
  35. ulong flags;
  36. spin_lock_irqsave(&devlist_lock, flags);
  37. for (d=devlist; d; d=d->next)
  38. if (d->aoemajor == maj && d->aoeminor == min)
  39. break;
  40. spin_unlock_irqrestore(&devlist_lock, flags);
  41. return d;
  42. }
  43. static void
  44. dummy_timer(ulong vp)
  45. {
  46. struct aoedev *d;
  47. d = (struct aoedev *)vp;
  48. if (d->flags & DEVFL_TKILL)
  49. return;
  50. d->timer.expires = jiffies + HZ;
  51. add_timer(&d->timer);
  52. }
  53. void
  54. aoedev_downdev(struct aoedev *d)
  55. {
  56. struct aoetgt **t, **te;
  57. struct frame *f, *e;
  58. struct buf *buf;
  59. struct bio *bio;
  60. t = d->targets;
  61. te = t + NTARGETS;
  62. for (; t < te && *t; t++) {
  63. f = (*t)->frames;
  64. e = f + (*t)->nframes;
  65. for (; f < e; f->tag = FREETAG, f->buf = NULL, f++) {
  66. if (f->tag == FREETAG || f->buf == NULL)
  67. continue;
  68. buf = f->buf;
  69. bio = buf->bio;
  70. if (--buf->nframesout == 0
  71. && buf != d->inprocess) {
  72. mempool_free(buf, d->bufpool);
  73. bio_endio(bio, -EIO);
  74. }
  75. }
  76. (*t)->maxout = (*t)->nframes;
  77. (*t)->nout = 0;
  78. }
  79. buf = d->inprocess;
  80. if (buf) {
  81. bio = buf->bio;
  82. mempool_free(buf, d->bufpool);
  83. bio_endio(bio, -EIO);
  84. }
  85. d->inprocess = NULL;
  86. d->htgt = NULL;
  87. while (!list_empty(&d->bufq)) {
  88. buf = container_of(d->bufq.next, struct buf, bufs);
  89. list_del(d->bufq.next);
  90. bio = buf->bio;
  91. mempool_free(buf, d->bufpool);
  92. bio_endio(bio, -EIO);
  93. }
  94. if (d->gd)
  95. d->gd->capacity = 0;
  96. d->flags &= ~DEVFL_UP;
  97. }
  98. static void
  99. aoedev_freedev(struct aoedev *d)
  100. {
  101. struct aoetgt **t, **e;
  102. if (d->gd) {
  103. aoedisk_rm_sysfs(d);
  104. del_gendisk(d->gd);
  105. put_disk(d->gd);
  106. }
  107. t = d->targets;
  108. e = t + NTARGETS;
  109. for (; t < e && *t; t++)
  110. freetgt(*t);
  111. if (d->bufpool)
  112. mempool_destroy(d->bufpool);
  113. kfree(d);
  114. }
  115. int
  116. aoedev_flush(const char __user *str, size_t cnt)
  117. {
  118. ulong flags;
  119. struct aoedev *d, **dd;
  120. struct aoedev *rmd = NULL;
  121. char buf[16];
  122. int all = 0;
  123. if (cnt >= 3) {
  124. if (cnt > sizeof buf)
  125. cnt = sizeof buf;
  126. if (copy_from_user(buf, str, cnt))
  127. return -EFAULT;
  128. all = !strncmp(buf, "all", 3);
  129. }
  130. flush_scheduled_work();
  131. spin_lock_irqsave(&devlist_lock, flags);
  132. dd = &devlist;
  133. while ((d = *dd)) {
  134. spin_lock(&d->lock);
  135. if ((!all && (d->flags & DEVFL_UP))
  136. || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
  137. || d->nopen) {
  138. spin_unlock(&d->lock);
  139. dd = &d->next;
  140. continue;
  141. }
  142. *dd = d->next;
  143. aoedev_downdev(d);
  144. d->flags |= DEVFL_TKILL;
  145. spin_unlock(&d->lock);
  146. d->next = rmd;
  147. rmd = d;
  148. }
  149. spin_unlock_irqrestore(&devlist_lock, flags);
  150. while ((d = rmd)) {
  151. rmd = d->next;
  152. del_timer_sync(&d->timer);
  153. aoedev_freedev(d); /* must be able to sleep */
  154. }
  155. return 0;
  156. }
  157. /* find it or malloc it */
  158. struct aoedev *
  159. aoedev_by_sysminor_m(ulong sysminor)
  160. {
  161. struct aoedev *d;
  162. ulong flags;
  163. spin_lock_irqsave(&devlist_lock, flags);
  164. for (d=devlist; d; d=d->next)
  165. if (d->sysminor == sysminor)
  166. break;
  167. if (d)
  168. goto out;
  169. d = kcalloc(1, sizeof *d, GFP_ATOMIC);
  170. if (!d)
  171. goto out;
  172. INIT_WORK(&d->work, aoecmd_sleepwork);
  173. spin_lock_init(&d->lock);
  174. init_timer(&d->timer);
  175. d->timer.data = (ulong) d;
  176. d->timer.function = dummy_timer;
  177. d->timer.expires = jiffies + HZ;
  178. add_timer(&d->timer);
  179. d->bufpool = NULL; /* defer to aoeblk_gdalloc */
  180. d->tgt = d->targets;
  181. INIT_LIST_HEAD(&d->bufq);
  182. d->sysminor = sysminor;
  183. d->aoemajor = AOEMAJOR(sysminor);
  184. d->aoeminor = AOEMINOR(sysminor);
  185. d->mintimer = MINTIMER;
  186. d->next = devlist;
  187. devlist = d;
  188. out:
  189. spin_unlock_irqrestore(&devlist_lock, flags);
  190. return d;
  191. }
  192. static void
  193. freetgt(struct aoetgt *t)
  194. {
  195. struct frame *f, *e;
  196. f = t->frames;
  197. e = f + t->nframes;
  198. for (; f < e; f++) {
  199. skb_shinfo(f->skb)->nr_frags = 0;
  200. dev_kfree_skb(f->skb);
  201. }
  202. kfree(t->frames);
  203. kfree(t);
  204. }
  205. void
  206. aoedev_exit(void)
  207. {
  208. struct aoedev *d;
  209. ulong flags;
  210. flush_scheduled_work();
  211. while ((d = devlist)) {
  212. devlist = d->next;
  213. spin_lock_irqsave(&d->lock, flags);
  214. aoedev_downdev(d);
  215. d->flags |= DEVFL_TKILL;
  216. spin_unlock_irqrestore(&d->lock, flags);
  217. del_timer_sync(&d->timer);
  218. aoedev_freedev(d);
  219. }
  220. }
  221. int __init
  222. aoedev_init(void)
  223. {
  224. spin_lock_init(&devlist_lock);
  225. return 0;
  226. }