buffers.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. * RelayFS buffer management code.
  3. *
  4. * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
  5. * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com)
  6. *
  7. * This file is released under the GPL.
  8. */
  9. #include <linux/module.h>
  10. #include <linux/vmalloc.h>
  11. #include <linux/mm.h>
  12. #include <linux/relayfs_fs.h>
  13. #include "relay.h"
  14. #include "buffers.h"
  15. /*
  16. * close() vm_op implementation for relayfs file mapping.
  17. */
  18. static void relay_file_mmap_close(struct vm_area_struct *vma)
  19. {
  20. struct rchan_buf *buf = vma->vm_private_data;
  21. buf->chan->cb->buf_unmapped(buf, vma->vm_file);
  22. }
  23. /*
  24. * nopage() vm_op implementation for relayfs file mapping.
  25. */
  26. static struct page *relay_buf_nopage(struct vm_area_struct *vma,
  27. unsigned long address,
  28. int *type)
  29. {
  30. struct page *page;
  31. struct rchan_buf *buf = vma->vm_private_data;
  32. unsigned long offset = address - vma->vm_start;
  33. if (address > vma->vm_end)
  34. return NOPAGE_SIGBUS; /* Disallow mremap */
  35. if (!buf)
  36. return NOPAGE_OOM;
  37. page = vmalloc_to_page(buf->start + offset);
  38. if (!page)
  39. return NOPAGE_OOM;
  40. get_page(page);
  41. if (type)
  42. *type = VM_FAULT_MINOR;
  43. return page;
  44. }
  45. /*
  46. * vm_ops for relay file mappings.
  47. */
  48. static struct vm_operations_struct relay_file_mmap_ops = {
  49. .nopage = relay_buf_nopage,
  50. .close = relay_file_mmap_close,
  51. };
  52. /**
  53. * relay_mmap_buf: - mmap channel buffer to process address space
  54. * @buf: relay channel buffer
  55. * @vma: vm_area_struct describing memory to be mapped
  56. *
  57. * Returns 0 if ok, negative on error
  58. *
  59. * Caller should already have grabbed mmap_sem.
  60. */
  61. int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
  62. {
  63. unsigned long length = vma->vm_end - vma->vm_start;
  64. struct file *filp = vma->vm_file;
  65. if (!buf)
  66. return -EBADF;
  67. if (length != (unsigned long)buf->chan->alloc_size)
  68. return -EINVAL;
  69. vma->vm_ops = &relay_file_mmap_ops;
  70. vma->vm_private_data = buf;
  71. buf->chan->cb->buf_mapped(buf, filp);
  72. return 0;
  73. }
  74. /**
  75. * relay_alloc_buf - allocate a channel buffer
  76. * @buf: the buffer struct
  77. * @size: total size of the buffer
  78. *
  79. * Returns a pointer to the resulting buffer, NULL if unsuccessful
  80. */
  81. static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size)
  82. {
  83. void *mem;
  84. unsigned int i, j, n_pages;
  85. size = PAGE_ALIGN(size);
  86. n_pages = size >> PAGE_SHIFT;
  87. buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL);
  88. if (!buf->page_array)
  89. return NULL;
  90. for (i = 0; i < n_pages; i++) {
  91. buf->page_array[i] = alloc_page(GFP_KERNEL);
  92. if (unlikely(!buf->page_array[i]))
  93. goto depopulate;
  94. }
  95. mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL);
  96. if (!mem)
  97. goto depopulate;
  98. memset(mem, 0, size);
  99. buf->page_count = n_pages;
  100. return mem;
  101. depopulate:
  102. for (j = 0; j < i; j++)
  103. __free_page(buf->page_array[j]);
  104. kfree(buf->page_array);
  105. return NULL;
  106. }
  107. /**
  108. * relay_create_buf - allocate and initialize a channel buffer
  109. * @alloc_size: size of the buffer to allocate
  110. * @n_subbufs: number of sub-buffers in the channel
  111. *
  112. * Returns channel buffer if successful, NULL otherwise
  113. */
  114. struct rchan_buf *relay_create_buf(struct rchan *chan)
  115. {
  116. struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL);
  117. if (!buf)
  118. return NULL;
  119. buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL);
  120. if (!buf->padding)
  121. goto free_buf;
  122. buf->start = relay_alloc_buf(buf, chan->alloc_size);
  123. if (!buf->start)
  124. goto free_buf;
  125. buf->chan = chan;
  126. kref_get(&buf->chan->kref);
  127. return buf;
  128. free_buf:
  129. kfree(buf->padding);
  130. kfree(buf);
  131. return NULL;
  132. }
  133. /**
  134. * relay_destroy_buf - destroy an rchan_buf struct and associated buffer
  135. * @buf: the buffer struct
  136. */
  137. void relay_destroy_buf(struct rchan_buf *buf)
  138. {
  139. struct rchan *chan = buf->chan;
  140. unsigned int i;
  141. if (likely(buf->start)) {
  142. vunmap(buf->start);
  143. for (i = 0; i < buf->page_count; i++)
  144. __free_page(buf->page_array[i]);
  145. kfree(buf->page_array);
  146. }
  147. kfree(buf->padding);
  148. kfree(buf);
  149. kref_put(&chan->kref, relay_destroy_channel);
  150. }
  151. /**
  152. * relay_remove_buf - remove a channel buffer
  153. *
  154. * Removes the file from the relayfs fileystem, which also frees the
  155. * rchan_buf_struct and the channel buffer. Should only be called from
  156. * kref_put().
  157. */
  158. void relay_remove_buf(struct kref *kref)
  159. {
  160. struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref);
  161. buf->chan->cb->remove_buf_file(buf->dentry);
  162. relay_destroy_buf(buf);
  163. }