file.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * linux/fs/file.c
  3. *
  4. * Copyright (C) 1998-1999, Stephen Tweedie and Bill Hawes
  5. *
  6. * Manage the dynamic fd arrays in the process files_struct.
  7. */
  8. #include <linux/fs.h>
  9. #include <linux/mm.h>
  10. #include <linux/time.h>
  11. #include <linux/slab.h>
  12. #include <linux/vmalloc.h>
  13. #include <linux/file.h>
  14. #include <linux/bitops.h>
  15. /*
  16. * Allocate an fd array, using kmalloc or vmalloc.
  17. * Note: the array isn't cleared at allocation time.
  18. */
  19. struct file ** alloc_fd_array(int num)
  20. {
  21. struct file **new_fds;
  22. int size = num * sizeof(struct file *);
  23. if (size <= PAGE_SIZE)
  24. new_fds = (struct file **) kmalloc(size, GFP_KERNEL);
  25. else
  26. new_fds = (struct file **) vmalloc(size);
  27. return new_fds;
  28. }
  29. void free_fd_array(struct file **array, int num)
  30. {
  31. int size = num * sizeof(struct file *);
  32. if (!array) {
  33. printk (KERN_ERR "free_fd_array: array = 0 (num = %d)\n", num);
  34. return;
  35. }
  36. if (num <= NR_OPEN_DEFAULT) /* Don't free the embedded fd array! */
  37. return;
  38. else if (size <= PAGE_SIZE)
  39. kfree(array);
  40. else
  41. vfree(array);
  42. }
  43. /*
  44. * Expand the fd array in the files_struct. Called with the files
  45. * spinlock held for write.
  46. */
  47. static int expand_fd_array(struct files_struct *files, int nr)
  48. __releases(files->file_lock)
  49. __acquires(files->file_lock)
  50. {
  51. struct file **new_fds;
  52. int error, nfds;
  53. error = -EMFILE;
  54. if (files->max_fds >= NR_OPEN || nr >= NR_OPEN)
  55. goto out;
  56. nfds = files->max_fds;
  57. spin_unlock(&files->file_lock);
  58. /*
  59. * Expand to the max in easy steps, and keep expanding it until
  60. * we have enough for the requested fd array size.
  61. */
  62. do {
  63. #if NR_OPEN_DEFAULT < 256
  64. if (nfds < 256)
  65. nfds = 256;
  66. else
  67. #endif
  68. if (nfds < (PAGE_SIZE / sizeof(struct file *)))
  69. nfds = PAGE_SIZE / sizeof(struct file *);
  70. else {
  71. nfds = nfds * 2;
  72. if (nfds > NR_OPEN)
  73. nfds = NR_OPEN;
  74. }
  75. } while (nfds <= nr);
  76. error = -ENOMEM;
  77. new_fds = alloc_fd_array(nfds);
  78. spin_lock(&files->file_lock);
  79. if (!new_fds)
  80. goto out;
  81. /* Copy the existing array and install the new pointer */
  82. if (nfds > files->max_fds) {
  83. struct file **old_fds;
  84. int i;
  85. old_fds = xchg(&files->fd, new_fds);
  86. i = xchg(&files->max_fds, nfds);
  87. /* Don't copy/clear the array if we are creating a new
  88. fd array for fork() */
  89. if (i) {
  90. memcpy(new_fds, old_fds, i * sizeof(struct file *));
  91. /* clear the remainder of the array */
  92. memset(&new_fds[i], 0,
  93. (nfds-i) * sizeof(struct file *));
  94. spin_unlock(&files->file_lock);
  95. free_fd_array(old_fds, i);
  96. spin_lock(&files->file_lock);
  97. }
  98. } else {
  99. /* Somebody expanded the array while we slept ... */
  100. spin_unlock(&files->file_lock);
  101. free_fd_array(new_fds, nfds);
  102. spin_lock(&files->file_lock);
  103. }
  104. error = 0;
  105. out:
  106. return error;
  107. }
  108. /*
  109. * Allocate an fdset array, using kmalloc or vmalloc.
  110. * Note: the array isn't cleared at allocation time.
  111. */
  112. fd_set * alloc_fdset(int num)
  113. {
  114. fd_set *new_fdset;
  115. int size = num / 8;
  116. if (size <= PAGE_SIZE)
  117. new_fdset = (fd_set *) kmalloc(size, GFP_KERNEL);
  118. else
  119. new_fdset = (fd_set *) vmalloc(size);
  120. return new_fdset;
  121. }
  122. void free_fdset(fd_set *array, int num)
  123. {
  124. int size = num / 8;
  125. if (num <= __FD_SETSIZE) /* Don't free an embedded fdset */
  126. return;
  127. else if (size <= PAGE_SIZE)
  128. kfree(array);
  129. else
  130. vfree(array);
  131. }
  132. /*
  133. * Expand the fdset in the files_struct. Called with the files spinlock
  134. * held for write.
  135. */
  136. static int expand_fdset(struct files_struct *files, int nr)
  137. __releases(file->file_lock)
  138. __acquires(file->file_lock)
  139. {
  140. fd_set *new_openset = NULL, *new_execset = NULL;
  141. int error, nfds = 0;
  142. error = -EMFILE;
  143. if (files->max_fdset >= NR_OPEN || nr >= NR_OPEN)
  144. goto out;
  145. nfds = files->max_fdset;
  146. spin_unlock(&files->file_lock);
  147. /* Expand to the max in easy steps */
  148. do {
  149. if (nfds < (PAGE_SIZE * 8))
  150. nfds = PAGE_SIZE * 8;
  151. else {
  152. nfds = nfds * 2;
  153. if (nfds > NR_OPEN)
  154. nfds = NR_OPEN;
  155. }
  156. } while (nfds <= nr);
  157. error = -ENOMEM;
  158. new_openset = alloc_fdset(nfds);
  159. new_execset = alloc_fdset(nfds);
  160. spin_lock(&files->file_lock);
  161. if (!new_openset || !new_execset)
  162. goto out;
  163. error = 0;
  164. /* Copy the existing tables and install the new pointers */
  165. if (nfds > files->max_fdset) {
  166. int i = files->max_fdset / (sizeof(unsigned long) * 8);
  167. int count = (nfds - files->max_fdset) / 8;
  168. /*
  169. * Don't copy the entire array if the current fdset is
  170. * not yet initialised.
  171. */
  172. if (i) {
  173. memcpy (new_openset, files->open_fds, files->max_fdset/8);
  174. memcpy (new_execset, files->close_on_exec, files->max_fdset/8);
  175. memset (&new_openset->fds_bits[i], 0, count);
  176. memset (&new_execset->fds_bits[i], 0, count);
  177. }
  178. nfds = xchg(&files->max_fdset, nfds);
  179. new_openset = xchg(&files->open_fds, new_openset);
  180. new_execset = xchg(&files->close_on_exec, new_execset);
  181. spin_unlock(&files->file_lock);
  182. free_fdset (new_openset, nfds);
  183. free_fdset (new_execset, nfds);
  184. spin_lock(&files->file_lock);
  185. return 0;
  186. }
  187. /* Somebody expanded the array while we slept ... */
  188. out:
  189. spin_unlock(&files->file_lock);
  190. if (new_openset)
  191. free_fdset(new_openset, nfds);
  192. if (new_execset)
  193. free_fdset(new_execset, nfds);
  194. spin_lock(&files->file_lock);
  195. return error;
  196. }
  197. /*
  198. * Expand files.
  199. * Return <0 on error; 0 nothing done; 1 files expanded, we may have blocked.
  200. * Should be called with the files->file_lock spinlock held for write.
  201. */
  202. int expand_files(struct files_struct *files, int nr)
  203. {
  204. int err, expand = 0;
  205. if (nr >= files->max_fdset) {
  206. expand = 1;
  207. if ((err = expand_fdset(files, nr)))
  208. goto out;
  209. }
  210. if (nr >= files->max_fds) {
  211. expand = 1;
  212. if ((err = expand_fd_array(files, nr)))
  213. goto out;
  214. }
  215. err = expand;
  216. out:
  217. return err;
  218. }