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 (c) 2013, Joyent, Inc. All rights reserved.
  29  */
  30 
  31 #ifndef _SYS_PORT_IMPL_H
  32 #define _SYS_PORT_IMPL_H
  33 
  34 
  35 #ifdef  __cplusplus
  36 extern "C" {
  37 #endif
  38 
  39 /*
  40  * Note:
  41  * The contents of this file are private to the implementation of the
  42  * Solaris system and event ports subsystem and are subject to change
  43  * at any time without notice.
  44  */
  45 
  46 #include <sys/poll_impl.h>
  47 #include <sys/port.h>
  48 #include <sys/port_kernel.h>
  49 #include <sys/vnode.h>
  50 #include <sys/fem.h>
  51 
  52 /*
  53  * port system call codes
  54  */
  55 #define PORT_CREATE     0       /* create a port */
  56 #define PORT_ASSOCIATE  1       /* register object or object list */
  57 #define PORT_DISSOCIATE 2       /* remove object association */
  58 #define PORT_SEND       3       /* send user-defined event to a port */
  59 #define PORT_SENDN      4       /* send user-defined event to a list of ports */
  60 #define PORT_GET        5       /* receive object with events */
  61 #define PORT_GETN       6       /* receive list of objects with events */
  62 #define PORT_ALERT      7       /* set port in alert mode */
  63 #define PORT_DISPATCH   8       /* dispatch object with events */
  64 
  65 #define PORT_SYS_NOPORT         0x100   /* system call without port-id */
  66 #define PORT_SYS_NOSHARE        0x200   /* non shareable event */
  67 #define PORT_CODE_MASK          0xff
  68 
  69 /* port_dispatch() flags */
  70 #define PORT_SHARE_EVENT        0x01    /* event can be shared between procs */
  71 
  72 /* port limits */
  73 #define PORT_MAX_LIST   8192    /* max. # of list ent. per syscall */
  74 
  75 #ifdef _KERNEL
  76 
  77 #define PORT_SCACHE_SIZE        16      /* start source cache size */
  78 #define PORT_SHASH(cookie)      (cookie & (PORT_SCACHE_SIZE-1))
  79 
  80 /* portkev_flags masks */
  81 #define PORT_CLEANUP_DONE       (PORT_KEV_FREE|PORT_KEV_DONEQ)
  82 #define PORT_KEV_CACHE          (PORT_KEV_CACHED|PORT_KEV_SCACHED)
  83 #define PORT_KEV_WIRED          (PORT_KEV_PRIVATE|PORT_KEV_CACHE)
  84 
  85 #define PORT_FREE_EVENT(pev)    (((pev)->portkev_flags & PORT_KEV_CACHE) == 0)
  86 
  87 typedef struct port_alert {
  88         int     portal_events;          /* passed to alert event */
  89         pid_t   portal_pid;             /* owner of the alert mode */
  90         uintptr_t portal_object;        /* passed to alert event */
  91         void    *portal_user;           /* passed to alert event */
  92 } port_alert_t;
  93 
  94 /*
  95  * The port_queue_t structure is responsible for the management of all
  96  * event activities within a port.
  97  */
  98 typedef struct port_queue {
  99         kmutex_t        portq_mutex;
 100         kcondvar_t      portq_closecv;
 101         kcondvar_t      portq_block_cv;
 102         int             portq_flags;
 103         uint_t          portq_nent;     /* number of events in the queue */
 104         uint_t          portq_nget;     /* events required for waiting thread */
 105         uint_t          portq_tnent;    /* number of events in the temp queue */
 106         int             portq_thrcnt;   /* # of threads waiting for events */
 107         int             portq_getn;     /* # of threads retrieving events */
 108         struct  portget *portq_thread;  /* queue of waiting threads */
 109         struct port_fdcache *portq_pcp; /* fd cache */
 110         list_t          portq_list;     /* port event list */
 111         list_t          portq_get_list; /* port event list for port_get(n) */
 112         kmutex_t        portq_source_mutex;
 113         port_source_t   **portq_scache;
 114         port_alert_t    portq_alert;    /* alert event data     */
 115 } port_queue_t;
 116 
 117 /* defines for portq_flags */
 118 #define PORTQ_ALERT        0x01 /* port in alert state */
 119 #define PORTQ_CLOSE        0x02 /* closing port */
 120 #define PORTQ_WAIT_EVENTS  0x04 /* waiting for new events */
 121 #define PORTQ_POLLIN       0x08 /* events available in the event queue */
 122 #define PORTQ_POLLOUT      0x10 /* space available for new events */
 123 #define PORTQ_BLOCKED      0x20 /* port is blocked by port_getn() */
 124 #define PORTQ_POLLWK_PEND  0x40 /* pollwakeup is pending, blocks port close */
 125 
 126 #define VTOEP(v)  ((struct port *)(v->v_data))
 127 #define EPTOV(ep) ((struct vnode *)(ep)->port_vnode)
 128 
 129 
 130 typedef struct  port {
 131         vnode_t         *port_vnode;
 132         kmutex_t        port_mutex;
 133         kcondvar_t      port_cv;        /* resource control */
 134         uint_t          port_flags;
 135         pid_t           port_pid;
 136         int             port_fd;
 137         uint_t          port_max_events; /* max. number of event per port */
 138         uint_t          port_max_list;  /* max. number of list structs  */
 139         uint_t          port_curr;      /* current number of event structs */
 140         pollhead_t      port_pollhd;
 141         timespec_t      port_ctime;
 142         uid_t           port_uid;
 143         gid_t           port_gid;
 144         port_queue_t    port_queue;     /* global queue */
 145 } port_t;
 146 
 147 /* defines for port_flags */
 148 #define PORT_INIT       0x01            /* port initialized */
 149 #define PORT_CLOSED     0x02            /* owner closed the port */
 150 #define PORT_EVENTS     0x04            /* waiting for event resources */
 151 
 152 /*
 153  * global control structure of port framework
 154  */
 155 typedef struct  port_control {
 156         kmutex_t        pc_mutex;
 157         uint_t          pc_nents;       /* ports currently allocated */
 158         struct  kmem_cache *pc_cache;   /* port event structures */
 159 } port_control_t;
 160 
 161 
 162 /*
 163  * Every thread waiting on an object will use this structure to store
 164  * all dependencies (flags, counters, events) before it awakes with
 165  * some events/transactions completed
 166  */
 167 typedef struct  portget {
 168         int             portget_state;
 169         uint_t          portget_nget;   /* number of expected events */
 170         pid_t           portget_pid;
 171         kcondvar_t      portget_cv;
 172         port_alert_t    portget_alert;
 173         struct  portget *portget_next;
 174         struct  portget *portget_prev;
 175 } portget_t;
 176 
 177 /* defines for portget_state */
 178 #define PORTGET_ALERT           0x01    /* wake up and return alert event */
 179 
 180 extern  port_control_t  port_control;
 181 extern  uint_t  port_max_list;
 182 
 183 /*
 184  * port_getn() needs this structure to manage inter-process event delivery.
 185  */
 186 typedef struct  port_gettimer {
 187         ushort_t        pgt_flags;
 188         ushort_t        pgt_loop;
 189         int             pgt_timecheck;
 190         timespec_t      pgt_rqtime;
 191         timespec_t      *pgt_rqtp;
 192         struct timespec *pgt_timeout;
 193 } port_gettimer_t;
 194 
 195 /* pgt_flags */
 196 #define PORTGET_ONE             0x01    /* return only 1 object */
 197 #define PORTGET_WAIT_EVENTS     0x02    /* thread is waiting for new events */
 198 
 199 /*
 200  * portfd_t is required to synchronize the association of fds with a port
 201  * and the per-process list of open files.
 202  * There is a pointer to a portfd structure in uf_entry_t.
 203  * If a fd is closed then closeandsetf() is able to detect the association of
 204  * the fd with a port or with a list of ports. closeandsetf() will dissociate
 205  * the fd from the port(s).
 206  */
 207 typedef struct portfd {
 208         struct polldat  pfd_pd;
 209         struct portfd   *pfd_next;
 210         struct portfd   *pfd_prev;
 211         kthread_t       *pfd_thread;
 212 } portfd_t;
 213 
 214 #define PFTOD(pfd)      (&(pfd)->pfd_pd)
 215 #define PDTOF(pdp)      ((struct portfd *)(pdp))
 216 #define PORT_FD_BUCKET(pcp, fd) \
 217         (&(pcp)->pc_hash[((fd) % (pcp)->pc_hashsize)])
 218 
 219 /*
 220  * PORT_SOURCE_FILE -- File Events Notification sources
 221  */
 222 #define PORT_FOP_BUCKET(pcp, id) \
 223         (portfop_t **)(&(pcp)->pfc_hash[(((ulong_t)id >> 8) & \
 224             (PORTFOP_HASHSIZE - 1))])
 225 
 226 /*
 227  * This structure is used to register a file object to be watched.
 228  *
 229  * The pfop_flags are protected by the vnode's pvp_mutex lock.
 230  * The pfop list (vnode's list) is protected by the pvp_mutex when it is on
 231  * the vnode's list.
 232  *
 233  * All the rest of the fields are protected by the port's source cache lock
 234  * pfcp_lock.
 235  */
 236 typedef struct  portfop {
 237         int             pfop_events;
 238         int             pfop_flags;     /* above flags. */
 239         uintptr_t       pfop_object;    /* object address */
 240         vnode_t         *pfop_vp;
 241         vnode_t         *pfop_dvp;
 242         port_t          *pfop_pp;
 243         fem_t           *pfop_fem;
 244         list_node_t     pfop_node;      /* list of pfop's per vnode */
 245         struct portfop  *pfop_hashnext; /* hash list */
 246         pid_t           pfop_pid;       /* owner of portfop */
 247         struct portfop_cache *pfop_pcache;
 248         port_kevent_t   *pfop_pev;      /* event pointers */
 249         char            *pfop_cname;    /* file component name */
 250         int             pfop_clen;
 251         kthread_t       *pfop_callrid;  /* thread doing the associate */
 252 } portfop_t;
 253 
 254 /*
 255  * pfop_flags
 256  */
 257 #define         PORT_FOP_ACTIVE         0x1
 258 #define         PORT_FOP_REMOVING       0x2
 259 #define         PORT_FOP_KEV_ONQ        0x4
 260 
 261 typedef struct portfop_vfs {
 262         vfs_t           *pvfs;
 263         int             pvfs_unmount;   /* 1 if unmount in progress */
 264         list_t          pvfs_pvplist;   /* list of vnodes from */
 265         fsem_t          *pvfs_fsemp;
 266         struct portfop_vfs *pvfs_next;  /* hash list */
 267 } portfop_vfs_t;
 268 
 269 typedef struct portfop_vfs_hash {
 270         kmutex_t        pvfshash_mutex;
 271         struct portfop_vfs *pvfshash_pvfsp;
 272 } portfop_vfs_hash_t;
 273 
 274 typedef struct portfop_vp {
 275         vnode_t         *pvp_vp;
 276         kmutex_t        pvp_mutex;
 277         int             pvp_cnt;        /* number of watches */
 278         list_t          pvp_pfoplist;
 279         list_node_t     pvp_pvfsnode;
 280         struct portfop *pvp_lpfop;      /* oldest pfop */
 281         fem_t           *pvp_femp;
 282         struct portfop_vfs *pvp_pvfsp;
 283 } portfop_vp_t;
 284 
 285 #define PORTFOP_PVFSHASH_SZ     256
 286 #define PORTFOP_PVFSHASH(vfsp)  (((uintptr_t)(vfsp) >> 4) % PORTFOP_PVFSHASH_SZ)
 287 
 288 /*
 289  * file operations flag.
 290  */
 291 
 292 /*
 293  * PORT_SOURCE_FILE - vnode operations
 294  */
 295 
 296 #define FOP_FILE_OPEN           0x00000001
 297 #define FOP_FILE_READ           0x00000002
 298 #define FOP_FILE_WRITE          0x00000004
 299 #define FOP_FILE_MAP            0x00000008
 300 #define FOP_FILE_IOCTL          0x00000010
 301 #define FOP_FILE_CREATE         0x00000020
 302 #define FOP_FILE_MKDIR          0x00000040
 303 #define FOP_FILE_SYMLINK        0x00000080
 304 #define FOP_FILE_LINK           0x00000100
 305 #define FOP_FILE_RENAME         0x00000200
 306 #define FOP_FILE_REMOVE         0x00000400
 307 #define FOP_FILE_RMDIR          0x00000800
 308 #define FOP_FILE_READDIR        0x00001000
 309 #define FOP_FILE_RENAMESRC      0x00002000
 310 #define FOP_FILE_RENAMEDST      0x00004000
 311 #define FOP_FILE_REMOVEFILE     0x00008000
 312 #define FOP_FILE_REMOVEDIR      0x00010000
 313 #define FOP_FILE_SETSECATTR     0x00020000
 314 #define FOP_FILE_SETATTR_ATIME  0x00040000
 315 #define FOP_FILE_SETATTR_MTIME  0x00080000
 316 #define FOP_FILE_SETATTR_CTIME  0x00100000
 317 #define FOP_FILE_LINK_SRC       0x00200000
 318 #define FOP_FILE_TRUNC          0x00400000
 319 
 320 /*
 321  * File modification event.
 322  */
 323 #define FOP_MODIFIED_MASK       (FOP_FILE_WRITE|FOP_FILE_CREATE \
 324                                 |FOP_FILE_REMOVE|FOP_FILE_LINK \
 325                                 |FOP_FILE_RENAMESRC|FOP_FILE_RENAMEDST \
 326                                 |FOP_FILE_MKDIR|FOP_FILE_RMDIR \
 327                                 |FOP_FILE_SYMLINK|FOP_FILE_SETATTR_MTIME)
 328 
 329 /*
 330  * File access event
 331  */
 332 #define FOP_ACCESS_MASK         (FOP_FILE_READ|FOP_FILE_READDIR \
 333                                 |FOP_FILE_MAP|FOP_FILE_SETATTR_ATIME)
 334 
 335 /*
 336  * File attrib event
 337  */
 338 #define FOP_ATTRIB_MASK         (FOP_FILE_WRITE|FOP_FILE_CREATE \
 339                                 |FOP_FILE_REMOVE|FOP_FILE_LINK \
 340                                 |FOP_FILE_RENAMESRC|FOP_FILE_RENAMEDST \
 341                                 |FOP_FILE_MKDIR|FOP_FILE_RMDIR \
 342                                 |FOP_FILE_SYMLINK|FOP_FILE_SETATTR_CTIME \
 343                                 |FOP_FILE_LINK_SRC|FOP_FILE_SETSECATTR)
 344 
 345 
 346 /*
 347  * File trunc event
 348  */
 349 #define FOP_TRUNC_MASK          (FOP_FILE_TRUNC|FOP_FILE_CREATE)
 350 
 351 /*
 352  * valid watchable events
 353  */
 354 #define FILE_EVENTS_MASK        (FILE_ACCESS|FILE_MODIFIED|FILE_ATTRIB \
 355                                 |FILE_NOFOLLOW|FILE_TRUNC)
 356 /* --- End file events --- */
 357 
 358 /*
 359  * port_kstat_t contains the event port kernel values which are
 360  * exported to kstat.
 361  * Currently only the number of active ports is exported.
 362  */
 363 typedef struct port_kstat {
 364         kstat_named_t   pks_ports;
 365 } port_kstat_t;
 366 
 367 /* misc functions */
 368 int     port_alloc_event_block(port_t *, int, int, struct port_kevent **);
 369 void    port_push_eventq(port_queue_t *);
 370 int     port_remove_done_event(struct port_kevent *);
 371 struct  port_kevent *port_get_kevent(list_t *, struct port_kevent *);
 372 void    port_block(port_queue_t *);
 373 void    port_unblock(port_queue_t *);
 374 
 375 /* PORT_SOURCE_FD cache management */
 376 void port_pcache_remove_fd(port_fdcache_t *, portfd_t *);
 377 int port_remove_fd_object(portfd_t *, struct port *, port_fdcache_t *);
 378 
 379 /* file close management */
 380 extern void addfd_port(int, portfd_t *);
 381 extern void delfd_port(int, portfd_t *);
 382 
 383 #endif  /* _KERNEL */
 384 
 385 #ifdef  __cplusplus
 386 }
 387 #endif
 388 
 389 #endif  /* _SYS_PORT_IMPL_H */