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