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