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 _LXCGRPS_H
  17 #define _LXCGRPS_H
  18 
  19 #ifdef  __cplusplus
  20 extern "C" {
  21 #endif
  22 
  23 /*
  24  * cgrps.h: declarations, data structures and macros for lx_cgroup
  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 
  49 /*
  50  * cgrpmgr ioctl interface.
  51  */
  52 #define CGRPFS_IOC      ('C' << 16 | 'G' << 8)
  53 #define CGRPFS_GETEVNT  (CGRPFS_IOC | 1)
  54 
  55 typedef struct cgrpmgr_info {
  56         pid_t   cgmi_pid;
  57         char    *cgmi_rel_agent_path;
  58         char    *cgmi_cgroup_path;
  59 } cgrpmgr_info_t;
  60 
  61 #if defined(_KERNEL)
  62 
  63 #include <sys/lx_brand.h>
  64 
  65 typedef struct cgrpmgr_info32 {
  66         pid_t           cgmi_pid;
  67         caddr32_t       cgmi_rel_agent_path;
  68         caddr32_t       cgmi_cgroup_path;
  69 } cgrpmgr_info32_t;
  70 
  71 #define CG_PSNSIZE      256     /* max size of pseudo file name entries */
  72 #define CG_PSDSIZE      16      /* pretend that a dir entry takes 16 bytes */
  73 
  74 /*
  75  * The order of these entries must be in sync with the cg_ssde_dir array.
  76  */
  77 typedef enum cgrp_ssid {
  78         CG_SSID_GENERIC = 1,
  79         CG_SSID_NUM             /* last ssid for range checking */
  80 } cgrp_ssid_t;
  81 
  82 typedef enum cgrp_nodetype {
  83         CG_CGROUP_DIR = 1,      /* cgroup directory entry */
  84         CG_NOTIFY,              /* notify_on_release file */
  85         CG_PROCS,               /* cgroup.procs file */
  86         CG_REL_AGENT,           /* release_agent file */
  87         CG_TASKS,               /* tasks file */
  88 } cgrp_nodetype_t;
  89 
  90 typedef struct cgrp_subsys_dirent {
  91         cgrp_nodetype_t cgrp_ssd_type;
  92         char            *cgrp_ssd_name;
  93 } cgrp_subsys_dirent_t;
  94 
  95 #define N_DIRENTS(m)    (cgrp_num_pseudo_ents((m)->cg_ssid) + 2)
  96 
  97 /*
  98  * A modern systemd-based Linux system typically has 50-60 cgroups so
  99  * we size the hash for 2x that number.
 100  */
 101 #define CGRP_HASH_SZ    128
 102 #define CGRP_AGENT_LEN  (MAXPATHLEN + 1)
 103 
 104 /*
 105  * cgroups per-mount data structure.
 106  *
 107  * All but the event related fields are protected by cg_contents.
 108  * The evnt_list and counter is protected by cg_events.
 109  */
 110 typedef struct cgrp_mnt {
 111         struct vfs      *cg_vfsp;       /* filesystem's vfs struct */
 112         struct cgrp_node *cg_rootnode;  /* root cgrp_node */
 113         char            *cg_mntpath;    /* name of cgroup mount point */
 114         cgrp_ssid_t     cg_ssid;        /* subsystem type */
 115         dev_t           cg_dev;         /* unique dev # of mounted `device' */
 116         uint_t          cg_gen;         /* node ID source for files */
 117         uint_t          cg_grp_gen;     /* ID source for cgroups */
 118         kmutex_t        cg_contents;    /* global lock for most fs activity */
 119         char            cg_agent[CGRP_AGENT_LEN]; /* release_agent path */
 120         /* ptr to zone data for containing zone */
 121         lx_zone_data_t  *cg_lxzdata;
 122         struct cgrp_node **cg_grp_hash; /* hash list of cgroups in the fs */
 123 } cgrp_mnt_t;
 124 
 125 /*
 126  * cgrp_node is the file system dependent node for cgroups.
 127  *
 128  * The node is used to represent both directories (a cgroup) and pseudo files
 129  * within the directory.
 130  *
 131  * Members are tagged in the comment to note which type of node they apply to:
 132  * A - all
 133  * D - dir (i.e. a cgroup)
 134  * F - pseudo file
 135  */
 136 
 137 typedef struct cgrp_node {
 138         struct cgrp_node        *cgn_back;      /* A lnked lst of cgrp_nodes */
 139         struct cgrp_node        *cgn_forw;      /* A lnked lst of cgrp_nodes */
 140         struct cgrp_dirent      *cgn_dir;       /* D dirent list */
 141         struct cgrp_node        *cgn_parent;    /* A dir containing this node */
 142         struct cgrp_node        *cgn_next;      /* D link in per-mount cgroup */
 143                                                 /*   hash table */
 144         uint_t                  cgn_dirents;    /* D number of dirents */
 145         cgrp_nodetype_t         cgn_type;       /* A type for this node */
 146         uint_t                  cgn_notify;     /* D notify_on_release value */
 147         uint_t                  cgn_task_cnt;   /* D number of threads in grp */
 148         struct vnode            *cgn_vnode;     /* A vnode for this cgrp_node */
 149         uint_t                  cgn_id;         /* D ID number for the cgroup */
 150         struct vattr            cgn_attr;       /* A attributes */
 151 } cgrp_node_t;
 152 
 153 /*
 154  * File system independent to cgroups conversion macros
 155  */
 156 #define VFSTOCGM(vfsp)          ((cgrp_mnt_t *)(vfsp)->vfs_data)
 157 #define VTOCGM(vp)              ((cgrp_mnt_t *)(vp)->v_vfsp->vfs_data)
 158 #define VTOCGN(vp)              ((struct cgrp_node *)(vp)->v_data)
 159 #define CGNTOV(cn)              ((cn)->cgn_vnode)
 160 #define cgnode_hold(cn)         VN_HOLD(CGNTOV(cn))
 161 #define cgnode_rele(cn)         VN_RELE(CGNTOV(cn))
 162 
 163 /*
 164  * Attributes
 165  */
 166 #define cgn_mask        cgn_attr.va_mask
 167 #define cgn_mode        cgn_attr.va_mode
 168 #define cgn_uid         cgn_attr.va_uid
 169 #define cgn_gid         cgn_attr.va_gid
 170 #define cgn_fsid        cgn_attr.va_fsid
 171 #define cgn_nodeid      cgn_attr.va_nodeid
 172 #define cgn_nlink       cgn_attr.va_nlink
 173 #define cgn_size        cgn_attr.va_size
 174 #define cgn_atime       cgn_attr.va_atime
 175 #define cgn_mtime       cgn_attr.va_mtime
 176 #define cgn_ctime       cgn_attr.va_ctime
 177 #define cgn_rdev        cgn_attr.va_rdev
 178 #define cgn_blksize     cgn_attr.va_blksize
 179 #define cgn_nblocks     cgn_attr.va_nblocks
 180 #define cgn_seq         cgn_attr.va_seq
 181 
 182 /*
 183  * cgroup directories are made up of a linked list of cg_dirent structures
 184  * hanging off directory cgrp_nodes.  File names are not fixed length,
 185  * but are null terminated.
 186  */
 187 typedef struct cgrp_dirent {
 188         struct cgrp_node        *cgd_cgrp_node; /* cg node for this file */
 189         struct cgrp_dirent      *cgd_next;      /* next directory entry */
 190         struct cgrp_dirent      *cgd_prev;      /* prev directory entry */
 191         uint_t                  cgd_offset;     /* "offset" of dir entry */
 192         uint_t                  cgd_hash;       /* a hash of cgd_name */
 193         struct cgrp_dirent      *cgd_link;      /* linked via hash table */
 194         struct cgrp_node        *cgd_parent;    /* parent, dir we are in */
 195         char                    *cgd_name;      /* null terminated */
 196 } cgrp_dirent_t;
 197 
 198 enum de_op      { DE_CREATE, DE_MKDIR, DE_RENAME };     /* direnter ops */
 199 enum dr_op      { DR_REMOVE, DR_RMDIR, DR_RENAME };     /* dirremove ops */
 200 
 201 extern struct vnodeops *cgrp_vnodeops;
 202 
 203 int cgrp_dirdelete(cgrp_node_t *, cgrp_node_t *, char *, enum dr_op, cred_t *);
 204 int cgrp_direnter(cgrp_mnt_t *, cgrp_node_t *, char *, enum de_op,
 205     cgrp_node_t *, struct vattr *, cgrp_node_t **, cred_t *);
 206 void cgrp_dirinit(cgrp_node_t *, cgrp_node_t *, cred_t *);
 207 int cgrp_dirlookup(cgrp_node_t *, char *, cgrp_node_t **, cred_t *);
 208 void cgrp_dirtrunc(cgrp_node_t *);
 209 void cgrp_node_init(cgrp_mnt_t *, cgrp_node_t *, vattr_t *, cred_t *);
 210 int cgrp_taccess(void *, int, cred_t *);
 211 ino_t cgrp_inode(cgrp_nodetype_t, unsigned int);
 212 int cgrp_num_pseudo_ents(cgrp_ssid_t);
 213 cgrp_node_t *cgrp_cg_hash_lookup(cgrp_mnt_t *, uint_t);
 214 void cgrp_rel_agent_event(cgrp_mnt_t *, cgrp_node_t *, boolean_t);
 215 
 216 #endif /* KERNEL */
 217 
 218 #ifdef  __cplusplus
 219 }
 220 #endif
 221 
 222 #endif /* _LXCGRPS_H */