]> Zhao Yanbai Git Server - minix.git/commitdiff
Import NetBSD dev_mkdb(8) 52/3252/2
authorDavid van Moolenbroek <david@minix3.org>
Tue, 6 Oct 2015 16:42:46 +0000 (16:42 +0000)
committerLionel Sambuc <lionel.sambuc@gmail.com>
Wed, 13 Jan 2016 19:32:51 +0000 (20:32 +0100)
Adapt libc devname(3) to make use of it, so that such device name
queries are now several orders of magnitude faster.  The database
is created and updated at system bootup time.

Change-Id: I0cbcb24c7d47577d4d6af9c8290c21ee4df9a0ff

distrib/sets/lists/minix-base/mi
distrib/sets/lists/minix-man/mi
etc/usr/rc
lib/libc/gen/devname.c
lib/libc/include/reentrant.h
minix/drivers/tty/pty/tty.h
minix/include/minix/dmap.h
usr.sbin/Makefile
usr.sbin/dev_mkdb/Makefile [new file with mode: 0644]
usr.sbin/dev_mkdb/dev_mkdb.8 [new file with mode: 0644]
usr.sbin/dev_mkdb/dev_mkdb.c [new file with mode: 0644]

index d9c86886c6f5231e28a293fab7fc77560bd4a880..e3eb91afb8af5e80ea48a0b2bafd6506b9af5a4b 100644 (file)
 ./usr/sbin/btrace                                       minix-base
 ./usr/sbin/chown                                        minix-base
 ./usr/sbin/chroot                                       minix-base
+./usr/sbin/dev_mkdb                                     minix-base
 ./usr/sbin/diskctl                                      minix-base
 ./usr/sbin/download-vulnerability-list                  minix-base      crypto
 ./usr/sbin/fbdctl                                       minix-base
index 9943820871cd3635ed300c93cee90bced6d21f29..1756fdeeb3615cf0b4bac405eaa99be4cd98a974 100644 (file)
 ./usr/man/man8/cleantmp.8                               minix-man
 ./usr/man/man8/config.8                                 minix-man
 ./usr/man/man8/cron.8                                   minix-man
+./usr/man/man8/dev_mkdb.8                               minix-man
 ./usr/man/man8/devsize.8                                minix-man
 ./usr/man/man8/dhcpd.8                                  minix-man
 ./usr/man/man8/diskctl.8                                minix-man
index a12a3e3a02d56e295b5358e6b2d4688c4c8d39c0..f8f36ad078f15a8c6cfe44ba8dc1f775c7869b3c 100644 (file)
@@ -393,6 +393,15 @@ start|autoboot)
        fi
     fi
 
+    # Now that all device files should be created, see if we need to update the
+    # device file database.  This code is butchered from NetBSD etc/rc.d/sysdb.
+    DEVDIR=/dev
+    DEVDB=/var/run/dev.cdb
+    if [ ! -f "$DEVDB" -o "$DEVDIR" -nt "$DEVDB" ]
+    then
+       dev_mkdb
+    fi
+
     if [ "$net" ]
     then
        # Get the nodename from the DNS and set it.
index 072c61e8ec02d9347072ddab89b0a71442afcfac..988d3cfd1c3a6e472bf44570ed8203a957975e70 100644 (file)
@@ -45,11 +45,14 @@ __RCSID("$NetBSD: devname.c,v 1.22 2012/06/03 21:42:46 joerg Exp $");
 #include <string.h>
 #include <stdlib.h>
 
+#ifdef __minix
+#include <minix/dmap.h>                /* for UNIX98_MINOR */
+#endif /* __minix */
+
 #ifdef __weak_alias
 __weak_alias(devname_r,_devname_r)
 #endif
 
-#if !defined(__minix)
 static once_t db_opened = ONCE_INITIALIZER;
 static struct cdbr *db;
 static devmajor_t pts;
@@ -95,14 +98,25 @@ devname_ptslookup(dev_t dev, mode_t type, char *path, size_t len)
 
        if (type != S_IFCHR || pts == NODEVMAJOR || major(dev) != pts)
                return ENOENT;
+#ifdef __minix
+       /*
+        * MINIX3 does not use an identity mapping for /dev/pts, because the
+        * same major number is also used for PTY masters and legacy PTYs.
+        */
+       if (minor(dev) < UNIX98_MINOR || !(minor(dev) & 1))
+               return ENOENT;
+#endif /* __minix */
 
        rv = snprintf(path, len, "%s%d", _PATH_DEV_PTS + sizeof(_PATH_DEV) - 1,
+#ifndef __minix
            minor(dev));
+#else /* __minix */
+           (minor(dev) - UNIX98_MINOR) >> 1);
+#endif /* __minix */
        if (rv < 0 || (size_t)rv >= len)
                return ERANGE;
        return 0;
 }
-#endif /* !defined(__minix) */
 
 static int
 devname_fts(dev_t dev, mode_t type, char *path, size_t len)
@@ -142,7 +156,6 @@ devname_r(dev_t dev, mode_t type, char *path, size_t len)
 {
        int rv;
 
-#if !defined(__minix)
        thr_once(&db_opened, devname_dbopen);
 
        if (db != NULL) {
@@ -157,7 +170,6 @@ devname_r(dev_t dev, mode_t type, char *path, size_t len)
 
        if (db != NULL)
                return ENOENT;
-#endif /* !defined(__minix) */
        rv = devname_fts(dev, type, path, len);
        return rv;
 }
index 109510388d120dc3f1e6f774b0cd760eb668d53e..55be7f022f96496e315a6f20701fc54221c00e0a 100644 (file)
  *
  */
 
-#if defined(_REENTRANT) && defined(__minix)
+#if !defined(__minix) || !defined(_LIBC_REENTRANT_H)
+#ifdef __minix
+/*
+ * If _REENTRANT is not defined, the header may not be included more than once.
+ * This is probably a NetBSD libc bug, but for now we solve it for MINIX3 only.
+ */
+#define _LIBC_REENTRANT_H
+#endif /* __minix */
 
 /*
  * Abstract thread interface for thread-safe libraries.  These routines
  * is.
  */
 
+#ifndef __minix
+
 #include <pthread.h>
 #include <signal.h>
 
 #define        once_t                  pthread_once_t
 #define        ONCE_INITIALIZER        PTHREAD_ONCE_INIT
 
+#else /* __minix */
+
+typedef struct {
+       int pto_done;
+} once_t;
+#define ONCE_INITIALIZER       { .pto_done = 0 }
+
+#endif /* __minix */
+
+#ifdef _REENTRANT
+
 #ifndef __LIBC_THREAD_STUBS
 
 __BEGIN_DECLS
@@ -311,7 +331,6 @@ __END_DECLS
 #define        mutexattr_settype(ma, t) __empty
 #define        mutexattr_destroy(ma) __empty
 
-#if !defined(__minix)
 static inline int
 thr_once(once_t *once_control, void (*routine)(void))
 {
@@ -321,7 +340,6 @@ thr_once(once_t *once_control, void (*routine)(void))
        }
        return 0;
 }
-#endif /* defined(__minix) */
 #define        thr_sigsetmask(f, n, o) __empty
 #define        thr_self() __empty
 #define        thr_errno() __empty
@@ -331,3 +349,5 @@ thr_once(once_t *once_control, void (*routine)(void))
 #define        FUNLOCKFILE(fp) __empty
 
 #endif /* _REENTRANT */
+
+#endif /* !defined(__minix) || !defined(_LIBC_REENTRANT_H) */
index 7dbb5f5c655f5742ee1d871a5284b74c4d6da475..1fa7e9defc3fb186da00a105a45d1ef121846255 100644 (file)
@@ -7,7 +7,7 @@
 #define PTMX_MINOR        0    /* minor of the Unix98 clone device */
 #define TTYPX_MINOR     128
 #define PTYPX_MINOR     192
-#define UNIX98_MINOR    256    /* start of Unix98 pairs */
+/* UNIX98_MINOR is defined in minix/dmap.h */
 
 #define TTY_IN_BYTES     256   /* tty input queue size */
 #define TTY_OUT_BYTES   2048   /* tty output queue size */
index 5cf821478dde1159c795e8a9c6b73c8fc3a73181..8c6560d3bad7e5cd6756024ab4c27b250e0f5802 100644 (file)
 /* Minor device numbers for the TTY driver. */
 #  define CONS_MINOR              0    /* console device */
 
+/* Minor device numbers for the PTY driver. */
+#  define UNIX98_MINOR           256   /* Base number of UNIX98 PTYs, which
+                                        * are allocated in (master,slave)
+                                        * pairs: 256=master#0, 257=slave#0,
+                                        * 258=master#1, 259=slave#1, etc.
+                                        * This logic is shared between the
+                                        * PTY service and libc devname(3).
+                                        */
+
 #define CTRLR(n) ((n)==0 ? 3 : (8 + 2*((n)-1)))        /* magic formula */
 
 /* Minor device numbers for log driver. */
 #  define DEV_IMGRD   ((dev_t) 0x0106) /* device number of /dev/imgrd */
 
 #endif /* _DMAP_H */
-
index 88af936f54be2ab75780a446fe6d431f49b2b913..c8ee775ab30bbe8c8a3d52e3e1019e261431635b 100644 (file)
@@ -6,7 +6,7 @@
 SUBDIR= \
        \
        chroot \
-       \
+       dev_mkdb \
        \
        \
        \
diff --git a/usr.sbin/dev_mkdb/Makefile b/usr.sbin/dev_mkdb/Makefile
new file mode 100644 (file)
index 0000000..598d928
--- /dev/null
@@ -0,0 +1,12 @@
+#      from: @(#)Makefile      8.1 (Berkeley) 6/6/93
+#      $NetBSD: Makefile,v 1.9 2012/08/10 12:10:28 joerg Exp $
+
+PROG=  dev_mkdb
+MAN=   dev_mkdb.8
+
+LDADD+=        -lutil
+DPADD+=        ${LIBUTIL}
+
+.include <bsd.prog.mk>
+
+LDFLAGS+=      -Wl,--no-fatal-warnings
diff --git a/usr.sbin/dev_mkdb/dev_mkdb.8 b/usr.sbin/dev_mkdb/dev_mkdb.8
new file mode 100644 (file)
index 0000000..1ac74ef
--- /dev/null
@@ -0,0 +1,95 @@
+.\" Copyright (c) 1990, 1993
+.\"    The Regents of the University of California.  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, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+.\"
+.\"    from: @(#)dev_mkdb.8    8.1 (Berkeley) 6/6/93
+.\"    $NetBSD: dev_mkdb.8,v 1.13 2012/06/03 21:42:47 joerg Exp $
+.\"
+.Dd June 1, 2012
+.Dt DEV_MKDB 8
+.Os
+.Sh NAME
+.Nm dev_mkdb
+.Nd create
+.Pa /dev
+database
+.Sh SYNOPSIS
+.Nm
+.Op Fl c
+.Op Fl o Ar database
+.Op directory
+.Sh DESCRIPTION
+The
+.Nm
+command creates a
+.Xr cdbr 3
+database in
+.Dq Pa /var/run/dev.cdb 
+which contains the names of all of the character and block special
+files in the specified directory, using the file type and the
+.Fa st_rdev
+field as the key.
+If no directory is specified, the
+.Dq Pa /dev
+directory is used.
+.Pp
+Keys are a structure containing a mode_t followed by a dev_t,
+with any padding zero'd out.
+The former is the type of the file (st_mode \*[Am] S_IFMT),
+the latter is the st_rdev field.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl c
+Create a
+.Xr db 3
+database for compatibility with libc versions and statically linked programs
+from before
+.Nx 6.0 .
+The default name is
+.Dq Pa /var/run/dev.db .
+.It Fl o Ar database
+Put the output databases in the named file.
+.El
+.Sh FILES
+.Bl -tag -width /var/run/dev.db -compact
+.It Pa /dev
+Device directory.
+.It Pa /var/run/dev.db
+Database file.
+.El
+.Sh SEE ALSO
+.Xr ps 1 ,
+.Xr stat 2 ,
+.Xr db 3 ,
+.Xr devname 3 ,
+.Xr kvm_nlist 3 ,
+.Xr ttyname 3
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.4 .
diff --git a/usr.sbin/dev_mkdb/dev_mkdb.c b/usr.sbin/dev_mkdb/dev_mkdb.c
new file mode 100644 (file)
index 0000000..c78cc9d
--- /dev/null
@@ -0,0 +1,268 @@
+/*     $NetBSD: dev_mkdb.c,v 1.29 2012/06/03 21:42:47 joerg Exp $      */
+
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: dev_mkdb.c,v 1.29 2012/06/03 21:42:47 joerg Exp $");
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <cdbw.h>
+#include <db.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <paths.h>
+#include <search.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+
+#define        HASH_SIZE       65536
+#define        FILE_PERMISSION S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH
+
+static struct cdbw *db;
+static DB *db_compat;
+static const char *db_name;
+static char *db_name_tmp;
+
+static void    usage(void) __dead;
+
+static void
+cdb_open(void)
+{
+       db = cdbw_open();
+       if (db == NULL)
+               err(1, "opening cdb writer failed");
+}
+
+static void
+cdb_close(void)
+{
+       int fd;
+
+       fd = open(db_name_tmp, O_CREAT|O_EXCL|O_WRONLY, FILE_PERMISSION);
+       if (fd == -1)
+               err(1, "opening %s failed", db_name_tmp);
+       if (cdbw_output(db, fd, "NetBSD6 devdb", NULL))
+               err(1, "failed to write temporary database %s", db_name_tmp);
+       cdbw_close(db);
+       db = NULL;
+       if (close(fd))
+               err(1, "failed to write temporary database %s", db_name_tmp);
+}
+
+static void
+cdb_add_entry(dev_t dev, mode_t type, const char *relpath)
+{
+       uint8_t *buf;
+       size_t len;
+
+       len = strlen(relpath) + 1;
+       buf = malloc(len + 10);
+       le64enc(buf, dev);
+       le16enc(buf + 8, type);
+       memcpy(buf + 10, relpath, len);
+       cdbw_put(db, buf, 10, buf, len + 10);
+       free(buf);
+}
+
+static void
+compat_open(void)
+{
+       static HASHINFO openinfo = {
+               4096,           /* bsize */
+               128,            /* ffactor */
+               1024,           /* nelem */
+               2048 * 1024,    /* cachesize */
+               NULL,           /* hash() */
+               0               /* lorder */
+       };
+
+       db_compat = dbopen(db_name_tmp, O_CREAT|O_EXCL|O_EXLOCK|O_RDWR|O_TRUNC,
+           FILE_PERMISSION, DB_HASH, &openinfo);
+
+       if (db_compat == NULL)
+               err(1, "failed to create temporary database %s",
+                   db_name_tmp);
+}
+
+static void
+compat_close(void)
+{
+       if ((*db_compat->close)(db_compat))
+               err(1, "failed to write temporary database %s", db_name_tmp);
+}
+
+static void
+compat_add_entry(dev_t dev, mode_t type, const char *relpath)
+{
+       /*
+        * Keys are a mode_t followed by a dev_t.  The former is the type of
+        * the file (mode & S_IFMT), the latter is the st_rdev field.  Note
+        * that the structure may contain padding, so we have to clear it
+        * out here.
+        */
+       struct {
+               mode_t type;
+               dev_t dev;
+       } bkey;
+       struct {
+               mode_t type;
+               int32_t dev;
+       } obkey;
+       DBT data, key;
+
+       (void)memset(&bkey, 0, sizeof(bkey));
+       key.data = &bkey;
+       key.size = sizeof(bkey);
+       data.data = __UNCONST(relpath);
+       data.size = strlen(relpath) + 1;
+       bkey.type = type;
+       bkey.dev = dev;
+       if ((*db_compat->put)(db_compat, &key, &data, 0))
+               err(1, "failed to write temporary database %s", db_name_tmp);
+
+       /*
+        * If the device fits into the old 32bit format, add compat entry
+        * for pre-NetBSD6 libc.
+        */
+
+       if ((dev_t)(int32_t)dev != dev)
+               return;
+
+       (void)memset(&obkey, 0, sizeof(obkey));
+       key.data = &obkey;
+       key.size = sizeof(obkey);
+       data.data = __UNCONST(relpath);
+       data.size = strlen(relpath) + 1;
+       obkey.type = type;
+       obkey.dev = (int32_t)dev;
+       if ((*db_compat->put)(db_compat, &key, &data, 0))
+               err(1, "failed to write temporary database %s", db_name_tmp);
+}
+
+int
+main(int argc, char **argv)
+{
+       struct stat *st;
+       FTS *ftsp;
+       FTSENT *p;
+       int ch;
+       char *pathv[2];
+       size_t dlen;
+       int compat_mode;
+
+       setprogname(argv[0]);
+       compat_mode = 0;
+
+       while ((ch = getopt(argc, argv, "co:")) != -1)
+               switch (ch) {
+               case 'c':
+                       compat_mode = 1;
+                       break;
+               case 'o':
+                       db_name = optarg;
+                       break;
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (argc > 1)
+               usage();
+
+       pathv[1] = NULL;
+       if (argc == 1)
+               pathv[0] = argv[0];
+       else
+               pathv[0] = __UNCONST(_PATH_DEV);
+       
+       ftsp = fts_open(pathv, FTS_NOCHDIR | FTS_PHYSICAL, NULL);
+       if (ftsp == NULL)
+               err(1, "fts_open: %s", pathv[0]);
+
+       if (db_name == NULL) {
+               if (compat_mode)
+                       db_name = _PATH_DEVDB;
+               else
+                       db_name = _PATH_DEVCDB;
+       }
+       easprintf(&db_name_tmp, "%s.XXXXXXX", db_name);
+       mktemp(db_name_tmp);
+
+       if (compat_mode)
+               compat_open();
+       else
+               cdb_open();
+
+       while ((p = fts_read(ftsp)) != NULL) {
+               if (p->fts_info != FTS_DEFAULT)
+                       continue;
+
+               st = p->fts_statp;
+               if (!S_ISCHR(st->st_mode) && !S_ISBLK(st->st_mode))
+                       continue;
+               dlen = strlen(pathv[0]);
+               while (pathv[0][dlen] == '/')
+                       ++dlen;
+               if (compat_mode)
+                       compat_add_entry(st->st_rdev, st->st_mode & S_IFMT,
+                           p->fts_path + dlen);
+               else
+                       cdb_add_entry(st->st_rdev, st->st_mode & S_IFMT,
+                           p->fts_path + dlen);
+       }
+       (void)fts_close(ftsp);
+
+       if (compat_mode)
+               compat_close();
+       else
+               cdb_close();
+
+       if (rename(db_name_tmp, db_name) == -1)
+               err(1, "rename %s to %s", db_name_tmp, db_name);
+       return 0;
+}
+
+static void
+usage(void)
+{
+
+       (void)fprintf(stderr, "Usage: %s [-c] [-o database] [directory]\n",
+           getprogname());
+       exit(1);
+}