iobuf.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:3k
源码类别:

嵌入式Linux

开发平台:

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. void end_kio_request(struct kiobuf *kiobuf, int uptodate)
  12. {
  13. if ((!uptodate) && !kiobuf->errno)
  14. kiobuf->errno = -EIO;
  15. if (atomic_dec_and_test(&kiobuf->io_count)) {
  16. if (kiobuf->end_io)
  17. kiobuf->end_io(kiobuf);
  18. wake_up(&kiobuf->wait_queue);
  19. }
  20. }
  21. static void kiobuf_init(struct kiobuf *iobuf)
  22. {
  23. memset(iobuf, 0, sizeof(*iobuf));
  24. init_waitqueue_head(&iobuf->wait_queue);
  25. iobuf->array_len = KIO_STATIC_PAGES;
  26. iobuf->maplist   = iobuf->map_array;
  27. }
  28. int alloc_kiobuf_bhs(struct kiobuf * kiobuf)
  29. {
  30. int i;
  31. for (i = 0; i < KIO_MAX_SECTORS; i++)
  32. if (!(kiobuf->bh[i] = kmem_cache_alloc(bh_cachep, SLAB_KERNEL))) {
  33. while (i--) {
  34. kmem_cache_free(bh_cachep, kiobuf->bh[i]);
  35. kiobuf->bh[i] = NULL;
  36. }
  37. return -ENOMEM;
  38. }
  39. return 0;
  40. }
  41. void free_kiobuf_bhs(struct kiobuf * kiobuf)
  42. {
  43. int i;
  44. for (i = 0; i < KIO_MAX_SECTORS; i++) {
  45. kmem_cache_free(bh_cachep, kiobuf->bh[i]);
  46. kiobuf->bh[i] = NULL;
  47. }
  48. }
  49. int alloc_kiovec(int nr, struct kiobuf **bufp)
  50. {
  51. int i;
  52. struct kiobuf *iobuf;
  53. for (i = 0; i < nr; i++) {
  54. iobuf = vmalloc(sizeof(struct kiobuf));
  55. if (!iobuf) {
  56. free_kiovec(i, bufp);
  57. return -ENOMEM;
  58. }
  59. kiobuf_init(iobuf);
  60.   if (alloc_kiobuf_bhs(iobuf)) {
  61. vfree(iobuf);
  62.   free_kiovec(i, bufp);
  63.   return -ENOMEM;
  64.   }
  65. bufp[i] = iobuf;
  66. }
  67. return 0;
  68. }
  69. void free_kiovec(int nr, struct kiobuf **bufp) 
  70. {
  71. int i;
  72. struct kiobuf *iobuf;
  73. for (i = 0; i < nr; i++) {
  74. iobuf = bufp[i];
  75. if (iobuf->locked)
  76. unlock_kiovec(1, &iobuf);
  77. if (iobuf->array_len > KIO_STATIC_PAGES)
  78. kfree (iobuf->maplist);
  79. free_kiobuf_bhs(iobuf);
  80. vfree(bufp[i]);
  81. }
  82. }
  83. int expand_kiobuf(struct kiobuf *iobuf, int wanted)
  84. {
  85. struct page ** maplist;
  86. if (iobuf->array_len >= wanted)
  87. return 0;
  88. maplist = (struct page **) 
  89. kmalloc(wanted * sizeof(struct page **), GFP_KERNEL);
  90. if (!maplist)
  91. return -ENOMEM;
  92. /* Did it grow while we waited? */
  93. if (iobuf->array_len >= wanted) {
  94. kfree(maplist);
  95. return 0;
  96. }
  97. memcpy (maplist, iobuf->maplist, iobuf->array_len * sizeof(struct page **));
  98. if (iobuf->array_len > KIO_STATIC_PAGES)
  99. kfree (iobuf->maplist);
  100. iobuf->maplist   = maplist;
  101. iobuf->array_len = wanted;
  102. return 0;
  103. }
  104. void kiobuf_wait_for_io(struct kiobuf *kiobuf)
  105. {
  106. struct task_struct *tsk = current;
  107. DECLARE_WAITQUEUE(wait, tsk);
  108. if (atomic_read(&kiobuf->io_count) == 0)
  109. return;
  110. add_wait_queue(&kiobuf->wait_queue, &wait);
  111. repeat:
  112. set_task_state(tsk, TASK_UNINTERRUPTIBLE);
  113. if (atomic_read(&kiobuf->io_count) != 0) {
  114. run_task_queue(&tq_disk);
  115. schedule();
  116. if (atomic_read(&kiobuf->io_count) != 0)
  117. goto repeat;
  118. }
  119. tsk->state = TASK_RUNNING;
  120. remove_wait_queue(&kiobuf->wait_queue, &wait);
  121. }