uipc_mqueue.c (152864) | uipc_mqueue.c (152948) |
---|---|
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 --- 29 unchanged lines hidden (view full) --- 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> | 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 --- 29 unchanged lines hidden (view full) --- 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: head/sys/kern/uipc_mqueue.c 152864 2005-11-27 22:59:47Z davidxu $"); | 46__FBSDID("$FreeBSD: head/sys/kern/uipc_mqueue.c 152948 2005-11-30 05:12:03Z davidxu $"); |
47 48#include <sys/param.h> 49#include <sys/kernel.h> 50#include <sys/systm.h> 51#include <sys/limits.h> 52#include <sys/buf.h> 53#include <sys/dirent.h> 54#include <sys/event.h> | 47 48#include <sys/param.h> 49#include <sys/kernel.h> 50#include <sys/systm.h> 51#include <sys/limits.h> 52#include <sys/buf.h> 53#include <sys/dirent.h> 54#include <sys/event.h> |
55#include <sys/eventhandler.h> |
|
55#include <sys/fcntl.h> 56#include <sys/filedesc.h> 57#include <sys/file.h> 58#include <sys/limits.h> 59#include <sys/lock.h> 60#include <sys/malloc.h> 61#include <sys/module.h> 62#include <sys/mount.h> --- 75 unchanged lines hidden (view full) --- 138 uid_t mn_uid; 139 gid_t mn_gid; 140 int mn_mode; 141}; 142 143#define VTON(vp) (((struct mqfs_vdata *)((vp)->v_data))->mv_node) 144#define VTOMQ(vp) ((struct mqueue *)(VTON(vp)->mn_data)) 145#define VFSTOMQFS(m) ((struct mqfs_info *)((m)->mnt_data)) | 56#include <sys/fcntl.h> 57#include <sys/filedesc.h> 58#include <sys/file.h> 59#include <sys/limits.h> 60#include <sys/lock.h> 61#include <sys/malloc.h> 62#include <sys/module.h> 63#include <sys/mount.h> --- 75 unchanged lines hidden (view full) --- 139 uid_t mn_uid; 140 gid_t mn_gid; 141 int mn_mode; 142}; 143 144#define VTON(vp) (((struct mqfs_vdata *)((vp)->v_data))->mv_node) 145#define VTOMQ(vp) ((struct mqueue *)(VTON(vp)->mn_data)) 146#define VFSTOMQFS(m) ((struct mqfs_info *)((m)->mnt_data)) |
146#define FPTOMQ(fp) (((struct mqueue_user *) \ 147 (fp)->f_data)->mu_node->mn_data) | 147#define FPTOMQ(fp) ((struct mqueue *)(((struct mqfs_node *) \ 148 (fp)->f_data)->mn_data)) 149 |
148TAILQ_HEAD(msgq, mqueue_msg); 149 150struct mqueue; | 150TAILQ_HEAD(msgq, mqueue_msg); 151 152struct mqueue; |
151struct mqueue_user 152{ 153 struct sigevent mu_sigev; 154 struct ksiginfo mu_ksi; 155 struct mqfs_node *mu_node; 156 struct proc *mu_proc; | 153 154struct mqueue_notifier { 155 LIST_ENTRY(mqueue_notifier) nt_link; 156 struct sigevent nt_sigev; 157 ksiginfo_t nt_ksi; 158 struct proc *nt_proc; 159 int nt_fd; |
157}; 158 159struct mqueue { 160 struct mtx mq_mutex; 161 int mq_flags; 162 long mq_maxmsg; 163 long mq_msgsize; 164 long mq_curmsgs; 165 long mq_totalbytes; 166 struct msgq mq_msgq; 167 int mq_receivers; 168 int mq_senders; 169 struct selinfo mq_rsel; 170 struct selinfo mq_wsel; | 160}; 161 162struct mqueue { 163 struct mtx mq_mutex; 164 int mq_flags; 165 long mq_maxmsg; 166 long mq_msgsize; 167 long mq_curmsgs; 168 long mq_totalbytes; 169 struct msgq mq_msgq; 170 int mq_receivers; 171 int mq_senders; 172 struct selinfo mq_rsel; 173 struct selinfo mq_wsel; |
171 struct mqueue_user *mq_notifier; | 174 struct mqueue_notifier *mq_notifier; |
172}; 173 174#define MQ_RSEL 0x01 175#define MQ_WSEL 0x02 176 177struct mqueue_msg { 178 TAILQ_ENTRY(mqueue_msg) msg_link; 179 unsigned int msg_prio; --- 17 unchanged lines hidden (view full) --- 197SYSCTL_INT(_kern_mqueue, OID_AUTO, maxmq, CTLFLAG_RW, 198 &maxmq, 0, "maximum message queues"); 199static int curmq = 0; 200SYSCTL_INT(_kern_mqueue, OID_AUTO, curmq, CTLFLAG_RW, 201 &curmq, 0, "current message queue number"); 202static int unloadable = 0; 203static MALLOC_DEFINE(M_MQUEUEDATA, "mqdata", "mqueue data"); 204 | 175}; 176 177#define MQ_RSEL 0x01 178#define MQ_WSEL 0x02 179 180struct mqueue_msg { 181 TAILQ_ENTRY(mqueue_msg) msg_link; 182 unsigned int msg_prio; --- 17 unchanged lines hidden (view full) --- 200SYSCTL_INT(_kern_mqueue, OID_AUTO, maxmq, CTLFLAG_RW, 201 &maxmq, 0, "maximum message queues"); 202static int curmq = 0; 203SYSCTL_INT(_kern_mqueue, OID_AUTO, curmq, CTLFLAG_RW, 204 &curmq, 0, "current message queue number"); 205static int unloadable = 0; 206static MALLOC_DEFINE(M_MQUEUEDATA, "mqdata", "mqueue data"); 207 |
208static eventhandler_tag exit_tag; 209 |
|
205/* Only one instance per-system */ 206static struct mqfs_info mqfs_data; 207static uma_zone_t mqnode_zone; 208static uma_zone_t mqueue_zone; 209static uma_zone_t mvdata_zone; | 210/* Only one instance per-system */ 211static struct mqfs_info mqfs_data; 212static uma_zone_t mqnode_zone; 213static uma_zone_t mqueue_zone; 214static uma_zone_t mvdata_zone; |
210static uma_zone_t mquser_zone; | 215static uma_zone_t mqnoti_zone; |
211static struct vop_vector mqfs_vnodeops; 212static struct fileops mqueueops; 213 214/* 215 * Directory structure construction and manipulation 216 */ 217#ifdef notyet 218static struct mqfs_node *mqfs_create_dir(struct mqfs_node *parent, --- 20 unchanged lines hidden (view full) --- 239static int mqueue_receive(struct mqueue *mq, char *msg_ptr, 240 size_t msg_len, unsigned *msg_prio, int waitok, 241 const struct timespec *abs_timeout); 242static int _mqueue_send(struct mqueue *mq, struct mqueue_msg *msg, 243 int timo); 244static int _mqueue_recv(struct mqueue *mq, struct mqueue_msg **msg, 245 int timo); 246static void mqueue_send_notification(struct mqueue *mq); | 216static struct vop_vector mqfs_vnodeops; 217static struct fileops mqueueops; 218 219/* 220 * Directory structure construction and manipulation 221 */ 222#ifdef notyet 223static struct mqfs_node *mqfs_create_dir(struct mqfs_node *parent, --- 20 unchanged lines hidden (view full) --- 244static int mqueue_receive(struct mqueue *mq, char *msg_ptr, 245 size_t msg_len, unsigned *msg_prio, int waitok, 246 const struct timespec *abs_timeout); 247static int _mqueue_send(struct mqueue *mq, struct mqueue_msg *msg, 248 int timo); 249static int _mqueue_recv(struct mqueue *mq, struct mqueue_msg **msg, 250 int timo); 251static void mqueue_send_notification(struct mqueue *mq); |
252static void mqueue_fdclose(struct thread *td, int fd, struct file *fp); 253static void mq_proc_exit(void *arg, struct proc *p); |
|
247 | 254 |
248/* kqueue filters */ | 255/* 256 * kqueue filters 257 */ |
249static void filt_mqdetach(struct knote *kn); 250static int filt_mqread(struct knote *kn, long hint); 251static int filt_mqwrite(struct knote *kn, long hint); 252 253struct filterops mq_rfiltops = 254 { 1, NULL, filt_mqdetach, filt_mqread }; 255struct filterops mq_wfiltops = 256 { 1, NULL, filt_mqdetach, filt_mqwrite }; --- 16 unchanged lines hidden (view full) --- 273static void 274mqfs_fileno_uninit(struct mqfs_info *mi) 275{ 276 struct unrhdr *up; 277 278 up = mi->mi_unrhdr; 279 mi->mi_unrhdr = NULL; 280 delete_unrhdr(up); | 258static void filt_mqdetach(struct knote *kn); 259static int filt_mqread(struct knote *kn, long hint); 260static int filt_mqwrite(struct knote *kn, long hint); 261 262struct filterops mq_rfiltops = 263 { 1, NULL, filt_mqdetach, filt_mqread }; 264struct filterops mq_wfiltops = 265 { 1, NULL, filt_mqdetach, filt_mqwrite }; --- 16 unchanged lines hidden (view full) --- 282static void 283mqfs_fileno_uninit(struct mqfs_info *mi) 284{ 285 struct unrhdr *up; 286 287 up = mi->mi_unrhdr; 288 mi->mi_unrhdr = NULL; 289 delete_unrhdr(up); |
281 282 uma_zdestroy(mqnode_zone); 283 uma_zdestroy(mqueue_zone); 284 uma_zdestroy(mvdata_zone); 285 uma_zdestroy(mquser_zone); | |
286} 287 288/* 289 * Allocate a file number 290 */ | 290} 291 292/* 293 * Allocate a file number 294 */ |
291void | 295static void |
292mqfs_fileno_alloc(struct mqfs_info *mi, struct mqfs_node *mn) 293{ 294 /* make sure our parent has a file number */ 295 if (mn->mn_parent && !mn->mn_parent->mn_fileno) 296 mqfs_fileno_alloc(mi, mn->mn_parent); 297 298 switch (mn->mn_type) { 299 case mqfstype_root: --- 24 unchanged lines hidden (view full) --- 324 mn->mn_type)); 325 break; 326 } 327} 328 329/* 330 * Release a file number 331 */ | 296mqfs_fileno_alloc(struct mqfs_info *mi, struct mqfs_node *mn) 297{ 298 /* make sure our parent has a file number */ 299 if (mn->mn_parent && !mn->mn_parent->mn_fileno) 300 mqfs_fileno_alloc(mi, mn->mn_parent); 301 302 switch (mn->mn_type) { 303 case mqfstype_root: --- 24 unchanged lines hidden (view full) --- 328 mn->mn_type)); 329 break; 330 } 331} 332 333/* 334 * Release a file number 335 */ |
332void | 336static void |
333mqfs_fileno_free(struct mqfs_info *mi, struct mqfs_node *mn) 334{ 335 switch (mn->mn_type) { 336 case mqfstype_root: 337 case mqfstype_dir: 338 case mqfstype_file: 339 case mqfstype_symlink: 340 free_unr(mi->mi_unrhdr, mn->mn_fileno); --- 95 unchanged lines hidden (view full) --- 436 return (0); 437} 438 439#ifdef notyet 440 441/* 442 * Create a directory 443 */ | 337mqfs_fileno_free(struct mqfs_info *mi, struct mqfs_node *mn) 338{ 339 switch (mn->mn_type) { 340 case mqfstype_root: 341 case mqfstype_dir: 342 case mqfstype_file: 343 case mqfstype_symlink: 344 free_unr(mi->mi_unrhdr, mn->mn_fileno); --- 95 unchanged lines hidden (view full) --- 440 return (0); 441} 442 443#ifdef notyet 444 445/* 446 * Create a directory 447 */ |
444struct mqfs_node * | 448static struct mqfs_node * |
445mqfs_create_dir(struct mqfs_node *parent, const char *name, int namelen) 446{ 447 struct mqfs_node *dir; 448 449 dir = mqnode_alloc(); 450 strncpy(dir->mn_name, name, namelen); 451 dir->mn_type = mqfstype_dir; 452 dir->mn_refcount = 1; --- 4 unchanged lines hidden (view full) --- 457 458 if (mqfs_fixup_dir(dir) != 0) { 459 mqfs_destroy(dir); 460 return (NULL); 461 } 462 463 return (dir); 464} | 449mqfs_create_dir(struct mqfs_node *parent, const char *name, int namelen) 450{ 451 struct mqfs_node *dir; 452 453 dir = mqnode_alloc(); 454 strncpy(dir->mn_name, name, namelen); 455 dir->mn_type = mqfstype_dir; 456 dir->mn_refcount = 1; --- 4 unchanged lines hidden (view full) --- 461 462 if (mqfs_fixup_dir(dir) != 0) { 463 mqfs_destroy(dir); 464 return (NULL); 465 } 466 467 return (dir); 468} |
469 470/* 471 * Create a symlink 472 */ 473static struct mqfs_node * 474mqfs_create_link(struct mqfs_node *parent, const char *name, int namelen) 475{ 476 struct mqfs_node *node; 477 478 node = mqfs_create_file(parent, name, namelen); 479 if (node == NULL) 480 return (NULL); 481 node->mn_type = mqfstype_symlink; 482 return (node); 483} 484 |
|
465#endif 466 467/* 468 * Create a file 469 */ | 485#endif 486 487/* 488 * Create a file 489 */ |
470struct mqfs_node * | 490static struct mqfs_node * |
471mqfs_create_file(struct mqfs_node *parent, const char *name, int namelen) 472{ 473 struct mqfs_node *node; 474 475 node = mqnode_alloc(); 476 strncpy(node->mn_name, name, namelen); 477 node->mn_type = mqfstype_file; 478 node->mn_refcount = 1; 479 480 if (mqfs_add_node(parent, node) != 0) { 481 mqnode_free(node); 482 return (NULL); 483 } 484 return (node); 485} 486 487/* | 491mqfs_create_file(struct mqfs_node *parent, const char *name, int namelen) 492{ 493 struct mqfs_node *node; 494 495 node = mqnode_alloc(); 496 strncpy(node->mn_name, name, namelen); 497 node->mn_type = mqfstype_file; 498 node->mn_refcount = 1; 499 500 if (mqfs_add_node(parent, node) != 0) { 501 mqnode_free(node); 502 return (NULL); 503 } 504 return (node); 505} 506 507/* |
488 * Create a symlink 489 */ 490struct mqfs_node * 491mqfs_create_link(struct mqfs_node *parent, const char *name, int namelen) 492{ 493 struct mqfs_node *node; 494 495 node = mqfs_create_file(parent, name, namelen); 496 if (node == NULL) 497 return (NULL); 498 node->mn_type = mqfstype_symlink; 499 return (node); 500} 501 502/* | |
503 * Destroy a node or a tree of nodes 504 */ | 508 * Destroy a node or a tree of nodes 509 */ |
505int | 510static int |
506mqfs_destroy(struct mqfs_node *node) 507{ 508 struct mqfs_node *parent; 509 510 KASSERT(node != NULL, 511 ("%s(): node is NULL", __func__)); 512 KASSERT(node->mn_info != NULL, 513 ("%s(): node has no mn_info", __func__)); --- 95 unchanged lines hidden (view full) --- 609 610 mqnode_zone = uma_zcreate("mqnode", sizeof(struct mqfs_node), 611 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); 612 mqueue_zone = uma_zcreate("mqueue", sizeof(struct mqueue), 613 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); 614 mvdata_zone = uma_zcreate("mvdata", 615 sizeof(struct mqfs_vdata), NULL, NULL, NULL, 616 NULL, UMA_ALIGN_PTR, 0); | 511mqfs_destroy(struct mqfs_node *node) 512{ 513 struct mqfs_node *parent; 514 515 KASSERT(node != NULL, 516 ("%s(): node is NULL", __func__)); 517 KASSERT(node->mn_info != NULL, 518 ("%s(): node has no mn_info", __func__)); --- 95 unchanged lines hidden (view full) --- 614 615 mqnode_zone = uma_zcreate("mqnode", sizeof(struct mqfs_node), 616 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); 617 mqueue_zone = uma_zcreate("mqueue", sizeof(struct mqueue), 618 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); 619 mvdata_zone = uma_zcreate("mvdata", 620 sizeof(struct mqfs_vdata), NULL, NULL, NULL, 621 NULL, UMA_ALIGN_PTR, 0); |
617 mquser_zone = uma_zcreate("mquser", sizeof(struct mqueue_user), | 622 mqnoti_zone = uma_zcreate("mqnotifier", sizeof(struct mqueue_notifier), |
618 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); 619 mi = &mqfs_data; 620 sx_init(&mi->mi_lock, "mqfs lock"); 621 /* set up the root diretory */ 622 root = mqnode_alloc(); 623 root->mn_type = mqfstype_root; 624 root->mn_refcount = 1; 625 root->mn_name[0] = '/'; 626 root->mn_info = mi; 627 LIST_INIT(&root->mn_children); 628 LIST_INIT(&root->mn_vnodes); 629 root->mn_mode = 01777; 630 mi->mi_root = root; 631 mqfs_fileno_init(mi); 632 mqfs_fileno_alloc(mi, root); 633 mqfs_fixup_dir(root); | 623 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); 624 mi = &mqfs_data; 625 sx_init(&mi->mi_lock, "mqfs lock"); 626 /* set up the root diretory */ 627 root = mqnode_alloc(); 628 root->mn_type = mqfstype_root; 629 root->mn_refcount = 1; 630 root->mn_name[0] = '/'; 631 root->mn_info = mi; 632 LIST_INIT(&root->mn_children); 633 LIST_INIT(&root->mn_vnodes); 634 root->mn_mode = 01777; 635 mi->mi_root = root; 636 mqfs_fileno_init(mi); 637 mqfs_fileno_alloc(mi, root); 638 mqfs_fixup_dir(root); |
639 exit_tag = EVENTHANDLER_REGISTER(process_exit, mq_proc_exit, NULL, 640 EVENTHANDLER_PRI_ANY); 641 mq_fdclose = mqueue_fdclose; |
|
634 return (0); 635} 636 637/* 638 * Destroy a mqfs instance 639 */ 640static int 641mqfs_uninit(struct vfsconf *vfc) 642{ 643 struct mqfs_info *mi; 644 645 if (!unloadable) 646 return (EOPNOTSUPP); | 642 return (0); 643} 644 645/* 646 * Destroy a mqfs instance 647 */ 648static int 649mqfs_uninit(struct vfsconf *vfc) 650{ 651 struct mqfs_info *mi; 652 653 if (!unloadable) 654 return (EOPNOTSUPP); |
655 EVENTHANDLER_DEREGISTER(process_exit, exit_tag); |
|
647 mi = &mqfs_data; 648 mqfs_destroy(mi->mi_root); 649 mi->mi_root = NULL; 650 mqfs_fileno_uninit(mi); 651 sx_destroy(&mi->mi_lock); | 656 mi = &mqfs_data; 657 mqfs_destroy(mi->mi_root); 658 mi->mi_root = NULL; 659 mqfs_fileno_uninit(mi); 660 sx_destroy(&mi->mi_lock); |
661 uma_zdestroy(mqnode_zone); 662 uma_zdestroy(mqueue_zone); 663 uma_zdestroy(mvdata_zone); 664 uma_zdestroy(mqnoti_zone); |
|
652 return (0); 653} 654 655/* 656 * task routine 657 */ 658static void 659do_recycle(void *context, int pending __unused) 660{ 661 struct vnode *vp = (struct vnode *)context; 662 663 vrecycle(vp, curthread); 664 vdrop(vp); 665} 666 667/* 668 * Allocate a vnode 669 */ | 665 return (0); 666} 667 668/* 669 * task routine 670 */ 671static void 672do_recycle(void *context, int pending __unused) 673{ 674 struct vnode *vp = (struct vnode *)context; 675 676 vrecycle(vp, curthread); 677 vdrop(vp); 678} 679 680/* 681 * Allocate a vnode 682 */ |
670int | 683static int |
671mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn) 672{ 673 struct mqfs_vdata *vd; 674 int error; 675 676 LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) { 677 if (vd->mv_vnode->v_mount == mp) 678 break; --- 843 unchanged lines hidden (view full) --- 1522 */ 1523static int 1524mqueue_savemsg(struct mqueue_msg *msg, char *msg_ptr, int *msg_prio) 1525{ 1526 int error; 1527 1528 error = copyout(((char *)msg) + sizeof(*msg), msg_ptr, 1529 msg->msg_size); | 684mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn) 685{ 686 struct mqfs_vdata *vd; 687 int error; 688 689 LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) { 690 if (vd->mv_vnode->v_mount == mp) 691 break; --- 843 unchanged lines hidden (view full) --- 1535 */ 1536static int 1537mqueue_savemsg(struct mqueue_msg *msg, char *msg_ptr, int *msg_prio) 1538{ 1539 int error; 1540 1541 error = copyout(((char *)msg) + sizeof(*msg), msg_ptr, 1542 msg->msg_size); |
1530 if (error == 0) | 1543 if (error == 0 && msg_prio != NULL) |
1531 error = copyout(&msg->msg_prio, msg_prio, sizeof(int)); 1532 return (error); 1533} 1534 1535/* 1536 * Free a message's memory 1537 */ 1538static __inline void --- 132 unchanged lines hidden (view full) --- 1671 1672/* 1673 * Send realtime a signal to process which registered itself 1674 * successfully by mq_notify. 1675 */ 1676static void 1677mqueue_send_notification(struct mqueue *mq) 1678{ | 1544 error = copyout(&msg->msg_prio, msg_prio, sizeof(int)); 1545 return (error); 1546} 1547 1548/* 1549 * Free a message's memory 1550 */ 1551static __inline void --- 132 unchanged lines hidden (view full) --- 1684 1685/* 1686 * Send realtime a signal to process which registered itself 1687 * successfully by mq_notify. 1688 */ 1689static void 1690mqueue_send_notification(struct mqueue *mq) 1691{ |
1679 struct mqueue_user *mu; | 1692 struct mqueue_notifier *nt; 1693 struct proc *p; |
1680 1681 mtx_assert(&mq->mq_mutex, MA_OWNED); | 1694 1695 mtx_assert(&mq->mq_mutex, MA_OWNED); |
1682 mu = mq->mq_notifier; 1683 PROC_LOCK(mu->mu_proc); 1684 if (!KSI_ONQ(&mu->mu_ksi)) 1685 psignal_event(mu->mu_proc, &mu->mu_sigev, &mu->mu_ksi); 1686 PROC_UNLOCK(mu->mu_proc); | 1696 nt = mq->mq_notifier; 1697 p = nt->nt_proc; 1698 PROC_LOCK(p); 1699 if (!KSI_ONQ(&nt->nt_ksi)) 1700 psignal_event(p, &nt->nt_sigev, &nt->nt_ksi); 1701 PROC_UNLOCK(p); |
1687 mq->mq_notifier = NULL; 1688} 1689 1690/* 1691 * Get a message. if waitok is false, thread will not be 1692 * blocked if there is no data in queue, otherwise, absolute 1693 * time will be checked. 1694 */ --- 105 unchanged lines hidden (view full) --- 1800 if (mq->mq_notifier != NULL && mq->mq_receivers == 0 && 1801 !TAILQ_EMPTY(&mq->mq_msgq)) { 1802 mqueue_send_notification(mq); 1803 } 1804 mtx_unlock(&mq->mq_mutex); 1805 return (error); 1806} 1807 | 1702 mq->mq_notifier = NULL; 1703} 1704 1705/* 1706 * Get a message. if waitok is false, thread will not be 1707 * blocked if there is no data in queue, otherwise, absolute 1708 * time will be checked. 1709 */ --- 105 unchanged lines hidden (view full) --- 1815 if (mq->mq_notifier != NULL && mq->mq_receivers == 0 && 1816 !TAILQ_EMPTY(&mq->mq_msgq)) { 1817 mqueue_send_notification(mq); 1818 } 1819 mtx_unlock(&mq->mq_mutex); 1820 return (error); 1821} 1822 |
1808static __inline struct mqueue_user * 1809mquser_alloc(void) | 1823static __inline struct mqueue_notifier * 1824notifier_alloc(void) |
1810{ | 1825{ |
1811 return (uma_zalloc(mquser_zone, M_WAITOK | M_ZERO)); | 1826 return (uma_zalloc(mqnoti_zone, M_WAITOK | M_ZERO)); |
1812} 1813 1814static __inline void | 1827} 1828 1829static __inline void |
1815mquser_free(struct mqueue_user *p) | 1830notifier_free(struct mqueue_notifier *p) |
1816{ | 1831{ |
1817 uma_zfree(mquser_zone, p); | 1832 uma_zfree(mqnoti_zone, p); |
1818} 1819 | 1833} 1834 |
1835static struct mqueue_notifier * 1836notifier_search(struct proc *p, int fd) 1837{ 1838 struct mqueue_notifier *nt; 1839 1840 LIST_FOREACH(nt, &p->p_mqnotifier, nt_link) { 1841 if (nt->nt_fd == fd) 1842 break; 1843 } 1844 return (nt); 1845} 1846 1847static void 1848notifier_insert(struct proc *p, struct mqueue_notifier *nt) 1849{ 1850 LIST_INSERT_HEAD(&p->p_mqnotifier, nt, nt_link); 1851} 1852 1853static void 1854notifier_delete(struct proc *p, struct mqueue_notifier *nt) 1855{ 1856 LIST_REMOVE(nt, nt_link); 1857 notifier_free(nt); 1858} 1859 1860static void 1861notifier_remove(struct proc *p, struct mqueue *mq, int fd) 1862{ 1863 struct mqueue_notifier *nt; 1864 1865 mtx_assert(&mq->mq_mutex, MA_OWNED); 1866 PROC_LOCK(p); 1867 nt = notifier_search(p, fd); 1868 if (nt != NULL) { 1869 if (mq->mq_notifier == nt) 1870 mq->mq_notifier = NULL; 1871 sigqueue_take(&nt->nt_ksi); 1872 notifier_delete(p, nt); 1873 } 1874 PROC_UNLOCK(p); 1875} 1876 |
|
1820/* 1821 * Syscall to open a message queue 1822 */ 1823int 1824mq_open(struct thread *td, struct mq_open_args *uap) 1825{ | 1877/* 1878 * Syscall to open a message queue 1879 */ 1880int 1881mq_open(struct thread *td, struct mq_open_args *uap) 1882{ |
1826 char path[MQFS_NAMELEN+1]; | 1883 char path[MQFS_NAMELEN + 1]; |
1827 struct mq_attr attr, *pattr; 1828 struct mqfs_node *pn; 1829 struct filedesc *fdp; 1830 struct file *fp; | 1884 struct mq_attr attr, *pattr; 1885 struct mqfs_node *pn; 1886 struct filedesc *fdp; 1887 struct file *fp; |
1831 struct mqueue_user *mu; | |
1832 struct mqueue *mq; 1833 int fd, error, len, flags, cmode; 1834 1835 if ((uap->flags & O_ACCMODE) == O_ACCMODE) 1836 return (EINVAL); 1837 1838 fdp = td->td_proc->p_fd; 1839 flags = FFLAGS(uap->flags); --- 8 unchanged lines hidden (view full) --- 1848 if (attr.mq_msgsize <= 0 || attr.mq_msgsize > maxmsgsize) 1849 return (EINVAL); 1850 pattr = &attr; 1851 } else 1852 pattr = NULL; 1853 1854 error = copyinstr(uap->path, path, MQFS_NAMELEN + 1, NULL); 1855 if (error) | 1888 struct mqueue *mq; 1889 int fd, error, len, flags, cmode; 1890 1891 if ((uap->flags & O_ACCMODE) == O_ACCMODE) 1892 return (EINVAL); 1893 1894 fdp = td->td_proc->p_fd; 1895 flags = FFLAGS(uap->flags); --- 8 unchanged lines hidden (view full) --- 1904 if (attr.mq_msgsize <= 0 || attr.mq_msgsize > maxmsgsize) 1905 return (EINVAL); 1906 pattr = &attr; 1907 } else 1908 pattr = NULL; 1909 1910 error = copyinstr(uap->path, path, MQFS_NAMELEN + 1, NULL); 1911 if (error) |
1856 return (error); | 1912 return (error); |
1857 1858 /* 1859 * The first character of name must be a slash (/) character 1860 * and the remaining characters of name cannot include any slash 1861 * characters. 1862 */ 1863 len = strlen(path); 1864 if (len < 2 || path[0] != '/' || index(path + 1, '/') != NULL) --- 5 unchanged lines hidden (view full) --- 1870 1871 sx_xlock(&mqfs_data.mi_lock); 1872 pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1); 1873 if (pn == NULL) { 1874 if (!(flags & O_CREAT)) { 1875 error = ENOENT; 1876 } else { 1877 mq = mqueue_alloc(pattr); | 1913 1914 /* 1915 * The first character of name must be a slash (/) character 1916 * and the remaining characters of name cannot include any slash 1917 * characters. 1918 */ 1919 len = strlen(path); 1920 if (len < 2 || path[0] != '/' || index(path + 1, '/') != NULL) --- 5 unchanged lines hidden (view full) --- 1926 1927 sx_xlock(&mqfs_data.mi_lock); 1928 pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1); 1929 if (pn == NULL) { 1930 if (!(flags & O_CREAT)) { 1931 error = ENOENT; 1932 } else { 1933 mq = mqueue_alloc(pattr); |
1878 if (mq != NULL) | 1934 if (mq == NULL) { 1935 error = ENFILE; 1936 } else { |
1879 pn = mqfs_create_file(mqfs_data.mi_root, 1880 path + 1, len - 1); | 1937 pn = mqfs_create_file(mqfs_data.mi_root, 1938 path + 1, len - 1); |
1881 if (pn == NULL) { 1882 if (mq != NULL) | 1939 if (pn == NULL) { 1940 error = ENOSPC; |
1883 mqueue_free(mq); | 1941 mqueue_free(mq); |
1884 error = ENOSPC; | 1942 } |
1885 } 1886 } 1887 1888 if (error == 0) { 1889 pn->mn_data = mq; 1890 getnanotime(&pn->mn_birth); 1891 pn->mn_ctime = pn->mn_atime = pn->mn_mtime 1892 = pn->mn_birth; --- 21 unchanged lines hidden (view full) --- 1914 fdclose(fdp, fp, fd, td); 1915 fdrop(fp, td); 1916 return (error); 1917 } 1918 1919 mqnode_addref(pn); 1920 sx_xunlock(&mqfs_data.mi_lock); 1921 | 1943 } 1944 } 1945 1946 if (error == 0) { 1947 pn->mn_data = mq; 1948 getnanotime(&pn->mn_birth); 1949 pn->mn_ctime = pn->mn_atime = pn->mn_mtime 1950 = pn->mn_birth; --- 21 unchanged lines hidden (view full) --- 1972 fdclose(fdp, fp, fd, td); 1973 fdrop(fp, td); 1974 return (error); 1975 } 1976 1977 mqnode_addref(pn); 1978 sx_xunlock(&mqfs_data.mi_lock); 1979 |
1922 mu = mquser_alloc(); 1923 mu->mu_node = pn; 1924 ksiginfo_init(&mu->mu_ksi); 1925 mu->mu_ksi.ksi_flags |= KSI_INS | KSI_EXT; 1926 mu->mu_ksi.ksi_code = SI_MESGQ; 1927 mu->mu_proc = td->td_proc; | |
1928 FILE_LOCK(fp); 1929 fp->f_flag = (flags & (FREAD | FWRITE | O_NONBLOCK)); 1930 fp->f_type = DTYPE_MQUEUE; 1931 fp->f_ops = &mqueueops; | 1980 FILE_LOCK(fp); 1981 fp->f_flag = (flags & (FREAD | FWRITE | O_NONBLOCK)); 1982 fp->f_type = DTYPE_MQUEUE; 1983 fp->f_ops = &mqueueops; |
1932 fp->f_data = mu; | 1984 fp->f_data = pn; |
1933 FILE_UNLOCK(fp); 1934 1935 FILEDESC_LOCK_FAST(fdp); 1936 if (fdp->fd_ofiles[fd] == fp) 1937 fdp->fd_ofileflags[fd] |= UF_EXCLOSE; 1938 FILEDESC_UNLOCK_FAST(fdp); 1939 td->td_retval[0] = fd; 1940 fdrop(fp, td); --- 32 unchanged lines hidden (view full) --- 1973 1974/* 1975 * Get message queue by giving file slot 1976 */ 1977static int 1978_getmq(struct thread *td, int fd, _fgetf func, 1979 struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) 1980{ | 1985 FILE_UNLOCK(fp); 1986 1987 FILEDESC_LOCK_FAST(fdp); 1988 if (fdp->fd_ofiles[fd] == fp) 1989 fdp->fd_ofileflags[fd] |= UF_EXCLOSE; 1990 FILEDESC_UNLOCK_FAST(fdp); 1991 td->td_retval[0] = fd; 1992 fdrop(fp, td); --- 32 unchanged lines hidden (view full) --- 2025 2026/* 2027 * Get message queue by giving file slot 2028 */ 2029static int 2030_getmq(struct thread *td, int fd, _fgetf func, 2031 struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) 2032{ |
1981 struct mqueue_user *mu; | |
1982 struct mqfs_node *pn; 1983 int error; 1984 1985 error = func(td, fd, fpp); 1986 if (error) 1987 return (error); 1988 if (&mqueueops != (*fpp)->f_ops) { 1989 fdrop(*fpp, td); 1990 return (EBADF); 1991 } | 2033 struct mqfs_node *pn; 2034 int error; 2035 2036 error = func(td, fd, fpp); 2037 if (error) 2038 return (error); 2039 if (&mqueueops != (*fpp)->f_ops) { 2040 fdrop(*fpp, td); 2041 return (EBADF); 2042 } |
1992 mu = (*fpp)->f_data; 1993 pn = mu->mu_node; | 2043 pn = (*fpp)->f_data; |
1994 if (ppn) 1995 *ppn = pn; 1996 if (pmq) 1997 *pmq = pn->mn_data; 1998 return (0); 1999} 2000 2001static __inline int --- 97 unchanged lines hidden (view full) --- 2099 2100/* 2101 * Syscall 2102 */ 2103int 2104mq_notify(struct thread *td, struct mq_notify_args *uap) 2105{ 2106 struct sigevent ev; | 2044 if (ppn) 2045 *ppn = pn; 2046 if (pmq) 2047 *pmq = pn->mn_data; 2048 return (0); 2049} 2050 2051static __inline int --- 97 unchanged lines hidden (view full) --- 2149 2150/* 2151 * Syscall 2152 */ 2153int 2154mq_notify(struct thread *td, struct mq_notify_args *uap) 2155{ 2156 struct sigevent ev; |
2107 struct mqueue_user *mu; | 2157 struct filedesc *fdp; 2158 struct proc *p; |
2108 struct mqueue *mq; 2109 struct file *fp; | 2159 struct mqueue *mq; 2160 struct file *fp; |
2161 struct mqueue_notifier *nt, *newnt = NULL; |
|
2110 int error; 2111 | 2162 int error; 2163 |
2164 p = td->td_proc; 2165 fdp = td->td_proc->p_fd; |
|
2112 if (uap->sigev) { 2113 error = copyin(uap->sigev, &ev, sizeof(ev)); 2114 if (error) 2115 return (error); 2116 if (ev.sigev_notify != SIGEV_SIGNAL && 2117 ev.sigev_notify != SIGEV_THREAD_ID) 2118 return (EINVAL); 2119 if ((ev.sigev_notify == SIGEV_SIGNAL || 2120 ev.sigev_notify == SIGEV_THREAD_ID) && 2121 !_SIG_VALID(ev.sigev_signo)) 2122 return (EINVAL); 2123 } 2124 error = getmq(td, uap->mqd, &fp, NULL, &mq); 2125 if (error) 2126 return (error); | 2166 if (uap->sigev) { 2167 error = copyin(uap->sigev, &ev, sizeof(ev)); 2168 if (error) 2169 return (error); 2170 if (ev.sigev_notify != SIGEV_SIGNAL && 2171 ev.sigev_notify != SIGEV_THREAD_ID) 2172 return (EINVAL); 2173 if ((ev.sigev_notify == SIGEV_SIGNAL || 2174 ev.sigev_notify == SIGEV_THREAD_ID) && 2175 !_SIG_VALID(ev.sigev_signo)) 2176 return (EINVAL); 2177 } 2178 error = getmq(td, uap->mqd, &fp, NULL, &mq); 2179 if (error) 2180 return (error); |
2127 mu = fp->f_data; | 2181again: 2182 FILEDESC_LOCK_FAST(fdp); 2183 if (fget_locked(fdp, uap->mqd) != fp) { 2184 FILEDESC_UNLOCK_FAST(fdp); 2185 error = EBADF; 2186 goto out; 2187 } |
2128 mtx_lock(&mq->mq_mutex); | 2188 mtx_lock(&mq->mq_mutex); |
2189 FILEDESC_UNLOCK_FAST(fdp); |
|
2129 if (uap->sigev != NULL) { 2130 if (mq->mq_notifier != NULL) { 2131 error = EBUSY; 2132 } else { | 2190 if (uap->sigev != NULL) { 2191 if (mq->mq_notifier != NULL) { 2192 error = EBUSY; 2193 } else { |
2133 PROC_LOCK(td->td_proc); 2134 sigqueue_take(&mu->mu_ksi); 2135 PROC_UNLOCK(td->td_proc); 2136 mq->mq_notifier = mu; 2137 mu->mu_sigev = ev; | 2194 PROC_LOCK(p); 2195 nt = notifier_search(p, uap->mqd); 2196 if (nt == NULL) { 2197 if (newnt == NULL) { 2198 PROC_UNLOCK(p); 2199 mtx_unlock(&mq->mq_mutex); 2200 newnt = notifier_alloc(); 2201 goto again; 2202 } 2203 } 2204 2205 if (nt != NULL) { 2206 sigqueue_take(&nt->nt_ksi); 2207 if (newnt != NULL) { 2208 notifier_free(newnt); 2209 newnt = NULL; 2210 } 2211 } else { 2212 nt = newnt; 2213 newnt = NULL; 2214 ksiginfo_init(&nt->nt_ksi); 2215 nt->nt_ksi.ksi_flags |= KSI_INS | KSI_EXT; 2216 nt->nt_ksi.ksi_code = SI_MESGQ; 2217 nt->nt_proc = p; 2218 nt->nt_fd = uap->mqd; 2219 notifier_insert(p, nt); 2220 } 2221 nt->nt_sigev = ev; 2222 mq->mq_notifier = nt; 2223 PROC_UNLOCK(p); |
2138 /* | 2224 /* |
2139 * if there is no receivers and message queue is not 2140 * empty, we should send notification as soon as 2141 * possible. | 2225 * if there is no receivers and message queue 2226 * is not empty, we should send notification 2227 * as soon as possible. |
2142 */ 2143 if (mq->mq_receivers == 0 && 2144 !TAILQ_EMPTY(&mq->mq_msgq)) 2145 mqueue_send_notification(mq); 2146 } 2147 } else { | 2228 */ 2229 if (mq->mq_receivers == 0 && 2230 !TAILQ_EMPTY(&mq->mq_msgq)) 2231 mqueue_send_notification(mq); 2232 } 2233 } else { |
2148 if (mq->mq_notifier == mu) 2149 mq->mq_notifier = NULL; 2150 else 2151 error = EPERM; | 2234 notifier_remove(p, mq, uap->mqd); |
2152 } 2153 mtx_unlock(&mq->mq_mutex); | 2235 } 2236 mtx_unlock(&mq->mq_mutex); |
2237 2238out: |
|
2154 fdrop(fp, td); | 2239 fdrop(fp, td); |
2240 if (newnt != NULL) 2241 notifier_free(newnt); |
|
2155 return (error); 2156} 2157 | 2242 return (error); 2243} 2244 |
2245static void 2246mqueue_fdclose(struct thread *td, int fd, struct file *fp) 2247{ 2248 struct filedesc *fdp; 2249 struct mqueue *mq; 2250 2251 fdp = td->td_proc->p_fd; 2252 FILEDESC_LOCK_ASSERT(fdp, MA_OWNED); 2253 if (fp->f_ops == &mqueueops) { 2254 mq = FPTOMQ(fp); 2255 mtx_lock(&mq->mq_mutex); 2256 notifier_remove(td->td_proc, mq, fd); 2257 2258 /* have to wakeup thread in same process */ 2259 if (mq->mq_flags & MQ_RSEL) { 2260 mq->mq_flags &= ~MQ_RSEL; 2261 selwakeuppri(&mq->mq_rsel, PSOCK); 2262 } 2263 if (mq->mq_flags & MQ_WSEL) { 2264 mq->mq_flags &= ~MQ_WSEL; 2265 selwakeuppri(&mq->mq_wsel, PSOCK); 2266 } 2267 mtx_unlock(&mq->mq_mutex); 2268 } 2269} 2270 2271static void 2272mq_proc_exit(void *arg __unused, struct proc *p) 2273{ 2274 struct filedesc *fdp; 2275 struct file *fp; 2276 struct mqueue *mq; 2277 int i; 2278 2279 fdp = p->p_fd; 2280 FILEDESC_LOCK_FAST(fdp); 2281 for (i = 0; i < fdp->fd_nfiles; ++i) { 2282 fp = fget_locked(fdp, i); 2283 if (fp != NULL && fp->f_ops == &mqueueops) { 2284 mq = FPTOMQ(fp); 2285 mtx_lock(&mq->mq_mutex); 2286 notifier_remove(p, FPTOMQ(fp), i); 2287 mtx_unlock(&mq->mq_mutex); 2288 } 2289 } 2290 FILEDESC_UNLOCK_FAST(fdp); 2291 KASSERT(LIST_EMPTY(&p->p_mqnotifier), ("mq notifiers left")); 2292} 2293 |
|
2158static int 2159mqf_read(struct file *fp, struct uio *uio, struct ucred *active_cred, 2160 int flags, struct thread *td) 2161{ 2162 return (EOPNOTSUPP); 2163} 2164 2165static int --- 36 unchanged lines hidden (view full) --- 2202 } 2203 mtx_unlock(&mq->mq_mutex); 2204 return (revents); 2205} 2206 2207static int 2208mqf_close(struct file *fp, struct thread *td) 2209{ | 2294static int 2295mqf_read(struct file *fp, struct uio *uio, struct ucred *active_cred, 2296 int flags, struct thread *td) 2297{ 2298 return (EOPNOTSUPP); 2299} 2300 2301static int --- 36 unchanged lines hidden (view full) --- 2338 } 2339 mtx_unlock(&mq->mq_mutex); 2340 return (revents); 2341} 2342 2343static int 2344mqf_close(struct file *fp, struct thread *td) 2345{ |
2210 struct mqueue_user *mu; | |
2211 struct mqfs_node *pn; | 2346 struct mqfs_node *pn; |
2212 struct mqueue *mq; | |
2213 2214 FILE_LOCK(fp); 2215 fp->f_ops = &badfileops; 2216 FILE_UNLOCK(fp); | 2347 2348 FILE_LOCK(fp); 2349 fp->f_ops = &badfileops; 2350 FILE_UNLOCK(fp); |
2217 mu = fp->f_data; | 2351 pn = fp->f_data; |
2218 fp->f_data = NULL; | 2352 fp->f_data = NULL; |
2219 pn = mu->mu_node; 2220 mq = pn->mn_data; 2221 mtx_lock(&mq->mq_mutex); 2222 if (mq->mq_notifier == mu) { 2223 PROC_LOCK(td->td_proc); 2224 sigqueue_take(&mu->mu_ksi); 2225 PROC_UNLOCK(td->td_proc); 2226 mq->mq_notifier = NULL; 2227 } 2228 /* have to wakeup thread in same process */ 2229 if (mq->mq_flags & MQ_RSEL) { 2230 mq->mq_flags &= ~MQ_RSEL; 2231 selwakeuppri(&mq->mq_rsel, PSOCK); 2232 } 2233 if (mq->mq_flags & MQ_WSEL) { 2234 mq->mq_flags &= ~MQ_WSEL; 2235 selwakeuppri(&mq->mq_wsel, PSOCK); 2236 } 2237 mtx_unlock(&mq->mq_mutex); | |
2238 sx_xlock(&mqfs_data.mi_lock); 2239 mqnode_release(pn); 2240 sx_xunlock(&mqfs_data.mi_lock); | 2353 sx_xlock(&mqfs_data.mi_lock); 2354 mqnode_release(pn); 2355 sx_xunlock(&mqfs_data.mi_lock); |
2241 mquser_free(mu); | |
2242 return (0); 2243} 2244 2245static int 2246mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred, 2247 struct thread *td) 2248{ | 2356 return (0); 2357} 2358 2359static int 2360mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred, 2361 struct thread *td) 2362{ |
2249 struct mqueue_user *mu = fp->f_data; 2250 struct mqfs_node *pn = mu->mu_node; | 2363 struct mqfs_node *pn = fp->f_data; |
2251 2252 bzero(st, sizeof *st); 2253 st->st_atimespec = pn->mn_atime; 2254 st->st_mtimespec = pn->mn_mtime; 2255 st->st_ctimespec = pn->mn_ctime; 2256 st->st_birthtimespec = pn->mn_birth; 2257 st->st_uid = pn->mn_uid; 2258 st->st_gid = pn->mn_gid; --- 100 unchanged lines hidden --- | 2364 2365 bzero(st, sizeof *st); 2366 st->st_atimespec = pn->mn_atime; 2367 st->st_mtimespec = pn->mn_mtime; 2368 st->st_ctimespec = pn->mn_ctime; 2369 st->st_birthtimespec = pn->mn_birth; 2370 st->st_uid = pn->mn_uid; 2371 st->st_gid = pn->mn_gid; --- 100 unchanged lines hidden --- |