HardenedBSD src tree https://hardenedbsd.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1874 lines
43 KiB

  1. /* $NetBSD: tmpfs_vnops.c,v 1.39 2007/07/23 15:41:01 jmmv Exp $ */
  2. /*-
  3. * SPDX-License-Identifier: BSD-2-Clause-NetBSD
  4. *
  5. * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
  6. * All rights reserved.
  7. *
  8. * This code is derived from software contributed to The NetBSD Foundation
  9. * by Julio M. Merino Vidal, developed as part of Google's Summer of Code
  10. * 2005 program.
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions
  14. * are met:
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in the
  19. * documentation and/or other materials provided with the distribution.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  22. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  23. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  24. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  25. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  26. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  27. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  30. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  31. * POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. /*
  34. * tmpfs vnode interface.
  35. */
  36. #include <sys/cdefs.h>
  37. __FBSDID("$FreeBSD$");
  38. #include <sys/param.h>
  39. #include <sys/systm.h>
  40. #include <sys/dirent.h>
  41. #include <sys/extattr.h>
  42. #include <sys/fcntl.h>
  43. #include <sys/limits.h>
  44. #include <sys/lockf.h>
  45. #include <sys/lock.h>
  46. #include <sys/mount.h>
  47. #include <sys/namei.h>
  48. #include <sys/priv.h>
  49. #include <sys/proc.h>
  50. #include <sys/rwlock.h>
  51. #include <sys/sched.h>
  52. #include <sys/stat.h>
  53. #include <sys/sysctl.h>
  54. #include <sys/unistd.h>
  55. #include <sys/vnode.h>
  56. #include <vm/vm.h>
  57. #include <vm/vm_param.h>
  58. #include <vm/vm_object.h>
  59. #include <fs/tmpfs/tmpfs_vnops.h>
  60. #include <fs/tmpfs/tmpfs.h>
  61. SYSCTL_DECL(_vfs_tmpfs);
  62. static volatile int tmpfs_rename_restarts;
  63. SYSCTL_INT(_vfs_tmpfs, OID_AUTO, rename_restarts, CTLFLAG_RD,
  64. __DEVOLATILE(int *, &tmpfs_rename_restarts), 0,
  65. "Times rename had to restart due to lock contention");
  66. static struct tmpfs_extattr_list_entry *tmpfs_node_has_extattr(
  67. struct tmpfs_node *, int, const char *);
  68. static int tmpfs_extattr_set(struct vnode *, int, const char *,
  69. struct uio *, struct ucred *, struct thread *);
  70. static int tmpfs_extattr_get(struct vnode *, int, const char *,
  71. struct uio *, size_t *, struct ucred *, struct thread *);
  72. static int tmpfs_listextattr(struct vop_listextattr_args *);
  73. static int tmpfs_extattr_list(struct vnode *, int, struct uio *,
  74. size_t *, struct ucred *, struct thread *);
  75. static int
  76. tmpfs_vn_get_ino_alloc(struct mount *mp, void *arg, int lkflags,
  77. struct vnode **rvp)
  78. {
  79. return (tmpfs_alloc_vp(mp, arg, lkflags, rvp));
  80. }
  81. static int
  82. tmpfs_lookup1(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
  83. {
  84. struct tmpfs_dirent *de;
  85. struct tmpfs_node *dnode, *pnode;
  86. struct tmpfs_mount *tm;
  87. int error;
  88. dnode = VP_TO_TMPFS_DIR(dvp);
  89. *vpp = NULLVP;
  90. /* Check accessibility of requested node as a first step. */
  91. error = vn_dir_check_exec(dvp, cnp);
  92. if (error != 0)
  93. goto out;
  94. /* We cannot be requesting the parent directory of the root node. */
  95. MPASS(IMPLIES(dnode->tn_type == VDIR &&
  96. dnode->tn_dir.tn_parent == dnode,
  97. !(cnp->cn_flags & ISDOTDOT)));
  98. TMPFS_ASSERT_LOCKED(dnode);
  99. if (dnode->tn_dir.tn_parent == NULL) {
  100. error = ENOENT;
  101. goto out;
  102. }
  103. if (cnp->cn_flags & ISDOTDOT) {
  104. tm = VFS_TO_TMPFS(dvp->v_mount);
  105. pnode = dnode->tn_dir.tn_parent;
  106. tmpfs_ref_node(pnode);
  107. error = vn_vget_ino_gen(dvp, tmpfs_vn_get_ino_alloc,
  108. pnode, cnp->cn_lkflags, vpp);
  109. tmpfs_free_node(tm, pnode);
  110. if (error != 0)
  111. goto out;
  112. } else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
  113. VREF(dvp);
  114. *vpp = dvp;
  115. error = 0;
  116. } else {
  117. de = tmpfs_dir_lookup(dnode, NULL, cnp);
  118. if (de != NULL && de->td_node == NULL)
  119. cnp->cn_flags |= ISWHITEOUT;
  120. if (de == NULL || de->td_node == NULL) {
  121. /*
  122. * The entry was not found in the directory.
  123. * This is OK if we are creating or renaming an
  124. * entry and are working on the last component of
  125. * the path name.
  126. */
  127. if ((cnp->cn_flags & ISLASTCN) &&
  128. (cnp->cn_nameiop == CREATE || \
  129. cnp->cn_nameiop == RENAME ||
  130. (cnp->cn_nameiop == DELETE &&
  131. cnp->cn_flags & DOWHITEOUT &&
  132. cnp->cn_flags & ISWHITEOUT))) {
  133. error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred,
  134. cnp->cn_thread);
  135. if (error != 0)
  136. goto out;
  137. /*
  138. * Keep the component name in the buffer for
  139. * future uses.
  140. */
  141. cnp->cn_flags |= SAVENAME;
  142. error = EJUSTRETURN;
  143. } else
  144. error = ENOENT;
  145. } else {
  146. struct tmpfs_node *tnode;
  147. /*
  148. * The entry was found, so get its associated
  149. * tmpfs_node.
  150. */
  151. tnode = de->td_node;
  152. /*
  153. * If we are not at the last path component and
  154. * found a non-directory or non-link entry (which
  155. * may itself be pointing to a directory), raise
  156. * an error.
  157. */
  158. if ((tnode->tn_type != VDIR &&
  159. tnode->tn_type != VLNK) &&
  160. !(cnp->cn_flags & ISLASTCN)) {
  161. error = ENOTDIR;
  162. goto out;
  163. }
  164. /*
  165. * If we are deleting or renaming the entry, keep
  166. * track of its tmpfs_dirent so that it can be
  167. * easily deleted later.
  168. */
  169. if ((cnp->cn_flags & ISLASTCN) &&
  170. (cnp->cn_nameiop == DELETE ||
  171. cnp->cn_nameiop == RENAME)) {
  172. error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred,
  173. cnp->cn_thread);
  174. if (error != 0)
  175. goto out;
  176. /* Allocate a new vnode on the matching entry. */
  177. error = tmpfs_alloc_vp(dvp->v_mount, tnode,
  178. cnp->cn_lkflags, vpp);
  179. if (error != 0)
  180. goto out;
  181. if ((dnode->tn_mode & S_ISTXT) &&
  182. VOP_ACCESS(dvp, VADMIN, cnp->cn_cred,
  183. cnp->cn_thread) && VOP_ACCESS(*vpp, VADMIN,
  184. cnp->cn_cred, cnp->cn_thread)) {
  185. error = EPERM;
  186. vput(*vpp);
  187. *vpp = NULL;
  188. goto out;
  189. }
  190. cnp->cn_flags |= SAVENAME;
  191. } else {
  192. error = tmpfs_alloc_vp(dvp->v_mount, tnode,
  193. cnp->cn_lkflags, vpp);
  194. if (error != 0)
  195. goto out;
  196. }
  197. }
  198. }
  199. /*
  200. * Store the result of this lookup in the cache. Avoid this if the
  201. * request was for creation, as it does not improve timings on
  202. * emprical tests.
  203. */
  204. if ((cnp->cn_flags & MAKEENTRY) != 0 && tmpfs_use_nc(dvp))
  205. cache_enter(dvp, *vpp, cnp);
  206. out:
  207. /*
  208. * If there were no errors, *vpp cannot be null and it must be
  209. * locked.
  210. */
  211. MPASS(IFF(error == 0, *vpp != NULLVP && VOP_ISLOCKED(*vpp)));
  212. return (error);
  213. }
  214. static int
  215. tmpfs_cached_lookup(struct vop_cachedlookup_args *v)
  216. {
  217. return (tmpfs_lookup1(v->a_dvp, v->a_vpp, v->a_cnp));
  218. }
  219. static int
  220. tmpfs_lookup(struct vop_lookup_args *v)
  221. {
  222. return (tmpfs_lookup1(v->a_dvp, v->a_vpp, v->a_cnp));
  223. }
  224. static int
  225. tmpfs_create(struct vop_create_args *v)
  226. {
  227. struct vnode *dvp = v->a_dvp;
  228. struct vnode **vpp = v->a_vpp;
  229. struct componentname *cnp = v->a_cnp;
  230. struct vattr *vap = v->a_vap;
  231. int error;
  232. MPASS(vap->va_type == VREG || vap->va_type == VSOCK);
  233. error = tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
  234. if (error == 0 && (cnp->cn_flags & MAKEENTRY) != 0 && tmpfs_use_nc(dvp))
  235. cache_enter(dvp, *vpp, cnp);
  236. return (error);
  237. }
  238. static int
  239. tmpfs_mknod(struct vop_mknod_args *v)
  240. {
  241. struct vnode *dvp = v->a_dvp;
  242. struct vnode **vpp = v->a_vpp;
  243. struct componentname *cnp = v->a_cnp;
  244. struct vattr *vap = v->a_vap;
  245. if (vap->va_type != VBLK && vap->va_type != VCHR &&
  246. vap->va_type != VFIFO)
  247. return EINVAL;
  248. return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
  249. }
  250. static int
  251. tmpfs_open(struct vop_open_args *v)
  252. {
  253. struct vnode *vp = v->a_vp;
  254. int mode = v->a_mode;
  255. int error;
  256. struct tmpfs_node *node;
  257. MPASS(VOP_ISLOCKED(vp));
  258. node = VP_TO_TMPFS_NODE(vp);
  259. /* The file is still active but all its names have been removed
  260. * (e.g. by a "rmdir $(pwd)"). It cannot be opened any more as
  261. * it is about to die. */
  262. if (node->tn_links < 1)
  263. return (ENOENT);
  264. /* If the file is marked append-only, deny write requests. */
  265. if (node->tn_flags & APPEND && (mode & (FWRITE | O_APPEND)) == FWRITE)
  266. error = EPERM;
  267. else {
  268. error = 0;
  269. /* For regular files, the call below is nop. */
  270. KASSERT(vp->v_type != VREG || (node->tn_reg.tn_aobj->flags &
  271. OBJ_DEAD) == 0, ("dead object"));
  272. vnode_create_vobject(vp, node->tn_size, v->a_td);
  273. }
  274. MPASS(VOP_ISLOCKED(vp));
  275. return error;
  276. }
  277. static int
  278. tmpfs_close(struct vop_close_args *v)
  279. {
  280. struct vnode *vp = v->a_vp;
  281. /* Update node times. */
  282. tmpfs_update(vp);
  283. return (0);
  284. }
  285. int
  286. tmpfs_access(struct vop_access_args *v)
  287. {
  288. struct vnode *vp = v->a_vp;
  289. accmode_t accmode = v->a_accmode;
  290. struct ucred *cred = v->a_cred;
  291. mode_t all_x = S_IXUSR | S_IXGRP | S_IXOTH;
  292. int error;
  293. struct tmpfs_node *node;
  294. MPASS(VOP_ISLOCKED(vp));
  295. node = VP_TO_TMPFS_NODE(vp);
  296. /*
  297. * Common case path lookup.
  298. */
  299. if (__predict_true(accmode == VEXEC && (node->tn_mode & all_x) == all_x))
  300. return (0);
  301. switch (vp->v_type) {
  302. case VDIR:
  303. /* FALLTHROUGH */
  304. case VLNK:
  305. /* FALLTHROUGH */
  306. case VREG:
  307. if (accmode & VWRITE && vp->v_mount->mnt_flag & MNT_RDONLY) {
  308. error = EROFS;
  309. goto out;
  310. }
  311. break;
  312. case VBLK:
  313. /* FALLTHROUGH */
  314. case VCHR:
  315. /* FALLTHROUGH */
  316. case VSOCK:
  317. /* FALLTHROUGH */
  318. case VFIFO:
  319. break;
  320. default:
  321. error = EINVAL;
  322. goto out;
  323. }
  324. if (accmode & VWRITE && node->tn_flags & IMMUTABLE) {
  325. error = EPERM;
  326. goto out;
  327. }
  328. error = vaccess(vp->v_type, node->tn_mode, node->tn_uid,
  329. node->tn_gid, accmode, cred, NULL);
  330. out:
  331. MPASS(VOP_ISLOCKED(vp));
  332. return error;
  333. }
  334. int
  335. tmpfs_getattr(struct vop_getattr_args *v)
  336. {
  337. struct vnode *vp = v->a_vp;
  338. struct vattr *vap = v->a_vap;
  339. vm_object_t obj;
  340. struct tmpfs_node *node;
  341. node = VP_TO_TMPFS_NODE(vp);
  342. tmpfs_update_getattr(vp);
  343. vap->va_type = vp->v_type;
  344. vap->va_mode = node->tn_mode;
  345. vap->va_nlink = node->tn_links;
  346. vap->va_uid = node->tn_uid;
  347. vap->va_gid = node->tn_gid;
  348. vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
  349. vap->va_fileid = node->tn_id;
  350. vap->va_size = node->tn_size;
  351. vap->va_blocksize = PAGE_SIZE;
  352. vap->va_atime = node->tn_atime;
  353. vap->va_mtime = node->tn_mtime;
  354. vap->va_ctime = node->tn_ctime;
  355. vap->va_birthtime = node->tn_birthtime;
  356. vap->va_gen = node->tn_gen;
  357. vap->va_flags = node->tn_flags;
  358. vap->va_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ?
  359. node->tn_rdev : NODEV;
  360. if (vp->v_type == VREG) {
  361. obj = node->tn_reg.tn_aobj;
  362. vap->va_bytes = (u_quad_t)obj->resident_page_count * PAGE_SIZE;
  363. } else
  364. vap->va_bytes = node->tn_size;
  365. vap->va_filerev = 0;
  366. return 0;
  367. }
  368. int
  369. tmpfs_setattr(struct vop_setattr_args *v)
  370. {
  371. struct vnode *vp = v->a_vp;
  372. struct vattr *vap = v->a_vap;
  373. struct ucred *cred = v->a_cred;
  374. struct thread *td = curthread;
  375. int error;
  376. MPASS(VOP_ISLOCKED(vp));
  377. error = 0;
  378. /* Abort if any unsettable attribute is given. */
  379. if (vap->va_type != VNON ||
  380. vap->va_nlink != VNOVAL ||
  381. vap->va_fsid != VNOVAL ||
  382. vap->va_fileid != VNOVAL ||
  383. vap->va_blocksize != VNOVAL ||
  384. vap->va_gen != VNOVAL ||
  385. vap->va_rdev != VNOVAL ||
  386. vap->va_bytes != VNOVAL)
  387. error = EINVAL;
  388. if (error == 0 && (vap->va_flags != VNOVAL))
  389. error = tmpfs_chflags(vp, vap->va_flags, cred, td);
  390. if (error == 0 && (vap->va_size != VNOVAL))
  391. error = tmpfs_chsize(vp, vap->va_size, cred, td);
  392. if (error == 0 && (vap->va_uid != VNOVAL || vap->va_gid != VNOVAL))
  393. error = tmpfs_chown(vp, vap->va_uid, vap->va_gid, cred, td);
  394. if (error == 0 && (vap->va_mode != (mode_t)VNOVAL))
  395. error = tmpfs_chmod(vp, vap->va_mode, cred, td);
  396. if (error == 0 && ((vap->va_atime.tv_sec != VNOVAL &&
  397. vap->va_atime.tv_nsec != VNOVAL) ||
  398. (vap->va_mtime.tv_sec != VNOVAL &&
  399. vap->va_mtime.tv_nsec != VNOVAL) ||
  400. (vap->va_birthtime.tv_sec != VNOVAL &&
  401. vap->va_birthtime.tv_nsec != VNOVAL)))
  402. error = tmpfs_chtimes(vp, vap, cred, td);
  403. /* Update the node times. We give preference to the error codes
  404. * generated by this function rather than the ones that may arise
  405. * from tmpfs_update. */
  406. tmpfs_update(vp);
  407. MPASS(VOP_ISLOCKED(vp));
  408. return error;
  409. }
  410. static int
  411. tmpfs_read(struct vop_read_args *v)
  412. {
  413. struct vnode *vp;
  414. struct uio *uio;
  415. struct tmpfs_node *node;
  416. vp = v->a_vp;
  417. if (vp->v_type != VREG)
  418. return (EISDIR);
  419. uio = v->a_uio;
  420. if (uio->uio_offset < 0)
  421. return (EINVAL);
  422. node = VP_TO_TMPFS_NODE(vp);
  423. tmpfs_set_status(VFS_TO_TMPFS(vp->v_mount), node, TMPFS_NODE_ACCESSED);
  424. return (uiomove_object(node->tn_reg.tn_aobj, node->tn_size, uio));
  425. }
  426. static int
  427. tmpfs_write(struct vop_write_args *v)
  428. {
  429. struct vnode *vp;
  430. struct uio *uio;
  431. struct tmpfs_node *node;
  432. off_t oldsize;
  433. int error, ioflag;
  434. vp = v->a_vp;
  435. uio = v->a_uio;
  436. ioflag = v->a_ioflag;
  437. error = 0;
  438. node = VP_TO_TMPFS_NODE(vp);
  439. oldsize = node->tn_size;
  440. if (uio->uio_offset < 0 || vp->v_type != VREG)
  441. return (EINVAL);
  442. if (uio->uio_resid == 0)
  443. return (0);
  444. if (ioflag & IO_APPEND)
  445. uio->uio_offset = node->tn_size;
  446. if (uio->uio_offset + uio->uio_resid >
  447. VFS_TO_TMPFS(vp->v_mount)->tm_maxfilesize)
  448. return (EFBIG);
  449. if (vn_rlimit_fsize(vp, uio, uio->uio_td))
  450. return (EFBIG);
  451. if (uio->uio_offset + uio->uio_resid > node->tn_size) {
  452. error = tmpfs_reg_resize(vp, uio->uio_offset + uio->uio_resid,
  453. FALSE);
  454. if (error != 0)
  455. goto out;
  456. }
  457. error = uiomove_object(node->tn_reg.tn_aobj, node->tn_size, uio);
  458. node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED |
  459. TMPFS_NODE_CHANGED;
  460. if (node->tn_mode & (S_ISUID | S_ISGID)) {
  461. if (priv_check_cred(v->a_cred, PRIV_VFS_RETAINSUGID))
  462. node->tn_mode &= ~(S_ISUID | S_ISGID);
  463. }
  464. if (error != 0)
  465. (void)tmpfs_reg_resize(vp, oldsize, TRUE);
  466. out:
  467. MPASS(IMPLIES(error == 0, uio->uio_resid == 0));
  468. MPASS(IMPLIES(error != 0, oldsize == node->tn_size));
  469. return (error);
  470. }
  471. static int
  472. tmpfs_fsync(struct vop_fsync_args *v)
  473. {
  474. struct vnode *vp = v->a_vp;
  475. MPASS(VOP_ISLOCKED(vp));
  476. tmpfs_check_mtime(vp);
  477. tmpfs_update(vp);
  478. return 0;
  479. }
  480. static int
  481. tmpfs_remove(struct vop_remove_args *v)
  482. {
  483. struct vnode *dvp = v->a_dvp;
  484. struct vnode *vp = v->a_vp;
  485. int error;
  486. struct tmpfs_dirent *de;
  487. struct tmpfs_mount *tmp;
  488. struct tmpfs_node *dnode;
  489. struct tmpfs_node *node;
  490. MPASS(VOP_ISLOCKED(dvp));
  491. MPASS(VOP_ISLOCKED(vp));
  492. if (vp->v_type == VDIR) {
  493. error = EISDIR;
  494. goto out;
  495. }
  496. dnode = VP_TO_TMPFS_DIR(dvp);
  497. node = VP_TO_TMPFS_NODE(vp);
  498. tmp = VFS_TO_TMPFS(vp->v_mount);
  499. de = tmpfs_dir_lookup(dnode, node, v->a_cnp);
  500. MPASS(de != NULL);
  501. /* Files marked as immutable or append-only cannot be deleted. */
  502. if ((node->tn_flags & (IMMUTABLE | APPEND | NOUNLINK)) ||
  503. (dnode->tn_flags & APPEND)) {
  504. error = EPERM;
  505. goto out;
  506. }
  507. /* Remove the entry from the directory; as it is a file, we do not
  508. * have to change the number of hard links of the directory. */
  509. tmpfs_dir_detach(dvp, de);
  510. if (v->a_cnp->cn_flags & DOWHITEOUT)
  511. tmpfs_dir_whiteout_add(dvp, v->a_cnp);
  512. /* Free the directory entry we just deleted. Note that the node
  513. * referred by it will not be removed until the vnode is really
  514. * reclaimed. */
  515. tmpfs_free_dirent(tmp, de);
  516. node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED;
  517. error = 0;
  518. out:
  519. return error;
  520. }
  521. static int
  522. tmpfs_link(struct vop_link_args *v)
  523. {
  524. struct vnode *dvp = v->a_tdvp;
  525. struct vnode *vp = v->a_vp;
  526. struct componentname *cnp = v->a_cnp;
  527. int error;
  528. struct tmpfs_dirent *de;
  529. struct tmpfs_node *node;
  530. MPASS(VOP_ISLOCKED(dvp));
  531. MPASS(cnp->cn_flags & HASBUF);
  532. MPASS(dvp != vp); /* XXX When can this be false? */
  533. node = VP_TO_TMPFS_NODE(vp);
  534. /* Ensure that we do not overflow the maximum number of links imposed
  535. * by the system. */
  536. MPASS(node->tn_links <= TMPFS_LINK_MAX);
  537. if (node->tn_links == TMPFS_LINK_MAX) {
  538. error = EMLINK;
  539. goto out;
  540. }
  541. /* We cannot create links of files marked immutable or append-only. */
  542. if (node->tn_flags & (IMMUTABLE | APPEND)) {
  543. error = EPERM;
  544. goto out;
  545. }
  546. /* Allocate a new directory entry to represent the node. */
  547. error = tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount), node,
  548. cnp->cn_nameptr, cnp->cn_namelen, &de);
  549. if (error != 0)
  550. goto out;
  551. /* Insert the new directory entry into the appropriate directory. */
  552. if (cnp->cn_flags & ISWHITEOUT)
  553. tmpfs_dir_whiteout_remove(dvp, cnp);
  554. tmpfs_dir_attach(dvp, de);
  555. /* vp link count has changed, so update node times. */
  556. node->tn_status |= TMPFS_NODE_CHANGED;
  557. tmpfs_update(vp);
  558. error = 0;
  559. out:
  560. return error;
  561. }
  562. /*
  563. * We acquire all but fdvp locks using non-blocking acquisitions. If we
  564. * fail to acquire any lock in the path we will drop all held locks,
  565. * acquire the new lock in a blocking fashion, and then release it and
  566. * restart the rename. This acquire/release step ensures that we do not
  567. * spin on a lock waiting for release. On error release all vnode locks
  568. * and decrement references the way tmpfs_rename() would do.
  569. */
  570. static int
  571. tmpfs_rename_relock(struct vnode *fdvp, struct vnode **fvpp,
  572. struct vnode *tdvp, struct vnode **tvpp,
  573. struct componentname *fcnp, struct componentname *tcnp)
  574. {
  575. struct vnode *nvp;
  576. struct mount *mp;
  577. struct tmpfs_dirent *de;
  578. int error, restarts = 0;
  579. VOP_UNLOCK(tdvp);
  580. if (*tvpp != NULL && *tvpp != tdvp)
  581. VOP_UNLOCK(*tvpp);
  582. mp = fdvp->v_mount;
  583. relock:
  584. restarts += 1;
  585. error = vn_lock(fdvp, LK_EXCLUSIVE);
  586. if (error)
  587. goto releout;
  588. if (vn_lock(tdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) {
  589. VOP_UNLOCK(fdvp);
  590. error = vn_lock(tdvp, LK_EXCLUSIVE);
  591. if (error)
  592. goto releout;
  593. VOP_UNLOCK(tdvp);
  594. goto relock;
  595. }
  596. /*
  597. * Re-resolve fvp to be certain it still exists and fetch the
  598. * correct vnode.
  599. */
  600. de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(fdvp), NULL, fcnp);
  601. if (de == NULL) {
  602. VOP_UNLOCK(fdvp);
  603. VOP_UNLOCK(tdvp);
  604. if ((fcnp->cn_flags & ISDOTDOT) != 0 ||
  605. (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.'))
  606. error = EINVAL;
  607. else
  608. error = ENOENT;
  609. goto releout;
  610. }
  611. error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE | LK_NOWAIT, &nvp);
  612. if (error != 0) {
  613. VOP_UNLOCK(fdvp);
  614. VOP_UNLOCK(tdvp);
  615. if (error != EBUSY)
  616. goto releout;
  617. error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE, &nvp);
  618. if (error != 0)
  619. goto releout;
  620. VOP_UNLOCK(nvp);
  621. /*
  622. * Concurrent rename race.
  623. */
  624. if (nvp == tdvp) {
  625. vrele(nvp);
  626. error = EINVAL;
  627. goto releout;
  628. }
  629. vrele(*fvpp);
  630. *fvpp = nvp;
  631. goto relock;
  632. }
  633. vrele(*fvpp);
  634. *fvpp = nvp;
  635. VOP_UNLOCK(*fvpp);
  636. /*
  637. * Re-resolve tvp and acquire the vnode lock if present.
  638. */
  639. de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(tdvp), NULL, tcnp);
  640. /*
  641. * If tvp disappeared we just carry on.
  642. */
  643. if (de == NULL && *tvpp != NULL) {
  644. vrele(*tvpp);
  645. *tvpp = NULL;
  646. }
  647. /*
  648. * Get the tvp ino if the lookup succeeded. We may have to restart
  649. * if the non-blocking acquire fails.
  650. */
  651. if (de != NULL) {
  652. nvp = NULL;
  653. error = tmpfs_alloc_vp(mp, de->td_node,
  654. LK_EXCLUSIVE | LK_NOWAIT, &nvp);
  655. if (*tvpp != NULL)
  656. vrele(*tvpp);
  657. *tvpp = nvp;
  658. if (error != 0) {
  659. VOP_UNLOCK(fdvp);
  660. VOP_UNLOCK(tdvp);
  661. if (error != EBUSY)
  662. goto releout;
  663. error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE,
  664. &nvp);
  665. if (error != 0)
  666. goto releout;
  667. VOP_UNLOCK(nvp);
  668. /*
  669. * fdvp contains fvp, thus tvp (=fdvp) is not empty.
  670. */
  671. if (nvp == fdvp) {
  672. error = ENOTEMPTY;
  673. goto releout;
  674. }
  675. goto relock;
  676. }
  677. }
  678. tmpfs_rename_restarts += restarts;
  679. return (0);
  680. releout:
  681. vrele(fdvp);
  682. vrele(*fvpp);
  683. vrele(tdvp);
  684. if (*tvpp != NULL)
  685. vrele(*tvpp);
  686. tmpfs_rename_restarts += restarts;
  687. return (error);
  688. }
  689. static int
  690. tmpfs_rename(struct vop_rename_args *v)
  691. {
  692. struct vnode *fdvp = v->a_fdvp;
  693. struct vnode *fvp = v->a_fvp;
  694. struct componentname *fcnp = v->a_fcnp;
  695. struct vnode *tdvp = v->a_tdvp;
  696. struct vnode *tvp = v->a_tvp;
  697. struct componentname *tcnp = v->a_tcnp;
  698. char *newname;
  699. struct tmpfs_dirent *de;
  700. struct tmpfs_mount *tmp;
  701. struct tmpfs_node *fdnode;
  702. struct tmpfs_node *fnode;
  703. struct tmpfs_node *tnode;
  704. struct tmpfs_node *tdnode;
  705. int error;
  706. MPASS(VOP_ISLOCKED(tdvp));
  707. MPASS(IMPLIES(tvp != NULL, VOP_ISLOCKED(tvp)));
  708. MPASS(fcnp->cn_flags & HASBUF);
  709. MPASS(tcnp->cn_flags & HASBUF);
  710. /*
  711. * Disallow cross-device renames.
  712. * XXX Why isn't this done by the caller?
  713. */
  714. if (fvp->v_mount != tdvp->v_mount ||
  715. (tvp != NULL && fvp->v_mount != tvp->v_mount)) {
  716. error = EXDEV;
  717. goto out;
  718. }
  719. /* If source and target are the same file, there is nothing to do. */
  720. if (fvp == tvp) {
  721. error = 0;
  722. goto out;
  723. }
  724. /*
  725. * If we need to move the directory between entries, lock the
  726. * source so that we can safely operate on it.
  727. */
  728. if (fdvp != tdvp && fdvp != tvp) {
  729. if (vn_lock(fdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) {
  730. error = tmpfs_rename_relock(fdvp, &fvp, tdvp, &tvp,
  731. fcnp, tcnp);
  732. if (error != 0)
  733. return (error);
  734. ASSERT_VOP_ELOCKED(fdvp,
  735. "tmpfs_rename: fdvp not locked");
  736. ASSERT_VOP_ELOCKED(tdvp,
  737. "tmpfs_rename: tdvp not locked");
  738. if (tvp != NULL)
  739. ASSERT_VOP_ELOCKED(tvp,
  740. "tmpfs_rename: tvp not locked");
  741. if (fvp == tvp) {
  742. error = 0;
  743. goto out_locked;
  744. }
  745. }
  746. }
  747. tmp = VFS_TO_TMPFS(tdvp->v_mount);
  748. tdnode = VP_TO_TMPFS_DIR(tdvp);
  749. tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp);
  750. fdnode = VP_TO_TMPFS_DIR(fdvp);
  751. fnode = VP_TO_TMPFS_NODE(fvp);
  752. de = tmpfs_dir_lookup(fdnode, fnode, fcnp);
  753. /*
  754. * Entry can disappear before we lock fdvp,
  755. * also avoid manipulating '.' and '..' entries.
  756. */
  757. if (de == NULL) {
  758. if ((fcnp->cn_flags & ISDOTDOT) != 0 ||
  759. (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.'))
  760. error = EINVAL;
  761. else
  762. error = ENOENT;
  763. goto out_locked;
  764. }
  765. MPASS(de->td_node == fnode);
  766. /*
  767. * If re-naming a directory to another preexisting directory
  768. * ensure that the target directory is empty so that its
  769. * removal causes no side effects.
  770. * Kern_rename guarantees the destination to be a directory
  771. * if the source is one.
  772. */
  773. if (tvp != NULL) {
  774. MPASS(tnode != NULL);
  775. if ((tnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
  776. (tdnode->tn_flags & (APPEND | IMMUTABLE))) {
  777. error = EPERM;
  778. goto out_locked;
  779. }
  780. if (fnode->tn_type == VDIR && tnode->tn_type == VDIR) {
  781. if (tnode->tn_size > 0) {
  782. error = ENOTEMPTY;
  783. goto out_locked;
  784. }
  785. } else if (fnode->tn_type == VDIR && tnode->tn_type != VDIR) {
  786. error = ENOTDIR;
  787. goto out_locked;
  788. } else if (fnode->tn_type != VDIR && tnode->tn_type == VDIR) {
  789. error = EISDIR;
  790. goto out_locked;
  791. } else {
  792. MPASS(fnode->tn_type != VDIR &&
  793. tnode->tn_type != VDIR);
  794. }
  795. }
  796. if ((fnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND))
  797. || (fdnode->tn_flags & (APPEND | IMMUTABLE))) {
  798. error = EPERM;
  799. goto out_locked;
  800. }
  801. /*
  802. * Ensure that we have enough memory to hold the new name, if it
  803. * has to be changed.
  804. */
  805. if (fcnp->cn_namelen != tcnp->cn_namelen ||
  806. bcmp(fcnp->cn_nameptr, tcnp->cn_nameptr, fcnp->cn_namelen) != 0) {
  807. newname = malloc(tcnp->cn_namelen, M_TMPFSNAME, M_WAITOK);
  808. } else
  809. newname = NULL;
  810. /*
  811. * If the node is being moved to another directory, we have to do
  812. * the move.
  813. */
  814. if (fdnode != tdnode) {
  815. /*
  816. * In case we are moving a directory, we have to adjust its
  817. * parent to point to the new parent.
  818. */
  819. if (de->td_node->tn_type == VDIR) {
  820. struct tmpfs_node *n;
  821. /*
  822. * Ensure the target directory is not a child of the
  823. * directory being moved. Otherwise, we'd end up
  824. * with stale nodes.
  825. */
  826. n = tdnode;
  827. /*
  828. * TMPFS_LOCK guaranties that no nodes are freed while
  829. * traversing the list. Nodes can only be marked as
  830. * removed: tn_parent == NULL.
  831. */
  832. TMPFS_LOCK(tmp);
  833. TMPFS_NODE_LOCK(n);
  834. while (n != n->tn_dir.tn_parent) {
  835. struct tmpfs_node *parent;
  836. if (n == fnode) {
  837. TMPFS_NODE_UNLOCK(n);
  838. TMPFS_UNLOCK(tmp);
  839. error = EINVAL;
  840. if (newname != NULL)
  841. free(newname, M_TMPFSNAME);
  842. goto out_locked;
  843. }
  844. parent = n->tn_dir.tn_parent;
  845. TMPFS_NODE_UNLOCK(n);
  846. if (parent == NULL) {
  847. n = NULL;
  848. break;
  849. }
  850. TMPFS_NODE_LOCK(parent);
  851. if (parent->tn_dir.tn_parent == NULL) {
  852. TMPFS_NODE_UNLOCK(parent);
  853. n = NULL;
  854. break;
  855. }
  856. n = parent;
  857. }
  858. TMPFS_UNLOCK(tmp);
  859. if (n == NULL) {
  860. error = EINVAL;
  861. if (newname != NULL)
  862. free(newname, M_TMPFSNAME);
  863. goto out_locked;
  864. }
  865. TMPFS_NODE_UNLOCK(n);
  866. /* Adjust the parent pointer. */
  867. TMPFS_VALIDATE_DIR(fnode);
  868. TMPFS_NODE_LOCK(de->td_node);
  869. de->td_node->tn_dir.tn_parent = tdnode;
  870. TMPFS_NODE_UNLOCK(de->td_node);
  871. /*
  872. * As a result of changing the target of the '..'
  873. * entry, the link count of the source and target
  874. * directories has to be adjusted.
  875. */
  876. TMPFS_NODE_LOCK(tdnode);
  877. TMPFS_ASSERT_LOCKED(tdnode);
  878. tdnode->tn_links++;
  879. TMPFS_NODE_UNLOCK(tdnode);
  880. TMPFS_NODE_LOCK(fdnode);
  881. TMPFS_ASSERT_LOCKED(fdnode);
  882. fdnode->tn_links--;
  883. TMPFS_NODE_UNLOCK(fdnode);
  884. }
  885. }
  886. /*
  887. * Do the move: just remove the entry from the source directory
  888. * and insert it into the target one.
  889. */
  890. tmpfs_dir_detach(fdvp, de);
  891. if (fcnp->cn_flags & DOWHITEOUT)
  892. tmpfs_dir_whiteout_add(fdvp, fcnp);
  893. if (tcnp->cn_flags & ISWHITEOUT)
  894. tmpfs_dir_whiteout_remove(tdvp, tcnp);
  895. /*
  896. * If the name has changed, we need to make it effective by changing
  897. * it in the directory entry.
  898. */
  899. if (newname != NULL) {
  900. MPASS(tcnp->cn_namelen <= MAXNAMLEN);
  901. free(de->ud.td_name, M_TMPFSNAME);
  902. de->ud.td_name = newname;
  903. tmpfs_dirent_init(de, tcnp->cn_nameptr, tcnp->cn_namelen);
  904. fnode->tn_status |= TMPFS_NODE_CHANGED;
  905. tdnode->tn_status |= TMPFS_NODE_MODIFIED;
  906. }
  907. /*
  908. * If we are overwriting an entry, we have to remove the old one
  909. * from the target directory.
  910. */
  911. if (tvp != NULL) {
  912. struct tmpfs_dirent *tde;
  913. /* Remove the old entry from the target directory. */
  914. tde = tmpfs_dir_lookup(tdnode, tnode, tcnp);
  915. tmpfs_dir_detach(tdvp, tde);
  916. /*
  917. * Free the directory entry we just deleted. Note that the
  918. * node referred by it will not be removed until the vnode is
  919. * really reclaimed.
  920. */
  921. tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), tde);
  922. }
  923. tmpfs_dir_attach(tdvp, de);
  924. if (tmpfs_use_nc(fvp)) {
  925. cache_purge(fvp);
  926. if (tvp != NULL)
  927. cache_purge(tvp);
  928. cache_purge_negative(tdvp);
  929. }
  930. error = 0;
  931. out_locked:
  932. if (fdvp != tdvp && fdvp != tvp)
  933. VOP_UNLOCK(fdvp);
  934. out:
  935. /*
  936. * Release target nodes.
  937. * XXX: I don't understand when tdvp can be the same as tvp, but
  938. * other code takes care of this...
  939. */
  940. if (tdvp == tvp)
  941. vrele(tdvp);
  942. else
  943. vput(tdvp);
  944. if (tvp != NULL)
  945. vput(tvp);
  946. /* Release source nodes. */
  947. vrele(fdvp);
  948. vrele(fvp);
  949. return (error);
  950. }
  951. static int
  952. tmpfs_mkdir(struct vop_mkdir_args *v)
  953. {
  954. struct vnode *dvp = v->a_dvp;
  955. struct vnode **vpp = v->a_vpp;
  956. struct componentname *cnp = v->a_cnp;
  957. struct vattr *vap = v->a_vap;
  958. MPASS(vap->va_type == VDIR);
  959. return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
  960. }
  961. static int
  962. tmpfs_rmdir(struct vop_rmdir_args *v)
  963. {
  964. struct vnode *dvp = v->a_dvp;
  965. struct vnode *vp = v->a_vp;
  966. int error;
  967. struct tmpfs_dirent *de;
  968. struct tmpfs_mount *tmp;
  969. struct tmpfs_node *dnode;
  970. struct tmpfs_node *node;
  971. MPASS(VOP_ISLOCKED(dvp));
  972. MPASS(VOP_ISLOCKED(vp));
  973. tmp = VFS_TO_TMPFS(dvp->v_mount);
  974. dnode = VP_TO_TMPFS_DIR(dvp);
  975. node = VP_TO_TMPFS_DIR(vp);
  976. /* Directories with more than two entries ('.' and '..') cannot be
  977. * removed. */
  978. if (node->tn_size > 0) {
  979. error = ENOTEMPTY;
  980. goto out;
  981. }
  982. if ((dnode->tn_flags & APPEND)
  983. || (node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND))) {
  984. error = EPERM;
  985. goto out;
  986. }
  987. /* This invariant holds only if we are not trying to remove "..".
  988. * We checked for that above so this is safe now. */
  989. MPASS(node->tn_dir.tn_parent == dnode);
  990. /* Get the directory entry associated with node (vp). This was
  991. * filled by tmpfs_lookup while looking up the entry. */
  992. de = tmpfs_dir_lookup(dnode, node, v->a_cnp);
  993. MPASS(TMPFS_DIRENT_MATCHES(de,
  994. v->a_cnp->cn_nameptr,
  995. v->a_cnp->cn_namelen));
  996. /* Check flags to see if we are allowed to remove the directory. */
  997. if ((dnode->tn_flags & APPEND) != 0 ||
  998. (node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) != 0) {
  999. error = EPERM;
  1000. goto out;
  1001. }
  1002. /* Detach the directory entry from the directory (dnode). */
  1003. tmpfs_dir_detach(dvp, de);
  1004. if (v->a_cnp->cn_flags & DOWHITEOUT)
  1005. tmpfs_dir_whiteout_add(dvp, v->a_cnp);
  1006. /* No vnode should be allocated for this entry from this point */
  1007. TMPFS_NODE_LOCK(node);
  1008. node->tn_links--;
  1009. node->tn_dir.tn_parent = NULL;
  1010. node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED |
  1011. TMPFS_NODE_MODIFIED;
  1012. TMPFS_NODE_UNLOCK(node);
  1013. TMPFS_NODE_LOCK(dnode);
  1014. dnode->tn_links--;
  1015. dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED |
  1016. TMPFS_NODE_MODIFIED;
  1017. TMPFS_NODE_UNLOCK(dnode);
  1018. if (tmpfs_use_nc(dvp)) {
  1019. cache_purge(dvp);
  1020. cache_purge(vp);
  1021. }
  1022. /* Free the directory entry we just deleted. Note that the node
  1023. * referred by it will not be removed until the vnode is really
  1024. * reclaimed. */
  1025. tmpfs_free_dirent(tmp, de);
  1026. /* Release the deleted vnode (will destroy the node, notify
  1027. * interested parties and clean it from the cache). */
  1028. dnode->tn_status |= TMPFS_NODE_CHANGED;
  1029. tmpfs_update(dvp);
  1030. error = 0;
  1031. out:
  1032. return error;
  1033. }
  1034. static int
  1035. tmpfs_symlink(struct vop_symlink_args *v)
  1036. {
  1037. struct vnode *dvp = v->a_dvp;
  1038. struct vnode **vpp = v->a_vpp;
  1039. struct componentname *cnp = v->a_cnp;
  1040. struct vattr *vap = v->a_vap;
  1041. const char *target = v->a_target;
  1042. #ifdef notyet /* XXX FreeBSD BUG: kern_symlink is not setting VLNK */
  1043. MPASS(vap->va_type == VLNK);
  1044. #else
  1045. vap->va_type = VLNK;
  1046. #endif
  1047. return tmpfs_alloc_file(dvp, vpp, vap, cnp, target);
  1048. }
  1049. static int
  1050. tmpfs_readdir(struct vop_readdir_args *va)
  1051. {
  1052. struct vnode *vp;
  1053. struct uio *uio;
  1054. struct tmpfs_mount *tm;
  1055. struct tmpfs_node *node;
  1056. u_long **cookies;
  1057. int *eofflag, *ncookies;
  1058. ssize_t startresid;
  1059. int error, maxcookies;
  1060. vp = va->a_vp;
  1061. uio = va->a_uio;
  1062. eofflag = va->a_eofflag;
  1063. cookies = va->a_cookies;
  1064. ncookies = va->a_ncookies;
  1065. /* This operation only makes sense on directory nodes. */
  1066. if (vp->v_type != VDIR)
  1067. return ENOTDIR;
  1068. maxcookies = 0;
  1069. node = VP_TO_TMPFS_DIR(vp);
  1070. tm = VFS_TO_TMPFS(vp->v_mount);
  1071. startresid = uio->uio_resid;
  1072. /* Allocate cookies for NFS and compat modules. */
  1073. if (cookies != NULL && ncookies != NULL) {
  1074. maxcookies = howmany(node->tn_size,
  1075. sizeof(struct tmpfs_dirent)) + 2;
  1076. *cookies = malloc(maxcookies * sizeof(**cookies), M_TEMP,
  1077. M_WAITOK);
  1078. *ncookies = 0;
  1079. }
  1080. if (cookies == NULL)
  1081. error = tmpfs_dir_getdents(tm, node, uio, 0, NULL, NULL);
  1082. else
  1083. error = tmpfs_dir_getdents(tm, node, uio, maxcookies, *cookies,
  1084. ncookies);
  1085. /* Buffer was filled without hitting EOF. */
  1086. if (error == EJUSTRETURN)
  1087. error = (uio->uio_resid != startresid) ? 0 : EINVAL;
  1088. if (error != 0 && cookies != NULL && ncookies != NULL) {
  1089. free(*cookies, M_TEMP);
  1090. *cookies = NULL;
  1091. *ncookies = 0;
  1092. }
  1093. if (eofflag != NULL)
  1094. *eofflag =
  1095. (error == 0 && uio->uio_offset == TMPFS_DIRCOOKIE_EOF);
  1096. return error;
  1097. }
  1098. static int
  1099. tmpfs_readlink(struct vop_readlink_args *v)
  1100. {
  1101. struct vnode *vp = v->a_vp;
  1102. struct uio *uio = v->a_uio;
  1103. int error;
  1104. struct tmpfs_node *node;
  1105. MPASS(uio->uio_offset == 0);
  1106. MPASS(vp->v_type == VLNK);
  1107. node = VP_TO_TMPFS_NODE(vp);
  1108. error = uiomove(node->tn_link, MIN(node->tn_size, uio->uio_resid),
  1109. uio);
  1110. tmpfs_set_status(VFS_TO_TMPFS(vp->v_mount), node, TMPFS_NODE_ACCESSED);
  1111. return (error);
  1112. }
  1113. static int
  1114. tmpfs_inactive(struct vop_inactive_args *v)
  1115. {
  1116. struct vnode *vp;
  1117. struct tmpfs_node *node;
  1118. vp = v->a_vp;
  1119. node = VP_TO_TMPFS_NODE(vp);
  1120. if (node->tn_links == 0)
  1121. vrecycle(vp);
  1122. else
  1123. tmpfs_check_mtime(vp);
  1124. return (0);
  1125. }
  1126. static int
  1127. tmpfs_need_inactive(struct vop_need_inactive_args *ap)
  1128. {
  1129. struct vnode *vp;
  1130. struct tmpfs_node *node;
  1131. struct vm_object *obj;
  1132. vp = ap->a_vp;
  1133. node = VP_TO_TMPFS_NODE(vp);
  1134. if (node->tn_links == 0)
  1135. goto need;
  1136. if (vp->v_type == VREG) {
  1137. obj = vp->v_object;
  1138. if (obj->generation != obj->cleangeneration)
  1139. goto need;
  1140. }
  1141. return (0);
  1142. need:
  1143. return (1);
  1144. }
  1145. int
  1146. tmpfs_reclaim(struct vop_reclaim_args *v)
  1147. {
  1148. struct vnode *vp = v->a_vp;
  1149. struct tmpfs_mount *tmp;
  1150. struct tmpfs_node *node;
  1151. node = VP_TO_TMPFS_NODE(vp);
  1152. tmp = VFS_TO_TMPFS(vp->v_mount);
  1153. if (vp->v_type == VREG)
  1154. tmpfs_destroy_vobject(vp, node->tn_reg.tn_aobj);
  1155. vp->v_object = NULL;
  1156. if (tmpfs_use_nc(vp))
  1157. cache_purge(vp);
  1158. TMPFS_NODE_LOCK(node);
  1159. tmpfs_free_vp(vp);
  1160. /* If the node referenced by this vnode was deleted by the user,
  1161. * we must free its associated data structures (now that the vnode
  1162. * is being reclaimed). */
  1163. if (node->tn_links == 0 &&
  1164. (node->tn_vpstate & TMPFS_VNODE_ALLOCATING) == 0) {
  1165. node->tn_vpstate = TMPFS_VNODE_DOOMED;
  1166. TMPFS_NODE_UNLOCK(node);
  1167. tmpfs_free_node(tmp, node);
  1168. } else
  1169. TMPFS_NODE_UNLOCK(node);
  1170. MPASS(vp->v_data == NULL);
  1171. return 0;
  1172. }
  1173. int
  1174. tmpfs_print(struct vop_print_args *v)
  1175. {
  1176. struct vnode *vp = v->a_vp;
  1177. struct tmpfs_node *node;
  1178. node = VP_TO_TMPFS_NODE(vp);
  1179. printf("tag VT_TMPFS, tmpfs_node %p, flags 0x%lx, links %jd\n",
  1180. node, node->tn_flags, (uintmax_t)node->tn_links);
  1181. printf("\tmode 0%o, owner %d, group %d, size %jd, status 0x%x\n",
  1182. node->tn_mode, node->tn_uid, node->tn_gid,
  1183. (intmax_t)node->tn_size, node->tn_status);
  1184. if (vp->v_type == VFIFO)
  1185. fifo_printinfo(vp);
  1186. printf("\n");
  1187. return 0;
  1188. }
  1189. int
  1190. tmpfs_pathconf(struct vop_pathconf_args *v)
  1191. {
  1192. struct vnode *vp = v->a_vp;
  1193. int name = v->a_name;
  1194. long *retval = v->a_retval;
  1195. int error;
  1196. error = 0;
  1197. switch (name) {
  1198. case _PC_LINK_MAX:
  1199. *retval = TMPFS_LINK_MAX;
  1200. break;
  1201. case _PC_NAME_MAX:
  1202. *retval = NAME_MAX;
  1203. break;
  1204. case _PC_PIPE_BUF:
  1205. if (vp->v_type == VDIR || vp->v_type == VFIFO)
  1206. *retval = PIPE_BUF;
  1207. else
  1208. error = EINVAL;
  1209. break;
  1210. case _PC_CHOWN_RESTRICTED:
  1211. *retval = 1;
  1212. break;
  1213. case _PC_NO_TRUNC:
  1214. *retval = 1;
  1215. break;
  1216. case _PC_SYNC_IO:
  1217. *retval = 1;
  1218. break;
  1219. case _PC_FILESIZEBITS:
  1220. *retval = 64;
  1221. break;
  1222. default:
  1223. error = vop_stdpathconf(v);
  1224. }
  1225. return error;
  1226. }
  1227. static int
  1228. tmpfs_vptofh(struct vop_vptofh_args *ap)
  1229. /*
  1230. vop_vptofh {
  1231. IN struct vnode *a_vp;
  1232. IN struct fid *a_fhp;
  1233. };
  1234. */
  1235. {
  1236. struct tmpfs_fid_data tfd;
  1237. struct tmpfs_node *node;
  1238. struct fid *fhp;
  1239. node = VP_TO_TMPFS_NODE(ap->a_vp);
  1240. fhp = ap->a_fhp;
  1241. fhp->fid_len = sizeof(tfd);
  1242. /*
  1243. * Copy into fid_data from the stack to avoid unaligned pointer use.
  1244. * See the comment in sys/mount.h on struct fid for details.
  1245. */
  1246. tfd.tfd_id = node->tn_id;
  1247. tfd.tfd_gen = node->tn_gen;
  1248. memcpy(fhp->fid_data, &tfd, fhp->fid_len);
  1249. return (0);
  1250. }
  1251. static int
  1252. tmpfs_whiteout(struct vop_whiteout_args *ap)
  1253. {
  1254. struct vnode *dvp = ap->a_dvp;
  1255. struct componentname *cnp = ap->a_cnp;
  1256. struct tmpfs_dirent *de;
  1257. switch (ap->a_flags) {
  1258. case LOOKUP:
  1259. return (0);
  1260. case CREATE:
  1261. de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(dvp), NULL, cnp);
  1262. if (de != NULL)
  1263. return (de->td_node == NULL ? 0 : EEXIST);
  1264. return (tmpfs_dir_whiteout_add(dvp, cnp));
  1265. case DELETE:
  1266. tmpfs_dir_whiteout_remove(dvp, cnp);
  1267. return (0);
  1268. default:
  1269. panic("tmpfs_whiteout: unknown op");
  1270. }
  1271. }
  1272. static int
  1273. tmpfs_vptocnp_dir(struct tmpfs_node *tn, struct tmpfs_node *tnp,
  1274. struct tmpfs_dirent **pde)
  1275. {
  1276. struct tmpfs_dir_cursor dc;
  1277. struct tmpfs_dirent *de;
  1278. for (de = tmpfs_dir_first(tnp, &dc); de != NULL;
  1279. de = tmpfs_dir_next(tnp, &dc)) {
  1280. if (de->td_node == tn) {
  1281. *pde = de;
  1282. return (0);
  1283. }
  1284. }
  1285. return (ENOENT);
  1286. }
  1287. static int
  1288. tmpfs_vptocnp_fill(struct vnode *vp, struct tmpfs_node *tn,
  1289. struct tmpfs_node *tnp, char *buf, size_t *buflen, struct vnode **dvp)
  1290. {
  1291. struct tmpfs_dirent *de;
  1292. int error, i;
  1293. error = vn_vget_ino_gen(vp, tmpfs_vn_get_ino_alloc, tnp, LK_SHARED,
  1294. dvp);
  1295. if (error != 0)
  1296. return (error);
  1297. error = tmpfs_vptocnp_dir(tn, tnp, &de);
  1298. if (error == 0) {
  1299. i = *buflen;
  1300. i -= de->td_namelen;
  1301. if (i < 0) {
  1302. error = ENOMEM;
  1303. } else {
  1304. bcopy(de->ud.td_name, buf + i, de->td_namelen);
  1305. *buflen = i;
  1306. }
  1307. }
  1308. if (error == 0) {
  1309. if (vp != *dvp)
  1310. VOP_UNLOCK(*dvp);
  1311. } else {
  1312. if (vp != *dvp)
  1313. vput(*dvp);
  1314. else
  1315. vrele(vp);
  1316. }
  1317. return (error);
  1318. }
  1319. static int
  1320. tmpfs_vptocnp(struct vop_vptocnp_args *ap)
  1321. {
  1322. struct vnode *vp, **dvp;
  1323. struct tmpfs_node *tn, *tnp, *tnp1;
  1324. struct tmpfs_dirent *de;
  1325. struct tmpfs_mount *tm;
  1326. char *buf;
  1327. size_t *buflen;
  1328. int error;
  1329. vp = ap->a_vp;
  1330. dvp = ap->a_vpp;
  1331. buf = ap->a_buf;
  1332. buflen = ap->a_buflen;
  1333. tm = VFS_TO_TMPFS(vp->v_mount);
  1334. tn = VP_TO_TMPFS_NODE(vp);
  1335. if (tn->tn_type == VDIR) {
  1336. tnp = tn->tn_dir.tn_parent;
  1337. if (tnp == NULL)
  1338. return (ENOENT);
  1339. tmpfs_ref_node(tnp);
  1340. error = tmpfs_vptocnp_fill(vp, tn, tn->tn_dir.tn_parent, buf,
  1341. buflen, dvp);
  1342. tmpfs_free_node(tm, tnp);
  1343. return (error);
  1344. }
  1345. restart:
  1346. TMPFS_LOCK(tm);
  1347. LIST_FOREACH_SAFE(tnp, &tm->tm_nodes_used, tn_entries, tnp1) {
  1348. if (tnp->tn_type != VDIR)
  1349. continue;
  1350. TMPFS_NODE_LOCK(tnp);
  1351. tmpfs_ref_node_locked(tnp);
  1352. /*
  1353. * tn_vnode cannot be instantiated while we hold the
  1354. * node lock, so the directory cannot be changed while
  1355. * we iterate over it. Do this to avoid instantiating
  1356. * vnode for directories which cannot point to our
  1357. * node.
  1358. */
  1359. error = tnp->tn_vnode == NULL ? tmpfs_vptocnp_dir(tn, tnp,
  1360. &de) : 0;
  1361. if (error == 0) {
  1362. TMPFS_NODE_UNLOCK(tnp);
  1363. TMPFS_UNLOCK(tm);
  1364. error = tmpfs_vptocnp_fill(vp, tn, tnp, buf, buflen,
  1365. dvp);
  1366. if (error == 0) {
  1367. tmpfs_free_node(tm, tnp);
  1368. return (0);
  1369. }
  1370. if (VN_IS_DOOMED(vp)) {
  1371. tmpfs_free_node(tm, tnp);
  1372. return (ENOENT);
  1373. }
  1374. TMPFS_LOCK(tm);
  1375. TMPFS_NODE_LOCK(tnp);
  1376. }
  1377. if (tmpfs_free_node_locked(tm, tnp, false)) {
  1378. goto restart;
  1379. } else {
  1380. KASSERT(tnp->tn_refcount > 0,
  1381. ("node %p refcount zero", tnp));
  1382. tnp1 = LIST_NEXT(tnp, tn_entries);
  1383. TMPFS_NODE_UNLOCK(tnp);
  1384. }
  1385. }
  1386. TMPFS_UNLOCK(tm);
  1387. return (ENOENT);
  1388. }
  1389. static struct tmpfs_extattr_list_entry *
  1390. tmpfs_node_has_extattr(struct tmpfs_node *node, int attrnamespace,
  1391. const char *name)
  1392. {
  1393. struct tmpfs_extattr_list_entry *entry, *tentry;
  1394. entry = NULL;
  1395. TMPFS_NODE_LOCK(node);
  1396. LIST_FOREACH_SAFE(entry, &(node->tn_reg.tn_extattr_list),
  1397. tele_entries, tentry) {
  1398. if (attrnamespace != entry->tele_attrnamespace) {
  1399. continue;
  1400. }
  1401. if (!strcmp(name, entry->tele_attrname)) {
  1402. break;
  1403. }
  1404. }
  1405. TMPFS_NODE_UNLOCK(node);
  1406. return (entry);
  1407. }
  1408. static int
  1409. tmpfs_getextattr(struct vop_getextattr_args *ap)
  1410. {
  1411. return (tmpfs_extattr_get(ap->a_vp, ap->a_attrnamespace,
  1412. ap->a_name, ap->a_uio, ap->a_size, ap->a_cred, ap->a_td));
  1413. }
  1414. static int
  1415. tmpfs_extattr_get(struct vnode *vp, int attrnamespace, const char *name,
  1416. struct uio *uio, size_t *size, struct ucred *cred, struct thread *td)
  1417. {
  1418. struct tmpfs_extattr_list_entry *attr;
  1419. struct tmpfs_node *node;
  1420. size_t len;
  1421. int error;
  1422. if (vp->v_type != VREG) {
  1423. return (EOPNOTSUPP);
  1424. }
  1425. error = extattr_check_cred(vp, attrnamespace, cred, td, VREAD);
  1426. if (error) {
  1427. return (error);
  1428. }
  1429. node = VP_TO_TMPFS_NODE(vp);
  1430. attr = tmpfs_node_has_extattr(node, attrnamespace, name);
  1431. if (attr == NULL) {
  1432. return (ENOATTR);
  1433. }
  1434. if (size) {
  1435. *size = attr->tele_value_size;
  1436. }
  1437. if (uio != NULL) {
  1438. len = MIN(attr->tele_value_size, uio->uio_resid);
  1439. uio->uio_resid = len;
  1440. uio->uio_offset = 0;
  1441. error = uiomove(attr->tele_value, len, uio);
  1442. }
  1443. return (error);
  1444. }
  1445. static int
  1446. tmpfs_setextattr(struct vop_setextattr_args *ap)
  1447. {
  1448. return (tmpfs_extattr_set(ap->a_vp, ap->a_attrnamespace,
  1449. ap->a_name, ap->a_uio, ap->a_cred, ap->a_td));
  1450. }
  1451. static int
  1452. tmpfs_extattr_set(struct vnode *vp, int attrnamespace, const char *name,
  1453. struct uio *uio, struct ucred *cred, struct thread *td)
  1454. {
  1455. struct tmpfs_extattr_list_entry *attr;
  1456. struct tmpfs_node *node;
  1457. size_t sz;
  1458. int error;
  1459. if (vp->v_type != VREG) {
  1460. return (EOPNOTSUPP);
  1461. }
  1462. error = extattr_check_cred(vp, attrnamespace, cred, td, VWRITE);
  1463. if (error) {
  1464. return (error);
  1465. }
  1466. if (uio->uio_resid > TMPFS_EXTATTR_MAXVALUESIZE) {
  1467. return (EINVAL);
  1468. }
  1469. if (strlen(name) == 0) {
  1470. return (EINVAL);
  1471. }
  1472. if (strlen(name) >= TMPFS_EXTATTR_MAXNAME) {
  1473. return (EINVAL);
  1474. }
  1475. node = VP_TO_TMPFS_NODE(vp);
  1476. attr = tmpfs_node_has_extattr(node, attrnamespace, name);
  1477. if (attr == NULL) {
  1478. sz = MIN(TMPFS_EXTATTR_MAXVALUESIZE, uio->uio_resid);
  1479. attr = malloc(sizeof(*attr), M_TEMP, M_WAITOK|M_ZERO);
  1480. attr->tele_value = malloc(sz, M_TEMP, M_WAITOK);
  1481. attr->tele_value_size = sz;
  1482. attr->tele_attrnamespace = attrnamespace;
  1483. strncpy(attr->tele_attrname, name,
  1484. sizeof(attr->tele_attrname)-1);
  1485. uiomove(attr->tele_value, sz, uio);
  1486. TMPFS_NODE_LOCK(node);
  1487. LIST_INSERT_HEAD(&(node->tn_reg.tn_extattr_list),
  1488. attr, tele_entries);
  1489. TMPFS_NODE_UNLOCK(node);
  1490. }
  1491. return (0);
  1492. }
  1493. static int
  1494. tmpfs_listextattr(struct vop_listextattr_args *ap)
  1495. {
  1496. return tmpfs_extattr_list(ap->a_vp, ap->a_attrnamespace,
  1497. ap->a_uio, ap->a_size, ap->a_cred, ap->a_td);
  1498. }
  1499. static int
  1500. tmpfs_extattr_list(struct vnode *vp, int attrnamespace, struct uio *uio,
  1501. size_t *size, struct ucred *cred, struct thread *td)
  1502. {
  1503. struct tmpfs_extattr_list_entry *attr, *tattr;
  1504. struct tmpfs_node *node;
  1505. size_t namelen;
  1506. uint8_t namelen8;
  1507. int error;
  1508. if (vp->v_type != VREG) {
  1509. return (EOPNOTSUPP);
  1510. }
  1511. error = extattr_check_cred(vp, attrnamespace, cred, td, VREAD);
  1512. if (error) {
  1513. return (error);
  1514. }
  1515. node = VP_TO_TMPFS_NODE(vp);
  1516. if (size) {
  1517. *size = 0;
  1518. }
  1519. LIST_FOREACH_SAFE(attr, &(node->tn_reg.tn_extattr_list),
  1520. tele_entries, tattr) {
  1521. if (attr->tele_attrnamespace != attrnamespace) {
  1522. continue;
  1523. }
  1524. namelen = strlen(attr->tele_attrname);
  1525. if (size) {
  1526. *size += namelen + sizeof(namelen8);
  1527. } else if (uio != NULL) {
  1528. namelen8 = namelen;
  1529. error = uiomove(&namelen8, sizeof(namelen8), uio);
  1530. if (error) {
  1531. break;
  1532. }
  1533. error = uiomove(attr->tele_attrname, namelen, uio);
  1534. if (error) {
  1535. break;
  1536. }
  1537. }
  1538. if (error) {
  1539. break;
  1540. }
  1541. }
  1542. return (error);
  1543. }
  1544. /*
  1545. * Vnode operations vector used for files stored in a tmpfs file system.
  1546. */
  1547. struct vop_vector tmpfs_vnodeop_entries = {
  1548. .vop_default = &default_vnodeops,
  1549. .vop_lookup = vfs_cache_lookup,
  1550. .vop_cachedlookup = tmpfs_cached_lookup,
  1551. .vop_create = tmpfs_create,
  1552. .vop_mknod = tmpfs_mknod,
  1553. .vop_open = tmpfs_open,
  1554. .vop_close = tmpfs_close,
  1555. .vop_access = tmpfs_access,
  1556. .vop_getattr = tmpfs_getattr,
  1557. .vop_setattr = tmpfs_setattr,
  1558. .vop_getextattr = tmpfs_getextattr,
  1559. .vop_setextattr = tmpfs_setextattr,
  1560. .vop_listextattr = tmpfs_listextattr,
  1561. .vop_read = tmpfs_read,
  1562. .vop_write = tmpfs_write,
  1563. .vop_fsync = tmpfs_fsync,
  1564. .vop_remove = tmpfs_remove,
  1565. .vop_link = tmpfs_link,
  1566. .vop_rename = tmpfs_rename,
  1567. .vop_mkdir = tmpfs_mkdir,
  1568. .vop_rmdir = tmpfs_rmdir,
  1569. .vop_symlink = tmpfs_symlink,
  1570. .vop_readdir = tmpfs_readdir,
  1571. .vop_readlink = tmpfs_readlink,
  1572. .vop_inactive = tmpfs_inactive,
  1573. .vop_need_inactive = tmpfs_need_inactive,
  1574. .vop_reclaim = tmpfs_reclaim,
  1575. .vop_print = tmpfs_print,
  1576. .vop_pathconf = tmpfs_pathconf,
  1577. .vop_vptofh = tmpfs_vptofh,
  1578. .vop_whiteout = tmpfs_whiteout,
  1579. .vop_bmap = VOP_EOPNOTSUPP,
  1580. .vop_vptocnp = tmpfs_vptocnp,
  1581. .vop_lock1 = vop_lock,
  1582. .vop_unlock = vop_unlock,
  1583. .vop_islocked = vop_islocked,
  1584. };
  1585. VFS_VOP_VECTOR_REGISTER(tmpfs_vnodeop_entries);
  1586. /*
  1587. * Same vector for mounts which do not use namecache.
  1588. */
  1589. struct vop_vector tmpfs_vnodeop_nonc_entries = {
  1590. .vop_default = &tmpfs_vnodeop_entries,
  1591. .vop_lookup = tmpfs_lookup,
  1592. };
  1593. VFS_VOP_VECTOR_REGISTER(tmpfs_vnodeop_nonc_entries);