Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys - Move some checks into mqueue_get() and avoid some dupl...



details:   https://anonhg.NetBSD.org/src/rev/2b42b56c16cf
branches:  trunk
changeset: 764466:2b42b56c16cf
user:      rmind <rmind%NetBSD.org@localhost>
date:      Sun Apr 24 20:17:53 2011 +0000

description:
- Move some checks into mqueue_get() and avoid some duplication.
- Simplify message queue descriptor unlinking and closure operations.
- Update proc_t::p_mqueue_cnt atomically.  Inherit it on fork().
- Use separate allocation for the name of message queue.

diffstat:

 sys/kern/kern_fork.c  |    7 +-
 sys/kern/sys_mqueue.c |  515 +++++++++++++++++++++++--------------------------
 sys/sys/mqueue.h      |   24 +-
 3 files changed, 260 insertions(+), 286 deletions(-)

diffs (truncated from 898 to 300 lines):

diff -r d881d5dd5a5a -r 2b42b56c16cf sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c      Sun Apr 24 19:00:56 2011 +0000
+++ b/sys/kern/kern_fork.c      Sun Apr 24 20:17:53 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_fork.c,v 1.180 2011/03/23 13:57:40 joerg Exp $    */
+/*     $NetBSD: kern_fork.c,v 1.181 2011/04/24 20:17:53 rmind Exp $    */
 
 /*-
  * Copyright (c) 1999, 2001, 2004, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.180 2011/03/23 13:57:40 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.181 2011/04/24 20:17:53 rmind Exp $");
 
 #include "opt_ktrace.h"
 
@@ -349,6 +349,9 @@
        else
                p2->p_fd = fd_copy();
 
+       /* XXX racy */
+       p2->p_mqueue_cnt = p1->p_mqueue_cnt;
+
        if (flags & FORK_SHARECWD)
                cwdshare(p2);
        else
diff -r d881d5dd5a5a -r 2b42b56c16cf sys/kern/sys_mqueue.c
--- a/sys/kern/sys_mqueue.c     Sun Apr 24 19:00:56 2011 +0000
+++ b/sys/kern/sys_mqueue.c     Sun Apr 24 20:17:53 2011 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: sys_mqueue.c,v 1.31 2011/01/18 20:32:53 rmind Exp $    */
+/*     $NetBSD: sys_mqueue.c,v 1.32 2011/04/24 20:17:53 rmind Exp $    */
 
 /*
- * Copyright (c) 2007-2009 Mindaugas Rasiukevicius <rmind at NetBSD org>
+ * Copyright (c) 2007-2011 Mindaugas Rasiukevicius <rmind at NetBSD org>
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -31,37 +31,30 @@
  * Defined in the Base Definitions volume of IEEE Std 1003.1-2001.
  *
  * Locking
- * 
- * Global list of message queues (mqueue_head) and proc_t::p_mqueue_cnt
- * counter are protected by mqlist_mtx lock.  The very message queue and
- * its members are protected by mqueue::mq_mtx.
- * 
+ *
+ * Global list of message queues (mqueue_head) is protected by mqlist_lock.
+ * Each message queue and its members are protected by mqueue::mq_mtx.
+ * Note that proc_t::p_mqueue_cnt is updated atomically.
+ *
  * Lock order:
- *     mqlist_mtx ->
- *             mqueue::mq_mtx
+ *
+ *     mqlist_lock ->
+ *             mqueue::mq_mtx
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.31 2011/01/18 20:32:53 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.32 2011/04/24 20:17:53 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
-#include <sys/condvar.h>
-#include <sys/errno.h>
-#include <sys/fcntl.h>
+
 #include <sys/file.h>
 #include <sys/filedesc.h>
 #include <sys/kauth.h>
-#include <sys/kernel.h>
-#include <sys/kmem.h>
 #include <sys/lwp.h>
 #include <sys/mqueue.h>
 #include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/pool.h>
 #include <sys/poll.h>
-#include <sys/proc.h>
-#include <sys/queue.h>
 #include <sys/select.h>
 #include <sys/signal.h>
 #include <sys/signalvar.h>
@@ -70,8 +63,6 @@
 #include <sys/syscall.h>
 #include <sys/syscallvar.h>
 #include <sys/syscallargs.h>
-#include <sys/systm.h>
-#include <sys/unistd.h>
 
 #include <miscfs/genfs/genfs.h>
 
@@ -84,10 +75,10 @@
 static u_int                   mq_def_maxmsg = 32;
 static u_int                   mq_max_maxmsg = 16 * 32;
 
-static kmutex_t                        mqlist_mtx;
-static pool_cache_t            mqmsg_cache;
-static LIST_HEAD(, mqueue)     mqueue_head;
-static struct sysctllog                *mqsysctl_log;
+static pool_cache_t            mqmsg_cache     __read_mostly;
+static kmutex_t                        mqlist_lock     __cacheline_aligned;
+static LIST_HEAD(, mqueue)     mqueue_head     __cacheline_aligned;
+static struct sysctllog *      mqsysctl_log;
 
 static int     mqueue_sysinit(void);
 static int     mqueue_sysfini(bool);
@@ -133,7 +124,7 @@
 
        mqmsg_cache = pool_cache_init(MQ_DEF_MSGSIZE, coherency_unit,
            0, 0, "mqmsgpl", NULL, IPL_NONE, NULL, NULL, NULL);
-       mutex_init(&mqlist_mtx, MUTEX_DEFAULT, IPL_NONE);
+       mutex_init(&mqlist_lock, MUTEX_DEFAULT, IPL_NONE);
        LIST_INIT(&mqueue_head);
 
        error = mqueue_sysctl_init();
@@ -160,13 +151,10 @@
                error = syscall_disestablish(NULL, mqueue_syscalls);
                if (error)
                        return error;
-               /*
-                * Check if there are any message queues in use.
-                * TODO: We shall support forced unload.
-                */
-               mutex_enter(&mqlist_mtx);
+               /* Check if there are any message queues in use. */
+               mutex_enter(&mqlist_lock);
                inuse = !LIST_EMPTY(&mqueue_head);
-               mutex_exit(&mqlist_mtx);
+               mutex_exit(&mqlist_lock);
                if (inuse) {
                        error = syscall_establish(NULL, mqueue_syscalls);
                        KASSERT(error == 0);
@@ -177,7 +165,7 @@
        if (mqsysctl_log != NULL)
                sysctl_teardown(&mqsysctl_log);
 
-       mutex_destroy(&mqlist_mtx);
+       mutex_destroy(&mqlist_lock);
        pool_cache_destroy(mqmsg_cache);
        return 0;
 }
@@ -231,6 +219,9 @@
                        mqueue_freemsg(msg, msz);
                }
        }
+       if (mq->mq_name) {
+               kmem_free(mq->mq_name, MQ_NAMELEN);
+       }
        seldestroy(&mq->mq_rsel);
        seldestroy(&mq->mq_wsel);
        cv_destroy(&mq->mq_send_cv);
@@ -240,14 +231,16 @@
 }
 
 /*
- * Lookup for file name in general list of message queues.
- *  => locks the message queue
+ * mqueue_lookup: lookup for file name in general list of message queues.
+ *
+ * => locks the message queue on success
  */
-static void *
-mqueue_lookup(char *name)
+static mqueue_t *
+mqueue_lookup(const char *name)
 {
-       struct mqueue *mq;
-       KASSERT(mutex_owned(&mqlist_mtx));
+       mqueue_t *mq;
+
+       KASSERT(mutex_owned(&mqlist_lock));
 
        LIST_FOREACH(mq, &mqueue_head, mq_list) {
                if (strncmp(mq->mq_name, name, MQ_NAMELEN) == 0) {
@@ -255,33 +248,38 @@
                        return mq;
                }
        }
-
        return NULL;
 }
 
 /*
  * mqueue_get: get the mqueue from the descriptor.
- *  => locks the message queue, if found.
- *  => holds a reference on the file descriptor.
+ *
+ * => locks the message queue, if found.
+ * => holds a reference on the file descriptor.
  */
 static int
-mqueue_get(mqd_t mqd, file_t **fpr)
+mqueue_get(mqd_t mqd, int fflag, mqueue_t **mqret)
 {
-       struct mqueue *mq;
+       const int fd = (int)mqd;
+       mqueue_t *mq;
        file_t *fp;
 
-       fp = fd_getfile((int)mqd);
+       fp = fd_getfile(fd);
        if (__predict_false(fp == NULL)) {
                return EBADF;
        }
        if (__predict_false(fp->f_type != DTYPE_MQUEUE)) {
-               fd_putfile((int)mqd);
+               fd_putfile(fd);
+               return EBADF;
+       }
+       if (fflag && (fp->f_flag & fflag) == 0) {
+               fd_putfile(fd);
                return EBADF;
        }
        mq = fp->f_data;
        mutex_enter(&mq->mq_mtx);
 
-       *fpr = fp;
+       *mqret = mq;
        return 0;
 }
 
@@ -358,49 +356,111 @@
 static int
 mq_close_fop(file_t *fp)
 {
-       struct proc *p = curproc;
-       struct mqueue *mq = fp->f_data;
-       bool destroy;
-
-       mutex_enter(&mqlist_mtx);
-       mutex_enter(&mq->mq_mtx);
+       proc_t *p = curproc;
+       mqueue_t *mq = fp->f_data;
+       bool destroy = false;
 
-       /* Decrease the counters */
-       p->p_mqueue_cnt--;
-       mq->mq_refcnt--;
-
-       /* Remove notification if registered for this process */
-       if (mq->mq_notify_proc == p)
-               mq->mq_notify_proc = NULL;
+       mutex_enter(&mq->mq_mtx);
+       KASSERT(mq->mq_refcnt > 0);
+       if (--mq->mq_refcnt == 0) {
+               /* Destroy if the last reference and unlinked. */
+               destroy = (mq->mq_attrib.mq_flags & MQ_UNLINKED) != 0;
+       }
+       mutex_exit(&mq->mq_mtx);
 
-       /*
-        * If this is the last reference and mqueue is marked for unlink,
-        * remove and later destroy the message queue.
-        */
-       if (mq->mq_refcnt == 0 && (mq->mq_attrib.mq_flags & MQ_UNLINK)) {
-               LIST_REMOVE(mq, mq_list);
-               destroy = true;
-       } else
-               destroy = false;
+       if (destroy) {
+               mqueue_destroy(mq);
+       }
+       atomic_dec_uint(&p->p_mqueue_cnt);
+       return 0;
+}
+
+static int
+mqueue_access(mqueue_t *mq, int access, kauth_cred_t cred)
+{
+       mode_t acc_mode = 0;
 
-       mutex_exit(&mq->mq_mtx);
-       mutex_exit(&mqlist_mtx);
-
-       if (destroy)
-               mqueue_destroy(mq);
-
+       /* Note the difference between VREAD/VWRITE and FREAD/FWRITE. */
+       if (access & FREAD) {
+               acc_mode |= VREAD;
+       }
+       if (access & FWRITE) {
+               acc_mode |= VWRITE;
+       }
+       if (genfs_can_access(VNON, mq->mq_mode, mq->mq_euid,
+           mq->mq_egid, acc_mode, cred)) {
+               return EACCES;
+       }
        return 0;
 }
 
 static int
-mqueue_access(struct mqueue *mq, mode_t mode, kauth_cred_t cred)



Home | Main Index | Thread Index | Old Index