diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -332,7 +332,6 @@ mpr.4 \ mps.4 \ mpt.4 \ - mqueuefs.4 \ mrsas.4 \ msdosfs.4 \ msk.4 \ diff --git a/share/man/man4/mqueuefs.4 b/share/man/man4/mqueuefs.4 deleted file mode 100644 --- a/share/man/man4/mqueuefs.4 +++ /dev/null @@ -1,122 +0,0 @@ -.\" Copyright (c) 2005 David Xu -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice(s), this list of conditions and the following disclaimer as -.\" the first lines of this file unmodified other than the possible -.\" addition of one or more copyright notices. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice(s), this list of conditions and the following disclaimer in -.\" the documentation and/or other materials provided with the -.\" distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY -.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE -.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -.\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd November 30, 2005 -.Dt MQUEUEFS 4 -.Os -.Sh NAME -.Nm mqueuefs -.Nd POSIX message queue file system -.Sh SYNOPSIS -To link into kernel: -.Pp -.Cd "options P1003_1B_MQUEUE" -.Pp -To load as a kernel loadable module: -.Pp -.Dl "kldload mqueuefs" -.Sh DESCRIPTION -The -.Nm -module will permit the -.Fx -kernel to support -.Tn POSIX -message queue. -The module contains system calls to manipulate -.Tn POSIX -message queues. -It also contains a file system to implement a view for all message queues of -the system. -This helps users to keep track of their message queues and make -it more easily usable without having to invent additional tools. -.Pp -The most common usage is as follows: -.Pp -.Dl "mount -t mqueuefs null /mnt/mqueue" -.Pp -where -.Pa /mnt/mqueue -is a mount point. -.Pp -It is possible to define an entry in -.Pa /etc/fstab -that looks similar to: -.Bd -literal -null /mnt/mqueue mqueuefs rw 0 0 -.Ed -.Pp -This will mount -.Nm -at the -.Pa /mnt/mqueue -mount point during system boot. -Using -.Pa /mnt/mqueue -as a permanent mount point is not advised as its intention -has always been to be a temporary mount point. -See -.Xr hier 7 -for more information on -.Fx -directory layout. -.Pp -Some common tools can be used on the file system, e.g.: -.Xr cat 1 , -.Xr chmod 1 , -.Xr chown 8 , -.Xr ls 1 , -.Xr rm 1 , -etc. -To use only the message queue system calls, it is not necessary for -user to mount the file system, just load the module or compile it -into the kernel. -Manually creating a file, for example, -.Dq Li "touch /mnt/mqueue/myqueue" , -will create a message queue named -.Pa myqueue -in the kernel, default -message queue attributes will be applied to the queue. -It is not -advised to use this method to create a queue; -it is better to use the -.Xr mq_open 2 -system call to create a queue as it -allows the user to specify different attributes. -.Pp -To see the queue's attributes, just read the file: -.Pp -.Dl "cat /mnt/mqueue/myqueue" -.Sh SEE ALSO -.Xr mq_open 2 , -.Xr nmount 2 , -.Xr unmount 2 , -.Xr mount 8 , -.Xr umount 8 -.Sh AUTHORS -This manual page was written by -.An David Xu Aq Mt davidxu@FreeBSD.org . diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -33,23 +33,6 @@ * */ -/* - * POSIX message queue implementation. - * - * 1) A mqueue filesystem can be mounted, each message queue appears - * in mounted directory, user can change queue's permission and - * ownership, or remove a queue. Manually creating a file in the - * directory causes a message queue to be created in the kernel with - * default message queue attributes applied and same name used, this - * method is not advocated since mq_open syscall allows user to specify - * different attributes. Also the file system can be mounted multiple - * times at different mount points but shows same contents. - * - * 2) Standard POSIX message queue API. The syscalls do not use vfs layer, - * but directly operate on internal data structure, this allows user to - * use the IPC facility without having to mount mqueue file system. - */ - #include "opt_capsicum.h" #include @@ -57,9 +40,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -68,26 +49,25 @@ #include #include #include -#include #include #include -#include +#include #include #include #include -#include #include -#include +#include #include +#include #include #include #include -#include #include -#include #include #include #include +#include +#include #include #include @@ -122,13 +102,6 @@ struct unrhdr *mi_unrhdr; }; -struct mqfs_vdata { - LIST_ENTRY(mqfs_vdata) mv_link; - struct mqfs_node *mv_node; - struct vnode *mv_vnode; - struct task mv_task; -}; - /* * mqfs_node: describes a node (file or directory) within a mqfs */ @@ -197,7 +170,7 @@ }; static SYSCTL_NODE(_kern, OID_AUTO, mqueue, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, - "POSIX real time message queue"); + "POSIX real time message queue"); static int default_maxmsg = 10; SYSCTL_INT(_kern_mqueue, OID_AUTO, default_maxmsg, CTLFLAG_RD, @@ -218,7 +191,6 @@ static int curmq = 0; SYSCTL_INT(_kern_mqueue, OID_AUTO, curmq, CTLFLAG_RW, &curmq, 0, "current message queue number"); -static int unloadable = 0; static MALLOC_DEFINE(M_MQUEUEDATA, "mqdata", "mqueue data"); static eventhandler_tag exit_tag; @@ -227,28 +199,15 @@ static struct mqfs_info mqfs_data; static uma_zone_t mqnode_zone; static uma_zone_t mqueue_zone; -static uma_zone_t mvdata_zone; static uma_zone_t mqnoti_zone; -static struct vop_vector mqfs_vnodeops; static struct fileops mqueueops; static unsigned mqfs_osd_jail_slot; -/* - * Directory structure construction and manipulation - */ -#ifdef notyet -static struct mqfs_node *mqfs_create_dir(struct mqfs_node *parent, - const char *name, int namelen, struct ucred *cred, int mode); -static struct mqfs_node *mqfs_create_link(struct mqfs_node *parent, - const char *name, int namelen, struct ucred *cred, int mode); -#endif - static struct mqfs_node *mqfs_create_file(struct mqfs_node *parent, const char *name, int namelen, struct ucred *cred, int mode); static int mqfs_destroy(struct mqfs_node *mn); static void mqfs_fileno_alloc(struct mqfs_info *mi, struct mqfs_node *mn); static void mqfs_fileno_free(struct mqfs_info *mi, struct mqfs_node *mn); -static int mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn); static int mqfs_prison_remove(void *obj, void *data); /* @@ -442,6 +401,27 @@ return (0); } +/* + * Search a directory entry + */ +static struct mqfs_node * +mqfs_search(struct mqfs_node *pd, const char *name, int len, struct ucred *cred) +{ + struct mqfs_node *pn; + const void *pr_root; + + sx_assert(&pd->mn_info->mi_lock, SX_LOCKED); + pr_root = cred->cr_prison->pr_root; + LIST_FOREACH(pn, &pd->mn_children, mn_sibling) { + /* Only match names within the same prison root directory */ + if ((pn->mn_pr_root == NULL || pn->mn_pr_root == pr_root) && + strncmp(pn->mn_name, name, len) == 0 && + pn->mn_name[len] == '\0') + return (pn); + } + return (NULL); +} + static struct mqfs_node * mqfs_create_node(const char *name, int namelen, struct ucred *cred, int mode, int nodetype) @@ -479,79 +459,6 @@ return (node); } -/* - * Add . and .. to a directory - */ -static int -mqfs_fixup_dir(struct mqfs_node *parent) -{ - struct mqfs_node *dir; - - dir = mqnode_alloc(); - dir->mn_name[0] = '.'; - dir->mn_type = mqfstype_this; - dir->mn_refcount = 1; - if (mqfs_add_node(parent, dir) != 0) { - mqnode_free(dir); - return (-1); - } - - dir = mqnode_alloc(); - dir->mn_name[0] = dir->mn_name[1] = '.'; - dir->mn_type = mqfstype_parent; - dir->mn_refcount = 1; - - if (mqfs_add_node(parent, dir) != 0) { - mqnode_free(dir); - return (-1); - } - - return (0); -} - -#ifdef notyet - -/* - * Create a directory - */ -static struct mqfs_node * -mqfs_create_dir(struct mqfs_node *parent, const char *name, int namelen, - struct ucred *cred, int mode) -{ - struct mqfs_node *node; - - node = mqfs_create_node(name, namelen, cred, mode, mqfstype_dir); - if (mqfs_add_node(parent, node) != 0) { - mqnode_free(node); - return (NULL); - } - - if (mqfs_fixup_dir(node) != 0) { - mqfs_destroy(node); - return (NULL); - } - return (node); -} - -/* - * Create a symlink - */ -static struct mqfs_node * -mqfs_create_link(struct mqfs_node *parent, const char *name, int namelen, - struct ucred *cred, int mode) -{ - struct mqfs_node *node; - - node = mqfs_create_node(name, namelen, cred, mode, mqfstype_symlink); - if (mqfs_add_node(parent, node) != 0) { - mqnode_free(node); - return (NULL); - } - return (node); -} - -#endif - /* * Destroy a node or a tree of nodes */ @@ -585,77 +492,11 @@ return (0); } -/* - * Mount a mqfs instance - */ -static int -mqfs_mount(struct mount *mp) -{ - struct statfs *sbp; - - if (mp->mnt_flag & MNT_UPDATE) - return (EOPNOTSUPP); - - mp->mnt_data = &mqfs_data; - MNT_ILOCK(mp); - mp->mnt_flag |= MNT_LOCAL; - MNT_IUNLOCK(mp); - vfs_getnewfsid(mp); - - sbp = &mp->mnt_stat; - vfs_mountedfrom(mp, "mqueue"); - sbp->f_bsize = PAGE_SIZE; - sbp->f_iosize = PAGE_SIZE; - sbp->f_blocks = 1; - sbp->f_bfree = 1; - sbp->f_bavail = 0; - sbp->f_files = 0; - sbp->f_ffree = 0; - return (0); -} - -/* - * Unmount a mqfs instance - */ -static int -mqfs_unmount(struct mount *mp, int mntflags) -{ - int error; - - error = vflush(mp, 0, (mntflags & MNT_FORCE) ? FORCECLOSE : 0, - curthread); - return (error); -} - -/* - * Return a root vnode - */ -static int -mqfs_root(struct mount *mp, int flags, struct vnode **vpp) -{ - struct mqfs_info *mqfs; - int ret; - - mqfs = VFSTOMQFS(mp); - ret = mqfs_allocv(mp, vpp, mqfs->mi_root); - return (ret); -} - -/* - * Return filesystem stats - */ -static int -mqfs_statfs(struct mount *mp, struct statfs *sbp) -{ - /* XXX update statistics */ - return (0); -} - /* * Initialize a mqfs instance */ -static int -mqfs_init(struct vfsconf *vfc) +static void +mqfs_init(void) { struct mqfs_node *root; struct mqfs_info *mi; @@ -664,44 +505,36 @@ }; mqnode_zone = uma_zcreate("mqnode", sizeof(struct mqfs_node), - NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); mqueue_zone = uma_zcreate("mqueue", sizeof(struct mqueue), - NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); - mvdata_zone = uma_zcreate("mvdata", - sizeof(struct mqfs_vdata), NULL, NULL, NULL, - NULL, UMA_ALIGN_PTR, 0); + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); mqnoti_zone = uma_zcreate("mqnotifier", sizeof(struct mqueue_notifier), - NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); mi = &mqfs_data; sx_init(&mi->mi_lock, "mqfs lock"); /* set up the root diretory */ root = mqfs_create_node("/", 1, curthread->td_ucred, 01777, - mqfstype_root); + mqfstype_root); root->mn_info = mi; LIST_INIT(&root->mn_children); - LIST_INIT(&root->mn_vnodes); mi->mi_root = root; mqfs_fileno_init(mi); mqfs_fileno_alloc(mi, root); - mqfs_fixup_dir(root); exit_tag = EVENTHANDLER_REGISTER(process_exit, mq_proc_exit, NULL, EVENTHANDLER_PRI_ANY); mq_fdclose = mqueue_fdclose; p31b_setcfg(CTL_P1003_1B_MESSAGE_PASSING, _POSIX_MESSAGE_PASSING); mqfs_osd_jail_slot = osd_jail_register(NULL, methods); - return (0); } /* * Destroy a mqfs instance */ static int -mqfs_uninit(struct vfsconf *vfc) +mqfs_uninit(void) { struct mqfs_info *mi; - if (!unloadable) - return (EOPNOTSUPP); osd_jail_deregister(mqfs_osd_jail_slot); EVENTHANDLER_DEREGISTER(process_exit, exit_tag); mi = &mqfs_data; @@ -711,313 +544,10 @@ sx_destroy(&mi->mi_lock); uma_zdestroy(mqnode_zone); uma_zdestroy(mqueue_zone); - uma_zdestroy(mvdata_zone); uma_zdestroy(mqnoti_zone); return (0); } -/* - * task routine - */ -static void -do_recycle(void *context, int pending __unused) -{ - struct vnode *vp = (struct vnode *)context; - - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - vrecycle(vp); - VOP_UNLOCK(vp); - vdrop(vp); -} - -/* - * Allocate a vnode - */ -static int -mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn) -{ - struct mqfs_vdata *vd; - struct mqfs_info *mqfs; - struct vnode *newvpp; - int error; - - mqfs = pn->mn_info; - *vpp = NULL; - sx_xlock(&mqfs->mi_lock); - LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) { - if (vd->mv_vnode->v_mount == mp) { - vhold(vd->mv_vnode); - break; - } - } - - if (vd != NULL) { -found: - *vpp = vd->mv_vnode; - sx_xunlock(&mqfs->mi_lock); - error = vget(*vpp, LK_RETRY | LK_EXCLUSIVE); - vdrop(*vpp); - return (error); - } - sx_xunlock(&mqfs->mi_lock); - - error = getnewvnode("mqueue", mp, &mqfs_vnodeops, &newvpp); - if (error) - return (error); - vn_lock(newvpp, LK_EXCLUSIVE | LK_RETRY); - error = insmntque(newvpp, mp); - if (error != 0) - return (error); - - sx_xlock(&mqfs->mi_lock); - /* - * Check if it has already been allocated - * while we were blocked. - */ - LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) { - if (vd->mv_vnode->v_mount == mp) { - vhold(vd->mv_vnode); - sx_xunlock(&mqfs->mi_lock); - - vgone(newvpp); - vput(newvpp); - goto found; - } - } - - *vpp = newvpp; - - vd = uma_zalloc(mvdata_zone, M_WAITOK); - (*vpp)->v_data = vd; - vd->mv_vnode = *vpp; - vd->mv_node = pn; - TASK_INIT(&vd->mv_task, 0, do_recycle, *vpp); - LIST_INSERT_HEAD(&pn->mn_vnodes, vd, mv_link); - mqnode_addref(pn); - switch (pn->mn_type) { - case mqfstype_root: - (*vpp)->v_vflag = VV_ROOT; - /* fall through */ - case mqfstype_dir: - case mqfstype_this: - case mqfstype_parent: - (*vpp)->v_type = VDIR; - break; - case mqfstype_file: - (*vpp)->v_type = VREG; - break; - case mqfstype_symlink: - (*vpp)->v_type = VLNK; - break; - case mqfstype_none: - KASSERT(0, ("mqfs_allocf called for null node\n")); - default: - panic("%s has unexpected type: %d", pn->mn_name, pn->mn_type); - } - sx_xunlock(&mqfs->mi_lock); - vn_set_state(*vpp, VSTATE_CONSTRUCTED); - return (0); -} - -/* - * Search a directory entry - */ -static struct mqfs_node * -mqfs_search(struct mqfs_node *pd, const char *name, int len, struct ucred *cred) -{ - struct mqfs_node *pn; - const void *pr_root; - - sx_assert(&pd->mn_info->mi_lock, SX_LOCKED); - pr_root = cred->cr_prison->pr_root; - LIST_FOREACH(pn, &pd->mn_children, mn_sibling) { - /* Only match names within the same prison root directory */ - if ((pn->mn_pr_root == NULL || pn->mn_pr_root == pr_root) && - strncmp(pn->mn_name, name, len) == 0 && - pn->mn_name[len] == '\0') - return (pn); - } - return (NULL); -} - -/* - * Look up a file or directory. - */ -static int -mqfs_lookupx(struct vop_cachedlookup_args *ap) -{ - struct componentname *cnp; - struct vnode *dvp, **vpp; - struct mqfs_node *pd; - struct mqfs_node *pn; - struct mqfs_info *mqfs; - int nameiop, flags, error, namelen; - char *pname; - struct thread *td; - - td = curthread; - cnp = ap->a_cnp; - vpp = ap->a_vpp; - dvp = ap->a_dvp; - pname = cnp->cn_nameptr; - namelen = cnp->cn_namelen; - flags = cnp->cn_flags; - nameiop = cnp->cn_nameiop; - pd = VTON(dvp); - pn = NULL; - mqfs = pd->mn_info; - *vpp = NULLVP; - - if (dvp->v_type != VDIR) - return (ENOTDIR); - - error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td); - if (error) - return (error); - - /* shortcut: check if the name is too long */ - if (cnp->cn_namelen >= MQFS_NAMELEN) - return (ENOENT); - - /* self */ - if (namelen == 1 && pname[0] == '.') { - if ((flags & ISLASTCN) && nameiop != LOOKUP) - return (EINVAL); - pn = pd; - *vpp = dvp; - VREF(dvp); - return (0); - } - - /* parent */ - if (cnp->cn_flags & ISDOTDOT) { - if (dvp->v_vflag & VV_ROOT) - return (EIO); - if ((flags & ISLASTCN) && nameiop != LOOKUP) - return (EINVAL); - VOP_UNLOCK(dvp); - KASSERT(pd->mn_parent, ("non-root directory has no parent")); - pn = pd->mn_parent; - error = mqfs_allocv(dvp->v_mount, vpp, pn); - vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); - return (error); - } - - /* named node */ - sx_xlock(&mqfs->mi_lock); - pn = mqfs_search(pd, pname, namelen, cnp->cn_cred); - if (pn != NULL) - mqnode_addref(pn); - sx_xunlock(&mqfs->mi_lock); - - /* found */ - if (pn != NULL) { - /* DELETE */ - if (nameiop == DELETE && (flags & ISLASTCN)) { - error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td); - if (error) { - mqnode_release(pn); - return (error); - } - if (*vpp == dvp) { - VREF(dvp); - *vpp = dvp; - mqnode_release(pn); - return (0); - } - } - - /* allocate vnode */ - error = mqfs_allocv(dvp->v_mount, vpp, pn); - mqnode_release(pn); - if (error == 0 && cnp->cn_flags & MAKEENTRY) - cache_enter(dvp, *vpp, cnp); - return (error); - } - - /* not found */ - - /* will create a new entry in the directory ? */ - if ((nameiop == CREATE || nameiop == RENAME) && (flags & LOCKPARENT) - && (flags & ISLASTCN)) { - error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td); - if (error) - return (error); - return (EJUSTRETURN); - } - return (ENOENT); -} - -#if 0 -struct vop_lookup_args { - struct vop_generic_args a_gen; - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; -}; -#endif - -/* - * vnode lookup operation - */ -static int -mqfs_lookup(struct vop_cachedlookup_args *ap) -{ - int rc; - - rc = mqfs_lookupx(ap); - return (rc); -} - -#if 0 -struct vop_create_args { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; -}; -#endif - -/* - * vnode creation operation - */ -static int -mqfs_create(struct vop_create_args *ap) -{ - struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount); - struct componentname *cnp = ap->a_cnp; - struct mqfs_node *pd; - struct mqfs_node *pn; - struct mqueue *mq; - int error; - - pd = VTON(ap->a_dvp); - if (pd->mn_type != mqfstype_root && pd->mn_type != mqfstype_dir) - return (ENOTDIR); - mq = mqueue_alloc(NULL); - if (mq == NULL) - return (EAGAIN); - sx_xlock(&mqfs->mi_lock); - pn = mqfs_create_file(pd, cnp->cn_nameptr, cnp->cn_namelen, - cnp->cn_cred, ap->a_vap->va_mode); - if (pn == NULL) { - sx_xunlock(&mqfs->mi_lock); - error = ENOSPC; - } else { - mqnode_addref(pn); - sx_xunlock(&mqfs->mi_lock); - error = mqfs_allocv(ap->a_dvp->v_mount, ap->a_vpp, pn); - mqnode_release(pn); - if (error) - mqfs_destroy(pn); - else - pn->mn_data = mq; - } - if (error) - mqueue_free(mq); - return (error); -} - /* * Remove an entry */ @@ -1025,7 +555,6 @@ do_unlink(struct mqfs_node *pn, struct ucred *ucred) { struct mqfs_node *parent; - struct mqfs_vdata *vd; int error = 0; sx_assert(&pn->mn_info->mi_lock, SX_LOCKED); @@ -1038,11 +567,6 @@ pn->mn_parent = NULL; pn->mn_deleted = 1; LIST_REMOVE(pn, mn_sibling); - LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) { - cache_purge(vd->mv_vnode); - vhold(vd->mv_vnode); - taskqueue_enqueue(taskqueue_thread, &vd->mv_task); - } mqnode_release(pn); mqnode_release(parent); } else @@ -1050,508 +574,6 @@ return (error); } -#if 0 -struct vop_remove_args { - struct vnode *a_dvp; - struct vnode *a_vp; - struct componentname *a_cnp; -}; -#endif - -/* - * vnode removal operation - */ -static int -mqfs_remove(struct vop_remove_args *ap) -{ - struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount); - struct mqfs_node *pn; - int error; - - if (ap->a_vp->v_type == VDIR) - return (EPERM); - pn = VTON(ap->a_vp); - sx_xlock(&mqfs->mi_lock); - error = do_unlink(pn, ap->a_cnp->cn_cred); - sx_xunlock(&mqfs->mi_lock); - return (error); -} - -#if 0 -struct vop_inactive_args { - struct vnode *a_vp; - struct thread *a_td; -}; -#endif - -static int -mqfs_inactive(struct vop_inactive_args *ap) -{ - struct mqfs_node *pn = VTON(ap->a_vp); - - if (pn->mn_deleted) - vrecycle(ap->a_vp); - return (0); -} - -#if 0 -struct vop_reclaim_args { - struct vop_generic_args a_gen; - struct vnode *a_vp; -}; -#endif - -static int -mqfs_reclaim(struct vop_reclaim_args *ap) -{ - struct mqfs_info *mqfs = VFSTOMQFS(ap->a_vp->v_mount); - struct vnode *vp = ap->a_vp; - struct mqfs_node *pn; - struct mqfs_vdata *vd; - - vd = vp->v_data; - pn = vd->mv_node; - sx_xlock(&mqfs->mi_lock); - vp->v_data = NULL; - LIST_REMOVE(vd, mv_link); - mqnode_release(pn); - sx_xunlock(&mqfs->mi_lock); - uma_zfree(mvdata_zone, vd); - return (0); -} - -#if 0 -struct vop_open_args { - struct vop_generic_args a_gen; - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct thread *a_td; - struct file *a_fp; -}; -#endif - -static int -mqfs_open(struct vop_open_args *ap) -{ - return (0); -} - -#if 0 -struct vop_close_args { - struct vop_generic_args a_gen; - struct vnode *a_vp; - int a_fflag; - struct ucred *a_cred; - struct thread *a_td; -}; -#endif - -static int -mqfs_close(struct vop_close_args *ap) -{ - return (0); -} - -#if 0 -struct vop_access_args { - struct vop_generic_args a_gen; - struct vnode *a_vp; - accmode_t a_accmode; - struct ucred *a_cred; - struct thread *a_td; -}; -#endif - -/* - * Verify permissions - */ -static int -mqfs_access(struct vop_access_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct vattr vattr; - int error; - - error = VOP_GETATTR(vp, &vattr, ap->a_cred); - if (error) - return (error); - error = vaccess(vp->v_type, vattr.va_mode, vattr.va_uid, vattr.va_gid, - ap->a_accmode, ap->a_cred); - return (error); -} - -#if 0 -struct vop_getattr_args { - struct vop_generic_args a_gen; - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; -}; -#endif - -/* - * Get file attributes - */ -static int -mqfs_getattr(struct vop_getattr_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct mqfs_node *pn = VTON(vp); - struct vattr *vap = ap->a_vap; - int error = 0; - - vap->va_type = vp->v_type; - vap->va_mode = pn->mn_mode; - vap->va_nlink = 1; - vap->va_uid = pn->mn_uid; - vap->va_gid = pn->mn_gid; - vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; - vap->va_fileid = pn->mn_fileno; - vap->va_size = 0; - vap->va_blocksize = PAGE_SIZE; - vap->va_bytes = vap->va_size = 0; - vap->va_atime = pn->mn_atime; - vap->va_mtime = pn->mn_mtime; - vap->va_ctime = pn->mn_ctime; - vap->va_birthtime = pn->mn_birth; - vap->va_gen = 0; - vap->va_flags = 0; - vap->va_rdev = NODEV; - vap->va_bytes = 0; - vap->va_filerev = 0; - return (error); -} - -#if 0 -struct vop_setattr_args { - struct vop_generic_args a_gen; - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; -}; -#endif -/* - * Set attributes - */ -static int -mqfs_setattr(struct vop_setattr_args *ap) -{ - struct mqfs_node *pn; - struct vattr *vap; - struct vnode *vp; - struct thread *td; - int c, error; - uid_t uid; - gid_t gid; - - td = curthread; - vap = ap->a_vap; - vp = ap->a_vp; - if (vap->va_type != VNON || - vap->va_nlink != VNOVAL || - vap->va_fsid != VNOVAL || - vap->va_fileid != VNOVAL || - vap->va_blocksize != VNOVAL || - (vap->va_flags != VNOVAL && vap->va_flags != 0) || - vap->va_rdev != VNOVAL || - (int)vap->va_bytes != VNOVAL || - vap->va_gen != VNOVAL) { - return (EINVAL); - } - - pn = VTON(vp); - - error = c = 0; - if (vap->va_uid == (uid_t)VNOVAL) - uid = pn->mn_uid; - else - uid = vap->va_uid; - if (vap->va_gid == (gid_t)VNOVAL) - gid = pn->mn_gid; - else - gid = vap->va_gid; - - if (uid != pn->mn_uid || gid != pn->mn_gid) { - /* - * To modify the ownership of a file, must possess VADMIN - * for that file. - */ - if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, td))) - return (error); - - /* - * XXXRW: Why is there a privilege check here: shouldn't the - * check in VOP_ACCESS() be enough? Also, are the group bits - * below definitely right? - */ - if ((ap->a_cred->cr_uid != pn->mn_uid || uid != pn->mn_uid || - (gid != pn->mn_gid && !groupmember(gid, ap->a_cred))) && - (error = priv_check(td, PRIV_MQ_ADMIN)) != 0) - return (error); - pn->mn_uid = uid; - pn->mn_gid = gid; - c = 1; - } - - if (vap->va_mode != (mode_t)VNOVAL) { - if (ap->a_cred->cr_uid != pn->mn_uid && - (error = priv_check(td, PRIV_MQ_ADMIN))) - return (error); - pn->mn_mode = vap->va_mode; - c = 1; - } - - if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { - /* See the comment in ufs_vnops::ufs_setattr(). */ - if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, td)) && - ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || - (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, td)))) - return (error); - if (vap->va_atime.tv_sec != VNOVAL) { - pn->mn_atime = vap->va_atime; - } - if (vap->va_mtime.tv_sec != VNOVAL) { - pn->mn_mtime = vap->va_mtime; - } - c = 1; - } - if (c) { - vfs_timestamp(&pn->mn_ctime); - } - return (0); -} - -#if 0 -struct vop_read_args { - struct vop_generic_args a_gen; - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; -}; -#endif - -/* - * Read from a file - */ -static int -mqfs_read(struct vop_read_args *ap) -{ - char buf[80]; - struct vnode *vp = ap->a_vp; - struct uio *uio = ap->a_uio; - struct mqueue *mq; - int len, error; - - if (vp->v_type != VREG) - return (EINVAL); - - mq = VTOMQ(vp); - snprintf(buf, sizeof(buf), - "QSIZE:%-10ld MAXMSG:%-10ld CURMSG:%-10ld MSGSIZE:%-10ld\n", - mq->mq_totalbytes, - mq->mq_maxmsg, - mq->mq_curmsgs, - mq->mq_msgsize); - buf[sizeof(buf)-1] = '\0'; - len = strlen(buf); - error = uiomove_frombuf(buf, len, uio); - return (error); -} - -#if 0 -struct vop_readdir_args { - struct vop_generic_args a_gen; - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - int *a_eofflag; - int *a_ncookies; - uint64_t **a_cookies; -}; -#endif - -/* - * Return directory entries. - */ -static int -mqfs_readdir(struct vop_readdir_args *ap) -{ - struct vnode *vp; - struct mqfs_info *mi; - struct mqfs_node *pd; - struct mqfs_node *pn; - struct dirent entry; - struct uio *uio; - const void *pr_root; - int *tmp_ncookies = NULL; - off_t offset; - int error, i; - - vp = ap->a_vp; - mi = VFSTOMQFS(vp->v_mount); - pd = VTON(vp); - uio = ap->a_uio; - - if (vp->v_type != VDIR) - return (ENOTDIR); - - if (uio->uio_offset < 0) - return (EINVAL); - - if (ap->a_ncookies != NULL) { - tmp_ncookies = ap->a_ncookies; - *ap->a_ncookies = 0; - ap->a_ncookies = NULL; - } - - error = 0; - offset = 0; - - pr_root = ap->a_cred->cr_prison->pr_root; - sx_xlock(&mi->mi_lock); - - LIST_FOREACH(pn, &pd->mn_children, mn_sibling) { - entry.d_reclen = sizeof(entry); - - /* - * Only show names within the same prison root directory - * (or not associated with a prison, e.g. "." and ".."). - */ - if (pn->mn_pr_root != NULL && pn->mn_pr_root != pr_root) - continue; - if (!pn->mn_fileno) - mqfs_fileno_alloc(mi, pn); - entry.d_fileno = pn->mn_fileno; - entry.d_off = offset + entry.d_reclen; - for (i = 0; i < MQFS_NAMELEN - 1 && pn->mn_name[i] != '\0'; ++i) - entry.d_name[i] = pn->mn_name[i]; - entry.d_namlen = i; - switch (pn->mn_type) { - case mqfstype_root: - case mqfstype_dir: - case mqfstype_this: - case mqfstype_parent: - entry.d_type = DT_DIR; - break; - case mqfstype_file: - entry.d_type = DT_REG; - break; - case mqfstype_symlink: - entry.d_type = DT_LNK; - break; - default: - panic("%s has unexpected node type: %d", pn->mn_name, - pn->mn_type); - } - dirent_terminate(&entry); - if (entry.d_reclen > uio->uio_resid) - break; - if (offset >= uio->uio_offset) { - error = vfs_read_dirent(ap, &entry, offset); - if (error) - break; - } - offset += entry.d_reclen; - } - sx_xunlock(&mi->mi_lock); - - uio->uio_offset = offset; - - if (tmp_ncookies != NULL) - ap->a_ncookies = tmp_ncookies; - - return (error); -} - -#ifdef notyet - -#if 0 -struct vop_mkdir_args { - struct vnode *a_dvp; - struvt vnode **a_vpp; - struvt componentname *a_cnp; - struct vattr *a_vap; -}; -#endif - -/* - * Create a directory. - */ -static int -mqfs_mkdir(struct vop_mkdir_args *ap) -{ - struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount); - struct componentname *cnp = ap->a_cnp; - struct mqfs_node *pd = VTON(ap->a_dvp); - struct mqfs_node *pn; - int error; - - if (pd->mn_type != mqfstype_root && pd->mn_type != mqfstype_dir) - return (ENOTDIR); - sx_xlock(&mqfs->mi_lock); - pn = mqfs_create_dir(pd, cnp->cn_nameptr, cnp->cn_namelen, - ap->a_vap->cn_cred, ap->a_vap->va_mode); - if (pn != NULL) - mqnode_addref(pn); - sx_xunlock(&mqfs->mi_lock); - if (pn == NULL) { - error = ENOSPC; - } else { - error = mqfs_allocv(ap->a_dvp->v_mount, ap->a_vpp, pn); - mqnode_release(pn); - } - return (error); -} - -#if 0 -struct vop_rmdir_args { - struct vnode *a_dvp; - struct vnode *a_vp; - struct componentname *a_cnp; -}; -#endif - -/* - * Remove a directory. - */ -static int -mqfs_rmdir(struct vop_rmdir_args *ap) -{ - struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount); - struct mqfs_node *pn = VTON(ap->a_vp); - struct mqfs_node *pt; - - if (pn->mn_type != mqfstype_dir) - return (ENOTDIR); - - sx_xlock(&mqfs->mi_lock); - if (pn->mn_deleted) { - sx_xunlock(&mqfs->mi_lock); - return (ENOENT); - } - - pt = LIST_FIRST(&pn->mn_children); - pt = LIST_NEXT(pt, mn_sibling); - pt = LIST_NEXT(pt, mn_sibling); - if (pt != NULL) { - sx_xunlock(&mqfs->mi_lock); - return (ENOTEMPTY); - } - pt = pn->mn_parent; - pn->mn_parent = NULL; - pn->mn_deleted = 1; - LIST_REMOVE(pn, mn_sibling); - mqnode_release(pn); - mqnode_release(pt); - sx_xunlock(&mqfs->mi_lock); - cache_purge(ap->a_vp); - return (0); -} - -#endif /* notyet */ - /* * See if this prison root is obsolete, and clean up associated queues if it is. */ @@ -1665,7 +687,7 @@ int error; error = copyout(((char *)msg) + sizeof(*msg), msg_ptr, - msg->msg_size); + msg->msg_size); if (error == 0 && msg_prio != NULL) error = copyout(&msg->msg_prio, msg_prio, sizeof(int)); return (error); @@ -2698,44 +1720,6 @@ .fo_flags = DFLAG_PASSABLE, }; -static struct vop_vector mqfs_vnodeops = { - .vop_default = &default_vnodeops, - .vop_access = mqfs_access, - .vop_cachedlookup = mqfs_lookup, - .vop_lookup = vfs_cache_lookup, - .vop_reclaim = mqfs_reclaim, - .vop_create = mqfs_create, - .vop_remove = mqfs_remove, - .vop_inactive = mqfs_inactive, - .vop_open = mqfs_open, - .vop_close = mqfs_close, - .vop_getattr = mqfs_getattr, - .vop_setattr = mqfs_setattr, - .vop_read = mqfs_read, - .vop_write = VOP_EOPNOTSUPP, - .vop_readdir = mqfs_readdir, - .vop_mkdir = VOP_EOPNOTSUPP, - .vop_rmdir = VOP_EOPNOTSUPP -}; -VFS_VOP_VECTOR_REGISTER(mqfs_vnodeops); - -static struct vfsops mqfs_vfsops = { - .vfs_init = mqfs_init, - .vfs_uninit = mqfs_uninit, - .vfs_mount = mqfs_mount, - .vfs_unmount = mqfs_unmount, - .vfs_root = mqfs_root, - .vfs_statfs = mqfs_statfs, -}; - -static struct vfsconf mqueuefs_vfsconf = { - .vfc_version = VFS_VERSION, - .vfc_name = "mqueuefs", - .vfc_vfsops = &mqfs_vfsops, - .vfc_typenum = -1, - .vfc_flags = VFCF_SYNTHETIC -}; - static struct syscall_helper_data mq_syscalls[] = { SYSCALL_INIT_HELPER(kmq_open), SYSCALL_INIT_HELPER_F(kmq_setattr, SYF_CAPENABLED), @@ -2897,6 +1881,7 @@ { int error; + mqfs_init(); error = syscall_helper_register(mq_syscalls, SY_THR_STATIC_KLD); if (error != 0) return (error); @@ -2911,11 +1896,12 @@ static int mqunload(void) { - #ifdef COMPAT_FREEBSD32 syscall32_helper_unregister(mq32_syscalls); #endif syscall_helper_unregister(mq_syscalls); + + mqfs_uninit(); return (0); } @@ -2924,10 +1910,6 @@ { int error = 0; - error = vfs_modevent(module, cmd, arg); - if (error != 0) - return (error); - switch (cmd) { case MOD_LOAD: error = mqinit(); @@ -2946,7 +1928,7 @@ static moduledata_t mqueuefs_mod = { "mqueuefs", mq_modload, - &mqueuefs_vfsconf + NULL }; DECLARE_MODULE(mqueuefs, mqueuefs_mod, SI_SUB_VFS, SI_ORDER_MIDDLE); MODULE_VERSION(mqueuefs, 1); diff --git a/usr.bin/posixmqcontrol/posixmqcontrol.1 b/usr.bin/posixmqcontrol/posixmqcontrol.1 --- a/usr.bin/posixmqcontrol/posixmqcontrol.1 +++ b/usr.bin/posixmqcontrol/posixmqcontrol.1 @@ -29,7 +29,7 @@ .Os .Sh NAME .Nm posixmqcontrol -.Nd Control POSIX mqueuefs message queues +.Nd Control POSIX message queues .Sh SYNOPSIS .Nm .Ar create @@ -68,14 +68,7 @@ The maximum message size, maximum queue size, and current queue size are displayed by the .Ic info -subcommand. This output is similar to running -.Ic cat -on a mqueuefs queue mounted under a mount point. -This utility requires the -.Ic mqueuefs -kernel module to be loaded but does not require -.Ic mqueuefs -to be mounted as a file system. +subcommand. .Pp The following subcommands are provided: .Bl -tag -width truncate @@ -164,10 +157,10 @@ .Xr mq_send 2 , .Xr mq_setattr 2 , .Xr mq_unlink 2 , -.Xr mqueuefs 4 .Sh BUGS mq_timedsend and mq_timedrecv are not implemented. -info reports a worst-case estimate for QSIZE. +info reports a worst-case estimate for +.Dv QSIZE . .Sh HISTORY The .Nm @@ -177,4 +170,4 @@ The .Nm command and this manual page were written by -.An Rick Parrish Aq Mt unitrunker@unitrunker.net. +.An Rick Parrish Aq Mt unitrunker@unitrunker.net .