aoedev.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* Copyright (c) 2004 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 struct aoedev *devlist;
  11. static spinlock_t devlist_lock;
  12. int
  13. aoedev_isbusy(struct aoedev *d)
  14. {
  15. struct frame *f, *e;
  16. f = d->frames;
  17. e = f + d->nframes;
  18. do {
  19. if (f->tag != FREETAG) {
  20. printk(KERN_DEBUG "aoe: %ld.%ld isbusy\n",
  21. d->aoemajor, d->aoeminor);
  22. return 1;
  23. }
  24. } while (++f < e);
  25. return 0;
  26. }
  27. struct aoedev *
  28. aoedev_by_aoeaddr(int maj, int min)
  29. {
  30. struct aoedev *d;
  31. ulong flags;
  32. spin_lock_irqsave(&devlist_lock, flags);
  33. for (d=devlist; d; d=d->next)
  34. if (d->aoemajor == maj && d->aoeminor == min)
  35. break;
  36. spin_unlock_irqrestore(&devlist_lock, flags);
  37. return d;
  38. }
  39. static void
  40. dummy_timer(ulong vp)
  41. {
  42. struct aoedev *d;
  43. d = (struct aoedev *)vp;
  44. if (d->flags & DEVFL_TKILL)
  45. return;
  46. d->timer.expires = jiffies + HZ;
  47. add_timer(&d->timer);
  48. }
  49. /* called with devlist lock held */
  50. static struct aoedev *
  51. aoedev_newdev(ulong nframes)
  52. {
  53. struct aoedev *d;
  54. struct frame *f, *e;
  55. d = kzalloc(sizeof *d, GFP_ATOMIC);
  56. if (d == NULL)
  57. return NULL;
  58. f = kcalloc(nframes, sizeof *f, GFP_ATOMIC);
  59. if (f == NULL) {
  60. kfree(d);
  61. return NULL;
  62. }
  63. INIT_WORK(&d->work, aoecmd_sleepwork, d);
  64. d->nframes = nframes;
  65. d->frames = f;
  66. e = f + nframes;
  67. for (; f<e; f++)
  68. f->tag = FREETAG;
  69. spin_lock_init(&d->lock);
  70. init_timer(&d->timer);
  71. d->timer.data = (ulong) d;
  72. d->timer.function = dummy_timer;
  73. d->timer.expires = jiffies + HZ;
  74. add_timer(&d->timer);
  75. d->bufpool = NULL; /* defer to aoeblk_gdalloc */
  76. INIT_LIST_HEAD(&d->bufq);
  77. d->next = devlist;
  78. devlist = d;
  79. return d;
  80. }
  81. void
  82. aoedev_downdev(struct aoedev *d)
  83. {
  84. struct frame *f, *e;
  85. struct buf *buf;
  86. struct bio *bio;
  87. f = d->frames;
  88. e = f + d->nframes;
  89. for (; f<e; f->tag = FREETAG, f->buf = NULL, f++) {
  90. if (f->tag == FREETAG || f->buf == NULL)
  91. continue;
  92. buf = f->buf;
  93. bio = buf->bio;
  94. if (--buf->nframesout == 0) {
  95. mempool_free(buf, d->bufpool);
  96. bio_endio(bio, bio->bi_size, -EIO);
  97. }
  98. }
  99. d->inprocess = NULL;
  100. while (!list_empty(&d->bufq)) {
  101. buf = container_of(d->bufq.next, struct buf, bufs);
  102. list_del(d->bufq.next);
  103. bio = buf->bio;
  104. mempool_free(buf, d->bufpool);
  105. bio_endio(bio, bio->bi_size, -EIO);
  106. }
  107. if (d->gd)
  108. d->gd->capacity = 0;
  109. d->flags &= ~(DEVFL_UP | DEVFL_PAUSE);
  110. }
  111. /* find it or malloc it */
  112. struct aoedev *
  113. aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt)
  114. {
  115. struct aoedev *d;
  116. ulong flags;
  117. spin_lock_irqsave(&devlist_lock, flags);
  118. for (d=devlist; d; d=d->next)
  119. if (d->sysminor == sysminor)
  120. break;
  121. if (d == NULL) {
  122. d = aoedev_newdev(bufcnt);
  123. if (d == NULL) {
  124. spin_unlock_irqrestore(&devlist_lock, flags);
  125. printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n");
  126. return NULL;
  127. }
  128. d->sysminor = sysminor;
  129. d->aoemajor = AOEMAJOR(sysminor);
  130. d->aoeminor = AOEMINOR(sysminor);
  131. }
  132. spin_unlock_irqrestore(&devlist_lock, flags);
  133. return d;
  134. }
  135. static void
  136. aoedev_freedev(struct aoedev *d)
  137. {
  138. if (d->gd) {
  139. aoedisk_rm_sysfs(d);
  140. del_gendisk(d->gd);
  141. put_disk(d->gd);
  142. }
  143. kfree(d->frames);
  144. if (d->bufpool)
  145. mempool_destroy(d->bufpool);
  146. kfree(d);
  147. }
  148. void
  149. aoedev_exit(void)
  150. {
  151. struct aoedev *d;
  152. ulong flags;
  153. flush_scheduled_work();
  154. while ((d = devlist)) {
  155. devlist = d->next;
  156. spin_lock_irqsave(&d->lock, flags);
  157. aoedev_downdev(d);
  158. d->flags |= DEVFL_TKILL;
  159. spin_unlock_irqrestore(&d->lock, flags);
  160. del_timer_sync(&d->timer);
  161. aoedev_freedev(d);
  162. }
  163. }
  164. int __init
  165. aoedev_init(void)
  166. {
  167. spin_lock_init(&devlist_lock);
  168. return 0;
  169. }