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

嵌入式Linux

开发平台:

Unix_Linux

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