1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2016 Joyent, Inc.
  14  */
  15 
  16 #ifndef _LXD_H
  17 #define _LXD_H
  18 
  19 #ifdef  __cplusplus
  20 extern "C" {
  21 #endif
  22 
  23 /*
  24  * lxd.h: declarations, data structures and macros for lxd (lxd devfs).
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <sys/param.h>
  29 #include <sys/policy.h>
  30 #include <sys/dirent.h>
  31 #include <sys/errno.h>
  32 #include <sys/kmem.h>
  33 #include <sys/pathname.h>
  34 #include <sys/systm.h>
  35 #include <sys/var.h>
  36 #include <sys/sysmacros.h>
  37 #include <sys/cred.h>
  38 #include <sys/priv.h>
  39 #include <sys/vnode.h>
  40 #include <sys/vfs.h>
  41 #include <sys/statvfs.h>
  42 #include <sys/cmn_err.h>
  43 #include <sys/zone.h>
  44 #include <sys/uio.h>
  45 #include <sys/utsname.h>
  46 #include <sys/atomic.h>
  47 #include <vm/anon.h>
  48 #include <sys/lx_types.h>
  49 
  50 #if defined(_KERNEL)
  51 
  52 #include <sys/lx_brand.h>
  53 
  54 /*
  55  * It's unlikely that we need to create more than 50-60 subdirs/symlinks
  56  * as front files so we size the file system hash for 2x that number.
  57  * The back devfs typically has ~80 nodes so this is also a comfortable size
  58  * for the back hash table.
  59  */
  60 #define LXD_HASH_SZ     128
  61 
  62 #define LXD_BACK_HASH(v)        ((((intptr_t)(v)) >> 10) & ((LXD_HASH_SZ) - 1))
  63 
  64 #define LXD_NM_HASH(ldn, name, hash)                            \
  65         {                                                       \
  66                 char Xc, *Xcp;                                  \
  67                 hash = (uint_t)(uintptr_t)(ldn) >> 8;             \
  68                 for (Xcp = (name); (Xc = *Xcp) != 0; Xcp++)     \
  69                         hash = (hash << 4) + hash + (uint_t)Xc;   \
  70                 hash &= (LXD_HASH_SZ - 1);                  \
  71         }
  72 
  73 
  74 enum lxd_node_type      { LXDNT_NONE, LXDNT_BACK, LXDNT_FRONT };
  75 
  76 typedef struct lxd_dev_attr {
  77         list_node_t     lxda_link;
  78         char            lxda_name[MAXPATHLEN];
  79         uid_t           lxda_uid;
  80         gid_t           lxda_gid;
  81         mode_t          lxda_mode;
  82 } lxd_dev_attr_t;
  83 
  84 /*
  85  * lxd per-mount data structure.
  86  *
  87  * All fields are protected by lxd_contents.
  88  * File renames on a specific file system are protected lxdm_renamelck.
  89  */
  90 typedef struct lxd_mnt {
  91         struct vfs      *lxdm_vfsp;     /* filesystem's vfs struct */
  92         struct lxd_node *lxdm_rootnode; /* root lxd_node */
  93         char            *lxdm_mntpath;  /* name of lxd mount point */
  94         dev_t           lxdm_dev;       /* unique dev # of mounted `device' */
  95         kmutex_t        lxdm_contents;  /* per-mount lock */
  96         kmutex_t        lxdm_renamelck; /* rename lock for this mount */
  97         kmutex_t        lxdm_attrlck;   /* per-mount attr. file lock */
  98         list_t          lxdm_devattrs;  /* list of device attr. settings */
  99         uint_t          lxdm_gen;       /* node ID source for files */
 100 
 101         /* protects buckets in both "dir ent" and "back" hash tables */
 102         kmutex_t        lxdm_hash_mutex[LXD_HASH_SZ];
 103 
 104         /* per-mount data for "back" vnodes in the fs */
 105         uint_t          lxdm_back_refcnt; /* # outstanding "back" vnodes */
 106         struct lxd_node *lxdm_back_htable[LXD_HASH_SZ];
 107 
 108         /*
 109          * Per-mount directory data for "front" nodes in the fs.
 110          * Each front node has a directory entry but directory entries can live
 111          * on either front or back nodes.
 112          */
 113         uint_t          lxdm_dent_refcnt; /* # outstanding dir ents */
 114         struct lxd_dirent *lxdm_dent_htable[LXD_HASH_SZ];
 115 } lxd_mnt_t;
 116 
 117 /*
 118  * lxd_node is the file system dependent node for lxd.
 119  *
 120  * The node is used to represent both front and back files. For front files
 121  * the node can represent either a directory or symlink.
 122  */
 123 typedef struct lxd_node {
 124         enum lxd_node_type      lxdn_type;
 125 
 126         /* Data for "front" nodes */
 127         struct lxd_node         *lxdn_prev;     /* lnked lst of lxd nodes */
 128         struct lxd_node         *lxdn_next;     /* lnked lst of lxd nodes */
 129         struct lxd_node         *lxdn_parent;   /* dir containing this node */
 130         krwlock_t               lxdn_rwlock;    /* serialize mods/dir updates */
 131         kmutex_t                lxdn_tlock;     /* time, flag, and nlink lock */
 132 
 133         /* these could be in a union ala tmpfs but not really necessary */
 134         uint_t                  lxdn_dirents;   /* number of dirents */
 135         struct lxd_dirent       *lxdn_dir;      /* dirent list */
 136         char                    *lxdn_symlink;  /* pointer to symlink */
 137         struct vattr            lxdn_attr;      /* attributes */
 138 
 139         /* Hash table link */
 140         struct lxd_node         *lxdn_hnxt;     /* link in per-mount entry */
 141                                                 /* hash table */
 142         vnode_t                 *lxdn_vnode;    /* vnode for this lxd_node */
 143 
 144         vnode_t                 *lxdn_real_vp;  /* back file - real vnode */
 145 } lxd_node_t;
 146 
 147 /*
 148  * Attributes
 149  */
 150 #define lxdn_mask       lxdn_attr.va_mask
 151 #define lxdn_mode       lxdn_attr.va_mode
 152 #define lxdn_uid        lxdn_attr.va_uid
 153 #define lxdn_gid        lxdn_attr.va_gid
 154 #define lxdn_fsid       lxdn_attr.va_fsid
 155 #define lxdn_nodeid     lxdn_attr.va_nodeid
 156 #define lxdn_nlink      lxdn_attr.va_nlink
 157 #define lxdn_size       lxdn_attr.va_size
 158 #define lxdn_atime      lxdn_attr.va_atime
 159 #define lxdn_mtime      lxdn_attr.va_mtime
 160 #define lxdn_ctime      lxdn_attr.va_ctime
 161 #define lxdn_rdev       lxdn_attr.va_rdev
 162 #define lxdn_blksize    lxdn_attr.va_blksize
 163 #define lxdn_nblocks    lxdn_attr.va_nblocks
 164 #define lxdn_seq        lxdn_attr.va_seq
 165 
 166 /*
 167  * lx devfs conversion macros
 168  */
 169 #define VFSTOLXDM(vfsp)         ((lxd_mnt_t *)(vfsp)->vfs_data)
 170 #define VTOLXDM(vp)             ((lxd_mnt_t *)(vp)->v_vfsp->vfs_data)
 171 #define VTOLDN(vp)              ((lxd_node_t *)(vp)->v_data)
 172 #define LDNTOV(ln)              ((ln)->lxdn_vnode)
 173 #define ldnode_hold(ln)         VN_HOLD(LDNTOV(ln))
 174 #define ldnode_rele(ln)         VN_RELE(LDNTOV(ln))
 175 
 176 #define REALVP(vp)              (VTOLDN(vp)->lxdn_real_vp)
 177 
 178 /*
 179  * front directories are made up of a linked list of lxd_dirent structures
 180  * hanging off directory lxdn_nodes.  File names are not fixed length, but are
 181  * null terminated.
 182  */
 183 typedef struct lxd_dirent {
 184         lxd_node_t              *lddir_node;    /* lxd node for this file */
 185         struct lxd_dirent       *lddir_next;    /* next directory entry */
 186         struct lxd_dirent       *lddir_prev;    /* prev directory entry */
 187         uint_t                  lddir_offset;   /* "offset" of dir entry */
 188         uint_t                  lddir_hash;     /* a hash of lddir_name */
 189         struct lxd_dirent       *lddir_link;    /* linked via hash table */
 190         lxd_node_t              *lddir_parent;  /* parent, dir we are in */
 191         char                    *lddir_name;    /* null terminated */
 192 } lxd_dirent_t;
 193 
 194 enum de_op      { DE_CREATE, DE_MKDIR, DE_RENAME };     /* direnter ops */
 195 enum dr_op      { DR_REMOVE, DR_RMDIR, DR_RENAME };     /* dirremove ops */
 196 
 197 typedef struct lxd_minor_translator {
 198         char    *lxd_mt_path;           /* illumos minor node path */
 199         minor_t lxd_mt_minor;           /* illumos minor node number */
 200         int     lxd_mt_lx_major;        /* linux major node number */
 201         int     lxd_mt_lx_minor;        /* linux minor node number */
 202 } lxd_minor_translator_t;
 203 
 204 enum lxd_xl_tp  { DTT_INVALID, DTT_LIST, DTT_CUSTOM };
 205 
 206 #define xl_list         lxd_xl_minor.lxd_xl_list
 207 #define xl_custom       lxd_xl_minor.lxd_xl_custom
 208 
 209 typedef struct lxd_devt_translator {
 210         char            *lxd_xl_driver; /* driver name */
 211         major_t         lxd_xl_major;   /* driver number */
 212 
 213         enum lxd_xl_tp  lxd_xl_type;    /* dictates how we intrep. xl_minor */
 214         union {
 215                 uintptr_t               lxd_xl_foo; /* required to compile */
 216                 lxd_minor_translator_t  *lxd_xl_list;
 217                 void                    (*lxd_xl_custom)(dev_t, dev_t *);
 218         } lxd_xl_minor;
 219 } lxd_devt_translator_t;
 220 
 221 extern struct vnodeops *lxd_vnodeops;
 222 extern lxd_devt_translator_t lxd_devt_translators[];
 223 
 224 vnode_t *lxd_make_back_node(vnode_t *, lxd_mnt_t *);
 225 void lxd_free_back_node(lxd_node_t *);
 226 int lxd_dirdelete(lxd_node_t *, lxd_node_t *, char *, enum dr_op, cred_t *);
 227 int lxd_direnter(lxd_mnt_t *, lxd_node_t *, char *, enum de_op, lxd_node_t *,
 228         lxd_node_t *, struct vattr *, lxd_node_t **, cred_t *);
 229 void lxd_dirinit(lxd_node_t *, lxd_node_t *);
 230 int lxd_dirlookup(lxd_node_t *, char *, lxd_node_t **, cred_t *);
 231 void lxd_dirtrunc(lxd_node_t *);
 232 void lxd_node_init(lxd_mnt_t *, lxd_node_t *, vnode_t *, vattr_t *, cred_t *);
 233 int lxd_naccess(void *, int, cred_t *);
 234 
 235 void lxd_save_attrs(lxd_mnt_t *, vnode_t *);
 236 void lxd_apply_db(lxd_mnt_t *);
 237 
 238 #endif /* KERNEL */
 239 
 240 #ifdef  __cplusplus
 241 }
 242 #endif
 243 
 244 #endif /* _LXD_H */