home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 March B / SCO_CASTOR4RRT.iso / update701 / root.17 / usr / include / sys / fs / memfs_mnode.h / memfs_mnode.h
Encoding:
C/C++ Source or Header  |  1998-08-18  |  16.9 KB  |  560 lines

  1. /*
  2.  * Copyright (c) 1998 The Santa Cruz Operation, Inc.. All Rights Reserved. 
  3.  *                                                                         
  4.  *        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF THE               
  5.  *                   SANTA CRUZ OPERATION INC.                             
  6.  *                                                                         
  7.  *   The copyright notice above does not evidence any actual or intended   
  8.  *   publication of such source code.                                      
  9.  */
  10.  
  11. #ifndef _MEMFS_NODE_H    /* wrapper symbol for kernel use */
  12. #define _MEMFS_NODE_H    /* subject to change without notice */
  13.  
  14. #ident    "@(#)kern:fs/memfs/memfs_mnode.h    1.10.6.2"
  15. #ident    "$Header: $"
  16.  
  17. #if defined(__cplusplus)
  18. extern "C" {
  19. #endif
  20.  
  21. /*
  22.  * MP: memfs - Memory Based File System using swap backing store
  23.  */
  24.  
  25. #ifdef _KERNEL_HEADERS
  26.  
  27. #include <fs/fski.h> /* REQUIRED */
  28. #include <fs/vfs.h> /* REQUIRED */
  29. #include <fs/vnode.h> /* REQUIRED */
  30. #include <mem/swap.h> /* REQUIRED */
  31. #include <util/ksynch.h> /* REQUIRED */
  32. #include <util/param.h> /* REQUIRED */
  33. #include <util/types.h> /* REQUIRED */
  34.  
  35. #elif defined(_KERNEL) || defined(_KMEMUSER)
  36.  
  37. #include <sys/fski.h> /* REQUIRED */
  38. #include <sys/ksynch.h> /* REQUIRED */
  39. #include <sys/param.h> /* REQUIRED */
  40. #include <sys/types.h> /* REQUIRED */
  41. #include <sys/vfs.h> /* REQUIRED */
  42. #include <sys/vnode.h> /* REQUIRED */
  43. #include <vm/swap.h> /* REQUIRED */
  44.  
  45. #endif /* _KERNEL_HEADERS */
  46.  
  47. /*
  48.  * mnode: the vnode carrier of the memfs file system
  49.  *
  50.  * Since memfs is a memory based file system, a memfs vnode (mnode) remains
  51.  * ACTIVE (memory resident) as long as its corresponding file exists.
  52.  *
  53.  * Excepting the case of fixed size files, each mnode has a backing store
  54.  * in the form of an N-ary tree, where N = MEMFS_BNODE_SIZE. Each node
  55.  * consists of an array of MEMFS_BNODE_SIZE of memfs_bs_t(s). Non-leaf nodes
  56.  * (level > 0) contain pointers to lower level nodes. Leaf nodes (level == 0)
  57.  * contain swaploc_t structures, directly describing swap backing store. All
  58.  * of the nodes are kmem_alloc(ed) and in memory. A single node is
  59.  * pre-allocated at mnode creation time. This node is kmem_alloc(ed) together
  60.  * with the mnode itself. All other backing store tree nodes are allocated
  61.  * independently.
  62.  *
  63.  * For a fixed size memfs file (indicated by flag MEMFS_FIXEDSIZE),
  64.  * the backing store tree consists of a single node containing
  65.  * btopr(mno_size) swaploc_t(s).
  66.  * 
  67.  * All backing store tree nodes have the property that once allocated, they
  68.  * never move, and are never deleted until the mnodes are inactivated (i.e.
  69.  * for memfs, this means that the file is removed). Thus, the tree can grow
  70.  * horizontally and vertically, but the pieces of the tree do not move once
  71.  * allocated. As a consequence, once the root of the tree is found, the tree
  72.  * can be traversed without holding any locks.
  73.  *
  74.  * Some mnodes are un-named (indicated by flag MEMFS_UNNAMED). These mnodes
  75.  * contain a smaller vnode structure (the vnode_unnamed_t), plus have a number
  76.  * of other fields deleted.
  77.  *
  78.  * A swaploc_t(s) structure in the backing store tree is mutexed by a pseudo
  79.  * lock that we call the MEM_T_LOCK. This lock is held if any of
  80.  * the folowing conditions are in force:
  81.  *
  82.  *    (1) The corresponding page of the file is held PAGE_IS_WRLOCKED, or
  83.  *
  84.  *    (2) The corresponding page of the file is held pageout locked
  85.  *        (i.e. the p_pageout bit is set), or
  86.  *
  87.  *    (3) The corresponding page of the file is held PAGE_VPGLOCKED and
  88.  *        p_invalid == 0 && p_pageout == 0, or
  89.  *
  90.  *    (4) The corresponding page of the file does not exist, and memfs
  91.  *        is enforcing this fact.
  92.  *
  93.  * Note that these conditions are indeed exclusive of each other.
  94.  */
  95.  
  96. /*
  97.  * memfs backing store descriptor
  98.  *
  99.  *    Each backing store tree node is composed of an array of
  100.  *    MEMFS_BNODE_SIZE memfs_bs_t(s).
  101.  */
  102. typedef union memfs_bs {
  103.     union memfs_bs        *mbs_ptr;    /* ptr to next lower level */
  104.     swaploc_t        mbs_swaploc;    /* backing store location */
  105. } memfs_bs_t;
  106.  
  107. /*
  108.  * Basic unit of memfs disk klustering:
  109.  *
  110.  *    memfs tries to kluster together MEMFS_KLUSTER_NUM pages for I/O.
  111.  *    Since memfs allocates swap storage when it is cleaning pages, and
  112.  *    since it never allocates backing store for uninstantiated pages,
  113.  *    the actual klusters of backing storage allocated on the swap device
  114.  *    may be less than this.
  115.  *
  116.  *    Note that in-memory backing store trees are also allocated in units
  117.  *    of MEMFS_BNODE_SIZE memfs_bs_t(s) and that MEMFS_KLUSTER_NUM is
  118.  *    equal to MEMFS_BNODE_SIZE. This equality is used by the
  119.  *    getpage/putpage code in order to efficiently determine actual
  120.  *    klustering.
  121.  */
  122.  
  123. #define MEMFS_LVL_SHIFT        4
  124. #define MEMFS_BNODE_SIZE    (1 << MEMFS_LVL_SHIFT)
  125. #define MEMFS_LVL_MASK        (MEMFS_BNODE_SIZE - 1)
  126. #define MEMFS_SHIFT(level)    ((level) * MEMFS_LVL_SHIFT)
  127. #define MEMFS_BNODE_BYTES    (MEMFS_BNODE_SIZE * sizeof(memfs_bs_t))
  128. #define MEMFS_LEVELS        ((NBITPOFF - PAGESHIFT + MEMFS_LVL_SHIFT - 1) \
  129.                  / MEMFS_LVL_SHIFT)
  130. #define MEMFS_MAXLEVEL        (MEMFS_LEVELS - 1)
  131. #define MEMFS_KLUSTER_NUM    MEMFS_BNODE_SIZE
  132. #define MEMFS_KLUSTER_SIZE    (ptob(MEMFS_KLUSTER_NUM))
  133. #define MEMFS_KLUSTER_OFF    (MEMFS_KLUSTER_SIZE - 1)
  134. #define MEMFS_KLUSTER_MASK    (~MEMFS_KLUSTER_OFF)
  135.  
  136. /*
  137.  *
  138.  *    +---------------------------------------------------------------+
  139.  *    |    0    |  L2    |  L1    |  L0    |    PAGESHIFT    |
  140.  *    +---------------------------------------------------------------+
  141.  *
  142.  *    The diagram above shows how a file offset is decomposed into
  143.  *    fields used for traversing the backing store tree.  In this
  144.  *    case, the backing store tree has 3 levels (mno_maxlevel == 2).
  145.  *    The L0, L1, and L2 fields each contain MEMFS_LVL_SHIFT bits. The L2
  146.  *    bits form an index into the root of the tree. The resulting value
  147.  *    (mno_bsp[L2]) points at a level 1 node. L1 is used similarly. L0
  148.  *    indexes into the level 0 node, which contains an actual backing
  149.  *    store location [swaploc_t(s)]. Thus, the backing store location
  150.  *    is given by:
  151.  *
  152.  *        mp->mno_bsp[L2].mbs_bsp[L1].mbs_swaploc[L0]
  153.  */
  154.  
  155. #ifdef _MEMFS_HIST
  156.  
  157. /*
  158.  * Logging facility for enhanced memfs debugging.
  159.  */
  160.  
  161. /*
  162.  * History Entry in an mnode.
  163.  */
  164. typedef struct memfs_hist_record {
  165.     off_t        mhr_offset;    /* offset */
  166.     swaploc_t    mhr_swaploc;    /* swap location */
  167.     char        *mhr_service;    /* service name */
  168.     uint_t        mhr_count;    /* saved v_count */
  169.     uint_t        mhr_softcnt;    /* saved v_softcnt */
  170.     int        mhr_line;    /* line number */
  171.     char        *mhr_file;    /* file name */
  172.     lwp_t        *mhr_lwp;    /* calling LWP */
  173.     ulong_t        mhr_stamp;    /* time stamp */
  174. } memfs_hist_record_t;
  175.  
  176. #define MEMFS_HIST_SIZE    128
  177.  
  178. typedef struct memfs_hist {
  179.     int            mli_cursor;        /* next avail rec */
  180.     memfs_hist_record_t    mli_rec[MEMFS_HIST_SIZE]; /* log of records */
  181. } memfs_hist_t;
  182.  
  183. #define MEMFS_LOG(mp, offset, service)    \
  184.     memfs_log(mp, offset, service, __LINE__, __FILE__)
  185.  
  186. #define MEMFS_LOG_INIT(mp)    {                \
  187.     struct_zero(&(mp)->mno_hist, sizeof(memfs_hist_t));    \
  188.     MEMFS_LOG(mp, -1, "MEMFS_INIT");            \
  189. }
  190.  
  191. extern void    memfs_log(struct mnode *, off_t, char *, int, char *);
  192.  
  193. #else /* !_MEMFS_HIST */
  194.  
  195. #define MEMFS_LOG(mp, offset, service)    ((void)0)
  196. #define MEMFS_LOG_INIT(mp)        /* nothing to initialize */
  197.  
  198. #endif /* _MEMFS_HIST */
  199.  
  200.  
  201. /*
  202.  * The fields of the mnode are mutexed as follows:
  203.  *
  204.  *    The following are mutexed by the memfs_list_lck:
  205.  *
  206.  *        mno_nextp, mno_lastp, mno_flags, mno_nlink
  207.  *
  208.  *    The following are mutexed by both mno_rwlock and mno_realloclck
  209.  *    (either can be held to read, mno_realloclck must be held and
  210.  *    mno_rwlock must be held in WRITEr mode to write):
  211.  *
  212.  *        mno_bsnp, mno_maxlevel
  213.  *
  214.  *    The following is mutexed by mno_realloclck:
  215.  *
  216.  *        mno_bsize
  217.  *
  218.  *    The following is mutexed by mno_rwlock;
  219.  *
  220.  *        mno_size
  221.  *
  222.  *    The following are are mutexed by mno_mutex:
  223.  *
  224.  *        mno_mode, mno_uid, mno_gid, mno_atime
  225.  *        mno_mtime, mno_ctime, mno_mapcnt, mno_rdev
  226.  */
  227. typedef struct mnode_header {
  228.     struct mnode_header    *mnh_nextp;    /* next mnode list member */
  229.     struct mnode_header    *mnh_lastp;    /* prev mnode list member */
  230.     uint_t            mnh_flags;    /* mnode flags */
  231. } mnode_header_t;
  232.  
  233. typedef struct mnode_top {
  234.     mnode_header_t    mnt_hdr;        /* mnode list linkages */
  235.     size_t        mnt_size;        /* file length */
  236.     rwsleep_t    mnt_rwlock;        /* lock for vop_rwlock */
  237.  
  238.     /*
  239.      * Backing Store Tree information.
  240.      *
  241.      * The first backing store tree node at level 0 is kmem_alloc(ed)
  242.      * together with the mnode. The other levels are kmem_alloc(ed)
  243.      * independently. For a fixed size file, the first level 0 node
  244.      * is sized to exactly provide for the entire file.
  245.      */
  246.     size_t        mnt_bsize;        /* tree coverage in bytes */
  247.     memfs_bs_t    *mnt_bsnp;        /* ptr to level 0 */
  248.     int        mnt_maxlevel;        /* ... tree depth */
  249.     fspin_t        mnt_realloclck;        /* mutexes reallocation */
  250. #ifdef _MEMFS_HIST
  251.     memfs_hist_t    mnt_hist;        /* history information */
  252. #endif
  253. } mnode_top_t;
  254.  
  255. typedef struct mnode {
  256.     mnode_top_t    mno_top;
  257.     vnode_t        mno_vnode;        /* the associated vnode */
  258.     struct mfs_frgopt *mno_fgmt;
  259.     uint_t        mno_nlink;        /* link count */
  260.     short        mno_flag;
  261.     fspin_t        mno_mutex;        /* mutex for fields below */
  262.     mode_t        mno_mode;        /* file mode and type */
  263.     uid_t        mno_uid;        /* owner */
  264.     gid_t        mno_gid;        /* group */
  265.     struct timeval    mno_atime;        /* last access time */
  266.     struct timeval    mno_mtime;        /* last modification time */
  267.     struct timeval    mno_ctime;        /* last "inode change" time */
  268.     uint_t        mno_nodeid;
  269.     uint_t        mno_fsid;
  270.     uint_t        mno_gen;
  271.     ulong        mno_vcode;
  272.     union {
  273.         struct memfs_dirent    *un_dir;    /* pointer to directory list */
  274.         char         *un_symlink;    /* pointer to symlink */
  275.     } un_mnode;
  276.     long           mno_mapcnt;           /* number of page mappings */
  277.     dev_t        mno_rdev;        /* for block/char specials */
  278. } mnode_t;
  279.  
  280. #define mno_dir          un_mnode.un_dir
  281. #define mno_symlink      un_mnode.un_symlink
  282.  
  283. typedef struct mnode_unnamed {
  284.     mnode_top_t    mnn_top;
  285.     vnode_unnamed_t    mnn_vnode;
  286. } mnode_unnamed_t;
  287.  
  288. #define mno_nextp        mno_top.mnt_hdr.mnh_nextp
  289. #define mno_lastp        mno_top.mnt_hdr.mnh_lastp
  290. #define mno_flags        mno_top.mnt_hdr.mnh_flags
  291. #define mno_size        mno_top.mnt_size
  292. #define mno_rwlock        mno_top.mnt_rwlock
  293. #define mno_bsnp        mno_top.mnt_bsnp
  294. #define mno_realloclck        mno_top.mnt_realloclck
  295. #define mno_bsize        mno_top.mnt_bsize
  296. #define mno_maxlevel        mno_top.mnt_maxlevel
  297. #define mno_hdr            mno_top.mnt_hdr
  298. #define mno_hist        mno_top.mnt_hist
  299.  
  300. /*
  301.  * mno_flag
  302.  */
  303. #define    TUPD        0x001        /* file modified */
  304. #define    TACC        0x002        /* file accessed */
  305. #define    TCHG        0x004        /* inode changed */
  306.  
  307. /* modes */
  308. #define IFMT            0170000         /* type of file */
  309. #define IFIFO           0010000         /* named pipe (fifo) */
  310. #define IFCHR           0020000         /* character special */
  311. #define IFDIR           0040000         /* directory */
  312. #define IFNAM           0050000         /* obsolete XENIX file */
  313. #define IFBLK           0060000         /* block special */
  314. #define IFREG           0100000         /* regular */
  315. #define IFLNK           0120000         /* symbolic link */
  316. #define IFSOCK          0140000         /* socket */
  317.  
  318. #define ISUID           04000           /* set user id on execution */
  319. #define ISGID           02000           /* set group id on execution */
  320. #define ISVTX           01000           /* save swapped text even after use */
  321. #define IREAD           0400            /* read, write, execute permissions */
  322. #define IWRITE          0200
  323. #define IEXEC           0100
  324.  
  325. /*
  326.  * memfs directories are made up of a linked list of memfs_dirent entries
  327.  * hanging off directory memfs nodes.  File names are not fixed length,
  328.  * but are null terminated.
  329.  */
  330. struct memfs_dirent {
  331.     mnode_t            *td_mnode;    /* mnode for this file */
  332.     struct memfs_dirent    *td_next;    /* next directory entry */
  333.     u_int             td_offset;    /* "offset" of dir entry */
  334.     ushort_t        td_namelen;    /* name length */
  335.     char            td_name[1];    /* variable length */
  336.                         /* not null terminated */
  337.                         /* max size is MAXNAMELEN-1 */
  338. };
  339.  
  340. /*
  341.  * Name length does not include the null terminator.
  342.  */
  343. #define MEMFS_DIRENT_SIZE(namelen) \
  344.             (offsetof(struct memfs_dirent, td_name) + (namelen))
  345.  
  346. /*
  347.  * tfid overlays the fid structure (for VFS_VGET)
  348.  */
  349. struct tfid {
  350.     u_short    tfid_len;
  351.     ino_t    tfid_ino;
  352.     long    tfid_gen;
  353. };
  354.  
  355. /*
  356.  * void
  357.  * MNODE_INIT_COMMON(mnode_t *mp, size_t size)
  358.  *    Common portion of mnode initialization for named and
  359.  *    unnamed mnodes.
  360.  *
  361.  * Calling/Exit State:
  362.  *    mp is privately held.
  363.  */
  364. #define MNODE_INIT_COMMON(mp, size) {                    \
  365.     FSPIN_INIT(&(mp)->mno_realloclck);                \
  366.         RWSLEEP_INIT(&(mp)->mno_rwlock, (uchar_t) 0,            \
  367.              &memfs_rw_lkinfo, KM_SLEEP);            \
  368.     (mp)->mno_size = (size);                    \
  369.     vop_attach(MNODE_TO_VP(mp), &memfs_vnodeops);            \
  370.     (MNODE_TO_VP(mp))->v_data = mp;                    \
  371.     MEMFS_LOG_INIT(mp);                        \
  372. }
  373.  
  374. /*
  375.  * void
  376.  * MNODE_INIT(mnode_t *mp, vattr_t vap)
  377.  *    Initialize a named mnode.
  378.  *
  379.  * Calling/Exit State:
  380.  *    mp is privately held.
  381.  */
  382. #define MNODE_INIT(mp, vap) {                    \
  383.     FSPIN_INIT(&(mp)->mno_mutex);                    \
  384.     (mp)->mno_mode = MAKEIMODE((vap)->va_type, (vap)->va_mode);    \
  385.     (mp)->mno_flag = 0;                        \
  386.     (mp)->mno_uid = (vap)->va_uid;                    \
  387.     (mp)->mno_gid = (vap)->va_gid;                    \
  388.     MNODE_INIT_COMMON(mp, 0);                    \
  389. }
  390.  
  391. /*
  392.  * void
  393.  * MNODE_INIT_UNNAMED(mnode_t *mp, uint_t flags, ulong_t size)
  394.  *    Initialize an unnamed mnode.
  395.  *
  396.  * Calling/Exit State:
  397.  *    mp is privately held.
  398.  */
  399. #define MNODE_INIT_UNNAMED(mp, flags, size) {                \
  400.     (mp)->mno_flags = (flags) | MEMFS_UNNAMED;            \
  401.     VN_INIT_UNNAMED(MNODE_TO_VP(mp), NULL, VUNNAMED, 0,        \
  402.          VSWAPBACK | VNOSYNC, KM_SLEEP);            \
  403.     MNODE_INIT_COMMON(mp, size);                    \
  404. }
  405.  
  406. /*
  407.  * void
  408.  * MNODE_DEINIT_COMMON(mnode_t *mp)
  409.  *    Common portion of mnode de-initialization for named and
  410.  *    unnamed mnodes.
  411.  *
  412.  * Calling/Exit State:
  413.  *    mp is privately held.
  414.  */
  415. #define MNODE_DEINIT_COMMON(mp) {                \
  416.     RWSLEEP_DEINIT(&(mp)->mno_rwlock);            \
  417. }
  418.  
  419. /*
  420.  * void
  421.  * MNODE_DEINIT_NAMED(mnode_t *mp)
  422.  *    Named specific portion of mnode de-initialization.
  423.  *
  424.  * Calling/Exit State:
  425.  *    mp is privately held.
  426.  */
  427. #define MNODE_DEINIT_NAMED(mp) {                \
  428.     VN_DEINIT(MNODE_TO_VP(mp));                \
  429. }
  430.  
  431. /*
  432.  * void
  433.  * MNODE_DEINIT_UNNAMED(mnode_t *mp)
  434.  *    Named specific portion of mnode de-initialization.
  435.  *
  436.  * Calling/Exit State:
  437.  *    mp is privately held.
  438.  */
  439. #define MNODE_DEINIT_UNNAMED(mp) {                \
  440.     VN_DEINIT_UNNAMED(MNODE_TO_VP(mp));            \
  441. }
  442.  
  443. #define MNODE_RELE(mp)    {                \
  444.     VN_RELE(MNODE_TO_VP(mp));            \
  445. }
  446.  
  447. /*
  448.  * Macros to convert between mnode, mode header, and vnode pointers.
  449.  */
  450. #define MNODE_TO_VP(mp)        (&(mp)->mno_vnode)
  451. #define VP_TO_MNODE(vp)        ((mnode_t *)((vp)->v_data))
  452. #define MNODE_TO_MNODEH(mp)    (&(mp)->mno_hdr)
  453. #define MNODEH_TO_MNODE(mhp)    ((mnode_t *)mhp)
  454.  
  455. /*
  456.  * void
  457.  * MNODE_LIST_INSERT(mnode_header_t *mhp, mnode_header_t *base_mhp)
  458.  *    Insert mnode ``mhp'' into an mnode list following ``base_mhp''.
  459.  *
  460.  * Calling/Exit State:
  461.  *    None.
  462.  */
  463. #define MNODE_LIST_INSERT(mhp, base_mhp) {            \
  464.     mnode_header_t *next_mhp = (base_mhp)->mnh_nextp;    \
  465.                                 \
  466.     (mhp)->mnh_nextp = next_mhp;                \
  467.     (mhp)->mnh_lastp = (base_mhp);                \
  468.     (base_mhp)->mnh_nextp = (mhp);                \
  469.     next_mhp->mnh_lastp = (mhp);                \
  470. }
  471.  
  472. /*
  473.  * void
  474.  * MNODE_LIST_INSERT_PREV(mnode_header_t *mhp, mnode_header_t *base_mhp)
  475.  *    Insert mnode ``mhp'' into an mnode list following ``base_mhp''.
  476.  *
  477.  * Calling/Exit State:
  478.  *    None.
  479.  */
  480. #define MNODE_LIST_INSERT_PREV(mhp, base_mhp) {            \
  481.     mnode_header_t *last_mhp = (base_mhp)->mnh_lastp;    \
  482.                                 \
  483.     (mhp)->mnh_nextp = (base_mhp);                \
  484.     (mhp)->mnh_lastp = last_mhp;                \
  485.     last_mhp->mnh_nextp = (mhp);                \
  486.     (base_mhp)->mnh_lastp = (mhp);                \
  487. }
  488.  
  489. /*
  490.  * void
  491.  * MNODE_LIST_DELETE(mnode_header_t *mhp, mnode_header_t *base_mhp)
  492.  *    Delete mnode ``mhp'' from a list.
  493.  *
  494.  * Calling/Exit State:
  495.  *    None.
  496.  */
  497. #define MNODE_LIST_DELETE(mhp) {                \
  498.     mnode_header_t *next_mhp = (mhp)->mnh_nextp;        \
  499.     mnode_header_t *last_mhp = (mhp)->mnh_lastp;        \
  500.                                 \
  501.     last_mhp->mnh_nextp = next_mhp;                \
  502.     next_mhp->mnh_lastp = last_mhp;                \
  503. }
  504.  
  505. #define MNODE_ACCESSED(mp) {                    \
  506.     timestruc_t timenow;                    \
  507.     GET_HRESTIME(&timenow);                    \
  508.     FSPIN_LOCK(&(mp)->mno_mutex);                \
  509.     (mp)->mno_atime.tv_sec = timenow.tv_sec;        \
  510.     (mp)->mno_atime.tv_usec = timenow.tv_nsec/1000;        \
  511.     FSPIN_UNLOCK(&(mp)->mno_mutex);                \
  512. }
  513.  
  514. #define MNODE_CHANGED(mp) {                    \
  515.     timestruc_t timenow;                    \
  516.     GET_HRESTIME(&timenow);                    \
  517.     FSPIN_LOCK(&(mp)->mno_mutex);                \
  518.     (mp)->mno_ctime.tv_sec = timenow.tv_sec;        \
  519.     (mp)->mno_ctime.tv_usec = timenow.tv_nsec/1000;        \
  520.     FSPIN_UNLOCK(&(mp)->mno_mutex);                \
  521. }
  522.  
  523. #define MNODE_MODIFIED(mp) {                    \
  524.     timestruc_t timenow;                    \
  525.     GET_HRESTIME(&timenow);                    \
  526.     FSPIN_LOCK(&(mp)->mno_mutex);                \
  527.     (mp)->mno_mtime.tv_sec = timenow.tv_sec;        \
  528.     (mp)->mno_mtime.tv_usec = timenow.tv_nsec/1000;        \
  529.     FSPIN_UNLOCK(&(mp)->mno_mutex);                \
  530. }
  531.  
  532. #define MNODE_MODIFIED_CHANGED(mp) {                    \
  533.     timestruc_t timenow;                    \
  534.     GET_HRESTIME(&timenow);                    \
  535.     FSPIN_LOCK(&(mp)->mno_mutex);                \
  536.     (mp)->mno_mtime.tv_sec = timenow.tv_sec;        \
  537.     (mp)->mno_mtime.tv_usec = timenow.tv_nsec/1000;        \
  538.     (mp)->mno_ctime.tv_sec = timenow.tv_sec;        \
  539.     (mp)->mno_ctime.tv_usec = timenow.tv_nsec/1000;        \
  540.     FSPIN_UNLOCK(&(mp)->mno_mutex);                \
  541. }
  542.  
  543. extern size_t memfs_maxbsize[];
  544. extern memfs_bs_t       memfs_empty_node[];
  545. extern mnode_header_t    mnode_anchor;
  546. extern mnode_header_t    mnode_ianchor;
  547. extern int        memfs_ndelabort;
  548. extern sv_t        memfs_sv;
  549. lock_t        memfs_sb_lck;
  550. extern lock_t memfs_list_lck;
  551. extern sleep_t memfs_renamelock;
  552. extern struct seg       memfs_seg;
  553.  
  554.  
  555. #if defined(__cplusplus)
  556.     }
  557. #endif
  558.  
  559. #endif /* _MEMFS_NODE_H */
  560.