1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright 2018 Nexenta Systems, Inc.
  29  */
  30 
  31 #ifndef _SYS_DV_NODE_H
  32 #define _SYS_DV_NODE_H
  33 
  34 /*
  35  * dv_nodes are the file-system specific part of the
  36  * vnodes for the device filesystem.
  37  *
  38  * The device filesystem exports two node types:
  39  *
  40  * VDIR nodes           to represent nexus drivers
  41  * VCHR & VBLK nodes        to represent devices
  42  */
  43 
  44 #include <sys/dirent.h>
  45 #include <sys/sunddi.h>
  46 #include <sys/devops.h>
  47 #include <sys/ddi_impldefs.h>
  48 #include <sys/fs/sdev_impl.h>
  49 #include <sys/devpolicy.h>
  50 #include <sys/avl.h>
  51 
  52 #ifdef _KERNEL
  53 #include <sys/vfs_opreg.h>
  54 #endif
  55 
  56 #ifdef __cplusplus
  57 extern "C" {
  58 #endif
  59 
  60 #ifdef _KERNEL
  61 
  62 
  63 /*
  64  * Here's the focal point of this filesystem
  65  */
  66 typedef struct dv_node {
  67         char            *dv_name;       /* pointer to name */
  68         size_t          dv_namelen;     /* strlen(dv_name) */
  69         struct vnode    *dv_vnode;      /* vnode for this dv_node */
  70 
  71         /*
  72          * The dv_contents lock should be held (read) before looking at
  73          * any of the fields below, and held (write) before modifying them.
  74          */
  75         krwlock_t       dv_contents;    /* held while anything is changing */
  76 
  77         dev_info_t      *dv_devi;       /* VDIR: underlying devinfo node */
  78                                         /* has ndi_devi_hold on device */
  79 
  80         struct dv_node  *dv_dotdot;     /* parent: my parent dv_node */
  81         avl_tree_t      dv_entries;     /* VDIR: contents as avl tree */
  82         avl_node_t      dv_avllink;     /* avl node linkage */
  83 
  84         struct vnode    *dv_attrvp;     /* persistent attribute store */
  85         struct vattr    *dv_attr;       /* attributes not yet persistent */
  86 
  87         ino64_t         dv_ino;         /* fake inode */
  88         int             dv_flags;       /* state bits and stuff */
  89         uint_t          dv_nlink;       /* link count */
  90         uint_t          dv_busy;        /* directory busy count */
  91         devplcy_t       *dv_priv;       /* access privilege */
  92         mode_t          dv_dflt_mode;   /* create_priv_minor_node mode */
  93         struct sdev_dv  *dv_sdev;       /* sdev node[s] if exists */
  94 } dvnode_t;
  95 
  96 #define DV_BUILD        0x1             /* directory out-of-date */
  97 #define DV_NO_FSPERM    0x2             /* ignore fs permissions */
  98 #define DV_INTERNAL     0x04            /* internal node */
  99 #define DV_ACL          0x08            /* node has acl */
 100 #define DV_DFLT_MODE    0x010           /* dv_dflt_mode set */
 101 
 102 #define DV_ROOTINO      ((ino_t)2)      /* root inode no. for devfs */
 103 
 104 #define DVTOV(n)        ((struct vnode *)(n)->dv_vnode)
 105 #define VTODV(vp)       ((struct dv_node *)(vp)->v_data)
 106 #define DV_STALE(dv)    (dv->dv_devi == NULL)
 107 
 108 #define DV_UID_DEFAULT  0       /* default uid for devs and dirs */
 109 #define DV_GID_DEFAULT  3       /* default gid for devs and dirs */
 110 #define DV_DIRMODE_DEFAULT      (S_IFDIR | 0755)        /* directories */
 111 #define DV_DEVMODE_DEFAULT      (0600)                  /* special files */
 112 #define DV_DEVMODE_PRIV         (0666)          /* priv based access only */
 113 
 114 /* flags for devfs_clean() */
 115 #define DV_CLEAN_FORCE  0x01    /* force clean of refed directories */
 116 #define DV_RESET_PERM   0x02    /* force resetting of node permission */
 117 #define DV_CLEANDIR_LCK 0x04    /* dv_contents already held */
 118 #define DV_DEVI_GONE    0x08    /* force clean of refed files */
 119 
 120 struct devfs_data {
 121         struct  dv_node *devfs_root;
 122         struct  vfs     *devfs_vfsp;
 123 };
 124 
 125 #define VFSTODVFS(vfsp) ((struct devfs_data *)((vfsp)->vfs_data))
 126 
 127 /* dv_fid overlays the fid structure (for VFS_VGET) */
 128 struct dv_fid {
 129         uint16_t        dvfid_len;
 130         ino32_t         dvfid_ino;
 131         int32_t         dvfid_gen;
 132 };
 133 
 134 /*
 135  * Compare a vattr's and mperm_t's minor permissions (uid, gid & mode)
 136  */
 137 #define VATTRP_MP_CMP(attrp, mp)                                \
 138         (!((attrp->va_uid == mp.mp_uid) &&                   \
 139         (attrp->va_gid == mp.mp_gid) &&                              \
 140         ((attrp->va_mode & S_IAMB) == (mp.mp_mode & S_IAMB))))
 141 
 142 /*
 143  * Merge an mperm_t's minor permissions into a vattr
 144  */
 145 #define VATTR_MP_MERGE(attr, mp)                                \
 146         attr.va_uid = mp.mp_uid;                                \
 147         attr.va_gid = mp.mp_gid;                                \
 148         attr.va_mode =                                          \
 149             (attr.va_mode & ~S_IAMB) | (mp.mp_mode & S_IAMB);
 150 
 151 #define VATTRP_MP_MERGE(attrp, mp)                              \
 152         attrp->va_uid = mp.mp_uid;                           \
 153         attrp->va_gid = mp.mp_gid;                           \
 154         attrp->va_mode =                                     \
 155             (attrp->va_mode & ~S_IAMB) | (mp.mp_mode & S_IAMB);
 156 
 157 /*
 158  * dv_shadow_node flags
 159  */
 160 #define DV_SHADOW_CREATE        0x01            /* create attribute node */
 161 #define DV_SHADOW_WRITE_HELD    0x02            /* dv_contents write held */
 162 
 163 /*
 164  * Directory tree traversal
 165  */
 166 #define DV_FIRST_ENTRY(ddv)     avl_first(&(ddv)->dv_entries)
 167 #define DV_NEXT_ENTRY(ddv, dv)  AVL_NEXT(&(ddv)->dv_entries, (dv))
 168 
 169 extern uint_t devfs_clean_key;  /* tsd key */
 170 extern const char dvnm[];       /* share some space.. */
 171 extern struct dv_node *dvroot;  /* devfs root node */
 172 
 173 extern void dv_node_cache_init(void);
 174 extern void dv_node_cache_fini(void);
 175 extern struct dv_node *dv_mkdir(struct dv_node *, dev_info_t *, char *);
 176 extern struct dv_node *dv_mkroot(struct vfs *, dev_t);
 177 extern void dv_destroy(struct dv_node *, uint_t);
 178 extern void dv_insert(struct dv_node *, struct dv_node *);
 179 extern void dv_shadow_node(struct vnode *, char *nm, struct vnode *,
 180     struct pathname *, struct vnode *, struct cred *, int);
 181 extern int dv_find(struct dv_node *, char *, struct vnode **,
 182     struct pathname *, struct vnode *, struct cred *, uint_t);
 183 extern void dv_filldir(struct dv_node *);
 184 extern int dv_cleandir(struct dv_node *, char *, uint_t);
 185 extern void dv_vattr_merge(struct dv_node *, struct vattr *);
 186 extern void dv_walk(struct dv_node *, char *,
 187     void (*f)(struct dv_node *, void *), void *);
 188 
 189 extern int devfs_clean(dev_info_t *, char *, uint_t);
 190 extern int devfs_lookupname(char *, vnode_t **, vnode_t **);
 191 extern int devfs_walk(char *, void (*f)(struct dv_node *, void *), void *);
 192 extern int devfs_devpolicy(vnode_t *, devplcy_t **);
 193 extern void devfs_get_defattr(vnode_t *, struct vattr *, int *);
 194 
 195 extern struct dv_node *devfs_dip_to_dvnode(dev_info_t *);
 196 extern int devfs_reset_perm(uint_t);
 197 extern int devfs_remdrv_cleanup(const char *, const char *);
 198 
 199 extern struct vnodeops *dv_vnodeops;
 200 extern const struct fs_operation_def dv_vnodeops_template[];
 201 
 202 
 203 #ifdef DEBUG
 204 extern int devfs_debug;
 205 #define DV_DEBUG        0x01
 206 #define DV_DEBUG2       0x02
 207 #define DV_DEBUG3       0x04
 208 #define DV_DEBUG4       0x08
 209 #define DV_DEBUG5       0x10
 210 #define DV_SYSERR       0x1000
 211 #define DV_SYSTRACE     0x2000
 212 #define dcmn_err(args) if (devfs_debug & DV_DEBUG) printf args
 213 #define dcmn_err2(args) if (devfs_debug & DV_DEBUG2) printf args
 214 #define dcmn_err3(args) if (devfs_debug & DV_DEBUG3) printf args
 215 #define dcmn_err4(args) if (devfs_debug & DV_DEBUG4) printf args
 216 #define dcmn_err5(args) if (devfs_debug & DV_DEBUG5) printf args
 217 
 218 #define dsysdebug(err, args)                            \
 219         if ((err && (devfs_debug & DV_SYSERR)) ||   \
 220             (devfs_debug & DV_SYSTRACE)) printf args
 221 #else
 222 #define dcmn_err(args) /* nothing */
 223 #define dcmn_err2(args) /* nothing */
 224 #define dcmn_err3(args) /* nothing */
 225 #define dcmn_err4(args) /* nothing */
 226 #define dcmn_err5(args) /* nothing */
 227 #define dsysdebug(err, args) /* nothing */
 228 #endif
 229 
 230 
 231 #endif  /* _KERNEL */
 232 
 233 #ifdef __cplusplus
 234 }
 235 #endif
 236 
 237 #endif  /* _SYS_DV_NODE_H */