xref: /freebsd/sys/kern/uipc_mqueue.c (revision 9947b45978e8ec4c110704f0d970b38ecb1c2e70)
1 /*-
2  * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27 
28 /*
29  * POSIX message queue implementation.
30  *
31  * 1) A mqueue filesystem can be mounted, each message queue appears
32  *    in mounted directory, user can change queue's permission and
33  *    ownership, or remove a queue. Manually creating a file in the
34  *    directory causes a message queue to be created in the kernel with
35  *    default message queue attributes applied and same name used, this
36  *    method is not advocated since mq_open syscall allows user to specify
37  *    different attributes. Also the file system can be mounted multiple
38  *    times at different mount points but shows same contents.
39  *
40  * 2) Standard POSIX message queue API. The syscalls do not use vfs layer,
41  *    but directly operate on internal data structure, this allows user to
42  *    use the IPC facility without having to mount mqueue file system.
43  */
44 
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD$");
47 
48 #include <sys/param.h>
49 #include <sys/kernel.h>
50 #include <sys/systm.h>
51 #include <sys/limits.h>
52 #include <sys/buf.h>
53 #include <sys/dirent.h>
54 #include <sys/event.h>
55 #include <sys/eventhandler.h>
56 #include <sys/fcntl.h>
57 #include <sys/file.h>
58 #include <sys/filedesc.h>
59 #include <sys/limits.h>
60 #include <sys/lock.h>
61 #include <sys/malloc.h>
62 #include <sys/module.h>
63 #include <sys/mount.h>
64 #include <sys/mqueue.h>
65 #include <sys/mutex.h>
66 #include <sys/namei.h>
67 #include <sys/poll.h>
68 #include <sys/proc.h>
69 #include <sys/queue.h>
70 #include <sys/sysproto.h>
71 #include <sys/stat.h>
72 #include <sys/syscall.h>
73 #include <sys/syscallsubr.h>
74 #include <sys/sysent.h>
75 #include <sys/sx.h>
76 #include <sys/sysctl.h>
77 #include <sys/taskqueue.h>
78 #include <sys/unistd.h>
79 #include <sys/vnode.h>
80 #include <machine/atomic.h>
81 #include <posix4/posix4.h>
82 
83 /*
84  * Limits and constants
85  */
86 #define	MQFS_NAMELEN		NAME_MAX
87 #define MQFS_DELEN		(8 + MQFS_NAMELEN)
88 
89 /* node types */
90 typedef enum {
91 	mqfstype_none = 0,
92 	mqfstype_root,
93 	mqfstype_dir,
94 	mqfstype_this,
95 	mqfstype_parent,
96 	mqfstype_file,
97 	mqfstype_symlink,
98 } mqfs_type_t;
99 
100 struct mqfs_node;
101 
102 /*
103  * mqfs_info: describes a mqfs instance
104  */
105 struct mqfs_info {
106 	struct sx		mi_lock;
107 	struct mqfs_node	*mi_root;
108 	struct unrhdr		*mi_unrhdr;
109 };
110 
111 struct mqfs_vdata {
112 	LIST_ENTRY(mqfs_vdata)	mv_link;
113 	struct mqfs_node	*mv_node;
114 	struct vnode		*mv_vnode;
115 	struct task		mv_task;
116 };
117 
118 /*
119  * mqfs_node: describes a node (file or directory) within a mqfs
120  */
121 struct mqfs_node {
122 	char			mn_name[MQFS_NAMELEN+1];
123 	struct mqfs_info	*mn_info;
124 	struct mqfs_node	*mn_parent;
125 	LIST_HEAD(,mqfs_node)	mn_children;
126 	LIST_ENTRY(mqfs_node)	mn_sibling;
127 	LIST_HEAD(,mqfs_vdata)	mn_vnodes;
128 	int			mn_refcount;
129 	mqfs_type_t		mn_type;
130 	int			mn_deleted;
131 	u_int32_t		mn_fileno;
132 	void			*mn_data;
133 	struct timespec		mn_birth;
134 	struct timespec		mn_ctime;
135 	struct timespec		mn_atime;
136 	struct timespec		mn_mtime;
137 	uid_t			mn_uid;
138 	gid_t			mn_gid;
139 	int			mn_mode;
140 };
141 
142 #define	VTON(vp)	(((struct mqfs_vdata *)((vp)->v_data))->mv_node)
143 #define VTOMQ(vp) 	((struct mqueue *)(VTON(vp)->mn_data))
144 #define	VFSTOMQFS(m)	((struct mqfs_info *)((m)->mnt_data))
145 #define	FPTOMQ(fp)	((struct mqueue *)(((struct mqfs_node *) \
146 				(fp)->f_data)->mn_data))
147 
148 TAILQ_HEAD(msgq, mqueue_msg);
149 
150 struct mqueue;
151 
152 struct mqueue_notifier {
153 	LIST_ENTRY(mqueue_notifier)	nt_link;
154 	struct sigevent			nt_sigev;
155 	ksiginfo_t			nt_ksi;
156 	struct proc			*nt_proc;
157 	int				nt_fd;
158 };
159 
160 struct mqueue {
161 	struct mtx	mq_mutex;
162 	int		mq_flags;
163 	long		mq_maxmsg;
164 	long		mq_msgsize;
165 	long		mq_curmsgs;
166 	long		mq_totalbytes;
167 	struct msgq	mq_msgq;
168 	int		mq_receivers;
169 	int		mq_senders;
170 	struct selinfo	mq_rsel;
171 	struct selinfo	mq_wsel;
172 	struct mqueue_notifier	*mq_notifier;
173 };
174 
175 #define	MQ_RSEL		0x01
176 #define	MQ_WSEL		0x02
177 
178 struct mqueue_msg {
179 	TAILQ_ENTRY(mqueue_msg)	msg_link;
180 	unsigned int	msg_prio;
181 	unsigned int	msg_size;
182 	/* following real data... */
183 };
184 
185 SYSCTL_NODE(_kern, OID_AUTO, mqueue, CTLFLAG_RW, 0,
186 	"POSIX real time message queue");
187 
188 static int	default_maxmsg  = 10;
189 static int	default_msgsize = 1024;
190 
191 static int	maxmsg = 100;
192 SYSCTL_INT(_kern_mqueue, OID_AUTO, maxmsg, CTLFLAG_RW,
193     &maxmsg, 0, "Default maximum messages in queue");
194 static int	maxmsgsize = 16384;
195 SYSCTL_INT(_kern_mqueue, OID_AUTO, maxmsgsize, CTLFLAG_RW,
196     &maxmsgsize, 0, "Default maximum message size");
197 static int	maxmq = 100;
198 SYSCTL_INT(_kern_mqueue, OID_AUTO, maxmq, CTLFLAG_RW,
199     &maxmq, 0, "maximum message queues");
200 static int	curmq = 0;
201 SYSCTL_INT(_kern_mqueue, OID_AUTO, curmq, CTLFLAG_RW,
202     &curmq, 0, "current message queue number");
203 static int	unloadable = 0;
204 static MALLOC_DEFINE(M_MQUEUEDATA, "mqdata", "mqueue data");
205 
206 static eventhandler_tag exit_tag;
207 
208 /* Only one instance per-system */
209 static struct mqfs_info		mqfs_data;
210 static uma_zone_t		mqnode_zone;
211 static uma_zone_t		mqueue_zone;
212 static uma_zone_t		mvdata_zone;
213 static uma_zone_t		mqnoti_zone;
214 static struct vop_vector	mqfs_vnodeops;
215 static struct fileops		mqueueops;
216 
217 /*
218  * Directory structure construction and manipulation
219  */
220 #ifdef notyet
221 static struct mqfs_node	*mqfs_create_dir(struct mqfs_node *parent,
222 	const char *name, int namelen);
223 #endif
224 
225 static struct mqfs_node	*mqfs_create_file(struct mqfs_node *parent,
226 	const char *name, int namelen);
227 struct mqfs_node	*mqfs_create_link(struct mqfs_node *parent,
228 	const char *name, int namelen);
229 static int	mqfs_destroy(struct mqfs_node *mn);
230 static void	mqfs_fileno_alloc(struct mqfs_info *mi, struct mqfs_node *mn);
231 static void	mqfs_fileno_free(struct mqfs_info *mi, struct mqfs_node *mn);
232 static int	mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn);
233 
234 /*
235  * Message queue construction and maniplation
236  */
237 static struct mqueue	*mqueue_alloc(const struct mq_attr *attr);
238 static void	mqueue_free(struct mqueue *mq);
239 static int	mqueue_send(struct mqueue *mq, const char *msg_ptr,
240 			size_t msg_len, unsigned msg_prio, int waitok,
241 			const struct timespec *abs_timeout);
242 static int	mqueue_receive(struct mqueue *mq, char *msg_ptr,
243 			size_t msg_len, unsigned *msg_prio, int waitok,
244 			const struct timespec *abs_timeout);
245 static int	_mqueue_send(struct mqueue *mq, struct mqueue_msg *msg,
246 			int timo);
247 static int	_mqueue_recv(struct mqueue *mq, struct mqueue_msg **msg,
248 			int timo);
249 static void	mqueue_send_notification(struct mqueue *mq);
250 static void	mqueue_fdclose(struct thread *td, int fd, struct file *fp);
251 static void	mq_proc_exit(void *arg, struct proc *p);
252 
253 /*
254  * kqueue filters
255  */
256 static void	filt_mqdetach(struct knote *kn);
257 static int	filt_mqread(struct knote *kn, long hint);
258 static int	filt_mqwrite(struct knote *kn, long hint);
259 
260 struct filterops mq_rfiltops =
261 	{ 1, NULL, filt_mqdetach, filt_mqread };
262 struct filterops mq_wfiltops =
263 	{ 1, NULL, filt_mqdetach, filt_mqwrite };
264 
265 /*
266  * Initialize fileno bitmap
267  */
268 static void
269 mqfs_fileno_init(struct mqfs_info *mi)
270 {
271 	struct unrhdr *up;
272 
273 	up = new_unrhdr(1, INT_MAX, NULL);
274 	mi->mi_unrhdr = up;
275 }
276 
277 /*
278  * Tear down fileno bitmap
279  */
280 static void
281 mqfs_fileno_uninit(struct mqfs_info *mi)
282 {
283 	struct unrhdr *up;
284 
285 	up = mi->mi_unrhdr;
286 	mi->mi_unrhdr = NULL;
287 	delete_unrhdr(up);
288 }
289 
290 /*
291  * Allocate a file number
292  */
293 static void
294 mqfs_fileno_alloc(struct mqfs_info *mi, struct mqfs_node *mn)
295 {
296 	/* make sure our parent has a file number */
297 	if (mn->mn_parent && !mn->mn_parent->mn_fileno)
298 		mqfs_fileno_alloc(mi, mn->mn_parent);
299 
300 	switch (mn->mn_type) {
301 	case mqfstype_root:
302 	case mqfstype_dir:
303 	case mqfstype_file:
304 	case mqfstype_symlink:
305 		mn->mn_fileno = alloc_unr(mi->mi_unrhdr);
306 		break;
307 	case mqfstype_this:
308 		KASSERT(mn->mn_parent != NULL,
309 		    ("mqfstype_this node has no parent"));
310 		mn->mn_fileno = mn->mn_parent->mn_fileno;
311 		break;
312 	case mqfstype_parent:
313 		KASSERT(mn->mn_parent != NULL,
314 		    ("mqfstype_parent node has no parent"));
315 		if (mn->mn_parent == mi->mi_root) {
316 			mn->mn_fileno = mn->mn_parent->mn_fileno;
317 			break;
318 		}
319 		KASSERT(mn->mn_parent->mn_parent != NULL,
320 		    ("mqfstype_parent node has no grandparent"));
321 		mn->mn_fileno = mn->mn_parent->mn_parent->mn_fileno;
322 		break;
323 	default:
324 		KASSERT(0,
325 		    ("mqfs_fileno_alloc() called for unknown type node: %d",
326 			mn->mn_type));
327 		break;
328 	}
329 }
330 
331 /*
332  * Release a file number
333  */
334 static void
335 mqfs_fileno_free(struct mqfs_info *mi, struct mqfs_node *mn)
336 {
337 	switch (mn->mn_type) {
338 	case mqfstype_root:
339 	case mqfstype_dir:
340 	case mqfstype_file:
341 	case mqfstype_symlink:
342 		free_unr(mi->mi_unrhdr, mn->mn_fileno);
343 		break;
344 	case mqfstype_this:
345 	case mqfstype_parent:
346 		/* ignore these, as they don't "own" their file number */
347 		break;
348 	default:
349 		KASSERT(0,
350 		    ("mqfs_fileno_free() called for unknown type node: %d",
351 			mn->mn_type));
352 		break;
353 	}
354 }
355 
356 static __inline struct mqfs_node *
357 mqnode_alloc(void)
358 {
359 	return uma_zalloc(mqnode_zone, M_WAITOK | M_ZERO);
360 }
361 
362 static __inline void
363 mqnode_free(struct mqfs_node *node)
364 {
365 	uma_zfree(mqnode_zone, node);
366 }
367 
368 static __inline void
369 mqnode_addref(struct mqfs_node *node)
370 {
371 	atomic_fetchadd_int(&node->mn_refcount, 1);
372 }
373 
374 static __inline void
375 mqnode_release(struct mqfs_node *node)
376 {
377 	int old, exp;
378 
379 	old = atomic_fetchadd_int(&node->mn_refcount, -1);
380 	if (node->mn_type == mqfstype_dir ||
381 	    node->mn_type == mqfstype_root)
382 		exp = 3; /* include . and .. */
383 	else
384 		exp = 1;
385 	if (old == exp)
386 		mqfs_destroy(node);
387 }
388 
389 /*
390  * Add a node to a directory
391  */
392 static int
393 mqfs_add_node(struct mqfs_node *parent, struct mqfs_node *node)
394 {
395 	KASSERT(parent != NULL, ("%s(): parent is NULL", __func__));
396 	KASSERT(parent->mn_info != NULL,
397 	    ("%s(): parent has no mn_info", __func__));
398 	KASSERT(parent->mn_type == mqfstype_dir ||
399 	    parent->mn_type == mqfstype_root,
400 	    ("%s(): parent is not a directory", __func__));
401 
402 	node->mn_info = parent->mn_info;
403 	node->mn_parent = parent;
404 	LIST_INIT(&node->mn_children);
405 	LIST_INIT(&node->mn_vnodes);
406 	LIST_INSERT_HEAD(&parent->mn_children, node, mn_sibling);
407 	mqnode_addref(parent);
408 	return (0);
409 }
410 
411 /*
412  * Add . and .. to a directory
413  */
414 static int
415 mqfs_fixup_dir(struct mqfs_node *parent)
416 {
417 	struct mqfs_node *dir;
418 
419 	dir = mqnode_alloc();
420 	dir->mn_name[0] = '.';
421 	dir->mn_type = mqfstype_this;
422 	dir->mn_refcount = 1;
423 	if (mqfs_add_node(parent, dir) != 0) {
424 		mqnode_free(dir);
425 		return (-1);
426 	}
427 
428 	dir = mqnode_alloc();
429 	dir->mn_name[0] = dir->mn_name[1] = '.';
430 	dir->mn_type = mqfstype_parent;
431 	dir->mn_refcount = 1;
432 
433 	if (mqfs_add_node(parent, dir) != 0) {
434 		mqnode_free(dir);
435 		return (-1);
436 	}
437 
438 	return (0);
439 }
440 
441 #ifdef notyet
442 
443 /*
444  * Create a directory
445  */
446 static struct mqfs_node *
447 mqfs_create_dir(struct mqfs_node *parent, const char *name, int namelen)
448 {
449 	struct mqfs_node *dir;
450 
451 	dir = mqnode_alloc();
452 	strncpy(dir->mn_name, name, namelen);
453 	dir->mn_type = mqfstype_dir;
454 	dir->mn_refcount = 1;
455 	if (mqfs_add_node(parent, dir) != 0) {
456 		mqnode_free(dir);
457 		return (NULL);
458 	}
459 
460 	if (mqfs_fixup_dir(dir) != 0) {
461 		mqfs_destroy(dir);
462 		return (NULL);
463 	}
464 
465 	return (dir);
466 }
467 
468 /*
469  * Create a symlink
470  */
471 static struct mqfs_node *
472 mqfs_create_link(struct mqfs_node *parent, const char *name, int namelen)
473 {
474 	struct mqfs_node *node;
475 
476 	node = mqfs_create_file(parent, name, namelen);
477 	if (node == NULL)
478 		return (NULL);
479 	node->mn_type = mqfstype_symlink;
480 	return (node);
481 }
482 
483 #endif
484 
485 /*
486  * Create a file
487  */
488 static struct mqfs_node *
489 mqfs_create_file(struct mqfs_node *parent, const char *name, int namelen)
490 {
491 	struct mqfs_node *node;
492 
493 	node = mqnode_alloc();
494 	strncpy(node->mn_name, name, namelen);
495 	node->mn_type = mqfstype_file;
496 	node->mn_refcount = 1;
497 
498 	if (mqfs_add_node(parent, node) != 0) {
499 		mqnode_free(node);
500 		return (NULL);
501 	}
502 	return (node);
503 }
504 
505 /*
506  * Destroy a node or a tree of nodes
507  */
508 static int
509 mqfs_destroy(struct mqfs_node *node)
510 {
511 	struct mqfs_node *parent;
512 
513 	KASSERT(node != NULL,
514 	    ("%s(): node is NULL", __func__));
515 	KASSERT(node->mn_info != NULL,
516 	    ("%s(): node has no mn_info", __func__));
517 
518 	/* destroy children */
519 	if (node->mn_type == mqfstype_dir || node->mn_type == mqfstype_root)
520 		while (! LIST_EMPTY(&node->mn_children))
521 			mqfs_destroy(LIST_FIRST(&node->mn_children));
522 
523 	/* unlink from parent */
524 	if ((parent = node->mn_parent) != NULL) {
525 		KASSERT(parent->mn_info == node->mn_info,
526 		    ("%s(): parent has different mn_info", __func__));
527 		LIST_REMOVE(node, mn_sibling);
528 	}
529 
530 	if (node->mn_fileno != 0)
531 		mqfs_fileno_free(node->mn_info, node);
532 	if (node->mn_data != NULL)
533 		mqueue_free(node->mn_data);
534 	mqnode_free(node);
535 	return (0);
536 }
537 
538 /*
539  * Mount a mqfs instance
540  */
541 static int
542 mqfs_mount(struct mount *mp, struct thread *td)
543 {
544 	struct statfs *sbp;
545 
546 	if (mp->mnt_flag & MNT_UPDATE)
547 		return (EOPNOTSUPP);
548 
549 	mp->mnt_data = &mqfs_data;
550 	mp->mnt_flag |= MNT_LOCAL;
551 	/* mp->mnt_kern_flag |= MNTK_MPSAFE; */
552 	vfs_getnewfsid(mp);
553 
554 	sbp = &mp->mnt_stat;
555 	vfs_mountedfrom(mp, "mqueue");
556 	sbp->f_bsize = PAGE_SIZE;
557 	sbp->f_iosize = PAGE_SIZE;
558 	sbp->f_blocks = 1;
559 	sbp->f_bfree = 0;
560 	sbp->f_bavail = 0;
561 	sbp->f_files = 1;
562 	sbp->f_ffree = 0;
563 	return (0);
564 }
565 
566 /*
567  * Unmount a mqfs instance
568  */
569 static int
570 mqfs_unmount(struct mount *mp, int mntflags, struct thread *td)
571 {
572 	int error;
573 
574 	error = vflush(mp, 0, (mntflags & MNT_FORCE) ?  FORCECLOSE : 0, td);
575 	return (error);
576 }
577 
578 /*
579  * Return a root vnode
580  */
581 static int
582 mqfs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td)
583 {
584 	struct mqfs_info *mqfs;
585 	int ret;
586 
587 	mqfs = VFSTOMQFS(mp);
588 	sx_xlock(&mqfs->mi_lock);
589 	ret = mqfs_allocv(mp, vpp, mqfs->mi_root);
590 	sx_xunlock(&mqfs->mi_lock);
591 	return (ret);
592 }
593 
594 /*
595  * Return filesystem stats
596  */
597 static int
598 mqfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
599 {
600 	/* XXX update statistics */
601 	return (0);
602 }
603 
604 /*
605  * Initialize a mqfs instance
606  */
607 static int
608 mqfs_init(struct vfsconf *vfc)
609 {
610 	struct mqfs_node *root;
611 	struct mqfs_info *mi;
612 
613 	mqnode_zone = uma_zcreate("mqnode", sizeof(struct mqfs_node),
614 		NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
615 	mqueue_zone = uma_zcreate("mqueue", sizeof(struct mqueue),
616 		NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
617 	mvdata_zone = uma_zcreate("mvdata",
618 		sizeof(struct mqfs_vdata), NULL, NULL, NULL,
619 		NULL, UMA_ALIGN_PTR, 0);
620 	mqnoti_zone = uma_zcreate("mqnotifier", sizeof(struct mqueue_notifier),
621 		NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
622 	mi = &mqfs_data;
623 	sx_init(&mi->mi_lock, "mqfs lock");
624 	/* set up the root diretory */
625 	root = mqnode_alloc();
626 	root->mn_type = mqfstype_root;
627 	root->mn_refcount = 1;
628 	root->mn_name[0] = '/';
629 	root->mn_info = mi;
630 	LIST_INIT(&root->mn_children);
631 	LIST_INIT(&root->mn_vnodes);
632 	root->mn_mode = 01777;
633 	mi->mi_root = root;
634 	mqfs_fileno_init(mi);
635 	mqfs_fileno_alloc(mi, root);
636 	mqfs_fixup_dir(root);
637 	exit_tag = EVENTHANDLER_REGISTER(process_exit, mq_proc_exit, NULL,
638 	    EVENTHANDLER_PRI_ANY);
639 	mq_fdclose = mqueue_fdclose;
640 	p31b_setcfg(CTL_P1003_1B_MESSAGE_PASSING, _POSIX_MESSAGE_PASSING);
641 	return (0);
642 }
643 
644 /*
645  * Destroy a mqfs instance
646  */
647 static int
648 mqfs_uninit(struct vfsconf *vfc)
649 {
650 	struct mqfs_info *mi;
651 
652 	if (!unloadable)
653 		return (EOPNOTSUPP);
654 	EVENTHANDLER_DEREGISTER(process_exit, exit_tag);
655 	mi = &mqfs_data;
656 	mqfs_destroy(mi->mi_root);
657 	mi->mi_root = NULL;
658 	mqfs_fileno_uninit(mi);
659 	sx_destroy(&mi->mi_lock);
660 	uma_zdestroy(mqnode_zone);
661 	uma_zdestroy(mqueue_zone);
662 	uma_zdestroy(mvdata_zone);
663 	uma_zdestroy(mqnoti_zone);
664 	return (0);
665 }
666 
667 /*
668  * task routine
669  */
670 static void
671 do_recycle(void *context, int pending __unused)
672 {
673 	struct vnode *vp = (struct vnode *)context;
674 
675 	vrecycle(vp, curthread);
676 	vdrop(vp);
677 }
678 
679 /*
680  * Allocate a vnode
681  */
682 static int
683 mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn)
684 {
685 	struct mqfs_vdata *vd;
686 	int error;
687 
688 	LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) {
689 		if (vd->mv_vnode->v_mount == mp)
690 			break;
691 	}
692 
693 	if (vd != NULL) {
694 		if (vget(vd->mv_vnode, 0, curthread) == 0) {
695 			*vpp = vd->mv_vnode;
696 			vn_lock(*vpp, LK_RETRY | LK_EXCLUSIVE,
697 			    curthread);
698 			return (0);
699 		}
700 		/* XXX if this can happen, we're in trouble */
701 	}
702 
703 	error = getnewvnode("mqueue", mp, &mqfs_vnodeops, vpp);
704 	if (error)
705 		return (error);
706 	vd = uma_zalloc(mvdata_zone, M_WAITOK);
707 	(*vpp)->v_data = vd;
708 	vd->mv_vnode = *vpp;
709 	vd->mv_node = pn;
710 	TASK_INIT(&vd->mv_task, 0, do_recycle, *vpp);
711 	LIST_INSERT_HEAD(&pn->mn_vnodes, vd, mv_link);
712 	mqnode_addref(pn);
713 	switch (pn->mn_type) {
714 	case mqfstype_root:
715 		(*vpp)->v_vflag = VV_ROOT;
716 		/* fall through */
717 	case mqfstype_dir:
718 	case mqfstype_this:
719 	case mqfstype_parent:
720 		(*vpp)->v_type = VDIR;
721 		break;
722 	case mqfstype_file:
723 		(*vpp)->v_type = VREG;
724 		break;
725 	case mqfstype_symlink:
726 		(*vpp)->v_type = VLNK;
727 		break;
728 	case mqfstype_none:
729 		KASSERT(0, ("mqfs_allocf called for null node\n"));
730 	default:
731 		panic("%s has unexpected type: %d", pn->mn_name, pn->mn_type);
732 	}
733 	vn_lock(*vpp, LK_RETRY | LK_EXCLUSIVE, curthread);
734 	return (0);
735 }
736 
737 /*
738  * Search a directory entry
739  */
740 static struct mqfs_node *
741 mqfs_search(struct mqfs_node *pd, const char *name, int len)
742 {
743 	struct mqfs_node *pn;
744 
745 	LIST_FOREACH(pn, &pd->mn_children, mn_sibling) {
746 		if (strncmp(pn->mn_name, name, len) == 0)
747 			return (pn);
748 	}
749 	return (NULL);
750 }
751 
752 /*
753  * Look up a file or directory
754  */
755 static int
756 mqfs_lookupx(struct vop_cachedlookup_args *ap)
757 {
758 	struct componentname *cnp;
759 	struct vnode *dvp, **vpp;
760 	struct mqfs_node *pd;
761 	struct mqfs_node *pn;
762 	int nameiop, flags, error, namelen;
763 	char *pname;
764 	struct thread *td;
765 
766 	cnp = ap->a_cnp;
767 	vpp = ap->a_vpp;
768 	dvp = ap->a_dvp;
769 	pname = cnp->cn_nameptr;
770 	namelen = cnp->cn_namelen;
771 	td = cnp->cn_thread;
772 	flags = cnp->cn_flags;
773 	nameiop = cnp->cn_nameiop;
774 	pd = VTON(dvp);
775 	pn = NULL;
776 	*vpp = NULLVP;
777 
778 	if (dvp->v_type != VDIR)
779 		return (ENOTDIR);
780 
781 	error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_thread);
782 	if (error)
783 		return (error);
784 
785 	/* shortcut: check if the name is too long */
786 	if (cnp->cn_namelen >= MQFS_NAMELEN)
787 		return (ENOENT);
788 
789 	/* self */
790 	if (namelen == 1 && pname[0] == '.') {
791 		if ((flags & ISLASTCN) && nameiop != LOOKUP)
792 			return (EINVAL);
793 		pn = pd;
794 		*vpp = dvp;
795 		VREF(dvp);
796 		return (0);
797 	}
798 
799 	/* parent */
800 	if (cnp->cn_flags & ISDOTDOT) {
801 		if (dvp->v_vflag & VV_ROOT)
802 			return (EIO);
803 		if ((flags & ISLASTCN) && nameiop != LOOKUP)
804 			return (EINVAL);
805 		VOP_UNLOCK(dvp, 0, cnp->cn_thread);
806 		KASSERT(pd->mn_parent, ("non-root directory has no parent"));
807 		pn = pd->mn_parent;
808 		error = mqfs_allocv(dvp->v_mount, vpp, pn);
809 		vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
810 		return (error);
811 	}
812 
813 	/* named node */
814 	pn = mqfs_search(pd, pname, namelen);
815 
816 	/* found */
817 	if (pn != NULL) {
818 		/* DELETE */
819 		if (nameiop == DELETE && (flags & ISLASTCN)) {
820 			error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
821 			if (error)
822 				return (error);
823 			if (*vpp == dvp) {
824 				VREF(dvp);
825 				*vpp = dvp;
826 				return (0);
827 			}
828 		}
829 
830 		/* allocate vnode */
831 		error = mqfs_allocv(dvp->v_mount, vpp, pn);
832 		if (error == 0 && cnp->cn_flags & MAKEENTRY)
833 			cache_enter(dvp, *vpp, cnp);
834 		return (error);
835 	}
836 
837 	/* not found */
838 
839 	/* will create a new entry in the directory ? */
840 	if ((nameiop == CREATE || nameiop == RENAME) && (flags & LOCKPARENT)
841 	    && (flags & ISLASTCN)) {
842 		error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
843 		if (error)
844 			return (error);
845 		cnp->cn_flags |= SAVENAME;
846 		return (EJUSTRETURN);
847 	}
848 	return (ENOENT);
849 }
850 
851 #if 0
852 struct vop_lookup_args {
853 	struct vop_generic_args a_gen;
854 	struct vnode *a_dvp;
855 	struct vnode **a_vpp;
856 	struct componentname *a_cnp;
857 };
858 #endif
859 
860 /*
861  * vnode lookup operation
862  */
863 static int
864 mqfs_lookup(struct vop_cachedlookup_args *ap)
865 {
866 	struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount);
867 	int rc;
868 
869 	sx_xlock(&mqfs->mi_lock);
870 	rc = mqfs_lookupx(ap);
871 	sx_xunlock(&mqfs->mi_lock);
872 	return (rc);
873 }
874 
875 #if 0
876 struct vop_create_args {
877 	struct vnode *a_dvp;
878 	struct vnode **a_vpp;
879 	struct componentname *a_cnp;
880 	struct vattr *a_vap;
881 };
882 #endif
883 
884 /*
885  * vnode creation operation
886  */
887 static int
888 mqfs_create(struct vop_create_args *ap)
889 {
890 	struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount);
891 	struct componentname *cnp = ap->a_cnp;
892 	struct mqfs_node *pd;
893 	struct mqfs_node *pn;
894 	struct mqueue *mq;
895 	int error;
896 
897 	pd = VTON(ap->a_dvp);
898 	if (pd->mn_type != mqfstype_root && pd->mn_type != mqfstype_dir)
899 		return (ENOTDIR);
900 	mq = mqueue_alloc(NULL);
901 	if (mq == NULL)
902 		return (EAGAIN);
903 	sx_xlock(&mqfs->mi_lock);
904 #if 0
905 	/* named node */
906 	pn = mqfs_search(pd, cnp->cn_nameptr, cnp->cn_namelen);
907 	if (pn != NULL) {
908 		mqueue_free(mq);
909 		sx_xunlock(&mqfs->mi_lock);
910 		return (EEXIST);
911 	}
912 #else
913 	if ((cnp->cn_flags & HASBUF) == 0)
914 		panic("%s: no name", __func__);
915 #endif
916 	pn = mqfs_create_file(pd, cnp->cn_nameptr, cnp->cn_namelen);
917 	pn->mn_mode = ap->a_vap->va_mode;
918 	pn->mn_uid = cnp->cn_cred->cr_uid;
919 	pn->mn_gid = cnp->cn_cred->cr_gid;
920 	pn->mn_data = mq;
921 	getnanotime(&pn->mn_birth);
922 	pn->mn_ctime = pn->mn_atime = pn->mn_mtime = pn->mn_birth;
923 	/* node attribute */
924 	error = mqfs_allocv(ap->a_dvp->v_mount, ap->a_vpp, pn);
925 	sx_xunlock(&mqfs->mi_lock);
926 	return (error);
927 }
928 
929 /*
930  * Remove an entry
931  */
932 static
933 int do_unlink(struct mqfs_node *pn, struct ucred *ucred)
934 {
935 	struct mqfs_node *parent;
936 	struct mqfs_vdata *vd;
937 	int error = 0;
938 
939 	sx_assert(&pn->mn_info->mi_lock, SX_LOCKED);
940 
941 	if (ucred->cr_uid != pn->mn_uid &&
942 	    (error = suser_cred(ucred, 0)) != 0)
943 		error = EACCES;
944 	else if (!pn->mn_deleted) {
945 		parent = pn->mn_parent;
946 		pn->mn_parent = NULL;
947 		pn->mn_deleted = 1;
948 		LIST_REMOVE(pn, mn_sibling);
949 		LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) {
950 			cache_purge(vd->mv_vnode);
951 			vhold(vd->mv_vnode);
952 			taskqueue_enqueue(taskqueue_thread, &vd->mv_task);
953 		}
954 		mqnode_release(pn);
955 		mqnode_release(parent);
956 	} else
957 		error = ENOENT;
958 	return (error);
959 }
960 
961 #if 0
962 struct vop_remove_args {
963 	struct vnode *a_dvp;
964 	struct vnode *a_vp;
965 	struct componentname *a_cnp;
966 };
967 #endif
968 
969 /*
970  * vnode removal operation
971  */
972 static int
973 mqfs_remove(struct vop_remove_args *ap)
974 {
975 	struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount);
976 	struct mqfs_node *pn;
977 	int error;
978 
979 	if (ap->a_vp->v_type == VDIR)
980                 return (EPERM);
981 	pn = VTON(ap->a_vp);
982 	sx_xlock(&mqfs->mi_lock);
983 	error = do_unlink(pn, ap->a_cnp->cn_cred);
984 	sx_xunlock(&mqfs->mi_lock);
985 	return (error);
986 }
987 
988 #if 0
989 struct vop_inactive_args {
990 	struct vnode *a_vp;
991 	struct thread *a_td;
992 };
993 #endif
994 
995 static int
996 mqfs_inactive(struct vop_inactive_args *ap)
997 {
998 	struct mqfs_node *pn = VTON(ap->a_vp);
999 
1000 	if (pn->mn_deleted)
1001 		vrecycle(ap->a_vp, ap->a_td);
1002 	return (0);
1003 }
1004 
1005 #if 0
1006 struct vop_reclaim_args {
1007 	struct vop_generic_args a_gen;
1008 	struct vnode *a_vp;
1009 	struct thread *a_td;
1010 };
1011 #endif
1012 
1013 static int
1014 mqfs_reclaim(struct vop_reclaim_args *ap)
1015 {
1016 	struct mqfs_info *mqfs = VFSTOMQFS(ap->a_vp->v_mount);
1017 	struct vnode *vp = ap->a_vp;
1018 	struct mqfs_node *pn;
1019 	struct mqfs_vdata *vd;
1020 
1021 	vd = vp->v_data;
1022 	pn = vd->mv_node;
1023 	sx_xlock(&mqfs->mi_lock);
1024 	vp->v_data = NULL;
1025 	LIST_REMOVE(vd, mv_link);
1026 	uma_zfree(mvdata_zone, vd);
1027 	mqnode_release(pn);
1028 	sx_xunlock(&mqfs->mi_lock);
1029 	return (0);
1030 }
1031 
1032 #if 0
1033 struct vop_open_args {
1034 	struct vop_generic_args a_gen;
1035 	struct vnode *a_vp;
1036 	int a_mode;
1037 	struct ucred *a_cred;
1038 	struct thread *a_td;
1039 	int a_fdidx;
1040 };
1041 #endif
1042 
1043 static int
1044 mqfs_open(struct vop_open_args *ap)
1045 {
1046 	return (0);
1047 }
1048 
1049 #if 0
1050 struct vop_close_args {
1051 	struct vop_generic_args a_gen;
1052 	struct vnode *a_vp;
1053 	int a_fflag;
1054 	struct ucred *a_cred;
1055 	struct thread *a_td;
1056 };
1057 #endif
1058 
1059 static int
1060 mqfs_close(struct vop_close_args *ap)
1061 {
1062 	return (0);
1063 }
1064 
1065 #if 0
1066 struct vop_access_args {
1067 	struct vop_generic_args a_gen;
1068 	struct vnode *a_vp;
1069 	int a_mode;
1070 	struct ucred *a_cred;
1071 	struct thread *a_td;
1072 };
1073 #endif
1074 
1075 /*
1076  * Verify permissions
1077  */
1078 static int
1079 mqfs_access(struct vop_access_args *ap)
1080 {
1081 	struct vnode *vp = ap->a_vp;
1082 	struct vattr vattr;
1083 	int error;
1084 
1085 	error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td);
1086 	if (error)
1087 		return (error);
1088 	error = vaccess(vp->v_type, vattr.va_mode, vattr.va_uid,
1089 	    vattr.va_gid, ap->a_mode, ap->a_cred, NULL);
1090 	return (error);
1091 }
1092 
1093 #if 0
1094 struct vop_getattr_args {
1095 	struct vop_generic_args a_gen;
1096 	struct vnode *a_vp;
1097 	struct vattr *a_vap;
1098 	struct ucred *a_cred;
1099 	struct thread *a_td;
1100 };
1101 #endif
1102 
1103 /*
1104  * Get file attributes
1105  */
1106 static int
1107 mqfs_getattr(struct vop_getattr_args *ap)
1108 {
1109 	struct vnode *vp = ap->a_vp;
1110 	struct mqfs_node *pn = VTON(vp);
1111 	struct vattr *vap = ap->a_vap;
1112 	int error = 0;
1113 
1114 	VATTR_NULL(vap);
1115 	vap->va_type = vp->v_type;
1116 	vap->va_mode = pn->mn_mode;
1117 	vap->va_nlink = 1;
1118 	vap->va_uid = pn->mn_uid;
1119 	vap->va_gid = pn->mn_gid;
1120 	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
1121 	vap->va_fileid = pn->mn_fileno;
1122 	vap->va_size = 0;
1123 	vap->va_blocksize = PAGE_SIZE;
1124 	vap->va_bytes = vap->va_size = 0;
1125 	vap->va_atime = pn->mn_atime;
1126 	vap->va_mtime = pn->mn_mtime;
1127 	vap->va_ctime = pn->mn_ctime;
1128 	vap->va_birthtime = pn->mn_birth;
1129 	vap->va_gen = 0;
1130 	vap->va_flags = 0;
1131 	vap->va_rdev = 0;
1132 	vap->va_bytes = 0;
1133 	vap->va_filerev = 0;
1134 	vap->va_vaflags = 0;
1135 	return (error);
1136 }
1137 
1138 #if 0
1139 struct vop_setattr_args {
1140 	struct vop_generic_args a_gen;
1141 	struct vnode *a_vp;
1142 	struct vattr *a_vap;
1143 	struct ucred *a_cred;
1144 	struct thread *a_td;
1145 };
1146 #endif
1147 /*
1148  * Set attributes
1149  */
1150 static int
1151 mqfs_setattr(struct vop_setattr_args *ap)
1152 {
1153 	struct mqfs_node *pn;
1154 	struct vattr *vap;
1155 	struct vnode *vp;
1156 	int c, error;
1157 	uid_t uid;
1158 	gid_t gid;
1159 
1160 	vap = ap->a_vap;
1161 	vp = ap->a_vp;
1162 	if ((vap->va_type != VNON) ||
1163 	    (vap->va_nlink != VNOVAL) ||
1164 	    (vap->va_fsid != VNOVAL) ||
1165 	    (vap->va_fileid != VNOVAL) ||
1166 	    (vap->va_blocksize != VNOVAL) ||
1167 	    (vap->va_flags != VNOVAL && vap->va_flags != 0) ||
1168 	    (vap->va_rdev != VNOVAL) ||
1169 	    ((int)vap->va_bytes != VNOVAL) ||
1170 	    (vap->va_gen != VNOVAL)) {
1171 		return (EINVAL);
1172 	}
1173 
1174 	pn = VTON(vp);
1175 
1176 	error = c = 0;
1177 	if (vap->va_uid == (uid_t)VNOVAL)
1178 		uid = pn->mn_uid;
1179 	else
1180 		uid = vap->va_uid;
1181 	if (vap->va_gid == (gid_t)VNOVAL)
1182 		gid = pn->mn_gid;
1183 	else
1184 		gid = vap->va_gid;
1185 
1186 	if (uid != pn->mn_uid || gid != pn->mn_gid) {
1187 		/*
1188 		 * To modify the ownership of a file, must possess VADMIN
1189 		 * for that file.
1190 		 */
1191 		if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td)))
1192 			return (error);
1193 		if (((ap->a_cred->cr_uid != pn->mn_uid) || uid != pn->mn_uid ||
1194 		    (gid != pn->mn_gid && !groupmember(gid, ap->a_cred))) &&
1195 		    (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL))
1196                        != 0)
1197 			return (error);
1198 		pn->mn_uid = uid;
1199 		pn->mn_gid = gid;
1200 		c = 1;
1201 	}
1202 
1203 	if (vap->va_mode != (mode_t)VNOVAL) {
1204 		if ((ap->a_cred->cr_uid != pn->mn_uid) &&
1205 		    (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL)))
1206 			return (error);
1207 		pn->mn_mode = vap->va_mode;
1208 		c = 1;
1209 	}
1210 
1211 	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
1212 		/* See the comment in ufs_vnops::ufs_setattr(). */
1213 		if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td)) &&
1214 		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
1215 		    (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, ap->a_td))))
1216 			return (error);
1217 		if (vap->va_atime.tv_sec != VNOVAL) {
1218 			pn->mn_atime = vap->va_atime;
1219 		}
1220 		if (vap->va_mtime.tv_sec != VNOVAL) {
1221 			pn->mn_mtime = vap->va_mtime;
1222 		}
1223 		c = 1;
1224 	}
1225 	if (c) {
1226 		vfs_timestamp(&pn->mn_ctime);
1227 	}
1228 	return (0);
1229 }
1230 
1231 #if 0
1232 struct vop_read_args {
1233 	struct vop_generic_args a_gen;
1234 	struct vnode *a_vp;
1235 	struct uio *a_uio;
1236 	int a_ioflag;
1237 	struct ucred *a_cred;
1238 };
1239 #endif
1240 
1241 /*
1242  * Read from a file
1243  */
1244 static int
1245 mqfs_read(struct vop_read_args *ap)
1246 {
1247 	char buf[80];
1248 	struct vnode *vp = ap->a_vp;
1249 	struct uio *uio = ap->a_uio;
1250 	struct mqfs_node *pn;
1251 	struct mqueue *mq;
1252 	int len, error;
1253 
1254 	if (vp->v_type != VREG)
1255 		return (EINVAL);
1256 
1257 	pn = VTON(vp);
1258 	mq = VTOMQ(vp);
1259 	snprintf(buf, sizeof(buf),
1260 		"QSIZE:%-10ld MAXMSG:%-10ld CURMSG:%-10ld MSGSIZE:%-10ld\n",
1261 		mq->mq_totalbytes,
1262 		mq->mq_maxmsg,
1263 		mq->mq_curmsgs,
1264 		mq->mq_msgsize);
1265 	buf[sizeof(buf)-1] = '\0';
1266 	len = strlen(buf);
1267 	error = uiomove_frombuf(buf, len, uio);
1268 	return (error);
1269 }
1270 
1271 #if 0
1272 struct vop_readdir_args {
1273 	struct vop_generic_args a_gen;
1274 	struct vnode *a_vp;
1275 	struct uio *a_uio;
1276 	struct ucred *a_cred;
1277 	int *a_eofflag;
1278 	int *a_ncookies;
1279 	u_long **a_cookies;
1280 };
1281 #endif
1282 
1283 /*
1284  * Return directory entries.
1285  */
1286 static int
1287 mqfs_readdir(struct vop_readdir_args *ap)
1288 {
1289 	struct vnode *vp;
1290 	struct mqfs_info *mi;
1291 	struct mqfs_node *pd;
1292 	struct mqfs_node *pn;
1293 	struct dirent entry;
1294 	struct uio *uio;
1295 	int *tmp_ncookies = NULL;
1296 	off_t offset;
1297 	int error, i;
1298 
1299 	vp = ap->a_vp;
1300 	mi = VFSTOMQFS(vp->v_mount);
1301 	pd = VTON(vp);
1302 	uio = ap->a_uio;
1303 
1304 	if (vp->v_type != VDIR)
1305 		return (ENOTDIR);
1306 
1307 	if (uio->uio_offset < 0)
1308 		return (EINVAL);
1309 
1310 	if (ap->a_ncookies != NULL) {
1311 		tmp_ncookies = ap->a_ncookies;
1312 		*ap->a_ncookies = 0;
1313 		ap->a_ncookies = NULL;
1314         }
1315 
1316 	error = 0;
1317 	offset = 0;
1318 
1319 	sx_xlock(&mi->mi_lock);
1320 
1321 	LIST_FOREACH(pn, &pd->mn_children, mn_sibling) {
1322 		entry.d_reclen = sizeof(entry);
1323 		if (!pn->mn_fileno)
1324 			mqfs_fileno_alloc(mi, pn);
1325 		entry.d_fileno = pn->mn_fileno;
1326 		for (i = 0; i < MQFS_NAMELEN - 1 && pn->mn_name[i] != '\0'; ++i)
1327 			entry.d_name[i] = pn->mn_name[i];
1328 		entry.d_name[i] = 0;
1329 		entry.d_namlen = i;
1330 		switch (pn->mn_type) {
1331 		case mqfstype_root:
1332 		case mqfstype_dir:
1333 		case mqfstype_this:
1334 		case mqfstype_parent:
1335 			entry.d_type = DT_DIR;
1336 			break;
1337 		case mqfstype_file:
1338 			entry.d_type = DT_REG;
1339 			break;
1340 		case mqfstype_symlink:
1341 			entry.d_type = DT_LNK;
1342 			break;
1343 		default:
1344 			panic("%s has unexpected node type: %d", pn->mn_name,
1345 				pn->mn_type);
1346 		}
1347 		if (entry.d_reclen > uio->uio_resid)
1348                         break;
1349 		if (offset >= uio->uio_offset) {
1350 			error = vfs_read_dirent(ap, &entry, offset);
1351                         if (error)
1352                                 break;
1353                 }
1354                 offset += entry.d_reclen;
1355 	}
1356 	sx_xunlock(&mi->mi_lock);
1357 
1358 	uio->uio_offset = offset;
1359 
1360 	if (tmp_ncookies != NULL)
1361 		ap->a_ncookies = tmp_ncookies;
1362 
1363 	return (error);
1364 }
1365 
1366 #ifdef notyet
1367 
1368 #if 0
1369 struct vop_mkdir_args {
1370 	struct vnode *a_dvp;
1371 	struvt vnode **a_vpp;
1372 	struvt componentname *a_cnp;
1373 	struct vattr *a_vap;
1374 };
1375 #endif
1376 
1377 /*
1378  * Create a directory.
1379  */
1380 static int
1381 mqfs_mkdir(struct vop_mkdir_args *ap)
1382 {
1383 	struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount);
1384 	struct componentname *cnp = ap->a_cnp;
1385 	struct mqfs_node *pd = VTON(ap->a_dvp);
1386 	struct mqfs_node *pn;
1387 	int error;
1388 
1389 	if (pd->mn_type != mqfstype_root && pd->mn_type != mqfstype_dir)
1390 		return (ENOTDIR);
1391 	sx_xlock(&mqfs->mi_lock);
1392 #if 0
1393 	/* named node */
1394 	pn = mqfs_search(pd, cnp->cn_nameptr, cnp->cn_namelen);
1395 	if (pn != NULL) {
1396 		sx_xunlock(&mqfs->mi_lock);
1397 		return (EEXIST);
1398 	}
1399 #else
1400 	if ((cnp->cn_flags & HASBUF) == 0)
1401 		panic("%s: no name", __func__);
1402 #endif
1403 	pn = mqfs_create_dir(pd, cnp->cn_nameptr, cnp->cn_namelen);
1404 	pn->mn_mode = ap->a_vap->va_mode;
1405 	pn->mn_uid = cnp->cn_cred->cr_uid;
1406 	pn->mn_gid = cnp->cn_cred->cr_gid;
1407 	getnanotime(&pn->mn_birth);
1408 	pn->mn_ctime = pn->mn_atime = pn->mn_mtime = pn->mn_birth;
1409 	/* node attribute */
1410 	error = mqfs_allocv(ap->a_dvp->v_mount, ap->a_vpp, pn);
1411 	sx_xunlock(&mqfs->mi_lock);
1412 	return (error);
1413 }
1414 
1415 #if 0
1416 struct vop_rmdir_args {
1417 	struct vnode *a_dvp;
1418 	struct vnode *a_vp;
1419 	struct componentname *a_cnp;
1420 };
1421 #endif
1422 
1423 /*
1424  * Remove a directory.
1425  */
1426 static int
1427 mqfs_rmdir(struct vop_rmdir_args *ap)
1428 {
1429 	struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount);
1430 	struct mqfs_node *pn = VTON(ap->a_vp);
1431 	struct mqfs_node *pt;
1432 
1433 	if (pn->mn_type != mqfstype_dir)
1434 		return (ENOTDIR);
1435 
1436 	sx_xlock(&mqfs->mi_lock);
1437 	if (pn->mn_deleted) {
1438 		sx_xunlock(&mqfs->mi_lock);
1439 		return (ENOENT);
1440 	}
1441 
1442 	pt = LIST_FIRST(&pn->mn_children);
1443 	pt = LIST_NEXT(pt, mn_sibling);
1444 	pt = LIST_NEXT(pt, mn_sibling);
1445 	if (pt != NULL) {
1446 		sx_xunlock(&mqfs->mi_lock);
1447 		return (ENOTEMPTY);
1448 	}
1449 	pt = pn->mn_parent;
1450 	pn->mn_parent = NULL;
1451 	pn->mn_deleted = 1;
1452 	LIST_REMOVE(pn, mn_sibling);
1453 	mqnode_release(pn);
1454 	mqnode_release(pt);
1455 	sx_xunlock(&mqfs->mi_lock);
1456 	cache_purge(ap->a_vp);
1457 	return (0);
1458 }
1459 
1460 #endif /* notyet */
1461 
1462 /*
1463  * Allocate a message queue
1464  */
1465 static struct mqueue *
1466 mqueue_alloc(const struct mq_attr *attr)
1467 {
1468 	struct mqueue *mq;
1469 
1470 	if (curmq >= maxmq)
1471 		return (NULL);
1472 	mq = uma_zalloc(mqueue_zone, M_WAITOK | M_ZERO);
1473 	TAILQ_INIT(&mq->mq_msgq);
1474 	if (attr != NULL) {
1475 		mq->mq_maxmsg = attr->mq_maxmsg;
1476 		mq->mq_msgsize = attr->mq_msgsize;
1477 	} else {
1478 		mq->mq_maxmsg = default_maxmsg;
1479 		mq->mq_msgsize = default_msgsize;
1480 	}
1481 	mtx_init(&mq->mq_mutex, "mqueue", NULL, MTX_DEF);
1482 	knlist_init(&mq->mq_rsel.si_note, &mq->mq_mutex, NULL, NULL, NULL);
1483 	knlist_init(&mq->mq_wsel.si_note, &mq->mq_mutex, NULL, NULL, NULL);
1484 	atomic_add_int(&curmq, 1);
1485 	return (mq);
1486 }
1487 
1488 /*
1489  * Destroy a message queue
1490  */
1491 static void
1492 mqueue_free(struct mqueue *mq)
1493 {
1494 	struct mqueue_msg *msg;
1495 
1496 	while ((msg = TAILQ_FIRST(&mq->mq_msgq)) != NULL) {
1497 		TAILQ_REMOVE(&mq->mq_msgq, msg, msg_link);
1498 		FREE(msg, M_MQUEUEDATA);
1499 	}
1500 
1501 	mtx_destroy(&mq->mq_mutex);
1502 	knlist_destroy(&mq->mq_rsel.si_note);
1503 	knlist_destroy(&mq->mq_wsel.si_note);
1504 	uma_zfree(mqueue_zone, mq);
1505 	atomic_add_int(&curmq, -1);
1506 }
1507 
1508 /*
1509  * Load a message from user space
1510  */
1511 static struct mqueue_msg *
1512 mqueue_loadmsg(const char *msg_ptr, size_t msg_size, int msg_prio)
1513 {
1514 	struct mqueue_msg *msg;
1515 	size_t len;
1516 	int error;
1517 
1518 	len = sizeof(struct mqueue_msg) + msg_size;
1519 	MALLOC(msg, struct mqueue_msg *, len, M_MQUEUEDATA, M_WAITOK);
1520 	error = copyin(msg_ptr, ((char *)msg) + sizeof(struct mqueue_msg),
1521 	    msg_size);
1522 	if (error) {
1523 		FREE(msg, M_MQUEUEDATA);
1524 		msg = NULL;
1525 	} else {
1526 		msg->msg_size = msg_size;
1527 		msg->msg_prio = msg_prio;
1528 	}
1529 	return (msg);
1530 }
1531 
1532 /*
1533  * Save a message to user space
1534  */
1535 static int
1536 mqueue_savemsg(struct mqueue_msg *msg, char *msg_ptr, int *msg_prio)
1537 {
1538 	int error;
1539 
1540 	error = copyout(((char *)msg) + sizeof(*msg), msg_ptr,
1541 		msg->msg_size);
1542 	if (error == 0 && msg_prio != NULL)
1543 		error = copyout(&msg->msg_prio, msg_prio, sizeof(int));
1544 	return (error);
1545 }
1546 
1547 /*
1548  * Free a message's memory
1549  */
1550 static __inline void
1551 mqueue_freemsg(struct mqueue_msg *msg)
1552 {
1553 	FREE(msg, M_MQUEUEDATA);
1554 }
1555 
1556 /*
1557  * Send a message. if waitok is false, thread will not be
1558  * blocked if there is no data in queue, otherwise, absolute
1559  * time will be checked.
1560  */
1561 int
1562 mqueue_send(struct mqueue *mq, const char *msg_ptr,
1563 	size_t msg_len, unsigned msg_prio, int waitok,
1564 	const struct timespec *abs_timeout)
1565 {
1566 	struct mqueue_msg *msg;
1567 	struct timespec ets, ts, ts2;
1568 	struct timeval tv;
1569 	int error;
1570 
1571 	if (msg_prio >= MQ_PRIO_MAX)
1572 		return (EINVAL);
1573 	if (msg_len > mq->mq_msgsize)
1574 		return (EMSGSIZE);
1575 	msg = mqueue_loadmsg(msg_ptr, msg_len, msg_prio);
1576 	if (msg == NULL)
1577 		return (EFAULT);
1578 
1579 	/* O_NONBLOCK case */
1580 	if (!waitok) {
1581 		error = _mqueue_send(mq, msg, -1);
1582 		if (error)
1583 			goto bad;
1584 		return (0);
1585 	}
1586 
1587 	/* we allow a null timeout (wait forever) */
1588 	if (abs_timeout == NULL) {
1589 		error = _mqueue_send(mq, msg, 0);
1590 		if (error)
1591 			goto bad;
1592 		return (0);
1593 	}
1594 
1595 	/* send it before checking time */
1596 	error = _mqueue_send(mq, msg, -1);
1597 	if (error == 0)
1598 		return (0);
1599 
1600 	if (error != EAGAIN)
1601 		goto bad;
1602 
1603 	error = copyin(abs_timeout, &ets, sizeof(ets));
1604 	if (error != 0)
1605 		goto bad;
1606 	if (ets.tv_nsec >= 1000000000 || ets.tv_nsec < 0) {
1607 		error = EINVAL;
1608 		goto bad;
1609 	}
1610 	for (;;) {
1611 		ts2 = ets;
1612 		getnanotime(&ts);
1613 		timespecsub(&ts2, &ts);
1614 		if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) {
1615 			error = ETIMEDOUT;
1616 			break;
1617 		}
1618 		TIMESPEC_TO_TIMEVAL(&tv, &ts2);
1619 		error = _mqueue_send(mq, msg, tvtohz(&tv));
1620 		if (error != ETIMEDOUT)
1621 			break;
1622 	}
1623 	if (error == 0)
1624 		return (0);
1625 bad:
1626 	mqueue_freemsg(msg);
1627 	return (error);
1628 }
1629 
1630 /*
1631  * Common routine to send a message
1632  */
1633 static int
1634 _mqueue_send(struct mqueue *mq, struct mqueue_msg *msg, int timo)
1635 {
1636 	struct mqueue_msg *msg2;
1637 	int error = 0;
1638 
1639 	mtx_lock(&mq->mq_mutex);
1640 	while (mq->mq_curmsgs >= mq->mq_maxmsg && error == 0) {
1641 		if (timo < 0) {
1642 			mtx_unlock(&mq->mq_mutex);
1643 			return (EAGAIN);
1644 		}
1645 		mq->mq_senders++;
1646 		error = msleep(&mq->mq_senders, &mq->mq_mutex,
1647 			    PSOCK | PCATCH, "mqsend", timo);
1648 		mq->mq_senders--;
1649 		if (error == EAGAIN)
1650 			error = ETIMEDOUT;
1651 	}
1652 	if (mq->mq_curmsgs >= mq->mq_maxmsg) {
1653 		mtx_unlock(&mq->mq_mutex);
1654 		return (error);
1655 	}
1656 	error = 0;
1657 	if (TAILQ_EMPTY(&mq->mq_msgq)) {
1658 		TAILQ_INSERT_HEAD(&mq->mq_msgq, msg, msg_link);
1659 	} else {
1660 		if (msg->msg_prio <= TAILQ_LAST(&mq->mq_msgq, msgq)->msg_prio) {
1661 			TAILQ_INSERT_TAIL(&mq->mq_msgq, msg, msg_link);
1662 		} else {
1663 			TAILQ_FOREACH(msg2, &mq->mq_msgq, msg_link) {
1664 				if (msg2->msg_prio < msg->msg_prio)
1665 					break;
1666 			}
1667 			TAILQ_INSERT_BEFORE(msg2, msg, msg_link);
1668 		}
1669 	}
1670 	mq->mq_curmsgs++;
1671 	mq->mq_totalbytes += msg->msg_size;
1672 	if (mq->mq_receivers)
1673 		wakeup_one(&mq->mq_receivers);
1674 	else if (mq->mq_notifier != NULL)
1675 		mqueue_send_notification(mq);
1676 	if (mq->mq_flags & MQ_RSEL) {
1677 		mq->mq_flags &= ~MQ_RSEL;
1678 		selwakeuppri(&mq->mq_rsel, PSOCK);
1679 	}
1680 	KNOTE_LOCKED(&mq->mq_rsel.si_note, 0);
1681 	mtx_unlock(&mq->mq_mutex);
1682 	return (0);
1683 }
1684 
1685 /*
1686  * Send realtime a signal to process which registered itself
1687  * successfully by mq_notify.
1688  */
1689 static void
1690 mqueue_send_notification(struct mqueue *mq)
1691 {
1692 	struct mqueue_notifier *nt;
1693 	struct proc *p;
1694 
1695 	mtx_assert(&mq->mq_mutex, MA_OWNED);
1696 	nt = mq->mq_notifier;
1697 	p = nt->nt_proc;
1698 	PROC_LOCK(p);
1699 	if (!KSI_ONQ(&nt->nt_ksi))
1700 		psignal_event(p, &nt->nt_sigev, &nt->nt_ksi);
1701 	PROC_UNLOCK(p);
1702 	mq->mq_notifier = NULL;
1703 }
1704 
1705 /*
1706  * Get a message. if waitok is false, thread will not be
1707  * blocked if there is no data in queue, otherwise, absolute
1708  * time will be checked.
1709  */
1710 int
1711 mqueue_receive(struct mqueue *mq, char *msg_ptr,
1712 	size_t msg_len, unsigned *msg_prio, int waitok,
1713 	const struct timespec *abs_timeout)
1714 {
1715 	struct mqueue_msg *msg;
1716 	struct timespec ets, ts, ts2;
1717 	struct timeval tv;
1718 	int error;
1719 
1720 	if (msg_len < mq->mq_msgsize)
1721 		return (EMSGSIZE);
1722 
1723 	/* O_NONBLOCK case */
1724 	if (!waitok) {
1725 		error = _mqueue_recv(mq, &msg, -1);
1726 		if (error)
1727 			return (error);
1728 		goto received;
1729 	}
1730 
1731 	/* we allow a null timeout (wait forever). */
1732 	if (abs_timeout == NULL) {
1733 		error = _mqueue_recv(mq, &msg, 0);
1734 		if (error)
1735 			return (error);
1736 		goto received;
1737 	}
1738 
1739 	/* try to get a message before checking time */
1740 	error = _mqueue_recv(mq, &msg, -1);
1741 	if (error == 0)
1742 		goto received;
1743 
1744 	if (error != EAGAIN)
1745 		return (error);
1746 
1747 	error = copyin(abs_timeout, &ets, sizeof(ets));
1748 	if (error != 0)
1749 		return (error);
1750 	if (ets.tv_nsec >= 1000000000 || ets.tv_nsec < 0) {
1751 		error = EINVAL;
1752 		return (error);
1753 	}
1754 
1755 	for (;;) {
1756 		ts2 = ets;
1757 		getnanotime(&ts);
1758 		timespecsub(&ts2, &ts);
1759 		if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) {
1760 			error = ETIMEDOUT;
1761 			return (error);
1762 		}
1763 		TIMESPEC_TO_TIMEVAL(&tv, &ts2);
1764 		error = _mqueue_recv(mq, &msg, tvtohz(&tv));
1765 		if (error == 0)
1766 			break;
1767 		if (error != ETIMEDOUT)
1768 			return (error);
1769 	}
1770 
1771 received:
1772 	error = mqueue_savemsg(msg, msg_ptr, msg_prio);
1773 	if (error == 0) {
1774 		curthread->td_retval[0] = msg->msg_size;
1775 		curthread->td_retval[1] = 0;
1776 	}
1777 	mqueue_freemsg(msg);
1778 	return (error);
1779 }
1780 
1781 /*
1782  * Common routine to receive a message
1783  */
1784 static int
1785 _mqueue_recv(struct mqueue *mq, struct mqueue_msg **msg, int timo)
1786 {
1787 	int error = 0;
1788 
1789 	mtx_lock(&mq->mq_mutex);
1790 	while ((*msg = TAILQ_FIRST(&mq->mq_msgq)) == NULL && error == 0) {
1791 		if (timo < 0) {
1792 			mtx_unlock(&mq->mq_mutex);
1793 			return (EAGAIN);
1794 		}
1795 		mq->mq_receivers++;
1796 		error = msleep(&mq->mq_receivers, &mq->mq_mutex,
1797 			    PSOCK | PCATCH, "mqrecv", timo);
1798 		mq->mq_receivers--;
1799 		if (error == EAGAIN)
1800 			error = ETIMEDOUT;
1801 	}
1802 	if (*msg != NULL) {
1803 		error = 0;
1804 		TAILQ_REMOVE(&mq->mq_msgq, *msg, msg_link);
1805 		mq->mq_curmsgs--;
1806 		mq->mq_totalbytes -= (*msg)->msg_size;
1807 		if (mq->mq_senders)
1808 			wakeup_one(&mq->mq_senders);
1809 		if (mq->mq_flags & MQ_WSEL) {
1810 			mq->mq_flags &= ~MQ_WSEL;
1811 			selwakeuppri(&mq->mq_wsel, PSOCK);
1812 		}
1813 		KNOTE_LOCKED(&mq->mq_wsel.si_note, 0);
1814 	}
1815 	if (mq->mq_notifier != NULL && mq->mq_receivers == 0 &&
1816 	    !TAILQ_EMPTY(&mq->mq_msgq)) {
1817 		mqueue_send_notification(mq);
1818 	}
1819 	mtx_unlock(&mq->mq_mutex);
1820 	return (error);
1821 }
1822 
1823 static __inline struct mqueue_notifier *
1824 notifier_alloc(void)
1825 {
1826 	return (uma_zalloc(mqnoti_zone, M_WAITOK | M_ZERO));
1827 }
1828 
1829 static __inline void
1830 notifier_free(struct mqueue_notifier *p)
1831 {
1832 	uma_zfree(mqnoti_zone, p);
1833 }
1834 
1835 static struct mqueue_notifier *
1836 notifier_search(struct proc *p, int fd)
1837 {
1838 	struct mqueue_notifier *nt;
1839 
1840 	LIST_FOREACH(nt, &p->p_mqnotifier, nt_link) {
1841 		if (nt->nt_fd == fd)
1842 			break;
1843 	}
1844 	return (nt);
1845 }
1846 
1847 static void
1848 notifier_insert(struct proc *p, struct mqueue_notifier *nt)
1849 {
1850 	LIST_INSERT_HEAD(&p->p_mqnotifier, nt, nt_link);
1851 }
1852 
1853 static void
1854 notifier_delete(struct proc *p, struct mqueue_notifier *nt)
1855 {
1856 	LIST_REMOVE(nt, nt_link);
1857 	notifier_free(nt);
1858 }
1859 
1860 static void
1861 notifier_remove(struct proc *p, struct mqueue *mq, int fd)
1862 {
1863 	struct mqueue_notifier *nt;
1864 
1865 	mtx_assert(&mq->mq_mutex, MA_OWNED);
1866 	PROC_LOCK(p);
1867 	nt = notifier_search(p, fd);
1868 	if (nt != NULL) {
1869 		if (mq->mq_notifier == nt)
1870 			mq->mq_notifier = NULL;
1871 		sigqueue_take(&nt->nt_ksi);
1872 		notifier_delete(p, nt);
1873 	}
1874 	PROC_UNLOCK(p);
1875 }
1876 
1877 /*
1878  * Syscall to open a message queue
1879  */
1880 int
1881 mq_open(struct thread *td, struct mq_open_args *uap)
1882 {
1883 	char path[MQFS_NAMELEN + 1];
1884 	struct mq_attr attr, *pattr;
1885 	struct mqfs_node *pn;
1886 	struct filedesc *fdp;
1887 	struct file *fp;
1888 	struct mqueue *mq;
1889 	int fd, error, len, flags, cmode;
1890 
1891 	if ((uap->flags & O_ACCMODE) == O_ACCMODE)
1892 		return (EINVAL);
1893 
1894 	fdp = td->td_proc->p_fd;
1895 	flags = FFLAGS(uap->flags);
1896 	cmode = (((uap->mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT);
1897 	mq = NULL;
1898 	if ((flags & O_CREAT) && (uap->attr != NULL)) {
1899 		error = copyin(uap->attr, &attr, sizeof(attr));
1900 		if (error)
1901 			return (error);
1902 		if (attr.mq_maxmsg <= 0 || attr.mq_maxmsg > maxmsg)
1903 			return (EINVAL);
1904 		if (attr.mq_msgsize <= 0 || attr.mq_msgsize > maxmsgsize)
1905 			return (EINVAL);
1906 		pattr = &attr;
1907 	} else
1908 		pattr = NULL;
1909 
1910 	error = copyinstr(uap->path, path, MQFS_NAMELEN + 1, NULL);
1911         if (error)
1912 		return (error);
1913 
1914 	/*
1915 	 * The first character of name must be a slash  (/) character
1916 	 * and the remaining characters of name cannot include any slash
1917 	 * characters.
1918 	 */
1919 	len = strlen(path);
1920 	if (len < 2  || path[0] != '/' || index(path + 1, '/') != NULL)
1921 		return (EINVAL);
1922 
1923 	error = falloc(td, &fp, &fd);
1924 	if (error)
1925 		return (error);
1926 
1927 	sx_xlock(&mqfs_data.mi_lock);
1928 	pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1);
1929 	if (pn == NULL) {
1930 		if (!(flags & O_CREAT)) {
1931 			error = ENOENT;
1932 		} else {
1933 			mq = mqueue_alloc(pattr);
1934 			if (mq == NULL) {
1935 				error = ENFILE;
1936 			} else {
1937 				pn = mqfs_create_file(mqfs_data.mi_root,
1938 				         path + 1, len - 1);
1939 				if (pn == NULL) {
1940 					error = ENOSPC;
1941 					mqueue_free(mq);
1942 				}
1943 			}
1944 		}
1945 
1946 		if (error == 0) {
1947 			pn->mn_data = mq;
1948 			getnanotime(&pn->mn_birth);
1949 			pn->mn_ctime = pn->mn_atime = pn->mn_mtime
1950 			  = pn->mn_birth;
1951 			pn->mn_uid = td->td_ucred->cr_uid;
1952 			pn->mn_gid = td->td_ucred->cr_gid;
1953 			pn->mn_mode = cmode;
1954 		}
1955 	} else {
1956 		if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
1957 			error = EEXIST;
1958 		} else {
1959 			int acc_mode = 0;
1960 
1961 			if (flags & FREAD)
1962 				acc_mode |= VREAD;
1963 			if (flags & FWRITE)
1964 				acc_mode |= VWRITE;
1965 			error = vaccess(VREG, pn->mn_mode, pn->mn_uid,
1966 				    pn->mn_gid, acc_mode, td->td_ucred, NULL);
1967 		}
1968 	}
1969 
1970 	if (error) {
1971 		sx_xunlock(&mqfs_data.mi_lock);
1972 		fdclose(fdp, fp, fd, td);
1973 		fdrop(fp, td);
1974 		return (error);
1975 	}
1976 
1977 	mqnode_addref(pn);
1978 	sx_xunlock(&mqfs_data.mi_lock);
1979 
1980 	FILE_LOCK(fp);
1981 	fp->f_flag = (flags & (FREAD | FWRITE | O_NONBLOCK));
1982 	fp->f_type = DTYPE_MQUEUE;
1983 	fp->f_ops = &mqueueops;
1984 	fp->f_data = pn;
1985 	FILE_UNLOCK(fp);
1986 
1987 	FILEDESC_LOCK_FAST(fdp);
1988 	if (fdp->fd_ofiles[fd] == fp)
1989 		fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
1990 	FILEDESC_UNLOCK_FAST(fdp);
1991 	td->td_retval[0] = fd;
1992 	fdrop(fp, td);
1993 	return (0);
1994 }
1995 
1996 /*
1997  * Syscall to unlink a message queue
1998  */
1999 int
2000 mq_unlink(struct thread *td, struct mq_unlink_args *uap)
2001 {
2002 	char path[MQFS_NAMELEN+1];
2003 	struct mqfs_node *pn;
2004 	int error, len;
2005 
2006 	error = copyinstr(uap->path, path, MQFS_NAMELEN + 1, NULL);
2007         if (error)
2008 		return (error);
2009 
2010 	len = strlen(path);
2011 	if (len < 2  || path[0] != '/' || index(path + 1, '/') != NULL)
2012 		return (EINVAL);
2013 
2014 	sx_xlock(&mqfs_data.mi_lock);
2015 	pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1);
2016 	if (pn != NULL)
2017 		error = do_unlink(pn, td->td_ucred);
2018 	else
2019 		error = ENOENT;
2020 	sx_xunlock(&mqfs_data.mi_lock);
2021 	return (error);
2022 }
2023 
2024 typedef int (*_fgetf)(struct thread *, int, struct file **);
2025 
2026 /*
2027  * Get message queue by giving file slot
2028  */
2029 static int
2030 _getmq(struct thread *td, int fd, _fgetf func,
2031        struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq)
2032 {
2033 	struct mqfs_node *pn;
2034 	int error;
2035 
2036 	error = func(td, fd, fpp);
2037 	if (error)
2038 		return (error);
2039 	if (&mqueueops != (*fpp)->f_ops) {
2040 		fdrop(*fpp, td);
2041 		return (EBADF);
2042 	}
2043 	pn = (*fpp)->f_data;
2044 	if (ppn)
2045 		*ppn = pn;
2046 	if (pmq)
2047 		*pmq = pn->mn_data;
2048 	return (0);
2049 }
2050 
2051 static __inline int
2052 getmq(struct thread *td, int fd, struct file **fpp, struct mqfs_node **ppn,
2053 	struct mqueue **pmq)
2054 {
2055 	return _getmq(td, fd, fget, fpp, ppn, pmq);
2056 }
2057 
2058 static __inline int
2059 getmq_read(struct thread *td, int fd, struct file **fpp,
2060 	 struct mqfs_node **ppn, struct mqueue **pmq)
2061 {
2062 	return _getmq(td, fd, fget_read, fpp, ppn, pmq);
2063 }
2064 
2065 static __inline int
2066 getmq_write(struct thread *td, int fd, struct file **fpp,
2067 	struct mqfs_node **ppn, struct mqueue **pmq)
2068 {
2069 	return _getmq(td, fd, fget_write, fpp, ppn, pmq);
2070 }
2071 
2072 /*
2073  * Syscall
2074  */
2075 int
2076 mq_setattr(struct thread *td, struct mq_setattr_args *uap)
2077 {
2078 	struct mqueue *mq;
2079 	struct file *fp;
2080 	struct mq_attr attr, oattr;
2081 	int error;
2082 
2083 	if (uap->attr) {
2084 		error = copyin(uap->attr, &attr, sizeof(attr));
2085 		if (error)
2086 			return (error);
2087 		if (attr.mq_flags & ~O_NONBLOCK)
2088 			return (EINVAL);
2089 	}
2090 	error = getmq(td, uap->mqd, &fp, NULL, &mq);
2091 	if (error)
2092 		return (error);
2093 	oattr.mq_maxmsg  = mq->mq_maxmsg;
2094 	oattr.mq_msgsize = mq->mq_msgsize;
2095 	oattr.mq_curmsgs = mq->mq_curmsgs;
2096 	FILE_LOCK(fp);
2097 	oattr.mq_flags = (O_NONBLOCK & fp->f_flag);
2098 	if (uap->attr) {
2099 		fp->f_flag &= ~O_NONBLOCK;
2100 		fp->f_flag |= (attr.mq_flags & O_NONBLOCK);
2101 	}
2102 	FILE_UNLOCK(fp);
2103 	fdrop(fp, td);
2104 	if (uap->oattr)
2105 		error = copyout(&oattr, uap->oattr, sizeof(oattr));
2106 	return (error);
2107 }
2108 
2109 /*
2110  * Syscall
2111  */
2112 int
2113 mq_timedreceive(struct thread *td, struct mq_timedreceive_args *uap)
2114 {
2115 	struct mqueue *mq;
2116 	struct file *fp;
2117 	int error;
2118 	int waitok;
2119 
2120 	error = getmq_read(td, uap->mqd, &fp, NULL, &mq);
2121 	if (error)
2122 		return (error);
2123 	waitok = !(fp->f_flag & O_NONBLOCK);
2124 	error = mqueue_receive(mq, uap->msg_ptr, uap->msg_len,
2125 		uap->msg_prio, waitok, uap->abs_timeout);
2126 	fdrop(fp, td);
2127 	return (error);
2128 }
2129 
2130 /*
2131  * Syscall
2132  */
2133 int
2134 mq_timedsend(struct thread *td, struct mq_timedsend_args *uap)
2135 {
2136 	struct mqueue *mq;
2137 	struct file *fp;
2138 	int error, waitok;
2139 
2140 	error = getmq_write(td, uap->mqd, &fp, NULL, &mq);
2141 	if (error)
2142 		return (error);
2143 	waitok = !(fp->f_flag & O_NONBLOCK);
2144 	error = mqueue_send(mq, uap->msg_ptr, uap->msg_len,
2145 		uap->msg_prio, waitok, uap->abs_timeout);
2146 	fdrop(fp, td);
2147 	return (error);
2148 }
2149 
2150 /*
2151  * Syscall
2152  */
2153 int
2154 mq_notify(struct thread *td, struct mq_notify_args *uap)
2155 {
2156 	struct sigevent ev;
2157 	struct filedesc *fdp;
2158 	struct proc *p;
2159 	struct mqueue *mq;
2160 	struct file *fp;
2161 	struct mqueue_notifier *nt, *newnt = NULL;
2162 	int error;
2163 
2164 	p = td->td_proc;
2165 	fdp = td->td_proc->p_fd;
2166 	if (uap->sigev) {
2167 		error = copyin(uap->sigev, &ev, sizeof(ev));
2168 		if (error)
2169 			return (error);
2170 		if (ev.sigev_notify != SIGEV_SIGNAL &&
2171 		    ev.sigev_notify != SIGEV_THREAD_ID &&
2172 		    ev.sigev_notify != SIGEV_NONE)
2173 			return (EINVAL);
2174 		if ((ev.sigev_notify == SIGEV_SIGNAL ||
2175 		     ev.sigev_notify == SIGEV_THREAD_ID) &&
2176 			!_SIG_VALID(ev.sigev_signo))
2177 			return (EINVAL);
2178 	}
2179 	error = getmq(td, uap->mqd, &fp, NULL, &mq);
2180 	if (error)
2181 		return (error);
2182 again:
2183 	FILEDESC_LOCK_FAST(fdp);
2184 	if (fget_locked(fdp, uap->mqd) != fp) {
2185 		FILEDESC_UNLOCK_FAST(fdp);
2186 		error = EBADF;
2187 		goto out;
2188 	}
2189 	mtx_lock(&mq->mq_mutex);
2190 	FILEDESC_UNLOCK_FAST(fdp);
2191 	if (uap->sigev != NULL) {
2192 		if (mq->mq_notifier != NULL) {
2193 			error = EBUSY;
2194 		} else if (ev.sigev_notify != SIGEV_NONE) {
2195 			PROC_LOCK(p);
2196 			nt = notifier_search(p, uap->mqd);
2197 			if (nt == NULL) {
2198 				if (newnt == NULL) {
2199 					PROC_UNLOCK(p);
2200 					mtx_unlock(&mq->mq_mutex);
2201 					newnt = notifier_alloc();
2202 					goto again;
2203 				}
2204 			}
2205 
2206 			if (nt != NULL) {
2207 				sigqueue_take(&nt->nt_ksi);
2208 				if (newnt != NULL) {
2209 					notifier_free(newnt);
2210 					newnt = NULL;
2211 				}
2212 			} else {
2213 				nt = newnt;
2214 				newnt = NULL;
2215 				ksiginfo_init(&nt->nt_ksi);
2216 				nt->nt_ksi.ksi_flags |= KSI_INS | KSI_EXT;
2217 				nt->nt_ksi.ksi_code = SI_MESGQ;
2218 				nt->nt_proc = p;
2219 				nt->nt_fd = uap->mqd;
2220 				notifier_insert(p, nt);
2221 			}
2222 			nt->nt_sigev = ev;
2223 			mq->mq_notifier = nt;
2224 			PROC_UNLOCK(p);
2225 			/*
2226 			 * if there is no receivers and message queue
2227 			 * is not empty, we should send notification
2228 			 * as soon as possible.
2229 			 */
2230 			if (mq->mq_receivers == 0 &&
2231 			    !TAILQ_EMPTY(&mq->mq_msgq))
2232 				mqueue_send_notification(mq);
2233 		}
2234 	} else {
2235 		notifier_remove(p, mq, uap->mqd);
2236 	}
2237 	mtx_unlock(&mq->mq_mutex);
2238 
2239 out:
2240 	fdrop(fp, td);
2241 	if (newnt != NULL)
2242 		notifier_free(newnt);
2243 	return (error);
2244 }
2245 
2246 static void
2247 mqueue_fdclose(struct thread *td, int fd, struct file *fp)
2248 {
2249 	struct filedesc *fdp;
2250 	struct mqueue *mq;
2251 
2252 	fdp = td->td_proc->p_fd;
2253 	FILEDESC_LOCK_ASSERT(fdp, MA_OWNED);
2254 	if (fp->f_ops == &mqueueops) {
2255 		mq = FPTOMQ(fp);
2256 		mtx_lock(&mq->mq_mutex);
2257 		notifier_remove(td->td_proc, mq, fd);
2258 
2259 		/* have to wakeup thread in same process */
2260 		if (mq->mq_flags & MQ_RSEL) {
2261 			mq->mq_flags &= ~MQ_RSEL;
2262 			selwakeuppri(&mq->mq_rsel, PSOCK);
2263 		}
2264 		if (mq->mq_flags & MQ_WSEL) {
2265 			mq->mq_flags &= ~MQ_WSEL;
2266 			selwakeuppri(&mq->mq_wsel, PSOCK);
2267 		}
2268 		mtx_unlock(&mq->mq_mutex);
2269 	}
2270 }
2271 
2272 static void
2273 mq_proc_exit(void *arg __unused, struct proc *p)
2274 {
2275 	struct filedesc *fdp;
2276 	struct file *fp;
2277 	struct mqueue *mq;
2278 	int i;
2279 
2280 	fdp = p->p_fd;
2281 	FILEDESC_LOCK_FAST(fdp);
2282 	for (i = 0; i < fdp->fd_nfiles; ++i) {
2283 		fp = fget_locked(fdp, i);
2284 		if (fp != NULL && fp->f_ops == &mqueueops) {
2285 			mq = FPTOMQ(fp);
2286 			mtx_lock(&mq->mq_mutex);
2287 			notifier_remove(p, FPTOMQ(fp), i);
2288 			mtx_unlock(&mq->mq_mutex);
2289 		}
2290 	}
2291 	FILEDESC_UNLOCK_FAST(fdp);
2292 	KASSERT(LIST_EMPTY(&p->p_mqnotifier), ("mq notifiers left"));
2293 }
2294 
2295 static int
2296 mqf_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
2297 	int flags, struct thread *td)
2298 {
2299 	return (EOPNOTSUPP);
2300 }
2301 
2302 static int
2303 mqf_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
2304 	int flags, struct thread *td)
2305 {
2306 	return (EOPNOTSUPP);
2307 }
2308 
2309 static int
2310 mqf_ioctl(struct file *fp, u_long cmd, void *data,
2311 	struct ucred *active_cred, struct thread *td)
2312 {
2313 	return (ENOTTY);
2314 }
2315 
2316 static int
2317 mqf_poll(struct file *fp, int events, struct ucred *active_cred,
2318 	struct thread *td)
2319 {
2320 	struct mqueue *mq = FPTOMQ(fp);
2321 	int revents = 0;
2322 
2323 	mtx_lock(&mq->mq_mutex);
2324 	if (events & (POLLIN | POLLRDNORM)) {
2325 		if (mq->mq_curmsgs) {
2326 			revents |= events & (POLLIN | POLLRDNORM);
2327 		} else {
2328 			mq->mq_flags |= MQ_RSEL;
2329 			selrecord(td, &mq->mq_rsel);
2330  		}
2331 	}
2332 	if (events & POLLOUT) {
2333 		if (mq->mq_curmsgs < mq->mq_maxmsg)
2334 			revents |= POLLOUT;
2335 		else {
2336 			mq->mq_flags |= MQ_WSEL;
2337 			selrecord(td, &mq->mq_wsel);
2338 		}
2339 	}
2340 	mtx_unlock(&mq->mq_mutex);
2341 	return (revents);
2342 }
2343 
2344 static int
2345 mqf_close(struct file *fp, struct thread *td)
2346 {
2347 	struct mqfs_node *pn;
2348 
2349 	FILE_LOCK(fp);
2350 	fp->f_ops = &badfileops;
2351 	FILE_UNLOCK(fp);
2352 	pn = fp->f_data;
2353 	fp->f_data = NULL;
2354 	sx_xlock(&mqfs_data.mi_lock);
2355 	mqnode_release(pn);
2356 	sx_xunlock(&mqfs_data.mi_lock);
2357 	return (0);
2358 }
2359 
2360 static int
2361 mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
2362 	struct thread *td)
2363 {
2364 	struct mqfs_node *pn = fp->f_data;
2365 
2366 	bzero(st, sizeof *st);
2367 	st->st_atimespec = pn->mn_atime;
2368 	st->st_mtimespec = pn->mn_mtime;
2369 	st->st_ctimespec = pn->mn_ctime;
2370 	st->st_birthtimespec = pn->mn_birth;
2371 	st->st_uid = pn->mn_uid;
2372 	st->st_gid = pn->mn_gid;
2373 	st->st_mode = S_IFIFO | pn->mn_mode;
2374 	return (0);
2375 }
2376 
2377 static int
2378 mqf_kqfilter(struct file *fp, struct knote *kn)
2379 {
2380 	struct mqueue *mq = FPTOMQ(fp);
2381 	int error = 0;
2382 
2383 	if (kn->kn_filter == EVFILT_READ) {
2384 		kn->kn_fop = &mq_rfiltops;
2385 		knlist_add(&mq->mq_rsel.si_note, kn, 0);
2386 	} else if (kn->kn_filter == EVFILT_WRITE) {
2387 		kn->kn_fop = &mq_wfiltops;
2388 		knlist_add(&mq->mq_wsel.si_note, kn, 0);
2389 	} else
2390 		error = EINVAL;
2391 	return (error);
2392 }
2393 
2394 static void
2395 filt_mqdetach(struct knote *kn)
2396 {
2397 	struct mqueue *mq = FPTOMQ(kn->kn_fp);
2398 
2399 	if (kn->kn_filter == EVFILT_READ)
2400 		knlist_remove(&mq->mq_rsel.si_note, kn, 0);
2401 	else if (kn->kn_filter == EVFILT_WRITE)
2402 		knlist_remove(&mq->mq_wsel.si_note, kn, 0);
2403 	else
2404 		panic("filt_mqdetach");
2405 }
2406 
2407 static int
2408 filt_mqread(struct knote *kn, long hint)
2409 {
2410 	struct mqueue *mq = FPTOMQ(kn->kn_fp);
2411 
2412 	mtx_assert(&mq->mq_mutex, MA_OWNED);
2413 	return (mq->mq_curmsgs != 0);
2414 }
2415 
2416 static int
2417 filt_mqwrite(struct knote *kn, long hint)
2418 {
2419 	struct mqueue *mq = FPTOMQ(kn->kn_fp);
2420 
2421 	mtx_assert(&mq->mq_mutex, MA_OWNED);
2422 	return (mq->mq_curmsgs < mq->mq_maxmsg);
2423 }
2424 
2425 static struct fileops mqueueops = {
2426 	.fo_read		= mqf_read,
2427 	.fo_write		= mqf_write,
2428 	.fo_ioctl		= mqf_ioctl,
2429 	.fo_poll		= mqf_poll,
2430 	.fo_kqfilter		= mqf_kqfilter,
2431 	.fo_stat		= mqf_stat,
2432 	.fo_close		= mqf_close
2433 };
2434 
2435 static struct vop_vector mqfs_vnodeops = {
2436 	.vop_default 		= &default_vnodeops,
2437 	.vop_access		= mqfs_access,
2438 	.vop_cachedlookup	= mqfs_lookup,
2439 	.vop_lookup		= vfs_cache_lookup,
2440 	.vop_reclaim		= mqfs_reclaim,
2441 	.vop_create		= mqfs_create,
2442 	.vop_remove		= mqfs_remove,
2443 	.vop_inactive		= mqfs_inactive,
2444 	.vop_open		= mqfs_open,
2445 	.vop_close		= mqfs_close,
2446 	.vop_getattr		= mqfs_getattr,
2447 	.vop_setattr		= mqfs_setattr,
2448 	.vop_read		= mqfs_read,
2449 	.vop_write		= VOP_EOPNOTSUPP,
2450 	.vop_readdir		= mqfs_readdir,
2451 	.vop_mkdir		= VOP_EOPNOTSUPP,
2452 	.vop_rmdir		= VOP_EOPNOTSUPP
2453 };
2454 
2455 static struct vfsops mqfs_vfsops = {
2456 	.vfs_init 		= mqfs_init,
2457 	.vfs_uninit		= mqfs_uninit,
2458 	.vfs_mount		= mqfs_mount,
2459 	.vfs_unmount		= mqfs_unmount,
2460 	.vfs_root		= mqfs_root,
2461 	.vfs_statfs		= mqfs_statfs,
2462 };
2463 
2464 SYSCALL_MODULE_HELPER(mq_open);
2465 SYSCALL_MODULE_HELPER(mq_setattr);
2466 SYSCALL_MODULE_HELPER(mq_timedsend);
2467 SYSCALL_MODULE_HELPER(mq_timedreceive);
2468 SYSCALL_MODULE_HELPER(mq_notify);
2469 SYSCALL_MODULE_HELPER(mq_unlink);
2470 
2471 VFS_SET(mqfs_vfsops, mqueuefs, VFCF_SYNTHETIC);
2472 MODULE_VERSION(mqueuefs, 1);
2473