filesystems.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * linux/fs/filesystems.c
  3. *
  4. * Copyright (C) 1991, 1992 Linus Torvalds
  5. *
  6. * table of configured filesystems
  7. */
  8. #include <linux/syscalls.h>
  9. #include <linux/fs.h>
  10. #include <linux/slab.h>
  11. #include <linux/kmod.h>
  12. #include <linux/init.h>
  13. #include <linux/module.h>
  14. #include <asm/uaccess.h>
  15. /*
  16. * Handling of filesystem drivers list.
  17. * Rules:
  18. * Inclusion to/removals from/scanning of list are protected by spinlock.
  19. * During the unload module must call unregister_filesystem().
  20. * We can access the fields of list element if:
  21. * 1) spinlock is held or
  22. * 2) we hold the reference to the module.
  23. * The latter can be guaranteed by call of try_module_get(); if it
  24. * returned 0 we must skip the element, otherwise we got the reference.
  25. * Once the reference is obtained we can drop the spinlock.
  26. */
  27. static struct file_system_type *file_systems;
  28. static DEFINE_RWLOCK(file_systems_lock);
  29. /* WARNING: This can be used only if we _already_ own a reference */
  30. void get_filesystem(struct file_system_type *fs)
  31. {
  32. __module_get(fs->owner);
  33. }
  34. void put_filesystem(struct file_system_type *fs)
  35. {
  36. module_put(fs->owner);
  37. }
  38. static struct file_system_type **find_filesystem(const char *name)
  39. {
  40. struct file_system_type **p;
  41. for (p=&file_systems; *p; p=&(*p)->next)
  42. if (strcmp((*p)->name,name) == 0)
  43. break;
  44. return p;
  45. }
  46. /**
  47. * register_filesystem - register a new filesystem
  48. * @fs: the file system structure
  49. *
  50. * Adds the file system passed to the list of file systems the kernel
  51. * is aware of for mount and other syscalls. Returns 0 on success,
  52. * or a negative errno code on an error.
  53. *
  54. * The &struct file_system_type that is passed is linked into the kernel
  55. * structures and must not be freed until the file system has been
  56. * unregistered.
  57. */
  58. int register_filesystem(struct file_system_type * fs)
  59. {
  60. int res = 0;
  61. struct file_system_type ** p;
  62. if (fs->next)
  63. return -EBUSY;
  64. INIT_LIST_HEAD(&fs->fs_supers);
  65. write_lock(&file_systems_lock);
  66. p = find_filesystem(fs->name);
  67. if (*p)
  68. res = -EBUSY;
  69. else
  70. *p = fs;
  71. write_unlock(&file_systems_lock);
  72. return res;
  73. }
  74. EXPORT_SYMBOL(register_filesystem);
  75. /**
  76. * unregister_filesystem - unregister a file system
  77. * @fs: filesystem to unregister
  78. *
  79. * Remove a file system that was previously successfully registered
  80. * with the kernel. An error is returned if the file system is not found.
  81. * Zero is returned on a success.
  82. *
  83. * Once this function has returned the &struct file_system_type structure
  84. * may be freed or reused.
  85. */
  86. int unregister_filesystem(struct file_system_type * fs)
  87. {
  88. struct file_system_type ** tmp;
  89. write_lock(&file_systems_lock);
  90. tmp = &file_systems;
  91. while (*tmp) {
  92. if (fs == *tmp) {
  93. *tmp = fs->next;
  94. fs->next = NULL;
  95. write_unlock(&file_systems_lock);
  96. return 0;
  97. }
  98. tmp = &(*tmp)->next;
  99. }
  100. write_unlock(&file_systems_lock);
  101. return -EINVAL;
  102. }
  103. EXPORT_SYMBOL(unregister_filesystem);
  104. static int fs_index(const char __user * __name)
  105. {
  106. struct file_system_type * tmp;
  107. char * name;
  108. int err, index;
  109. name = getname(__name);
  110. err = PTR_ERR(name);
  111. if (IS_ERR(name))
  112. return err;
  113. err = -EINVAL;
  114. read_lock(&file_systems_lock);
  115. for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
  116. if (strcmp(tmp->name,name) == 0) {
  117. err = index;
  118. break;
  119. }
  120. }
  121. read_unlock(&file_systems_lock);
  122. putname(name);
  123. return err;
  124. }
  125. static int fs_name(unsigned int index, char __user * buf)
  126. {
  127. struct file_system_type * tmp;
  128. int len, res;
  129. read_lock(&file_systems_lock);
  130. for (tmp = file_systems; tmp; tmp = tmp->next, index--)
  131. if (index <= 0 && try_module_get(tmp->owner))
  132. break;
  133. read_unlock(&file_systems_lock);
  134. if (!tmp)
  135. return -EINVAL;
  136. /* OK, we got the reference, so we can safely block */
  137. len = strlen(tmp->name) + 1;
  138. res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
  139. put_filesystem(tmp);
  140. return res;
  141. }
  142. static int fs_maxindex(void)
  143. {
  144. struct file_system_type * tmp;
  145. int index;
  146. read_lock(&file_systems_lock);
  147. for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
  148. ;
  149. read_unlock(&file_systems_lock);
  150. return index;
  151. }
  152. /*
  153. * Whee.. Weird sysv syscall.
  154. */
  155. asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
  156. {
  157. int retval = -EINVAL;
  158. switch (option) {
  159. case 1:
  160. retval = fs_index((const char __user *) arg1);
  161. break;
  162. case 2:
  163. retval = fs_name(arg1, (char __user *) arg2);
  164. break;
  165. case 3:
  166. retval = fs_maxindex();
  167. break;
  168. }
  169. return retval;
  170. }
  171. int get_filesystem_list(char * buf)
  172. {
  173. int len = 0;
  174. struct file_system_type * tmp;
  175. read_lock(&file_systems_lock);
  176. tmp = file_systems;
  177. while (tmp && len < PAGE_SIZE - 80) {
  178. len += sprintf(buf+len, "%s\t%s\n",
  179. (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
  180. tmp->name);
  181. tmp = tmp->next;
  182. }
  183. read_unlock(&file_systems_lock);
  184. return len;
  185. }
  186. struct file_system_type *get_fs_type(const char *name)
  187. {
  188. struct file_system_type *fs;
  189. read_lock(&file_systems_lock);
  190. fs = *(find_filesystem(name));
  191. if (fs && !try_module_get(fs->owner))
  192. fs = NULL;
  193. read_unlock(&file_systems_lock);
  194. if (!fs && (request_module("%s", name) == 0)) {
  195. read_lock(&file_systems_lock);
  196. fs = *(find_filesystem(name));
  197. if (fs && !try_module_get(fs->owner))
  198. fs = NULL;
  199. read_unlock(&file_systems_lock);
  200. }
  201. return fs;
  202. }
  203. EXPORT_SYMBOL(get_fs_type);