From: David van Moolenbroek Date: Tue, 6 Oct 2015 16:42:46 +0000 (+0000) Subject: Import NetBSD dev_mkdb(8) X-Git-Url: http://zhaoyanbai.com/repos/?a=commitdiff_plain;h=180e74704d3b012a5a9186f196cd218b8ab783f4;p=minix.git Import NetBSD dev_mkdb(8) 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 --- diff --git a/distrib/sets/lists/minix-base/mi b/distrib/sets/lists/minix-base/mi index d9c86886c..e3eb91afb 100644 --- a/distrib/sets/lists/minix-base/mi +++ b/distrib/sets/lists/minix-base/mi @@ -883,6 +883,7 @@ ./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 diff --git a/distrib/sets/lists/minix-man/mi b/distrib/sets/lists/minix-man/mi index 994382087..1756fdeeb 100644 --- a/distrib/sets/lists/minix-man/mi +++ b/distrib/sets/lists/minix-man/mi @@ -3358,6 +3358,7 @@ ./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 diff --git a/etc/usr/rc b/etc/usr/rc index a12a3e3a0..f8f36ad07 100644 --- a/etc/usr/rc +++ b/etc/usr/rc @@ -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. diff --git a/lib/libc/gen/devname.c b/lib/libc/gen/devname.c index 072c61e8e..988d3cfd1 100644 --- a/lib/libc/gen/devname.c +++ b/lib/libc/gen/devname.c @@ -45,11 +45,14 @@ __RCSID("$NetBSD: devname.c,v 1.22 2012/06/03 21:42:46 joerg Exp $"); #include #include +#ifdef __minix +#include /* 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; } diff --git a/lib/libc/include/reentrant.h b/lib/libc/include/reentrant.h index 109510388..55be7f022 100644 --- a/lib/libc/include/reentrant.h +++ b/lib/libc/include/reentrant.h @@ -84,7 +84,14 @@ * */ -#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 @@ -93,6 +100,8 @@ * is. */ +#ifndef __minix + #include #include @@ -124,6 +133,17 @@ #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) */ diff --git a/minix/drivers/tty/pty/tty.h b/minix/drivers/tty/pty/tty.h index 7dbb5f5c6..1fa7e9def 100644 --- a/minix/drivers/tty/pty/tty.h +++ b/minix/drivers/tty/pty/tty.h @@ -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 */ diff --git a/minix/include/minix/dmap.h b/minix/include/minix/dmap.h index 5cf821478..8c6560d3b 100644 --- a/minix/include/minix/dmap.h +++ b/minix/include/minix/dmap.h @@ -94,6 +94,15 @@ /* 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. */ @@ -104,4 +113,3 @@ # define DEV_IMGRD ((dev_t) 0x0106) /* device number of /dev/imgrd */ #endif /* _DMAP_H */ - diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 88af936f5..c8ee775ab 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -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 index 000000000..598d92838 --- /dev/null +++ b/usr.sbin/dev_mkdb/Makefile @@ -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 + +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 index 000000000..1ac74ef2e --- /dev/null +++ b/usr.sbin/dev_mkdb/dev_mkdb.8 @@ -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 index 000000000..c78cc9d05 --- /dev/null +++ b/usr.sbin/dev_mkdb/dev_mkdb.c @@ -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 +__RCSID("$NetBSD: dev_mkdb.c,v 1.29 2012/06/03 21:42:47 joerg Exp $"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +}