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