xref: /illumos-gate/usr/src/uts/common/sys/port_impl.h (revision 43449cdcd0600512dd862537f2cf014140dd0844)
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) 2012, 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 */
390