/core/10.4/fusefs/fuse_node.c

http://macfuse.googlecode.com/ · C · 249 lines · 187 code · 44 blank · 18 comment · 48 complexity · 51f79e54e2438c6a8ab61bb729e4daad MD5 · raw file

  1. /*
  2. * Copyright (C) 2006-2008 Google. All Rights Reserved.
  3. * Amit Singh <singh@>
  4. */
  5. #include "fuse.h"
  6. #include "fuse_internal.h"
  7. #include "fuse_ipc.h"
  8. #include "fuse_locking.h"
  9. #include "fuse_node.h"
  10. #include "fuse_sysctl.h"
  11. void
  12. FSNodeScrub(struct fuse_vnode_data *fvdat)
  13. {
  14. lck_mtx_free(fvdat->createlock, fuse_lock_group);
  15. #if M_MACFUSE_ENABLE_TSLOCKING
  16. lck_rw_free(fvdat->nodelock, fuse_lock_group);
  17. lck_rw_free(fvdat->truncatelock, fuse_lock_group);
  18. #endif
  19. fvdat->fMagic = kFSNodeBadMagic;
  20. }
  21. errno_t
  22. FSNodeGetOrCreateFileVNodeByID(vnode_t *vnPtr,
  23. uint32_t flags,
  24. struct fuse_entry_out *feo,
  25. mount_t mp,
  26. vnode_t dvp,
  27. vfs_context_t context,
  28. uint32_t *oflags)
  29. {
  30. int err;
  31. int junk;
  32. vnode_t vn = NULLVP;
  33. HNodeRef hn = NULL;
  34. vnode_t dirVN = NULLVP;
  35. struct fuse_vnode_data *fvdat = NULL;
  36. struct fuse_data *mntdata = NULL;
  37. fuse_device_t dummy_device;
  38. enum vtype vtyp = IFTOVT(feo->attr.mode);
  39. if ((vtyp >= VBAD) || (vtyp < 0) || (vtyp == VNON)) {
  40. return EINVAL;
  41. }
  42. int markroot = (flags & FN_IS_ROOT) ? TRUE : FALSE;
  43. uint64_t size = (flags & FN_IS_ROOT) ? 0 : feo->attr.size;
  44. uint32_t rdev = (flags & FN_IS_ROOT) ? 0 : feo->attr.rdev;
  45. uint64_t generation = feo->generation;
  46. mntdata = fuse_get_mpdata(mp);
  47. dummy_device = mntdata->fdev;
  48. err = HNodeLookupCreatingIfNecessary(dummy_device, feo->nodeid,
  49. 0 /* fork index */, &hn, &vn);
  50. if ((err == 0) && (vn == NULL)) {
  51. struct vnode_fsparam params;
  52. fvdat = (struct fuse_vnode_data *)FSNodeGenericFromHNode(hn);
  53. if (!fvdat->fInitialised) {
  54. /* check */
  55. fvdat->fMagic = kFSNodeMagic;
  56. fvdat->fInitialised = TRUE;
  57. /* self */
  58. fvdat->vp = NULLVP; /* hold on */
  59. fvdat->nodeid = feo->nodeid;
  60. fvdat->generation = generation;
  61. /* parent */
  62. fvdat->parentvp = dvp;
  63. if (dvp) {
  64. fvdat->parent_nodeid = VTOI(dvp);
  65. } else {
  66. fvdat->parent_nodeid = 0;
  67. }
  68. /* I/O */
  69. {
  70. int k;
  71. for (k = 0; k < FUFH_MAXTYPE; k++) {
  72. FUFH_USE_RESET(&(fvdat->fufh[k]));
  73. }
  74. }
  75. /* flags */
  76. fvdat->flag = flags;
  77. fvdat->c_flag = 0;
  78. /* meta */
  79. /* XXX: truncation */
  80. fvdat->entry_valid.tv_sec = (time_t)feo->entry_valid;
  81. fvdat->entry_valid.tv_nsec = feo->entry_valid_nsec;
  82. /* XXX: truncation */
  83. fvdat->attr_valid.tv_sec = (time_t)feo->attr_valid;
  84. fvdat->attr_valid.tv_nsec = feo->attr_valid_nsec;
  85. /* XXX: truncation */
  86. fvdat->modify_time.tv_sec = (time_t)feo->attr.mtime;
  87. fvdat->modify_time.tv_nsec = feo->attr.mtimensec;
  88. fvdat->filesize = size;
  89. fvdat->nlookup = 0;
  90. fvdat->vtype = vtyp;
  91. /* locking */
  92. fvdat->createlock = lck_mtx_alloc_init(fuse_lock_group,
  93. fuse_lock_attr);
  94. fvdat->creator = current_thread();
  95. #if M_MACFUSE_ENABLE_TSLOCKING
  96. fvdat->nodelock = lck_rw_alloc_init(fuse_lock_group,
  97. fuse_lock_attr);
  98. fvdat->nodelockowner = NULL;
  99. fvdat->truncatelock = lck_rw_alloc_init(fuse_lock_group,
  100. fuse_lock_attr);
  101. #endif
  102. }
  103. if (err == 0) {
  104. params.vnfs_mp = mp;
  105. params.vnfs_vtype = vtyp;
  106. params.vnfs_str = NULL;
  107. params.vnfs_dvp = dvp; /* NULLVP for the root vnode */
  108. params.vnfs_fsnode = hn;
  109. #if M_MACFUSE_ENABLE_SPECFS
  110. if ((vtyp == VBLK) || (vtyp == VCHR)) {
  111. params.vnfs_vops = fuse_spec_operations;
  112. params.vnfs_rdev = (dev_t)rdev;
  113. #else
  114. if (0) {
  115. #endif
  116. #if M_MACFUSE_ENABLE_FIFOFS
  117. } else if (vtyp == VFIFO) {
  118. params.vnfs_vops = fuse_fifo_operations;
  119. params.vnfs_rdev = 0;
  120. (void)rdev;
  121. #else
  122. } else if (0) {
  123. #endif
  124. } else {
  125. params.vnfs_vops = fuse_vnode_operations;
  126. params.vnfs_rdev = 0;
  127. (void)rdev;
  128. }
  129. params.vnfs_marksystem = FALSE;
  130. params.vnfs_cnp = NULL;
  131. params.vnfs_flags = VNFS_NOCACHE | VNFS_CANTCACHE;
  132. params.vnfs_filesize = size;
  133. params.vnfs_markroot = markroot;
  134. err = vnode_create(VNCREATE_FLAVOR, (uint32_t)sizeof(params),
  135. &params, &vn);
  136. }
  137. if (err == 0) {
  138. if (markroot == TRUE) {
  139. fvdat->parentvp = vn;
  140. } else {
  141. fvdat->parentvp = dvp;
  142. }
  143. if (oflags) {
  144. *oflags |= MAKEENTRY;
  145. }
  146. HNodeAttachVNodeSucceeded(hn, 0 /* forkIndex */, vn);
  147. FUSE_OSAddAtomic(1, (SInt32 *)&fuse_vnodes_current);
  148. } else {
  149. if (HNodeAttachVNodeFailed(hn, 0 /* forkIndex */)) {
  150. FSNodeScrub(fvdat);
  151. HNodeScrubDone(hn);
  152. }
  153. }
  154. }
  155. if (err == 0) {
  156. if (vnode_vtype(vn) != vtyp) {
  157. IOLog("MacFUSE: vnode changed type behind us (old=%d, new=%d)\n",
  158. vnode_vtype(vn), vtyp);
  159. fuse_internal_vnode_disappear(vn, context, REVOKE_SOFT);
  160. vnode_put(vn);
  161. err = EIO;
  162. } else if (VTOFUD(vn)->generation != generation) {
  163. IOLog("MacFUSE: vnode changed generation\n");
  164. fuse_internal_vnode_disappear(vn, context, REVOKE_SOFT);
  165. vnode_put(vn);
  166. err = ESTALE;
  167. }
  168. }
  169. if (err == 0) {
  170. *vnPtr = vn;
  171. /* Need VT_MACFUSE from xnu */
  172. vnode_settag(vn, VT_OTHER);
  173. }
  174. if (dirVN != NULL) {
  175. junk = vnode_put(dirVN);
  176. /* assert(junk == 0); */
  177. }
  178. /* assert((err == 0) == (*vnPtr != NULL); */
  179. return err;
  180. }
  181. int
  182. fuse_vget_i(vnode_t *vpp,
  183. uint32_t flags,
  184. struct fuse_entry_out *feo,
  185. struct componentname *cnp,
  186. vnode_t dvp,
  187. mount_t mp,
  188. vfs_context_t context)
  189. {
  190. int err = 0;
  191. if (!feo) {
  192. return EINVAL;
  193. }
  194. err = FSNodeGetOrCreateFileVNodeByID(vpp, flags, feo, mp, dvp,
  195. context, NULL);
  196. if (err) {
  197. return err;
  198. }
  199. if (!fuse_isnovncache_mp(mp) && (cnp->cn_flags & MAKEENTRY)) {
  200. fuse_vncache_enter(dvp, *vpp, cnp);
  201. }
  202. /* found: */
  203. VTOFUD(*vpp)->nlookup++;
  204. return 0;
  205. }