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.
 
 
 
 
 
 

590 lines
18 KiB

  1. /* $NetBSD: tmpfs.h,v 1.26 2007/02/22 06:37:00 thorpej 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. * $FreeBSD$
  34. */
  35. #ifndef _FS_TMPFS_TMPFS_H_
  36. #define _FS_TMPFS_TMPFS_H_
  37. #include <sys/cdefs.h>
  38. #include <sys/queue.h>
  39. #include <sys/tree.h>
  40. #ifdef _SYS_MALLOC_H_
  41. MALLOC_DECLARE(M_TMPFSMNT);
  42. MALLOC_DECLARE(M_TMPFSNAME);
  43. #endif
  44. /*
  45. * Internal representation of a tmpfs directory entry.
  46. */
  47. LIST_HEAD(tmpfs_dir_duphead, tmpfs_dirent);
  48. struct tmpfs_dirent {
  49. /*
  50. * Depending on td_cookie flag entry can be of 3 types:
  51. * - regular -- no hash collisions, stored in RB-Tree
  52. * - duphead -- synthetic linked list head for dup entries
  53. * - dup -- stored in linked list instead of RB-Tree
  54. */
  55. union {
  56. /* regular and duphead entry types */
  57. RB_ENTRY(tmpfs_dirent) td_entries;
  58. /* dup entry type */
  59. struct {
  60. LIST_ENTRY(tmpfs_dirent) entries;
  61. LIST_ENTRY(tmpfs_dirent) index_entries;
  62. } td_dup;
  63. } uh;
  64. uint32_t td_cookie;
  65. uint32_t td_hash;
  66. u_int td_namelen;
  67. /*
  68. * Pointer to the node this entry refers to. In case this field
  69. * is NULL, the node is a whiteout.
  70. */
  71. struct tmpfs_node * td_node;
  72. union {
  73. /*
  74. * The name of the entry, allocated from a string pool. This
  75. * string is not required to be zero-terminated.
  76. */
  77. char * td_name; /* regular, dup */
  78. struct tmpfs_dir_duphead td_duphead; /* duphead */
  79. } ud;
  80. };
  81. /*
  82. * A directory in tmpfs holds a collection of directory entries, which
  83. * in turn point to other files (which can be directories themselves).
  84. *
  85. * In tmpfs, this collection is managed by a RB-Tree, whose head is
  86. * defined by the struct tmpfs_dir type.
  87. *
  88. * It is important to notice that directories do not have entries for . and
  89. * .. as other file systems do. These can be generated when requested
  90. * based on information available by other means, such as the pointer to
  91. * the node itself in the former case or the pointer to the parent directory
  92. * in the latter case. This is done to simplify tmpfs's code and, more
  93. * importantly, to remove redundancy.
  94. */
  95. RB_HEAD(tmpfs_dir, tmpfs_dirent);
  96. /*
  97. * Each entry in a directory has a cookie that identifies it. Cookies
  98. * supersede offsets within directories because, given how tmpfs stores
  99. * directories in memory, there is no such thing as an offset.
  100. *
  101. * The '.', '..' and the end of directory markers have fixed cookies which
  102. * cannot collide with the cookies generated by other entries. The cookies
  103. * for the other entries are generated based on the file name hash value or
  104. * unique number in case of name hash collision.
  105. *
  106. * To preserve compatibility cookies are limited to 31 bits.
  107. */
  108. #define TMPFS_DIRCOOKIE_DOT 0
  109. #define TMPFS_DIRCOOKIE_DOTDOT 1
  110. #define TMPFS_DIRCOOKIE_EOF 2
  111. #define TMPFS_DIRCOOKIE_MASK ((off_t)0x3fffffffU)
  112. #define TMPFS_DIRCOOKIE_MIN ((off_t)0x00000004U)
  113. #define TMPFS_DIRCOOKIE_DUP ((off_t)0x40000000U)
  114. #define TMPFS_DIRCOOKIE_DUPHEAD ((off_t)0x80000000U)
  115. #define TMPFS_DIRCOOKIE_DUP_MIN TMPFS_DIRCOOKIE_DUP
  116. #define TMPFS_DIRCOOKIE_DUP_MAX \
  117. (TMPFS_DIRCOOKIE_DUP | TMPFS_DIRCOOKIE_MASK)
  118. /*
  119. * Extended attribute support.
  120. *
  121. * A good portion of this support is based upon the UFS
  122. * implementation. Stand on the shoulders of giants. This
  123. * implementation aims to only provide support for applying extended
  124. * attributes to files (VREG).
  125. */
  126. #define TMPFS_EXTATTR_MAXNAME 33 /* Includes terminating NUL */
  127. #define TMPFS_EXTATTR_MAXVALUESIZE 64
  128. struct tmpfs_extattr_list_entry {
  129. LIST_ENTRY(tmpfs_extattr_list_entry) tele_entries;
  130. int tele_attrnamespace;
  131. char tele_attrname[TMPFS_EXTATTR_MAXNAME];
  132. void *tele_value;
  133. size_t tele_value_size;
  134. };
  135. LIST_HEAD(tmpfs_extattr_list_head, tmpfs_extattr_list_entry);
  136. /*
  137. * Internal representation of a tmpfs file system node.
  138. *
  139. * This structure is splitted in two parts: one holds attributes common
  140. * to all file types and the other holds data that is only applicable to
  141. * a particular type. The code must be careful to only access those
  142. * attributes that are actually allowed by the node's type.
  143. *
  144. * Below is the key of locks used to protected the fields in the following
  145. * structures.
  146. * (v) vnode lock in exclusive mode
  147. * (vi) vnode lock in exclusive mode, or vnode lock in shared vnode and
  148. * tn_interlock
  149. * (i) tn_interlock
  150. * (m) tmpfs_mount tm_allnode_lock
  151. * (c) stable after creation
  152. */
  153. struct tmpfs_node {
  154. /*
  155. * Doubly-linked list entry which links all existing nodes for
  156. * a single file system. This is provided to ease the removal
  157. * of all nodes during the unmount operation, and to support
  158. * the implementation of VOP_VNTOCNP(). tn_attached is false
  159. * when the node is removed from list and unlocked.
  160. */
  161. LIST_ENTRY(tmpfs_node) tn_entries; /* (m) */
  162. bool tn_attached; /* (m) */
  163. /*
  164. * The node's type. Any of 'VBLK', 'VCHR', 'VDIR', 'VFIFO',
  165. * 'VLNK', 'VREG' and 'VSOCK' is allowed. The usage of vnode
  166. * types instead of a custom enumeration is to make things simpler
  167. * and faster, as we do not need to convert between two types.
  168. */
  169. enum vtype tn_type; /* (c) */
  170. /* Node identifier. */
  171. ino_t tn_id; /* (c) */
  172. /*
  173. * Node's internal status. This is used by several file system
  174. * operations to do modifications to the node in a delayed
  175. * fashion.
  176. */
  177. int tn_status; /* (vi) */
  178. #define TMPFS_NODE_ACCESSED (1 << 1)
  179. #define TMPFS_NODE_MODIFIED (1 << 2)
  180. #define TMPFS_NODE_CHANGED (1 << 3)
  181. /*
  182. * The node size. It does not necessarily match the real amount
  183. * of memory consumed by it.
  184. */
  185. off_t tn_size; /* (v) */
  186. /* Generic node attributes. */
  187. uid_t tn_uid; /* (v) */
  188. gid_t tn_gid; /* (v) */
  189. mode_t tn_mode; /* (v) */
  190. int tn_links; /* (v) */
  191. u_long tn_flags; /* (v) */
  192. struct timespec tn_atime; /* (vi) */
  193. struct timespec tn_mtime; /* (vi) */
  194. struct timespec tn_ctime; /* (vi) */
  195. struct timespec tn_birthtime; /* (v) */
  196. unsigned long tn_gen; /* (c) */
  197. /*
  198. * As there is a single vnode for each active file within the
  199. * system, care has to be taken to avoid allocating more than one
  200. * vnode per file. In order to do this, a bidirectional association
  201. * is kept between vnodes and nodes.
  202. *
  203. * Whenever a vnode is allocated, its v_data field is updated to
  204. * point to the node it references. At the same time, the node's
  205. * tn_vnode field is modified to point to the new vnode representing
  206. * it. Further attempts to allocate a vnode for this same node will
  207. * result in returning a new reference to the value stored in
  208. * tn_vnode.
  209. *
  210. * May be NULL when the node is unused (that is, no vnode has been
  211. * allocated for it or it has been reclaimed).
  212. */
  213. struct vnode * tn_vnode; /* (i) */
  214. /*
  215. * Interlock to protect tn_vpstate, and tn_status under shared
  216. * vnode lock.
  217. */
  218. struct mtx tn_interlock;
  219. /*
  220. * Identify if current node has vnode assiocate with
  221. * or allocating vnode.
  222. */
  223. int tn_vpstate; /* (i) */
  224. /* Transient refcounter on this node. */
  225. u_int tn_refcount; /* (m) + (i) */
  226. /* misc data field for different tn_type node */
  227. union {
  228. /* Valid when tn_type == VBLK || tn_type == VCHR. */
  229. dev_t tn_rdev; /* (c) */
  230. /* Valid when tn_type == VDIR. */
  231. struct tn_dir {
  232. /*
  233. * Pointer to the parent directory. The root
  234. * directory has a pointer to itself in this field;
  235. * this property identifies the root node.
  236. */
  237. struct tmpfs_node * tn_parent;
  238. /*
  239. * Head of a tree that links the contents of
  240. * the directory together.
  241. */
  242. struct tmpfs_dir tn_dirhead;
  243. /*
  244. * Head of a list the contains fake directory entries
  245. * heads, i.e. entries with TMPFS_DIRCOOKIE_DUPHEAD
  246. * flag.
  247. */
  248. struct tmpfs_dir_duphead tn_dupindex;
  249. /*
  250. * Number and pointer of the first directory entry
  251. * returned by the readdir operation if it were
  252. * called again to continue reading data from the
  253. * same directory as before. This is used to speed
  254. * up reads of long directories, assuming that no
  255. * more than one read is in progress at a given time.
  256. * Otherwise, these values are discarded.
  257. */
  258. off_t tn_readdir_lastn;
  259. struct tmpfs_dirent * tn_readdir_lastp;
  260. } tn_dir;
  261. /* Valid when tn_type == VLNK. */
  262. /* The link's target, allocated from a string pool. */
  263. char * tn_link; /* (c) */
  264. /* Valid when tn_type == VREG. */
  265. struct tn_reg {
  266. /*
  267. * The contents of regular files stored in a
  268. * tmpfs file system are represented by a
  269. * single anonymous memory object (aobj, for
  270. * short). The aobj provides direct access to
  271. * any position within the file. It is a task
  272. * of the memory management subsystem to issue
  273. * the required page ins or page outs whenever
  274. * a position within the file is accessed.
  275. */
  276. vm_object_t tn_aobj; /* (c) */
  277. /*
  278. * The extended attributes list, which may be
  279. * empty.
  280. */
  281. struct tmpfs_extattr_list_head tn_extattr_list; /* (i) */
  282. } tn_reg;
  283. } tn_spec; /* (v) */
  284. };
  285. LIST_HEAD(tmpfs_node_list, tmpfs_node);
  286. #define tn_rdev tn_spec.tn_rdev
  287. #define tn_dir tn_spec.tn_dir
  288. #define tn_link tn_spec.tn_link
  289. #define tn_reg tn_spec.tn_reg
  290. #define tn_fifo tn_spec.tn_fifo
  291. #define TMPFS_LINK_MAX INT_MAX
  292. #define TMPFS_NODE_LOCK(node) mtx_lock(&(node)->tn_interlock)
  293. #define TMPFS_NODE_UNLOCK(node) mtx_unlock(&(node)->tn_interlock)
  294. #define TMPFS_NODE_MTX(node) (&(node)->tn_interlock)
  295. #define TMPFS_NODE_ASSERT_LOCKED(node) mtx_assert(TMPFS_NODE_MTX(node), \
  296. MA_OWNED)
  297. #ifdef INVARIANTS
  298. #define TMPFS_ASSERT_LOCKED(node) do { \
  299. MPASS((node) != NULL); \
  300. MPASS((node)->tn_vnode != NULL); \
  301. ASSERT_VOP_LOCKED((node)->tn_vnode, "tmpfs assert"); \
  302. } while (0)
  303. #else
  304. #define TMPFS_ASSERT_LOCKED(node) (void)0
  305. #endif
  306. #define TMPFS_VNODE_ALLOCATING 1
  307. #define TMPFS_VNODE_WANT 2
  308. #define TMPFS_VNODE_DOOMED 4
  309. #define TMPFS_VNODE_WRECLAIM 8
  310. /*
  311. * Internal representation of a tmpfs mount point.
  312. */
  313. struct tmpfs_mount {
  314. /*
  315. * Original value of the "size" parameter, for reference purposes,
  316. * mostly.
  317. */
  318. off_t tm_size_max;
  319. /*
  320. * Maximum number of memory pages available for use by the file
  321. * system, set during mount time. This variable must never be
  322. * used directly as it may be bigger than the current amount of
  323. * free memory; in the extreme case, it will hold the ULONG_MAX
  324. * value.
  325. */
  326. u_long tm_pages_max;
  327. /* Number of pages in use by the file system. */
  328. u_long tm_pages_used;
  329. /*
  330. * Pointer to the node representing the root directory of this
  331. * file system.
  332. */
  333. struct tmpfs_node * tm_root;
  334. /*
  335. * Maximum number of possible nodes for this file system; set
  336. * during mount time. We need a hard limit on the maximum number
  337. * of nodes to avoid allocating too much of them; their objects
  338. * cannot be released until the file system is unmounted.
  339. * Otherwise, we could easily run out of memory by creating lots
  340. * of empty files and then simply removing them.
  341. */
  342. ino_t tm_nodes_max;
  343. /* unrhdr used to allocate inode numbers */
  344. struct unrhdr64 tm_ino_unr;
  345. /* Number of nodes currently that are in use. */
  346. ino_t tm_nodes_inuse;
  347. /* Refcounter on this struct tmpfs_mount. */
  348. uint64_t tm_refcount;
  349. /* maximum representable file size */
  350. u_int64_t tm_maxfilesize;
  351. /*
  352. * The used list contains all nodes that are currently used by
  353. * the file system; i.e., they refer to existing files.
  354. */
  355. struct tmpfs_node_list tm_nodes_used;
  356. /* All node lock to protect the node list and tmp_pages_used. */
  357. struct mtx tm_allnode_lock;
  358. /* Read-only status. */
  359. bool tm_ronly;
  360. /* Do not use namecache. */
  361. bool tm_nonc;
  362. /* Do not update mtime on writes through mmaped areas. */
  363. bool tm_nomtime;
  364. };
  365. #define TMPFS_LOCK(tm) mtx_lock(&(tm)->tm_allnode_lock)
  366. #define TMPFS_UNLOCK(tm) mtx_unlock(&(tm)->tm_allnode_lock)
  367. #define TMPFS_MP_ASSERT_LOCKED(tm) mtx_assert(&(tm)->tm_allnode_lock, MA_OWNED)
  368. /*
  369. * This structure maps a file identifier to a tmpfs node. Used by the
  370. * NFS code.
  371. */
  372. struct tmpfs_fid_data {
  373. ino_t tfd_id;
  374. unsigned long tfd_gen;
  375. };
  376. _Static_assert(sizeof(struct tmpfs_fid_data) <= MAXFIDSZ,
  377. "(struct tmpfs_fid_data) is larger than (struct fid).fid_data");
  378. struct tmpfs_dir_cursor {
  379. struct tmpfs_dirent *tdc_current;
  380. struct tmpfs_dirent *tdc_tree;
  381. };
  382. #ifdef _KERNEL
  383. /*
  384. * Prototypes for tmpfs_subr.c.
  385. */
  386. void tmpfs_ref_node(struct tmpfs_node *node);
  387. void tmpfs_ref_node_locked(struct tmpfs_node *node);
  388. int tmpfs_alloc_node(struct mount *mp, struct tmpfs_mount *, enum vtype,
  389. uid_t uid, gid_t gid, mode_t mode, struct tmpfs_node *,
  390. const char *, dev_t, struct tmpfs_node **);
  391. void tmpfs_free_node(struct tmpfs_mount *, struct tmpfs_node *);
  392. bool tmpfs_free_node_locked(struct tmpfs_mount *, struct tmpfs_node *, bool);
  393. void tmpfs_free_tmp(struct tmpfs_mount *);
  394. int tmpfs_alloc_dirent(struct tmpfs_mount *, struct tmpfs_node *,
  395. const char *, u_int, struct tmpfs_dirent **);
  396. void tmpfs_free_dirent(struct tmpfs_mount *, struct tmpfs_dirent *);
  397. void tmpfs_dirent_init(struct tmpfs_dirent *, const char *, u_int);
  398. void tmpfs_destroy_vobject(struct vnode *vp, vm_object_t obj);
  399. int tmpfs_alloc_vp(struct mount *, struct tmpfs_node *, int,
  400. struct vnode **);
  401. void tmpfs_free_vp(struct vnode *);
  402. int tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *,
  403. struct componentname *, const char *);
  404. void tmpfs_check_mtime(struct vnode *);
  405. void tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *);
  406. void tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *);
  407. void tmpfs_dir_destroy(struct tmpfs_mount *, struct tmpfs_node *);
  408. struct tmpfs_dirent * tmpfs_dir_lookup(struct tmpfs_node *node,
  409. struct tmpfs_node *f,
  410. struct componentname *cnp);
  411. int tmpfs_dir_getdents(struct tmpfs_mount *, struct tmpfs_node *,
  412. struct uio *, int, u_long *, int *);
  413. int tmpfs_dir_whiteout_add(struct vnode *, struct componentname *);
  414. void tmpfs_dir_whiteout_remove(struct vnode *, struct componentname *);
  415. int tmpfs_reg_resize(struct vnode *, off_t, boolean_t);
  416. int tmpfs_chflags(struct vnode *, u_long, struct ucred *, struct thread *);
  417. int tmpfs_chmod(struct vnode *, mode_t, struct ucred *, struct thread *);
  418. int tmpfs_chown(struct vnode *, uid_t, gid_t, struct ucred *,
  419. struct thread *);
  420. int tmpfs_chsize(struct vnode *, u_quad_t, struct ucred *, struct thread *);
  421. int tmpfs_chtimes(struct vnode *, struct vattr *, struct ucred *cred,
  422. struct thread *);
  423. void tmpfs_itimes(struct vnode *, const struct timespec *,
  424. const struct timespec *);
  425. void tmpfs_set_status(struct tmpfs_mount *tm, struct tmpfs_node *node,
  426. int status);
  427. int tmpfs_truncate(struct vnode *, off_t);
  428. struct tmpfs_dirent *tmpfs_dir_first(struct tmpfs_node *dnode,
  429. struct tmpfs_dir_cursor *dc);
  430. struct tmpfs_dirent *tmpfs_dir_next(struct tmpfs_node *dnode,
  431. struct tmpfs_dir_cursor *dc);
  432. static __inline void
  433. tmpfs_update(struct vnode *vp)
  434. {
  435. tmpfs_itimes(vp, NULL, NULL);
  436. }
  437. /*
  438. * Convenience macros to simplify some logical expressions.
  439. */
  440. #define IMPLIES(a, b) (!(a) || (b))
  441. #define IFF(a, b) (IMPLIES(a, b) && IMPLIES(b, a))
  442. /*
  443. * Checks that the directory entry pointed by 'de' matches the name 'name'
  444. * with a length of 'len'.
  445. */
  446. #define TMPFS_DIRENT_MATCHES(de, name, len) \
  447. (de->td_namelen == len && \
  448. bcmp((de)->ud.td_name, (name), (de)->td_namelen) == 0)
  449. /*
  450. * Ensures that the node pointed by 'node' is a directory and that its
  451. * contents are consistent with respect to directories.
  452. */
  453. #define TMPFS_VALIDATE_DIR(node) do { \
  454. MPASS((node)->tn_type == VDIR); \
  455. MPASS((node)->tn_size % sizeof(struct tmpfs_dirent) == 0); \
  456. } while (0)
  457. /*
  458. * Amount of memory pages to reserve for the system (e.g., to not use by
  459. * tmpfs).
  460. */
  461. #if !defined(TMPFS_PAGES_MINRESERVED)
  462. #define TMPFS_PAGES_MINRESERVED (4 * 1024 * 1024 / PAGE_SIZE)
  463. #endif
  464. size_t tmpfs_mem_avail(void);
  465. size_t tmpfs_pages_used(struct tmpfs_mount *tmp);
  466. void tmpfs_subr_init(void);
  467. void tmpfs_subr_uninit(void);
  468. /*
  469. * Macros/functions to convert from generic data structures to tmpfs
  470. * specific ones.
  471. */
  472. static inline struct tmpfs_mount *
  473. VFS_TO_TMPFS(struct mount *mp)
  474. {
  475. struct tmpfs_mount *tmp;
  476. MPASS(mp != NULL && mp->mnt_data != NULL);
  477. tmp = (struct tmpfs_mount *)mp->mnt_data;
  478. return (tmp);
  479. }
  480. static inline struct tmpfs_node *
  481. VP_TO_TMPFS_NODE(struct vnode *vp)
  482. {
  483. struct tmpfs_node *node;
  484. MPASS(vp != NULL && vp->v_data != NULL);
  485. node = (struct tmpfs_node *)vp->v_data;
  486. return (node);
  487. }
  488. static inline struct tmpfs_node *
  489. VP_TO_TMPFS_DIR(struct vnode *vp)
  490. {
  491. struct tmpfs_node *node;
  492. node = VP_TO_TMPFS_NODE(vp);
  493. TMPFS_VALIDATE_DIR(node);
  494. return (node);
  495. }
  496. static inline bool
  497. tmpfs_use_nc(struct vnode *vp)
  498. {
  499. return (!(VFS_TO_TMPFS(vp->v_mount)->tm_nonc));
  500. }
  501. static inline void
  502. tmpfs_update_getattr(struct vnode *vp)
  503. {
  504. struct tmpfs_node *node;
  505. int update_flags;
  506. update_flags = TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED | TMPFS_NODE_CHANGED;
  507. node = VP_TO_TMPFS_NODE(vp);
  508. if (__predict_false(node->tn_status & update_flags) != 0)
  509. tmpfs_update(vp);
  510. }
  511. #endif /* _KERNEL */
  512. #endif /* _FS_TMPFS_TMPFS_H_ */