mntpt.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /* mountpoint management
  2. *
  3. * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/init.h>
  14. #include <linux/fs.h>
  15. #include <linux/pagemap.h>
  16. #include <linux/mount.h>
  17. #include <linux/namei.h>
  18. #include <linux/gfp.h>
  19. #include "internal.h"
  20. static struct dentry *afs_mntpt_lookup(struct inode *dir,
  21. struct dentry *dentry,
  22. unsigned int flags);
  23. static int afs_mntpt_open(struct inode *inode, struct file *file);
  24. static void afs_mntpt_expiry_timed_out(struct work_struct *work);
  25. const struct file_operations afs_mntpt_file_operations = {
  26. .open = afs_mntpt_open,
  27. .llseek = noop_llseek,
  28. };
  29. const struct inode_operations afs_mntpt_inode_operations = {
  30. .lookup = afs_mntpt_lookup,
  31. .readlink = page_readlink,
  32. .getattr = afs_getattr,
  33. .listxattr = afs_listxattr,
  34. };
  35. const struct inode_operations afs_autocell_inode_operations = {
  36. .getattr = afs_getattr,
  37. };
  38. static LIST_HEAD(afs_vfsmounts);
  39. static DECLARE_DELAYED_WORK(afs_mntpt_expiry_timer, afs_mntpt_expiry_timed_out);
  40. static unsigned long afs_mntpt_expiry_timeout = 10 * 60;
  41. /*
  42. * no valid lookup procedure on this sort of dir
  43. */
  44. static struct dentry *afs_mntpt_lookup(struct inode *dir,
  45. struct dentry *dentry,
  46. unsigned int flags)
  47. {
  48. _enter("%p,%p{%pd2}", dir, dentry, dentry);
  49. return ERR_PTR(-EREMOTE);
  50. }
  51. /*
  52. * no valid open procedure on this sort of dir
  53. */
  54. static int afs_mntpt_open(struct inode *inode, struct file *file)
  55. {
  56. _enter("%p,%p{%pD2}", inode, file, file);
  57. return -EREMOTE;
  58. }
  59. /*
  60. * create a vfsmount to be automounted
  61. */
  62. static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
  63. {
  64. struct afs_super_info *as;
  65. struct vfsmount *mnt;
  66. struct afs_vnode *vnode;
  67. struct page *page;
  68. char *devname, *options;
  69. bool rwpath = false;
  70. int ret;
  71. _enter("{%pd}", mntpt);
  72. BUG_ON(!d_inode(mntpt));
  73. ret = -ENOMEM;
  74. devname = (char *) get_zeroed_page(GFP_KERNEL);
  75. if (!devname)
  76. goto error_no_devname;
  77. options = (char *) get_zeroed_page(GFP_KERNEL);
  78. if (!options)
  79. goto error_no_options;
  80. vnode = AFS_FS_I(d_inode(mntpt));
  81. if (test_bit(AFS_VNODE_PSEUDODIR, &vnode->flags)) {
  82. /* if the directory is a pseudo directory, use the d_name */
  83. static const char afs_root_cell[] = ":root.cell.";
  84. unsigned size = mntpt->d_name.len;
  85. ret = -ENOENT;
  86. if (size < 2 || size > AFS_MAXCELLNAME)
  87. goto error_no_page;
  88. if (mntpt->d_name.name[0] == '.') {
  89. devname[0] = '%';
  90. memcpy(devname + 1, mntpt->d_name.name + 1, size - 1);
  91. memcpy(devname + size, afs_root_cell,
  92. sizeof(afs_root_cell));
  93. rwpath = true;
  94. } else {
  95. devname[0] = '#';
  96. memcpy(devname + 1, mntpt->d_name.name, size);
  97. memcpy(devname + size + 1, afs_root_cell,
  98. sizeof(afs_root_cell));
  99. }
  100. } else {
  101. /* read the contents of the AFS special symlink */
  102. loff_t size = i_size_read(d_inode(mntpt));
  103. char *buf;
  104. ret = -EINVAL;
  105. if (size > PAGE_SIZE - 1)
  106. goto error_no_page;
  107. page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL);
  108. if (IS_ERR(page)) {
  109. ret = PTR_ERR(page);
  110. goto error_no_page;
  111. }
  112. ret = -EIO;
  113. if (PageError(page))
  114. goto error;
  115. buf = kmap_atomic(page);
  116. memcpy(devname, buf, size);
  117. kunmap_atomic(buf);
  118. put_page(page);
  119. page = NULL;
  120. }
  121. /* work out what options we want */
  122. as = AFS_FS_S(mntpt->d_sb);
  123. if (as->cell) {
  124. memcpy(options, "cell=", 5);
  125. strcpy(options + 5, as->cell->name);
  126. if ((as->volume && as->volume->type == AFSVL_RWVOL) || rwpath)
  127. strcat(options, ",rwpath");
  128. }
  129. /* try and do the mount */
  130. _debug("--- attempting mount %s -o %s ---", devname, options);
  131. mnt = vfs_submount(mntpt, &afs_fs_type, devname, options);
  132. _debug("--- mount result %p ---", mnt);
  133. free_page((unsigned long) devname);
  134. free_page((unsigned long) options);
  135. _leave(" = %p", mnt);
  136. return mnt;
  137. error:
  138. put_page(page);
  139. error_no_page:
  140. free_page((unsigned long) options);
  141. error_no_options:
  142. free_page((unsigned long) devname);
  143. error_no_devname:
  144. _leave(" = %d", ret);
  145. return ERR_PTR(ret);
  146. }
  147. /*
  148. * handle an automount point
  149. */
  150. struct vfsmount *afs_d_automount(struct path *path)
  151. {
  152. struct vfsmount *newmnt;
  153. _enter("{%pd}", path->dentry);
  154. newmnt = afs_mntpt_do_automount(path->dentry);
  155. if (IS_ERR(newmnt))
  156. return newmnt;
  157. mntget(newmnt); /* prevent immediate expiration */
  158. mnt_set_expiry(newmnt, &afs_vfsmounts);
  159. queue_delayed_work(afs_wq, &afs_mntpt_expiry_timer,
  160. afs_mntpt_expiry_timeout * HZ);
  161. _leave(" = %p", newmnt);
  162. return newmnt;
  163. }
  164. /*
  165. * handle mountpoint expiry timer going off
  166. */
  167. static void afs_mntpt_expiry_timed_out(struct work_struct *work)
  168. {
  169. _enter("");
  170. if (!list_empty(&afs_vfsmounts)) {
  171. mark_mounts_for_expiry(&afs_vfsmounts);
  172. queue_delayed_work(afs_wq, &afs_mntpt_expiry_timer,
  173. afs_mntpt_expiry_timeout * HZ);
  174. }
  175. _leave("");
  176. }
  177. /*
  178. * kill the AFS mountpoint timer if it's still running
  179. */
  180. void afs_mntpt_kill_timer(void)
  181. {
  182. _enter("");
  183. ASSERT(list_empty(&afs_vfsmounts));
  184. cancel_delayed_work_sync(&afs_mntpt_expiry_timer);
  185. }