iobuf.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:4k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * iobuf.c
  3.  *
  4.  * Keep track of the general-purpose IO-buffer structures used to track
  5.  * abstract kernel-space io buffers.
  6.  * 
  7.  */
  8. #include <linux/iobuf.h>
  9. #include <linux/slab.h>
  10. #include <linux/vmalloc.h>
  11. static kmem_cache_t *kiobuf_cachep;
  12. void end_kio_request(struct kiobuf *kiobuf, int uptodate)
  13. {
  14. if ((!uptodate) && !kiobuf->errno)
  15. kiobuf->errno = -EIO;
  16. if (atomic_dec_and_test(&kiobuf->io_count)) {
  17. if (kiobuf->end_io)
  18. kiobuf->end_io(kiobuf);
  19. wake_up(&kiobuf->wait_queue);
  20. }
  21. }
  22. static int kiobuf_init(struct kiobuf *iobuf)
  23. {
  24. init_waitqueue_head(&iobuf->wait_queue);
  25. iobuf->array_len = 0;
  26. iobuf->nr_pages = 0;
  27. iobuf->locked = 0;
  28. iobuf->bh = NULL;
  29. iobuf->blocks = NULL;
  30. atomic_set(&iobuf->io_count, 0);
  31. iobuf->end_io = NULL;
  32. return expand_kiobuf(iobuf, KIO_STATIC_PAGES);
  33. }
  34. int alloc_kiobuf_bhs(struct kiobuf * kiobuf)
  35. {
  36. int i;
  37. kiobuf->blocks =
  38. kmalloc(sizeof(*kiobuf->blocks) * KIO_MAX_SECTORS, GFP_KERNEL);
  39. if (unlikely(!kiobuf->blocks))
  40. goto nomem;
  41. kiobuf->bh =
  42. kmalloc(sizeof(*kiobuf->bh) * KIO_MAX_SECTORS, GFP_KERNEL);
  43. if (unlikely(!kiobuf->bh))
  44. goto nomem;
  45. for (i = 0; i < KIO_MAX_SECTORS; i++) {
  46. kiobuf->bh[i] = kmem_cache_alloc(bh_cachep, GFP_KERNEL);
  47. if (unlikely(!kiobuf->bh[i]))
  48. goto nomem2;
  49. }
  50. return 0;
  51. nomem2:
  52. while (i--) {
  53. kmem_cache_free(bh_cachep, kiobuf->bh[i]);
  54. kiobuf->bh[i] = NULL;
  55. }
  56. memset(kiobuf->bh, 0, sizeof(*kiobuf->bh) * KIO_MAX_SECTORS);
  57. nomem:
  58. free_kiobuf_bhs(kiobuf);
  59. return -ENOMEM;
  60. }
  61. void free_kiobuf_bhs(struct kiobuf * kiobuf)
  62. {
  63. int i;
  64. if (kiobuf->bh) {
  65. for (i = 0; i < KIO_MAX_SECTORS; i++)
  66. if (kiobuf->bh[i])
  67. kmem_cache_free(bh_cachep, kiobuf->bh[i]);
  68. kfree(kiobuf->bh);
  69. kiobuf->bh = NULL;
  70. }
  71. if (kiobuf->blocks) {
  72. kfree(kiobuf->blocks);
  73. kiobuf->blocks = NULL;
  74. }
  75. }
  76. int alloc_kiovec(int nr, struct kiobuf **bufp)
  77. {
  78. int i;
  79. struct kiobuf *iobuf;
  80. for (i = 0; i < nr; i++) {
  81. iobuf = kmem_cache_alloc(kiobuf_cachep, GFP_KERNEL);
  82. if (unlikely(!iobuf))
  83. goto nomem;
  84. if (unlikely(kiobuf_init(iobuf)))
  85. goto nomem2;
  86.   if (unlikely(alloc_kiobuf_bhs(iobuf)))
  87. goto nomem2;
  88. bufp[i] = iobuf;
  89. }
  90. return 0;
  91. nomem2:
  92. kmem_cache_free(kiobuf_cachep, iobuf);
  93. nomem:
  94. free_kiovec(i, bufp);
  95. return -ENOMEM;
  96. }
  97. void free_kiovec(int nr, struct kiobuf **bufp) 
  98. {
  99. int i;
  100. struct kiobuf *iobuf;
  101. for (i = 0; i < nr; i++) {
  102. iobuf = bufp[i];
  103. if (iobuf->locked)
  104. unlock_kiovec(1, &iobuf);
  105. kfree(iobuf->maplist);
  106. free_kiobuf_bhs(iobuf);
  107. kmem_cache_free(kiobuf_cachep, bufp[i]);
  108. }
  109. }
  110. int expand_kiobuf(struct kiobuf *iobuf, int wanted)
  111. {
  112. struct page ** maplist;
  113. if (iobuf->array_len >= wanted)
  114. return 0;
  115. maplist = kmalloc(wanted * sizeof(struct page **), GFP_KERNEL);
  116. if (unlikely(!maplist))
  117. return -ENOMEM;
  118. /* Did it grow while we waited? */
  119. if (unlikely(iobuf->array_len >= wanted)) {
  120. kfree(maplist);
  121. return 0;
  122. }
  123. if (iobuf->array_len) {
  124. memcpy(maplist, iobuf->maplist, iobuf->array_len * sizeof(*maplist));
  125. kfree(iobuf->maplist);
  126. }
  127. iobuf->maplist   = maplist;
  128. iobuf->array_len = wanted;
  129. return 0;
  130. }
  131. void kiobuf_wait_for_io(struct kiobuf *kiobuf)
  132. {
  133. struct task_struct *tsk = current;
  134. DECLARE_WAITQUEUE(wait, tsk);
  135. if (atomic_read(&kiobuf->io_count) == 0)
  136. return;
  137. add_wait_queue(&kiobuf->wait_queue, &wait);
  138. repeat:
  139. set_task_state(tsk, TASK_UNINTERRUPTIBLE);
  140. if (atomic_read(&kiobuf->io_count) != 0) {
  141. run_task_queue(&tq_disk);
  142. schedule();
  143. if (atomic_read(&kiobuf->io_count) != 0)
  144. goto repeat;
  145. }
  146. tsk->state = TASK_RUNNING;
  147. remove_wait_queue(&kiobuf->wait_queue, &wait);
  148. }
  149. void __init iobuf_cache_init(void)
  150. {
  151. kiobuf_cachep = kmem_cache_create("kiobuf", sizeof(struct kiobuf),
  152.   0, SLAB_HWCACHE_ALIGN, NULL, NULL);
  153. if (!kiobuf_cachep)
  154. panic("Cannot create kiobuf SLAB cache");
  155. }