aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/mount_zfs/Makefile.am5
-rw-r--r--cmd/raidz_test/Makefile.am2
-rw-r--r--cmd/zdb/Makefile.am4
-rw-r--r--cmd/zed/Makefile.am9
-rw-r--r--cmd/zfs/Makefile.am3
-rw-r--r--cmd/zfs/zfs_main.c3
-rw-r--r--cmd/zhack/Makefile.am4
-rw-r--r--cmd/zinject/Makefile.am4
-rw-r--r--cmd/zpool/Makefile.am7
-rw-r--r--cmd/zpool/zpool_iter.c28
-rw-r--r--cmd/zpool/zpool_main.c11
-rw-r--r--cmd/zpool/zpool_util.c26
-rw-r--r--cmd/zpool/zpool_util.h2
-rw-r--r--cmd/zstreamdump/Makefile.am5
-rw-r--r--cmd/ztest/Makefile.am5
-rw-r--r--configure.ac1
-rw-r--r--include/Makefile.am3
-rw-r--r--include/libzfs.h1
-rw-r--r--include/sys/zfs_context.h4
-rw-r--r--include/thread_pool.h72
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/libnvpair/Makefile.am4
-rw-r--r--lib/libspl/Makefile.am1
-rw-r--r--lib/libspl/gethostid.c86
-rw-r--r--lib/libspl/include/sys/systeminfo.h3
-rw-r--r--lib/libtpool/Makefile.am26
-rw-r--r--lib/libtpool/thread_pool.c650
-rw-r--r--lib/libtpool/thread_pool_impl.h93
-rw-r--r--lib/libuutil/Makefile.am3
-rw-r--r--lib/libzfs/Makefile.am32
-rw-r--r--lib/libzfs/libzfs_import.c45
-rw-r--r--lib/libzfs/libzfs_pool.c1
-rw-r--r--lib/libzfs/libzfs_status.c1
-rw-r--r--lib/libzpool/Makefile.am16
-rw-r--r--lib/libzpool/kernel.c195
-rw-r--r--module/icp/algs/sha2/sha2.c19
-rw-r--r--module/icp/os/modhash.c2
-rw-r--r--module/zcommon/Makefile.in13
-rw-r--r--module/zcommon/zfeature_common.c (renamed from module/zfs/zfeature_common.c)9
-rw-r--r--module/zcommon/zfs_comutil.c75
-rw-r--r--module/zcommon/zfs_deleg.c2
-rw-r--r--module/zcommon/zfs_fletcher.c9
-rw-r--r--module/zfs/Makefile.in2
-rw-r--r--module/zfs/zfs_ratelimit.c99
-rwxr-xr-xscripts/zfs2zol-patch.sed8
-rw-r--r--tests/zfs-tests/tests/functional/libzfs/Makefile.am6
46 files changed, 1191 insertions, 410 deletions
diff --git a/cmd/mount_zfs/Makefile.am b/cmd/mount_zfs/Makefile.am
index b1d938922..bc9fb4c34 100644
--- a/cmd/mount_zfs/Makefile.am
+++ b/cmd/mount_zfs/Makefile.am
@@ -16,7 +16,4 @@ mount_zfs_SOURCES = \
mount_zfs_LDADD = \
$(top_builddir)/lib/libnvpair/libnvpair.la \
- $(top_builddir)/lib/libuutil/libuutil.la \
- $(top_builddir)/lib/libzpool/libzpool.la \
- $(top_builddir)/lib/libzfs/libzfs.la \
- $(top_builddir)/lib/libzfs_core/libzfs_core.la
+ $(top_builddir)/lib/libzfs/libzfs.la
diff --git a/cmd/raidz_test/Makefile.am b/cmd/raidz_test/Makefile.am
index 15edb2b1e..02cc746ec 100644
--- a/cmd/raidz_test/Makefile.am
+++ b/cmd/raidz_test/Makefile.am
@@ -15,8 +15,6 @@ raidz_test_SOURCES = \
raidz_bench.c
raidz_test_LDADD = \
- $(top_builddir)/lib/libnvpair/libnvpair.la \
- $(top_builddir)/lib/libuutil/libuutil.la \
$(top_builddir)/lib/libzpool/libzpool.la
raidz_test_LDADD += -lm -ldl
diff --git a/cmd/zdb/Makefile.am b/cmd/zdb/Makefile.am
index eb8e6777f..ea6806b2c 100644
--- a/cmd/zdb/Makefile.am
+++ b/cmd/zdb/Makefile.am
@@ -14,7 +14,5 @@ zdb_SOURCES = \
zdb_LDADD = \
$(top_builddir)/lib/libnvpair/libnvpair.la \
- $(top_builddir)/lib/libuutil/libuutil.la \
- $(top_builddir)/lib/libzpool/libzpool.la \
$(top_builddir)/lib/libzfs/libzfs.la \
- $(top_builddir)/lib/libzfs_core/libzfs_core.la
+ $(top_builddir)/lib/libzpool/libzpool.la
diff --git a/cmd/zed/Makefile.am b/cmd/zed/Makefile.am
index 97733a512..53d5aa71c 100644
--- a/cmd/zed/Makefile.am
+++ b/cmd/zed/Makefile.am
@@ -40,15 +40,12 @@ FMA_SRC = \
zed_SOURCES = $(ZED_SRC) $(FMA_SRC)
zed_LDADD = \
- $(top_builddir)/lib/libavl/libavl.la \
$(top_builddir)/lib/libnvpair/libnvpair.la \
- $(top_builddir)/lib/libspl/libspl.la \
$(top_builddir)/lib/libuutil/libuutil.la \
- $(top_builddir)/lib/libzpool/libzpool.la \
- $(top_builddir)/lib/libzfs/libzfs.la \
- $(top_builddir)/lib/libzfs_core/libzfs_core.la
+ $(top_builddir)/lib/libzfs/libzfs.la
-zed_LDFLAGS = -lrt -pthread
+zed_LDADD += -lrt
+zed_LDFLAGS = -pthread
zedconfdir = $(sysconfdir)/zfs/zed.d
diff --git a/cmd/zfs/Makefile.am b/cmd/zfs/Makefile.am
index e40909516..4e689d1ee 100644
--- a/cmd/zfs/Makefile.am
+++ b/cmd/zfs/Makefile.am
@@ -15,8 +15,5 @@ zfs_SOURCES = \
zfs_LDADD = \
$(top_builddir)/lib/libnvpair/libnvpair.la \
$(top_builddir)/lib/libuutil/libuutil.la \
- $(top_builddir)/lib/libzpool/libzpool.la \
$(top_builddir)/lib/libzfs/libzfs.la \
$(top_builddir)/lib/libzfs_core/libzfs_core.la
-
-zfs_LDFLAGS = -pthread
diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c
index e8fe6a9fa..0d18ca7b6 100644
--- a/cmd/zfs/zfs_main.c
+++ b/cmd/zfs/zfs_main.c
@@ -55,6 +55,7 @@
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/fs/zfs.h>
+#include <sys/systeminfo.h>
#include <sys/types.h>
#include <time.h>
@@ -7045,8 +7046,6 @@ main(int argc, char **argv)
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
- dprintf_setup(&argc, argv);
-
opterr = 0;
/*
diff --git a/cmd/zhack/Makefile.am b/cmd/zhack/Makefile.am
index a7bce5dde..f720e8286 100644
--- a/cmd/zhack/Makefile.am
+++ b/cmd/zhack/Makefile.am
@@ -11,7 +11,5 @@ zhack_SOURCES = \
zhack_LDADD = \
$(top_builddir)/lib/libnvpair/libnvpair.la \
- $(top_builddir)/lib/libuutil/libuutil.la \
- $(top_builddir)/lib/libzpool/libzpool.la \
$(top_builddir)/lib/libzfs/libzfs.la \
- $(top_builddir)/lib/libzfs_core/libzfs_core.la
+ $(top_builddir)/lib/libzpool/libzpool.la
diff --git a/cmd/zinject/Makefile.am b/cmd/zinject/Makefile.am
index 2500beec2..b709a2f5a 100644
--- a/cmd/zinject/Makefile.am
+++ b/cmd/zinject/Makefile.am
@@ -13,7 +13,5 @@ zinject_SOURCES = \
zinject_LDADD = \
$(top_builddir)/lib/libnvpair/libnvpair.la \
- $(top_builddir)/lib/libuutil/libuutil.la \
- $(top_builddir)/lib/libzpool/libzpool.la \
$(top_builddir)/lib/libzfs/libzfs.la \
- $(top_builddir)/lib/libzfs_core/libzfs_core.la
+ $(top_builddir)/lib/libzpool/libzpool.la
diff --git a/cmd/zpool/Makefile.am b/cmd/zpool/Makefile.am
index 6eff1d143..d7e1741c1 100644
--- a/cmd/zpool/Makefile.am
+++ b/cmd/zpool/Makefile.am
@@ -16,10 +16,9 @@ zpool_SOURCES = \
zpool_LDADD = \
$(top_builddir)/lib/libnvpair/libnvpair.la \
$(top_builddir)/lib/libuutil/libuutil.la \
- $(top_builddir)/lib/libzpool/libzpool.la \
- $(top_builddir)/lib/libzfs/libzfs.la \
- $(top_builddir)/lib/libzfs_core/libzfs_core.la \
- -lm $(LIBBLKID)
+ $(top_builddir)/lib/libzfs/libzfs.la
+
+zpool_LDADD += -lm $(LIBBLKID)
zpoolconfdir = $(sysconfdir)/zfs/zpool.d
zpoolexecdir = $(libexecdir)/zfs/zpool.d
diff --git a/cmd/zpool/zpool_iter.c b/cmd/zpool/zpool_iter.c
index e55c2f102..019f0b136 100644
--- a/cmd/zpool/zpool_iter.c
+++ b/cmd/zpool/zpool_iter.c
@@ -33,6 +33,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
+#include <thread_pool.h>
#include <libzfs.h>
#include <sys/zfs_context.h>
@@ -668,34 +669,21 @@ all_pools_for_each_vdev_gather_cb(zpool_handle_t *zhp, void *cb_vcdl)
static void
all_pools_for_each_vdev_run_vcdl(vdev_cmd_data_list_t *vcdl)
{
- taskq_t *t;
- int i;
- /* 5 * boot_ncpus selfishly chosen since it works best on LLNL's HW */
- int max_threads = 5 * boot_ncpus;
-
- /*
- * Under Linux we use a taskq to parallelize running a command
- * on each vdev. It is therefore necessary to initialize this
- * functionality for the duration of the threads.
- */
- thread_init();
+ tpool_t *t;
- t = taskq_create("z_pool_cmd", max_threads, defclsyspri, max_threads,
- INT_MAX, 0);
+ t = tpool_create(1, 5 * sysconf(_SC_NPROCESSORS_ONLN), 0, NULL);
if (t == NULL)
return;
/* Spawn off the command for each vdev */
- for (i = 0; i < vcdl->count; i++) {
- (void) taskq_dispatch(t, vdev_run_cmd_thread,
- (void *) &vcdl->data[i], TQ_SLEEP);
+ for (int i = 0; i < vcdl->count; i++) {
+ (void) tpool_dispatch(t, vdev_run_cmd_thread,
+ (void *) &vcdl->data[i]);
}
/* Wait for threads to finish */
- taskq_wait(t);
- taskq_destroy(t);
- thread_fini();
-
+ tpool_wait(t);
+ tpool_destroy(t);
}
/*
diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c
index 338b9952c..60713197d 100644
--- a/cmd/zpool/zpool_main.c
+++ b/cmd/zpool/zpool_main.c
@@ -50,6 +50,7 @@
#include <zfs_prop.h>
#include <sys/fs/zfs.h>
#include <sys/stat.h>
+#include <sys/systeminfo.h>
#include <sys/fm/fs/zfs.h>
#include <sys/fm/util.h>
#include <sys/fm/protocol.h>
@@ -2645,15 +2646,7 @@ zpool_do_import(int argc, char **argv)
idata.cachefile = cachefile;
idata.scan = do_scan;
- /*
- * Under Linux the zpool_find_import_impl() function leverages the
- * taskq implementation to parallelize device scanning. It is
- * therefore necessary to initialize this functionality for the
- * duration of the zpool_search_import() function.
- */
- thread_init();
pools = zpool_search_import(g_zfs, &idata);
- thread_fini();
if (pools != NULL && idata.exists &&
(argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
@@ -7968,8 +7961,6 @@ main(int argc, char **argv)
(void) textdomain(TEXT_DOMAIN);
srand(time(NULL));
- dprintf_setup(&argc, argv);
-
opterr = 0;
/*
diff --git a/cmd/zpool/zpool_util.c b/cmd/zpool/zpool_util.c
index 43abfa23b..c26c0eb39 100644
--- a/cmd/zpool/zpool_util.c
+++ b/cmd/zpool/zpool_util.c
@@ -111,3 +111,29 @@ isnumber(char *str)
return (1);
}
+
+/*
+ * Find highest one bit set.
+ * Returns bit number + 1 of highest bit that is set, otherwise returns 0.
+ */
+int
+highbit64(uint64_t i)
+{
+ if (i == 0)
+ return (0);
+
+ return (NBBY * sizeof (uint64_t) - __builtin_clzll(i));
+}
+
+/*
+ * Find lowest one bit set.
+ * Returns bit number + 1 of lowest bit that is set, otherwise returns 0.
+ */
+int
+lowbit64(uint64_t i)
+{
+ if (i == 0)
+ return (0);
+
+ return (__builtin_ffsll(i));
+}
diff --git a/cmd/zpool/zpool_util.h b/cmd/zpool/zpool_util.h
index aef2cff27..3afc82d54 100644
--- a/cmd/zpool/zpool_util.h
+++ b/cmd/zpool/zpool_util.h
@@ -43,6 +43,8 @@ void zpool_no_memory(void);
uint_t num_logs(nvlist_t *nv);
uint64_t array64_max(uint64_t array[], unsigned int len);
int isnumber(char *str);
+int highbit64(uint64_t i);
+int lowbit64(uint64_t i);
/*
* Misc utility functions
diff --git a/cmd/zstreamdump/Makefile.am b/cmd/zstreamdump/Makefile.am
index b46958d65..f80b5018e 100644
--- a/cmd/zstreamdump/Makefile.am
+++ b/cmd/zstreamdump/Makefile.am
@@ -11,7 +11,4 @@ zstreamdump_SOURCES = \
zstreamdump_LDADD = \
$(top_builddir)/lib/libnvpair/libnvpair.la \
- $(top_builddir)/lib/libuutil/libuutil.la \
- $(top_builddir)/lib/libzpool/libzpool.la \
- $(top_builddir)/lib/libzfs/libzfs.la \
- $(top_builddir)/lib/libzfs_core/libzfs_core.la
+ $(top_builddir)/lib/libzfs/libzfs.la
diff --git a/cmd/ztest/Makefile.am b/cmd/ztest/Makefile.am
index 5167d0c1d..930a7ec3a 100644
--- a/cmd/ztest/Makefile.am
+++ b/cmd/ztest/Makefile.am
@@ -16,9 +16,8 @@ ztest_SOURCES = \
ztest_LDADD = \
$(top_builddir)/lib/libnvpair/libnvpair.la \
- $(top_builddir)/lib/libuutil/libuutil.la \
- $(top_builddir)/lib/libzpool/libzpool.la \
$(top_builddir)/lib/libzfs/libzfs.la \
- $(top_builddir)/lib/libzfs_core/libzfs_core.la
+ $(top_builddir)/lib/libzpool/libzpool.la
ztest_LDADD += -lm
+ztest_LDFLAGS = -pthread
diff --git a/configure.ac b/configure.ac
index 0c7977ef8..6d0270a7a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -87,6 +87,7 @@ AC_CONFIG_FILES([
lib/libefi/Makefile
lib/libicp/Makefile
lib/libnvpair/Makefile
+ lib/libtpool/Makefile
lib/libunicode/Makefile
lib/libuutil/Makefile
lib/libzpool/Makefile
diff --git a/include/Makefile.am b/include/Makefile.am
index a94cad50d..a5e98bba8 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -19,7 +19,8 @@ USER_H = \
$(top_srcdir)/include/libuutil_impl.h \
$(top_srcdir)/include/libzfs.h \
$(top_srcdir)/include/libzfs_core.h \
- $(top_srcdir)/include/libzfs_impl.h
+ $(top_srcdir)/include/libzfs_impl.h \
+ $(top_srcdir)/include/thread_pool.h
EXTRA_DIST = $(COMMON_H) $(KERNEL_H) $(USER_H)
diff --git a/include/libzfs.h b/include/libzfs.h
index 147589bbf..d60ebbdbd 100644
--- a/include/libzfs.h
+++ b/include/libzfs.h
@@ -368,7 +368,6 @@ typedef enum {
ZPOOL_STATUS_OK
} zpool_status_t;
-extern unsigned long get_system_hostid(void);
extern zpool_status_t zpool_get_status(zpool_handle_t *, char **,
zpool_errata_t *);
extern zpool_status_t zpool_import_status(nvlist_t *, char **,
diff --git a/include/sys/zfs_context.h b/include/sys/zfs_context.h
index 4fe35342d..21a9a8481 100644
--- a/include/sys/zfs_context.h
+++ b/include/sys/zfs_context.h
@@ -668,15 +668,11 @@ extern uint64_t physmem;
extern int highbit64(uint64_t i);
extern int lowbit64(uint64_t i);
-extern int highbit(ulong_t i);
-extern int lowbit(ulong_t i);
extern int random_get_bytes(uint8_t *ptr, size_t len);
extern int random_get_pseudo_bytes(uint8_t *ptr, size_t len);
extern void kernel_init(int);
extern void kernel_fini(void);
-extern void thread_init(void);
-extern void thread_fini(void);
extern void random_init(void);
extern void random_fini(void);
diff --git a/include/thread_pool.h b/include/thread_pool.h
new file mode 100644
index 000000000..57266f11c
--- /dev/null
+++ b/include/thread_pool.h
@@ -0,0 +1,72 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _THREAD_POOL_H_
+#define _THREAD_POOL_H_
+
+#include <sys/types.h>
+#include <thread.h>
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct tpool tpool_t; /* opaque thread pool descriptor */
+
+#if defined(__STDC__)
+
+extern tpool_t *tpool_create(uint_t min_threads, uint_t max_threads,
+ uint_t linger, pthread_attr_t *attr);
+extern int tpool_dispatch(tpool_t *tpool,
+ void (*func)(void *), void *arg);
+extern void tpool_destroy(tpool_t *tpool);
+extern void tpool_abandon(tpool_t *tpool);
+extern void tpool_wait(tpool_t *tpool);
+extern void tpool_suspend(tpool_t *tpool);
+extern int tpool_suspended(tpool_t *tpool);
+extern void tpool_resume(tpool_t *tpool);
+extern int tpool_member(tpool_t *tpool);
+
+#else /* Non ANSI */
+
+extern tpool_t *tpool_create();
+extern int tpool_dispatch();
+extern void tpool_destroy();
+extern void tpool_abandon();
+extern void tpool_wait();
+extern void tpool_suspend();
+extern int tpool_suspended();
+extern void tpool_resume();
+extern int tpool_member();
+
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _THREAD_POOL_H_ */
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 3aec922c9..e1833b842 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,6 +1,6 @@
# NB: GNU Automake Manual, Chapter 8.3.5: Libtool Convenience Libraries
# These six libraries are intermediary build components.
-SUBDIRS = libspl libavl libefi libshare libunicode libicp
+SUBDIRS = libavl libefi libicp libshare libspl libtpool libunicode
# These four libraries, which are installed as the final build product,
# incorporate the six convenience libraries given above.
diff --git a/lib/libnvpair/Makefile.am b/lib/libnvpair/Makefile.am
index 2833557a3..6da679fd5 100644
--- a/lib/libnvpair/Makefile.am
+++ b/lib/libnvpair/Makefile.am
@@ -25,9 +25,7 @@ nodist_libnvpair_la_SOURCES = \
$(USER_C) \
$(KERNEL_C)
-libnvpair_la_LIBADD = \
- $(top_builddir)/lib/libuutil/libuutil.la \
- $(LIBTIRPC)
+libnvpair_la_LIBADD = $(LIBTIRPC)
libnvpair_la_LDFLAGS = -version-info 1:1:0
EXTRA_DIST = $(USER_C)
diff --git a/lib/libspl/Makefile.am b/lib/libspl/Makefile.am
index 3c99529f1..28ae15351 100644
--- a/lib/libspl/Makefile.am
+++ b/lib/libspl/Makefile.am
@@ -19,6 +19,7 @@ noinst_LTLIBRARIES = libspl.la
USER_C = \
getexecname.c \
+ gethostid.c \
gethrtime.c \
gethrestime.c \
getmntany.c \
diff --git a/lib/libspl/gethostid.c b/lib/libspl/gethostid.c
new file mode 100644
index 000000000..1eb93f441
--- /dev/null
+++ b/lib/libspl/gethostid.c
@@ -0,0 +1,86 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2017, Lawrence Livermore National Security, LLC.
+ */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/systeminfo.h>
+
+static unsigned long
+get_spl_hostid(void)
+{
+ FILE *f;
+ unsigned long hostid;
+ char *env;
+
+ /*
+ * Allow the hostid to be subverted for testing.
+ */
+ env = getenv("ZFS_HOSTID");
+ if (env) {
+ hostid = strtoull(env, NULL, 0);
+ return (hostid & HOSTID_MASK);
+ }
+
+ f = fopen("/sys/module/spl/parameters/spl_hostid", "r");
+ if (!f)
+ return (0);
+
+ if (fscanf(f, "%lu", &hostid) != 1)
+ hostid = 0;
+
+ fclose(f);
+
+ return (hostid & HOSTID_MASK);
+}
+
+unsigned long
+get_system_hostid(void)
+{
+ unsigned long system_hostid = get_spl_hostid();
+ /*
+ * We do not use the library call gethostid() because
+ * it generates a hostid value that the kernel is
+ * unaware of, if the spl_hostid module parameter has not
+ * been set and there is no system hostid file (e.g.
+ * /etc/hostid). The kernel and userspace must agree.
+ * See comments above hostid_read() in the SPL.
+ */
+ if (system_hostid == 0) {
+ int fd, rc;
+ unsigned long hostid;
+ int hostid_size = 4; /* 4 bytes regardless of arch */
+
+ fd = open("/etc/hostid", O_RDONLY);
+ if (fd >= 0) {
+ rc = read(fd, &hostid, hostid_size);
+ if (rc > 0)
+ system_hostid = (hostid & HOSTID_MASK);
+ close(fd);
+ }
+ }
+ return (system_hostid);
+}
diff --git a/lib/libspl/include/sys/systeminfo.h b/lib/libspl/include/sys/systeminfo.h
index 3f7cef5b9..cc6c1793c 100644
--- a/lib/libspl/include/sys/systeminfo.h
+++ b/lib/libspl/include/sys/systeminfo.h
@@ -27,11 +27,12 @@
#ifndef _LIBSPL_SYS_SYSTEMINFO_H
#define _LIBSPL_SYS_SYSTEMINFO_H
+#define HOSTID_MASK 0xFFFFFFFF
#define HW_INVALID_HOSTID 0xFFFFFFFF /* an invalid hostid */
#define HW_HOSTID_LEN 11 /* minimum buffer size needed */
/* to hold a decimal or hex */
/* hostid string */
-#define sysinfo(cmd, buf, cnt) (-1)
+unsigned long get_system_hostid(void);
#endif
diff --git a/lib/libtpool/Makefile.am b/lib/libtpool/Makefile.am
new file mode 100644
index 000000000..adbaee6c3
--- /dev/null
+++ b/lib/libtpool/Makefile.am
@@ -0,0 +1,26 @@
+include $(top_srcdir)/config/Rules.am
+
+AM_CFLAGS += $(DEBUG_STACKFLAGS)
+
+DEFAULT_INCLUDES += \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/libspl/include
+
+noinst_LTLIBRARIES = libtpool.la
+
+USER_C = \
+ thread_pool.c \
+ thread_pool_impl.h
+
+KERNEL_C =
+
+nodist_libtpool_la_SOURCES = \
+ $(USER_C) \
+ $(KERNEL_C)
+
+libtpool_la_LIBADD = \
+ $(top_builddir)/lib/libspl/libspl.la
+
+libtpool_la_LDFLAGS = -pthread
+
+EXTRA_DIST = $(USER_C)
diff --git a/lib/libtpool/thread_pool.c b/lib/libtpool/thread_pool.c
new file mode 100644
index 000000000..166ce3e67
--- /dev/null
+++ b/lib/libtpool/thread_pool.c
@@ -0,0 +1,650 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include <assert.h>
+#include "thread_pool_impl.h"
+
+static pthread_mutex_t thread_pool_lock = PTHREAD_MUTEX_INITIALIZER;
+static tpool_t *thread_pools = NULL;
+
+static void
+delete_pool(tpool_t *tpool)
+{
+ tpool_job_t *job;
+
+ ASSERT(tpool->tp_current == 0 && tpool->tp_active == NULL);
+
+ /*
+ * Unlink the pool from the global list of all pools.
+ */
+ (void) pthread_mutex_lock(&thread_pool_lock);
+ if (thread_pools == tpool)
+ thread_pools = tpool->tp_forw;
+ if (thread_pools == tpool)
+ thread_pools = NULL;
+ else {
+ tpool->tp_back->tp_forw = tpool->tp_forw;
+ tpool->tp_forw->tp_back = tpool->tp_back;
+ }
+ pthread_mutex_unlock(&thread_pool_lock);
+
+ /*
+ * There should be no pending jobs, but just in case...
+ */
+ for (job = tpool->tp_head; job != NULL; job = tpool->tp_head) {
+ tpool->tp_head = job->tpj_next;
+ free(job);
+ }
+ (void) pthread_attr_destroy(&tpool->tp_attr);
+ free(tpool);
+}
+
+/*
+ * Worker thread is terminating.
+ */
+static void
+worker_cleanup(void *arg)
+{
+ tpool_t *tpool = (tpool_t *)arg;
+
+ if (--tpool->tp_current == 0 &&
+ (tpool->tp_flags & (TP_DESTROY | TP_ABANDON))) {
+ if (tpool->tp_flags & TP_ABANDON) {
+ pthread_mutex_unlock(&tpool->tp_mutex);
+ delete_pool(tpool);
+ return;
+ }
+ if (tpool->tp_flags & TP_DESTROY)
+ (void) pthread_cond_broadcast(&tpool->tp_busycv);
+ }
+ pthread_mutex_unlock(&tpool->tp_mutex);
+}
+
+static void
+notify_waiters(tpool_t *tpool)
+{
+ if (tpool->tp_head == NULL && tpool->tp_active == NULL) {
+ tpool->tp_flags &= ~TP_WAIT;
+ (void) pthread_cond_broadcast(&tpool->tp_waitcv);
+ }
+}
+
+/*
+ * Called by a worker thread on return from a tpool_dispatch()d job.
+ */
+static void
+job_cleanup(void *arg)
+{
+ tpool_t *tpool = (tpool_t *)arg;
+
+ pthread_t my_tid = pthread_self();
+ tpool_active_t *activep;
+ tpool_active_t **activepp;
+
+ pthread_mutex_lock(&tpool->tp_mutex);
+ /* CSTYLED */
+ for (activepp = &tpool->tp_active;; activepp = &activep->tpa_next) {
+ activep = *activepp;
+ if (activep->tpa_tid == my_tid) {
+ *activepp = activep->tpa_next;
+ break;
+ }
+ }
+ if (tpool->tp_flags & TP_WAIT)
+ notify_waiters(tpool);
+}
+
+static void *
+tpool_worker(void *arg)
+{
+ tpool_t *tpool = (tpool_t *)arg;
+ int elapsed;
+ tpool_job_t *job;
+ void (*func)(void *);
+ tpool_active_t active;
+
+ pthread_mutex_lock(&tpool->tp_mutex);
+ pthread_cleanup_push(worker_cleanup, tpool);
+
+ /*
+ * This is the worker's main loop.
+ * It will only be left if a timeout or an error has occured.
+ */
+ active.tpa_tid = pthread_self();
+ for (;;) {
+ elapsed = 0;
+ tpool->tp_idle++;
+ if (tpool->tp_flags & TP_WAIT)
+ notify_waiters(tpool);
+ while ((tpool->tp_head == NULL ||
+ (tpool->tp_flags & TP_SUSPEND)) &&
+ !(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))) {
+ if (tpool->tp_current <= tpool->tp_minimum ||
+ tpool->tp_linger == 0) {
+ (void) pthread_cond_wait(&tpool->tp_workcv,
+ &tpool->tp_mutex);
+ } else {
+ struct timespec ts;
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += tpool->tp_linger;
+
+ if (pthread_cond_timedwait(&tpool->tp_workcv,
+ &tpool->tp_mutex, &ts) != 0) {
+ elapsed = 1;
+ break;
+ }
+ }
+ }
+ tpool->tp_idle--;
+ if (tpool->tp_flags & TP_DESTROY)
+ break;
+ if (tpool->tp_flags & TP_ABANDON) {
+ /* can't abandon a suspended pool */
+ if (tpool->tp_flags & TP_SUSPEND) {
+ tpool->tp_flags &= ~TP_SUSPEND;
+ (void) pthread_cond_broadcast(
+ &tpool->tp_workcv);
+ }
+ if (tpool->tp_head == NULL)
+ break;
+ }
+ if ((job = tpool->tp_head) != NULL &&
+ !(tpool->tp_flags & TP_SUSPEND)) {
+ elapsed = 0;
+ func = job->tpj_func;
+ arg = job->tpj_arg;
+ tpool->tp_head = job->tpj_next;
+ if (job == tpool->tp_tail)
+ tpool->tp_tail = NULL;
+ tpool->tp_njobs--;
+ active.tpa_next = tpool->tp_active;
+ tpool->tp_active = &active;
+ pthread_mutex_unlock(&tpool->tp_mutex);
+ pthread_cleanup_push(job_cleanup, tpool);
+ free(job);
+
+ sigset_t maskset;
+ (void) pthread_sigmask(SIG_SETMASK, NULL, &maskset);
+
+ /*
+ * Call the specified function.
+ */
+ func(arg);
+ /*
+ * We don't know what this thread has been doing,
+ * so we reset its signal mask and cancellation
+ * state back to the values prior to calling func().
+ */
+ (void) pthread_sigmask(SIG_SETMASK, &maskset, NULL);
+ (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,
+ NULL);
+ (void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,
+ NULL);
+ pthread_cleanup_pop(1);
+ }
+ if (elapsed && tpool->tp_current > tpool->tp_minimum) {
+ /*
+ * We timed out and there is no work to be done
+ * and the number of workers exceeds the minimum.
+ * Exit now to reduce the size of the pool.
+ */
+ break;
+ }
+ }
+ pthread_cleanup_pop(1);
+ return (arg);
+}
+
+/*
+ * Create a worker thread, with default signals blocked.
+ */
+static int
+create_worker(tpool_t *tpool)
+{
+ pthread_t thread;
+ sigset_t oset;
+ int error;
+
+ (void) pthread_sigmask(SIG_SETMASK, NULL, &oset);
+ error = pthread_create(&thread, &tpool->tp_attr, tpool_worker, tpool);
+ (void) pthread_sigmask(SIG_SETMASK, &oset, NULL);
+ return (error);
+}
+
+
+/*
+ * pthread_attr_clone: make a copy of a pthread_attr_t. When old_attr
+ * is NULL initialize the cloned attr using default values.
+ */
+static int
+pthread_attr_clone(pthread_attr_t *attr, const pthread_attr_t *old_attr)
+{
+ int error;
+
+ error = pthread_attr_init(attr);
+ if (error || (old_attr == NULL))
+ return (error);
+
+ cpu_set_t cpuset;
+ size_t cpusetsize = sizeof (cpuset);
+ error = pthread_attr_getaffinity_np(old_attr, cpusetsize, &cpuset);
+ if (error == 0)
+ error = pthread_attr_setaffinity_np(attr, cpusetsize, &cpuset);
+ if (error)
+ goto error;
+
+ int detachstate;
+ error = pthread_attr_getdetachstate(old_attr, &detachstate);
+ if (error == 0)
+ error = pthread_attr_setdetachstate(attr, detachstate);
+ if (error)
+ goto error;
+
+ size_t guardsize;
+ error = pthread_attr_getguardsize(old_attr, &guardsize);
+ if (error == 0)
+ error = pthread_attr_setguardsize(attr, guardsize);
+ if (error)
+ goto error;
+
+ int inheritsched;
+ error = pthread_attr_getinheritsched(old_attr, &inheritsched);
+ if (error == 0)
+ error = pthread_attr_setinheritsched(attr, inheritsched);
+ if (error)
+ goto error;
+
+ struct sched_param param;
+ error = pthread_attr_getschedparam(old_attr, &param);
+ if (error == 0)
+ error = pthread_attr_setschedparam(attr, &param);
+ if (error)
+ goto error;
+
+ int policy;
+ error = pthread_attr_getschedpolicy(old_attr, &policy);
+ if (error == 0)
+ error = pthread_attr_setschedpolicy(attr, policy);
+ if (error)
+ goto error;
+
+ int scope;
+ error = pthread_attr_getscope(old_attr, &scope);
+ if (error == 0)
+ error = pthread_attr_setscope(attr, scope);
+ if (error)
+ goto error;
+
+ void *stackaddr;
+ size_t stacksize;
+ error = pthread_attr_getstack(old_attr, &stackaddr, &stacksize);
+ if (error == 0)
+ error = pthread_attr_setstack(attr, stackaddr, stacksize);
+ if (error)
+ goto error;
+
+ return (0);
+error:
+ pthread_attr_destroy(attr);
+ return (error);
+}
+
+tpool_t *
+tpool_create(uint_t min_threads, uint_t max_threads, uint_t linger,
+ pthread_attr_t *attr)
+{
+ tpool_t *tpool;
+ void *stackaddr;
+ size_t stacksize;
+ size_t minstack;
+ int error;
+
+ if (min_threads > max_threads || max_threads < 1) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (attr != NULL) {
+ if (pthread_attr_getstack(attr, &stackaddr, &stacksize) != 0) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ /*
+ * Allow only one thread in the pool with a specified stack.
+ * Require threads to have at least the minimum stack size.
+ */
+ minstack = PTHREAD_STACK_MIN;
+ if (stackaddr != NULL) {
+ if (stacksize < minstack || max_threads != 1) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ } else if (stacksize != 0 && stacksize < minstack) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ }
+
+ tpool = calloc(1, sizeof (*tpool));
+ if (tpool == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ (void) pthread_mutex_init(&tpool->tp_mutex, NULL);
+ (void) pthread_cond_init(&tpool->tp_busycv, NULL);
+ (void) pthread_cond_init(&tpool->tp_workcv, NULL);
+ (void) pthread_cond_init(&tpool->tp_waitcv, NULL);
+ tpool->tp_minimum = min_threads;
+ tpool->tp_maximum = max_threads;
+ tpool->tp_linger = linger;
+
+ /*
+ * We cannot just copy the attribute pointer.
+ * We need to initialize a new pthread_attr_t structure
+ * with the values from the user-supplied pthread_attr_t.
+ * If the attribute pointer is NULL, we need to initialize
+ * the new pthread_attr_t structure with default values.
+ */
+ error = pthread_attr_clone(&tpool->tp_attr, attr);
+ if (error) {
+ free(tpool);
+ errno = error;
+ return (NULL);
+ }
+
+ /* make all pool threads be detached daemon threads */
+ (void) pthread_attr_setdetachstate(&tpool->tp_attr,
+ PTHREAD_CREATE_DETACHED);
+
+ /* insert into the global list of all thread pools */
+ pthread_mutex_lock(&thread_pool_lock);
+ if (thread_pools == NULL) {
+ tpool->tp_forw = tpool;
+ tpool->tp_back = tpool;
+ thread_pools = tpool;
+ } else {
+ thread_pools->tp_back->tp_forw = tpool;
+ tpool->tp_forw = thread_pools;
+ tpool->tp_back = thread_pools->tp_back;
+ thread_pools->tp_back = tpool;
+ }
+ pthread_mutex_unlock(&thread_pool_lock);
+
+ return (tpool);
+}
+
+/*
+ * Dispatch a work request to the thread pool.
+ * If there are idle workers, awaken one.
+ * Else, if the maximum number of workers has
+ * not been reached, spawn a new worker thread.
+ * Else just return with the job added to the queue.
+ */
+int
+tpool_dispatch(tpool_t *tpool, void (*func)(void *), void *arg)
+{
+ tpool_job_t *job;
+
+ ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON)));
+
+ if ((job = calloc(1, sizeof (*job))) == NULL)
+ return (-1);
+ job->tpj_next = NULL;
+ job->tpj_func = func;
+ job->tpj_arg = arg;
+
+ pthread_mutex_lock(&tpool->tp_mutex);
+
+ if (tpool->tp_head == NULL)
+ tpool->tp_head = job;
+ else
+ tpool->tp_tail->tpj_next = job;
+ tpool->tp_tail = job;
+ tpool->tp_njobs++;
+
+ if (!(tpool->tp_flags & TP_SUSPEND)) {
+ if (tpool->tp_idle > 0)
+ (void) pthread_cond_signal(&tpool->tp_workcv);
+ else if (tpool->tp_current < tpool->tp_maximum &&
+ create_worker(tpool) == 0)
+ tpool->tp_current++;
+ }
+
+ pthread_mutex_unlock(&tpool->tp_mutex);
+ return (0);
+}
+
+static void
+tpool_cleanup(void *arg)
+{
+ tpool_t *tpool = (tpool_t *)arg;
+
+ pthread_mutex_unlock(&tpool->tp_mutex);
+}
+
+/*
+ * Assumes: by the time tpool_destroy() is called no one will use this
+ * thread pool in any way and no one will try to dispatch entries to it.
+ * Calling tpool_destroy() from a job in the pool will cause deadlock.
+ */
+void
+tpool_destroy(tpool_t *tpool)
+{
+ tpool_active_t *activep;
+
+ ASSERT(!tpool_member(tpool));
+ ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON)));
+
+ pthread_mutex_lock(&tpool->tp_mutex);
+ pthread_cleanup_push(tpool_cleanup, tpool);
+
+ /* mark the pool as being destroyed; wakeup idle workers */
+ tpool->tp_flags |= TP_DESTROY;
+ tpool->tp_flags &= ~TP_SUSPEND;
+ (void) pthread_cond_broadcast(&tpool->tp_workcv);
+
+ /* cancel all active workers */
+ for (activep = tpool->tp_active; activep; activep = activep->tpa_next)
+ (void) pthread_cancel(activep->tpa_tid);
+
+ /* wait for all active workers to finish */
+ while (tpool->tp_active != NULL) {
+ tpool->tp_flags |= TP_WAIT;
+ (void) pthread_cond_wait(&tpool->tp_waitcv, &tpool->tp_mutex);
+ }
+
+ /* the last worker to terminate will wake us up */
+ while (tpool->tp_current != 0)
+ (void) pthread_cond_wait(&tpool->tp_busycv, &tpool->tp_mutex);
+
+ pthread_cleanup_pop(1); /* pthread_mutex_unlock(&tpool->tp_mutex); */
+ delete_pool(tpool);
+}
+
+/*
+ * Like tpool_destroy(), but don't cancel workers or wait for them to finish.
+ * The last worker to terminate will delete the pool.
+ */
+void
+tpool_abandon(tpool_t *tpool)
+{
+ ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON)));
+
+ pthread_mutex_lock(&tpool->tp_mutex);
+ if (tpool->tp_current == 0) {
+ /* no workers, just delete the pool */
+ pthread_mutex_unlock(&tpool->tp_mutex);
+ delete_pool(tpool);
+ } else {
+ /* wake up all workers, last one will delete the pool */
+ tpool->tp_flags |= TP_ABANDON;
+ tpool->tp_flags &= ~TP_SUSPEND;
+ (void) pthread_cond_broadcast(&tpool->tp_workcv);
+ pthread_mutex_unlock(&tpool->tp_mutex);
+ }
+}
+
+/*
+ * Wait for all jobs to complete.
+ * Calling tpool_wait() from a job in the pool will cause deadlock.
+ */
+void
+tpool_wait(tpool_t *tpool)
+{
+ ASSERT(!tpool_member(tpool));
+ ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON)));
+
+ pthread_mutex_lock(&tpool->tp_mutex);
+ pthread_cleanup_push(tpool_cleanup, tpool);
+ while (tpool->tp_head != NULL || tpool->tp_active != NULL) {
+ tpool->tp_flags |= TP_WAIT;
+ (void) pthread_cond_wait(&tpool->tp_waitcv, &tpool->tp_mutex);
+ ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON)));
+ }
+ pthread_cleanup_pop(1); /* pthread_mutex_unlock(&tpool->tp_mutex); */
+}
+
+void
+tpool_suspend(tpool_t *tpool)
+{
+ ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON)));
+
+ pthread_mutex_lock(&tpool->tp_mutex);
+ tpool->tp_flags |= TP_SUSPEND;
+ pthread_mutex_unlock(&tpool->tp_mutex);
+}
+
+int
+tpool_suspended(tpool_t *tpool)
+{
+ int suspended;
+
+ ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON)));
+
+ pthread_mutex_lock(&tpool->tp_mutex);
+ suspended = (tpool->tp_flags & TP_SUSPEND) != 0;
+ pthread_mutex_unlock(&tpool->tp_mutex);
+
+ return (suspended);
+}
+
+void
+tpool_resume(tpool_t *tpool)
+{
+ int excess;
+
+ ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON)));
+
+ pthread_mutex_lock(&tpool->tp_mutex);
+ if (!(tpool->tp_flags & TP_SUSPEND)) {
+ pthread_mutex_unlock(&tpool->tp_mutex);
+ return;
+ }
+ tpool->tp_flags &= ~TP_SUSPEND;
+ (void) pthread_cond_broadcast(&tpool->tp_workcv);
+ excess = tpool->tp_njobs - tpool->tp_idle;
+ while (excess-- > 0 && tpool->tp_current < tpool->tp_maximum) {
+ if (create_worker(tpool) != 0)
+ break; /* pthread_create() failed */
+ tpool->tp_current++;
+ }
+ pthread_mutex_unlock(&tpool->tp_mutex);
+}
+
+int
+tpool_member(tpool_t *tpool)
+{
+ pthread_t my_tid = pthread_self();
+ tpool_active_t *activep;
+
+ ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON)));
+
+ pthread_mutex_lock(&tpool->tp_mutex);
+ for (activep = tpool->tp_active; activep; activep = activep->tpa_next) {
+ if (activep->tpa_tid == my_tid) {
+ pthread_mutex_unlock(&tpool->tp_mutex);
+ return (1);
+ }
+ }
+ pthread_mutex_unlock(&tpool->tp_mutex);
+ return (0);
+}
+
+void
+postfork1_child_tpool(void)
+{
+ pthread_t my_tid = pthread_self();
+ tpool_t *tpool;
+ tpool_job_t *job;
+
+ /*
+ * All of the thread pool workers are gone, except possibly
+ * for the current thread, if it is a thread pool worker thread.
+ * Retain the thread pools, but make them all empty. Whatever
+ * jobs were queued or running belong to the parent process.
+ */
+top:
+ if ((tpool = thread_pools) == NULL)
+ return;
+
+ do {
+ tpool_active_t *activep;
+
+ (void) pthread_mutex_init(&tpool->tp_mutex, NULL);
+ (void) pthread_cond_init(&tpool->tp_busycv, NULL);
+ (void) pthread_cond_init(&tpool->tp_workcv, NULL);
+ (void) pthread_cond_init(&tpool->tp_waitcv, NULL);
+ for (job = tpool->tp_head; job; job = tpool->tp_head) {
+ tpool->tp_head = job->tpj_next;
+ free(job);
+ }
+ tpool->tp_tail = NULL;
+ tpool->tp_njobs = 0;
+ for (activep = tpool->tp_active; activep;
+ activep = activep->tpa_next) {
+ if (activep->tpa_tid == my_tid) {
+ activep->tpa_next = NULL;
+ break;
+ }
+ }
+ tpool->tp_idle = 0;
+ tpool->tp_current = 0;
+ if ((tpool->tp_active = activep) != NULL)
+ tpool->tp_current = 1;
+ tpool->tp_flags &= ~TP_WAIT;
+ if (tpool->tp_flags & (TP_DESTROY | TP_ABANDON)) {
+ tpool->tp_flags &= ~TP_DESTROY;
+ tpool->tp_flags |= TP_ABANDON;
+ if (tpool->tp_current == 0) {
+ delete_pool(tpool);
+ goto top; /* start over */
+ }
+ }
+ } while ((tpool = tpool->tp_forw) != thread_pools);
+}
diff --git a/lib/libtpool/thread_pool_impl.h b/lib/libtpool/thread_pool_impl.h
new file mode 100644
index 000000000..5349c2ade
--- /dev/null
+++ b/lib/libtpool/thread_pool_impl.h
@@ -0,0 +1,93 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _THREAD_POOL_IMPL_H
+#define _THREAD_POOL_IMPL_H
+
+#include <thread_pool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Thread pool implementation definitions.
+ * See <thread_pool.h> for interface declarations.
+ */
+
+/*
+ * FIFO queued job
+ */
+typedef struct tpool_job tpool_job_t;
+struct tpool_job {
+ tpool_job_t *tpj_next; /* list of jobs */
+ void (*tpj_func)(void *); /* function to call */
+ void *tpj_arg; /* its argument */
+};
+
+/*
+ * List of active threads, linked through their stacks.
+ */
+typedef struct tpool_active tpool_active_t;
+struct tpool_active {
+ tpool_active_t *tpa_next; /* list of active threads */
+ pthread_t tpa_tid; /* active thread id */
+};
+
+/*
+ * The thread pool.
+ */
+struct tpool {
+ tpool_t *tp_forw; /* circular list of all thread pools */
+ tpool_t *tp_back;
+ pthread_mutex_t tp_mutex; /* protects the pool data */
+ pthread_cond_t tp_busycv; /* synchronization in tpool_dispatch */
+ pthread_cond_t tp_workcv; /* synchronization with workers */
+ pthread_cond_t tp_waitcv; /* synchronization in tpool_wait() */
+ tpool_active_t *tp_active; /* threads performing work */
+ tpool_job_t *tp_head; /* FIFO job queue */
+ tpool_job_t *tp_tail;
+ pthread_attr_t tp_attr; /* attributes of the workers */
+ int tp_flags; /* see below */
+ uint_t tp_linger; /* seconds before idle workers exit */
+ int tp_njobs; /* number of jobs in job queue */
+ int tp_minimum; /* minimum number of worker threads */
+ int tp_maximum; /* maximum number of worker threads */
+ int tp_current; /* current number of worker threads */
+ int tp_idle; /* number of idle workers */
+};
+
+/* tp_flags */
+#define TP_WAIT 0x01 /* waiting in tpool_wait() */
+#define TP_SUSPEND 0x02 /* pool is being suspended */
+#define TP_DESTROY 0x04 /* pool is being destroyed */
+#define TP_ABANDON 0x08 /* pool is abandoned (auto-destroy) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _THREAD_POOL_IMPL_H */
diff --git a/lib/libuutil/Makefile.am b/lib/libuutil/Makefile.am
index 4d54485b7..c2659b619 100644
--- a/lib/libuutil/Makefile.am
+++ b/lib/libuutil/Makefile.am
@@ -28,8 +28,7 @@ nodist_libuutil_la_SOURCES = \
libuutil_la_LIBADD = \
$(top_builddir)/lib/libavl/libavl.la \
- $(top_builddir)/lib/libspl/libspl.la \
- $(top_builddir)/lib/libefi/libefi.la
+ $(top_builddir)/lib/libspl/libspl.la
libuutil_la_LDFLAGS = -pthread -version-info 1:1:0
diff --git a/lib/libzfs/Makefile.am b/lib/libzfs/Makefile.am
index f1260ea71..7ab8658e4 100644
--- a/lib/libzfs/Makefile.am
+++ b/lib/libzfs/Makefile.am
@@ -1,10 +1,16 @@
include $(top_srcdir)/config/Rules.am
+VPATH = \
+ $(top_srcdir)/module/icp \
+ $(top_srcdir)/module/zcommon \
+ $(top_srcdir)/lib/libzfs
+
libzfs_pcdir = $(datarootdir)/pkgconfig
libzfs_pc_DATA = libzfs.pc libzfs_core.pc
DEFAULT_INCLUDES += \
-I$(top_srcdir)/include \
+ -I$(top_srcdir)/module/icp/include \
-I$(top_srcdir)/lib/libspl/include
lib_LTLIBRARIES = libzfs.la
@@ -23,17 +29,35 @@ USER_C = \
libzfs_status.c \
libzfs_util.c
-KERNEL_C =
+KERNEL_C = \
+ algs/sha2/sha2.c \
+ zfeature_common.c \
+ zfs_comutil.c \
+ zfs_deleg.c \
+ zfs_fletcher.c \
+ zfs_fletcher_aarch64_neon.c \
+ zfs_fletcher_avx512.c \
+ zfs_fletcher_intel.c \
+ zfs_fletcher_sse.c \
+ zfs_fletcher_superscalar.c \
+ zfs_fletcher_superscalar4.c \
+ zfs_namecheck.c \
+ zfs_prop.c \
+ zfs_uio.c \
+ zpool_prop.c \
+ zprop_common.c
nodist_libzfs_la_SOURCES = \
$(USER_C) \
$(KERNEL_C)
libzfs_la_LIBADD = \
- $(top_builddir)/lib/libzfs_core/libzfs_core.la \
- $(top_builddir)/lib/libshare/libshare.la \
+ $(top_builddir)/lib/libefi/libefi.la \
$(top_builddir)/lib/libnvpair/libnvpair.la \
- $(top_builddir)/lib/libzpool/libzpool.la
+ $(top_builddir)/lib/libshare/libshare.la \
+ $(top_builddir)/lib/libtpool/libtpool.la \
+ $(top_builddir)/lib/libuutil/libuutil.la \
+ $(top_builddir)/lib/libzfs_core/libzfs_core.la
libzfs_la_LIBADD += -lm $(LIBBLKID) $(LIBUDEV)
libzfs_la_LDFLAGS = -version-info 2:0:0
diff --git a/lib/libzfs/libzfs_import.c b/lib/libzfs/libzfs_import.c
index f371d925b..833568356 100644
--- a/lib/libzfs/libzfs_import.c
+++ b/lib/libzfs/libzfs_import.c
@@ -60,6 +60,7 @@
#include <sys/vtoc.h>
#include <sys/dktp/fdisk.h>
#include <sys/efi_partition.h>
+#include <thread_pool.h>
#include <sys/vdev_impl.h>
#include <blkid/blkid.h>
#include "libzfs.h"
@@ -1388,7 +1389,7 @@ typedef struct rdsk_node {
nvlist_t *rn_config; /* Label config */
avl_tree_t *rn_avl;
avl_node_t rn_node;
- kmutex_t *rn_lock;
+ pthread_mutex_t *rn_lock;
boolean_t rn_labelpaths;
} rdsk_node_t;
@@ -1603,14 +1604,14 @@ zpool_open_func(void *arg)
slice->rn_hdl = hdl;
slice->rn_order = IMPORT_ORDER_PREFERRED_1;
slice->rn_labelpaths = B_FALSE;
- mutex_enter(rn->rn_lock);
+ pthread_mutex_lock(rn->rn_lock);
if (avl_find(rn->rn_avl, slice, &where)) {
- mutex_exit(rn->rn_lock);
+ pthread_mutex_unlock(rn->rn_lock);
free(slice->rn_name);
free(slice);
} else {
avl_insert(rn->rn_avl, slice, where);
- mutex_exit(rn->rn_lock);
+ pthread_mutex_unlock(rn->rn_lock);
zpool_open_func(slice);
}
}
@@ -1629,14 +1630,14 @@ zpool_open_func(void *arg)
slice->rn_hdl = hdl;
slice->rn_order = IMPORT_ORDER_PREFERRED_2;
slice->rn_labelpaths = B_FALSE;
- mutex_enter(rn->rn_lock);
+ pthread_mutex_lock(rn->rn_lock);
if (avl_find(rn->rn_avl, slice, &where)) {
- mutex_exit(rn->rn_lock);
+ pthread_mutex_unlock(rn->rn_lock);
free(slice->rn_name);
free(slice);
} else {
avl_insert(rn->rn_avl, slice, where);
- mutex_exit(rn->rn_lock);
+ pthread_mutex_unlock(rn->rn_lock);
zpool_open_func(slice);
}
}
@@ -1679,7 +1680,7 @@ zpool_clear_label(int fd)
* Scan a list of directories for zfs devices.
*/
static int
-zpool_find_import_scan(libzfs_handle_t *hdl, kmutex_t *lock,
+zpool_find_import_scan(libzfs_handle_t *hdl, pthread_mutex_t *lock,
avl_tree_t **slice_cache, char **dir, int dirs)
{
avl_tree_t *cache;
@@ -1735,9 +1736,9 @@ zpool_find_import_scan(libzfs_handle_t *hdl, kmutex_t *lock,
slice->rn_hdl = hdl;
slice->rn_order = i + IMPORT_ORDER_SCAN_OFFSET;
slice->rn_labelpaths = B_FALSE;
- mutex_enter(lock);
+ pthread_mutex_lock(lock);
avl_add(cache, slice);
- mutex_exit(lock);
+ pthread_mutex_unlock(lock);
}
(void) closedir(dirp);
@@ -1761,7 +1762,7 @@ error:
* Use libblkid to quickly enumerate all known zfs devices.
*/
static int
-zpool_find_import_blkid(libzfs_handle_t *hdl, kmutex_t *lock,
+zpool_find_import_blkid(libzfs_handle_t *hdl, pthread_mutex_t *lock,
avl_tree_t **slice_cache)
{
rdsk_node_t *slice;
@@ -1815,14 +1816,14 @@ zpool_find_import_blkid(libzfs_handle_t *hdl, kmutex_t *lock,
else
slice->rn_order = IMPORT_ORDER_DEFAULT;
- mutex_enter(lock);
+ pthread_mutex_lock(lock);
if (avl_find(*slice_cache, slice, &where)) {
free(slice->rn_name);
free(slice);
} else {
avl_insert(*slice_cache, slice, where);
}
- mutex_exit(lock);
+ pthread_mutex_unlock(lock);
}
blkid_dev_iterate_end(iter);
@@ -1860,14 +1861,14 @@ zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg)
vdev_entry_t *ve, *venext;
config_entry_t *ce, *cenext;
name_entry_t *ne, *nenext;
- kmutex_t lock;
+ pthread_mutex_t lock;
avl_tree_t *cache;
rdsk_node_t *slice;
void *cookie;
- taskq_t *t;
+ tpool_t *t;
verify(iarg->poolname == NULL || iarg->guid == 0);
- mutex_init(&lock, NULL, MUTEX_DEFAULT, NULL);
+ pthread_mutex_init(&lock, NULL);
/*
* Locate pool member vdevs using libblkid or by directory scanning.
@@ -1896,15 +1897,13 @@ zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg)
* validating labels, a large number of threads can be used due to
* minimal contention.
*/
- t = taskq_create("z_import", 2 * boot_ncpus, defclsyspri,
- 2 * boot_ncpus, INT_MAX, TASKQ_PREPOPULATE);
-
+ t = tpool_create(1, 2 * sysconf(_SC_NPROCESSORS_ONLN), 0, NULL);
for (slice = avl_first(cache); slice;
(slice = avl_walk(cache, slice, AVL_AFTER)))
- (void) taskq_dispatch(t, zpool_open_func, slice, TQ_SLEEP);
+ (void) tpool_dispatch(t, zpool_open_func, slice);
- taskq_wait(t);
- taskq_destroy(t);
+ tpool_wait(t);
+ tpool_destroy(t);
/*
* Process the cache filtering out any entries which are not
@@ -1974,7 +1973,7 @@ zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg)
}
avl_destroy(cache);
free(cache);
- mutex_destroy(&lock);
+ pthread_mutex_destroy(&lock);
ret = get_configs(hdl, &pools, iarg->can_be_active);
diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c
index 73af75f9d..d3363809d 100644
--- a/lib/libzfs/libzfs_pool.c
+++ b/lib/libzfs/libzfs_pool.c
@@ -40,6 +40,7 @@
#include <zone.h>
#include <sys/stat.h>
#include <sys/efi_partition.h>
+#include <sys/systeminfo.h>
#include <sys/vtoc.h>
#include <sys/zfs_ioctl.h>
#include <dlfcn.h>
diff --git a/lib/libzfs/libzfs_status.c b/lib/libzfs/libzfs_status.c
index 05a9afce8..ccc472153 100644
--- a/lib/libzfs/libzfs_status.c
+++ b/lib/libzfs/libzfs_status.c
@@ -44,6 +44,7 @@
#include <libzfs.h>
#include <string.h>
#include <unistd.h>
+#include <sys/systeminfo.h>
#include "libzfs_impl.h"
#include "zfeature_common.h"
diff --git a/lib/libzpool/Makefile.am b/lib/libzpool/Makefile.am
index a8c72c98d..aed8868ae 100644
--- a/lib/libzpool/Makefile.am
+++ b/lib/libzpool/Makefile.am
@@ -19,13 +19,14 @@ USER_C = \
util.c
KERNEL_C = \
+ zfeature_common.c \
zfs_comutil.c \
zfs_deleg.c \
zfs_fletcher.c \
+ zfs_fletcher_aarch64_neon.c \
+ zfs_fletcher_avx512.c \
zfs_fletcher_intel.c \
zfs_fletcher_sse.c \
- zfs_fletcher_avx512.c \
- zfs_fletcher_aarch64_neon.c \
zfs_fletcher_superscalar.c \
zfs_fletcher_superscalar4.c \
zfs_namecheck.c \
@@ -115,13 +116,13 @@ KERNEL_C = \
zap_leaf.c \
zap_micro.c \
zfeature.c \
- zfeature_common.c \
zfs_byteswap.c \
zfs_debug.c \
zfs_fm.c \
zfs_fuid.c \
zfs_sa.c \
zfs_znode.c \
+ zfs_ratelimit.c \
zfs_rlock.c \
zil.c \
zio.c \
@@ -136,12 +137,13 @@ nodist_libzpool_la_SOURCES = \
$(KERNEL_C)
libzpool_la_LIBADD = \
- $(top_builddir)/lib/libunicode/libunicode.la \
- $(top_builddir)/lib/libuutil/libuutil.la \
+ $(top_builddir)/lib/libavl/libavl.la \
+ $(top_builddir)/lib/libicp/libicp.la \
$(top_builddir)/lib/libnvpair/libnvpair.la \
- $(top_builddir)/lib/libicp/libicp.la
+ $(top_builddir)/lib/libspl/libspl.la \
+ $(top_builddir)/lib/libunicode/libunicode.la
libzpool_la_LIBADD += $(ZLIB) -ldl
-libzpool_la_LDFLAGS = -version-info 2:0:0
+libzpool_la_LDFLAGS = -pthread -version-info 2:0:0
EXTRA_DIST = $(USER_C)
diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c
index e67d13c92..3fc7337e8 100644
--- a/lib/libzpool/kernel.c
+++ b/lib/libzpool/kernel.c
@@ -71,7 +71,7 @@ pthread_mutex_t kthread_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_key_t kthread_key;
int kthread_nr = 0;
-void
+static void
thread_init(void)
{
kthread_t *kt;
@@ -90,7 +90,7 @@ thread_init(void)
kthread_nr = 1;
}
-void
+static void
thread_fini(void)
{
kthread_t *kt = curthread;
@@ -1051,149 +1051,30 @@ delay(clock_t ticks)
/*
* Find highest one bit set.
- * Returns bit number + 1 of highest bit that is set, otherwise returns 0.
- * High order bit is 31 (or 63 in _LP64 kernel).
+ * Returns bit number + 1 of highest bit that is set, otherwise returns 0.
+ * The __builtin_clzll() function is supported by both GCC and Clang.
*/
int
highbit64(uint64_t i)
{
- register int h = 1;
-
if (i == 0)
- return (0);
- if (i & 0xffffffff00000000ULL) {
- h += 32; i >>= 32;
- }
- if (i & 0xffff0000) {
- h += 16; i >>= 16;
- }
- if (i & 0xff00) {
- h += 8; i >>= 8;
- }
- if (i & 0xf0) {
- h += 4; i >>= 4;
- }
- if (i & 0xc) {
- h += 2; i >>= 2;
- }
- if (i & 0x2) {
- h += 1;
- }
- return (h);
+ return (0);
+
+ return (NBBY * sizeof (uint64_t) - __builtin_clzll(i));
}
/*
* Find lowest one bit set.
* Returns bit number + 1 of lowest bit that is set, otherwise returns 0.
- * This is basically a reimplementation of ffsll(), which is GNU specific.
+ * The __builtin_ffsll() function is supported by both GCC and Clang.
*/
int
lowbit64(uint64_t i)
{
- register int h = 64;
if (i == 0)
return (0);
- if (i & 0x00000000ffffffffULL)
- h -= 32;
- else
- i >>= 32;
-
- if (i & 0x0000ffff)
- h -= 16;
- else
- i >>= 16;
-
- if (i & 0x00ff)
- h -= 8;
- else
- i >>= 8;
-
- if (i & 0x0f)
- h -= 4;
- else
- i >>= 4;
-
- if (i & 0x3)
- h -= 2;
- else
- i >>= 2;
-
- if (i & 0x1)
- h -= 1;
-
- return (h);
-}
-
-/*
- * Find highest one bit set.
- * Returns bit number + 1 of highest bit that is set, otherwise returns 0.
- * High order bit is 31 (or 63 in _LP64 kernel).
- */
-int
-highbit(ulong_t i)
-{
-register int h = 1;
-
- if (i == 0)
- return (0);
-#ifdef _LP64
- if (i & 0xffffffff00000000ul) {
- h += 32; i >>= 32;
- }
-#endif
- if (i & 0xffff0000) {
- h += 16; i >>= 16;
- }
- if (i & 0xff00) {
- h += 8; i >>= 8;
- }
- if (i & 0xf0) {
- h += 4; i >>= 4;
- }
- if (i & 0xc) {
- h += 2; i >>= 2;
- }
- if (i & 0x2) {
- h += 1;
- }
- return (h);
-}
-
-/*
- * Find lowest one bit set.
- * Returns bit number + 1 of lowest bit that is set, otherwise returns 0.
- * Low order bit is 0.
- */
-int
-lowbit(ulong_t i)
-{
- register int h = 1;
-
- if (i == 0)
- return (0);
-
-#ifdef _LP64
- if (!(i & 0xffffffff)) {
- h += 32; i >>= 32;
- }
-#endif
- if (!(i & 0xffff)) {
- h += 16; i >>= 16;
- }
- if (!(i & 0xff)) {
- h += 8; i >>= 8;
- }
- if (!(i & 0xf)) {
- h += 4; i >>= 4;
- }
- if (!(i & 0x3)) {
- h += 2; i >>= 2;
- }
- if (!(i & 0x1)) {
- h += 1;
- }
- return (h);
+ return (__builtin_ffsll(i));
}
static int random_fd = -1, urandom_fd = -1;
@@ -1288,64 +1169,6 @@ umem_out_of_memory(void)
return (0);
}
-#define HOSTID_MASK 0xffffffff
-
-static unsigned long
-get_spl_hostid(void)
-{
- FILE *f;
- unsigned long hostid;
- char *env;
-
- /*
- * Allow the hostid to be subverted for testing.
- */
- env = getenv("ZFS_HOSTID");
- if (env) {
- hostid = strtoull(env, NULL, 0);
- return (hostid & HOSTID_MASK);
- }
-
- f = fopen("/sys/module/spl/parameters/spl_hostid", "r");
- if (!f)
- return (0);
-
- if (fscanf(f, "%lu", &hostid) != 1)
- hostid = 0;
-
- fclose(f);
-
- return (hostid & HOSTID_MASK);
-}
-
-unsigned long
-get_system_hostid(void)
-{
- unsigned long system_hostid = get_spl_hostid();
- /*
- * We do not use the library call gethostid() because
- * it generates a hostid value that the kernel is
- * unaware of, if the spl_hostid module parameter has not
- * been set and there is no system hostid file (e.g.
- * /etc/hostid). The kernel and userspace must agree.
- * See comments above hostid_read() in the SPL.
- */
- if (system_hostid == 0) {
- int fd, rc;
- unsigned long hostid;
- int hostid_size = 4; /* 4 bytes regardless of arch */
-
- fd = open("/etc/hostid", O_RDONLY);
- if (fd >= 0) {
- rc = read(fd, &hostid, hostid_size);
- if (rc > 0)
- system_hostid = (hostid & HOSTID_MASK);
- close(fd);
- }
- }
- return (system_hostid);
-}
-
void
kernel_init(int mode)
{
diff --git a/module/icp/algs/sha2/sha2.c b/module/icp/algs/sha2/sha2.c
index dbe008190..c585993f1 100644
--- a/module/icp/algs/sha2/sha2.c
+++ b/module/icp/algs/sha2/sha2.c
@@ -52,7 +52,7 @@
static void Encode(uint8_t *, uint32_t *, size_t);
static void Encode64(uint8_t *, uint64_t *, size_t);
-#if defined(__amd64)
+#if defined(__amd64) && defined(_KERNEL)
#define SHA512Transform(ctx, in) SHA512TransformBlocks((ctx), (in), 1)
#define SHA256Transform(ctx, in) SHA256TransformBlocks((ctx), (in), 1)
@@ -62,7 +62,7 @@ void SHA256TransformBlocks(SHA2_CTX *ctx, const void *in, size_t num);
#else
static void SHA256Transform(SHA2_CTX *, const uint8_t *);
static void SHA512Transform(SHA2_CTX *, const uint8_t *);
-#endif /* __amd64 */
+#endif /* __amd64 && _KERNEL */
static uint8_t PADDING[128] = { 0x80, /* all zeros */ };
@@ -142,7 +142,7 @@ static uint8_t PADDING[128] = { 0x80, /* all zeros */ };
#endif /* _BIG_ENDIAN */
-#if !defined(__amd64)
+#if !defined(__amd64) || !defined(_KERNEL)
/* SHA256 Transform */
static void
@@ -600,7 +600,7 @@ SHA512Transform(SHA2_CTX *ctx, const uint8_t *blk)
ctx->state.s64[7] += h;
}
-#endif /* !__amd64 */
+#endif /* !__amd64 || !_KERNEL */
/*
@@ -783,10 +783,6 @@ SHA2Update(SHA2_CTX *ctx, const void *inptr, size_t input_len)
uint32_t i, buf_index, buf_len, buf_limit;
const uint8_t *input = inptr;
uint32_t algotype = ctx->algotype;
-#if defined(__amd64)
- uint32_t block_count;
-#endif /* !__amd64 */
-
/* check for noop */
if (input_len == 0)
@@ -842,7 +838,7 @@ SHA2Update(SHA2_CTX *ctx, const void *inptr, size_t input_len)
i = buf_len;
}
-#if !defined(__amd64)
+#if !defined(__amd64) || !defined(_KERNEL)
if (algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) {
for (; i + buf_limit - 1 < input_len; i += buf_limit) {
SHA256Transform(ctx, &input[i]);
@@ -854,6 +850,7 @@ SHA2Update(SHA2_CTX *ctx, const void *inptr, size_t input_len)
}
#else
+ uint32_t block_count;
if (algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) {
block_count = (input_len - i) >> 6;
if (block_count > 0) {
@@ -869,7 +866,7 @@ SHA2Update(SHA2_CTX *ctx, const void *inptr, size_t input_len)
i += block_count << 7;
}
}
-#endif /* !__amd64 */
+#endif /* !__amd64 || !_KERNEL */
/*
* general optimization:
@@ -951,8 +948,6 @@ SHA2Final(void *digest, SHA2_CTX *ctx)
bzero(ctx, sizeof (*ctx));
}
-
-
#ifdef _KERNEL
EXPORT_SYMBOL(SHA2Init);
EXPORT_SYMBOL(SHA2Update);
diff --git a/module/icp/os/modhash.c b/module/icp/os/modhash.c
index 1ff782afc..497e84396 100644
--- a/module/icp/os/modhash.c
+++ b/module/icp/os/modhash.c
@@ -312,7 +312,7 @@ mod_hash_create_ptrhash(char *name, size_t nchains,
* The high bits, which are also unused, will get taken out when
* mod_hash takes hashkey % nchains.
*/
- rshift = highbit(key_elem_size);
+ rshift = highbit64(key_elem_size);
return mod_hash_create_extended(name, nchains, mod_hash_null_keydtor,
val_dtor, mod_hash_byptr, (void *)rshift, mod_hash_ptrkey_cmp,
diff --git a/module/zcommon/Makefile.in b/module/zcommon/Makefile.in
index 74bb4378e..86eb8ad39 100644
--- a/module/zcommon/Makefile.in
+++ b/module/zcommon/Makefile.in
@@ -7,16 +7,17 @@ EXTRA_CFLAGS = $(ZFS_MODULE_CFLAGS) @KERNELCPPFLAGS@
obj-$(CONFIG_ZFS) := $(MODULE).o
-$(MODULE)-objs += zfs_deleg.o
-$(MODULE)-objs += zfs_prop.o
-$(MODULE)-objs += zprop_common.o
-$(MODULE)-objs += zfs_namecheck.o
+$(MODULE)-objs += zfeature_common.o
$(MODULE)-objs += zfs_comutil.o
+$(MODULE)-objs += zfs_deleg.o
$(MODULE)-objs += zfs_fletcher.o
-$(MODULE)-objs += zfs_uio.o
-$(MODULE)-objs += zpool_prop.o
$(MODULE)-objs += zfs_fletcher_superscalar.o
$(MODULE)-objs += zfs_fletcher_superscalar4.o
+$(MODULE)-objs += zfs_namecheck.o
+$(MODULE)-objs += zfs_prop.o
+$(MODULE)-objs += zfs_uio.o
+$(MODULE)-objs += zpool_prop.o
+$(MODULE)-objs += zprop_common.o
$(MODULE)-$(CONFIG_X86) += zfs_fletcher_intel.o
$(MODULE)-$(CONFIG_X86) += zfs_fletcher_sse.o
diff --git a/module/zfs/zfeature_common.c b/module/zcommon/zfeature_common.c
index 73abcb236..321ee04bf 100644
--- a/module/zfs/zfeature_common.c
+++ b/module/zcommon/zfeature_common.c
@@ -319,3 +319,12 @@ zpool_feature_init(void)
userobj_accounting_deps);
}
}
+
+#if defined(_KERNEL) && defined(HAVE_SPL)
+EXPORT_SYMBOL(zfeature_lookup_name);
+EXPORT_SYMBOL(zfeature_is_supported);
+EXPORT_SYMBOL(zfeature_is_valid_guid);
+EXPORT_SYMBOL(zfeature_depends_on);
+EXPORT_SYMBOL(zpool_feature_init);
+EXPORT_SYMBOL(spa_feature_table);
+#endif
diff --git a/module/zcommon/zfs_comutil.c b/module/zcommon/zfs_comutil.c
index 52cb7e365..685a20c44 100644
--- a/module/zcommon/zfs_comutil.c
+++ b/module/zcommon/zfs_comutil.c
@@ -207,85 +207,10 @@ const char *zfs_history_event_names[ZFS_NUM_LEGACY_HISTORY_EVENTS] = {
"pool split",
};
-/*
- * Initialize rate limit struct
- *
- * rl: zfs_ratelimit_t struct
- * burst: Number to allow in an interval before rate limiting
- * interval: Interval time in seconds
- */
-void
-zfs_ratelimit_init(zfs_ratelimit_t *rl, unsigned int burst,
- unsigned int interval)
-{
- rl->count = 0;
- rl->start = 0;
- rl->interval = interval;
- rl->burst = burst;
- mutex_init(&rl->lock, NULL, MUTEX_DEFAULT, NULL);
-}
-
-/*
- * Finalize rate limit struct
- *
- * rl: zfs_ratelimit_t struct
- */
-void
-zfs_ratelimit_fini(zfs_ratelimit_t *rl)
-{
- mutex_destroy(&rl->lock);
-}
-
-/*
- * Re-implementation of the kernel's __ratelimit() function
- *
- * We had to write our own rate limiter because the kernel's __ratelimit()
- * function annoyingly prints out how many times it rate limited to the kernel
- * logs (and there's no way to turn it off):
- *
- * __ratelimit: 59 callbacks suppressed
- *
- * If the kernel ever allows us to disable these prints, we should go back to
- * using __ratelimit() instead.
- *
- * Return values are the same as __ratelimit():
- *
- * 0: If we're rate limiting
- * 1: If we're not rate limiting.
- */
-int
-zfs_ratelimit(zfs_ratelimit_t *rl)
-{
- hrtime_t now;
- hrtime_t elapsed;
- int rc = 1;
-
- mutex_enter(&rl->lock);
-
- now = gethrtime();
- elapsed = now - rl->start;
-
- rl->count++;
- if (NSEC2SEC(elapsed) >= rl->interval) {
- rl->start = now;
- rl->count = 0;
- } else {
- if (rl->count >= rl->burst) {
- rc = 0; /* We're ratelimiting */
- }
- }
- mutex_exit(&rl->lock);
-
- return (rc);
-}
-
#if defined(_KERNEL) && defined(HAVE_SPL)
EXPORT_SYMBOL(zfs_allocatable_devs);
EXPORT_SYMBOL(zpool_get_rewind_policy);
EXPORT_SYMBOL(zfs_zpl_version_map);
EXPORT_SYMBOL(zfs_spa_version_map);
EXPORT_SYMBOL(zfs_history_event_names);
-EXPORT_SYMBOL(zfs_ratelimit_init);
-EXPORT_SYMBOL(zfs_ratelimit_fini);
-EXPORT_SYMBOL(zfs_ratelimit);
#endif
diff --git a/module/zcommon/zfs_deleg.c b/module/zcommon/zfs_deleg.c
index ce659d7f5..90e9048b1 100644
--- a/module/zcommon/zfs_deleg.c
+++ b/module/zcommon/zfs_deleg.c
@@ -233,7 +233,7 @@ zfs_deleg_whokey(char *attr, zfs_deleg_who_type_t type,
ZFS_DELEG_FIELD_SEP_CHR);
break;
default:
- cmn_err(CE_PANIC, "bad zfs_deleg_who_type_t %d", type);
+ ASSERT(!"bad zfs_deleg_who_type_t");
}
}
diff --git a/module/zcommon/zfs_fletcher.c b/module/zcommon/zfs_fletcher.c
index 9cdf36d44..0cd992979 100644
--- a/module/zcommon/zfs_fletcher.c
+++ b/module/zcommon/zfs_fletcher.c
@@ -212,7 +212,9 @@ static struct fletcher_4_impl_selector {
{ "scalar", IMPL_SCALAR }
};
+#if defined(_KERNEL)
static kstat_t *fletcher_4_kstat;
+#endif
static struct fletcher_4_kstat {
uint64_t native;
@@ -589,7 +591,7 @@ fletcher_4_incremental_byteswap(void *buf, size_t size, void *data)
return (0);
}
-
+#if defined(_KERNEL)
/* Fletcher 4 kstats */
static int
@@ -642,6 +644,7 @@ fletcher_4_kstat_addr(kstat_t *ksp, loff_t n)
return (ksp->ks_private);
}
+#endif
#define FLETCHER_4_FASTEST_FN_COPY(type, src) \
{ \
@@ -753,6 +756,7 @@ fletcher_4_init(void)
vmem_free(databuf, data_size);
+#if defined(_KERNEL)
/* install kstats for all implementations */
fletcher_4_kstat = kstat_create("zfs", 0, "fletcher_4_bench", "misc",
KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL);
@@ -765,6 +769,7 @@ fletcher_4_init(void)
fletcher_4_kstat_addr);
kstat_install(fletcher_4_kstat);
}
+#endif
/* Finish initialization */
fletcher_4_initialized = B_TRUE;
@@ -773,10 +778,12 @@ fletcher_4_init(void)
void
fletcher_4_fini(void)
{
+#if defined(_KERNEL)
if (fletcher_4_kstat != NULL) {
kstat_delete(fletcher_4_kstat);
fletcher_4_kstat = NULL;
}
+#endif
}
/* ABD adapters */
diff --git a/module/zfs/Makefile.in b/module/zfs/Makefile.in
index d6336f314..b849d9010 100644
--- a/module/zfs/Makefile.in
+++ b/module/zfs/Makefile.in
@@ -82,7 +82,6 @@ $(MODULE)-objs += zap.o
$(MODULE)-objs += zap_leaf.o
$(MODULE)-objs += zap_micro.o
$(MODULE)-objs += zfeature.o
-$(MODULE)-objs += zfeature_common.o
$(MODULE)-objs += zfs_acl.o
$(MODULE)-objs += zfs_byteswap.o
$(MODULE)-objs += zfs_ctldir.o
@@ -93,6 +92,7 @@ $(MODULE)-objs += zfs_fuid.o
$(MODULE)-objs += zfs_ioctl.o
$(MODULE)-objs += zfs_log.o
$(MODULE)-objs += zfs_onexit.o
+$(MODULE)-objs += zfs_ratelimit.o
$(MODULE)-objs += zfs_replay.o
$(MODULE)-objs += zfs_rlock.o
$(MODULE)-objs += zfs_sa.o
diff --git a/module/zfs/zfs_ratelimit.c b/module/zfs/zfs_ratelimit.c
new file mode 100644
index 000000000..d4a7d5217
--- /dev/null
+++ b/module/zfs/zfs_ratelimit.c
@@ -0,0 +1,99 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2017, Lawrence Livermore National Security, LLC.
+ */
+
+#include <sys/zfs_ratelimit.h>
+
+/*
+ * Initialize rate limit struct
+ *
+ * rl: zfs_ratelimit_t struct
+ * burst: Number to allow in an interval before rate limiting
+ * interval: Interval time in seconds
+ */
+void
+zfs_ratelimit_init(zfs_ratelimit_t *rl, unsigned int burst,
+ unsigned int interval)
+{
+ rl->count = 0;
+ rl->start = 0;
+ rl->interval = interval;
+ rl->burst = burst;
+ mutex_init(&rl->lock, NULL, MUTEX_DEFAULT, NULL);
+}
+
+/*
+ * Finalize rate limit struct
+ *
+ * rl: zfs_ratelimit_t struct
+ */
+void
+zfs_ratelimit_fini(zfs_ratelimit_t *rl)
+{
+ mutex_destroy(&rl->lock);
+}
+
+/*
+ * Re-implementation of the kernel's __ratelimit() function
+ *
+ * We had to write our own rate limiter because the kernel's __ratelimit()
+ * function annoyingly prints out how many times it rate limited to the kernel
+ * logs (and there's no way to turn it off):
+ *
+ * __ratelimit: 59 callbacks suppressed
+ *
+ * If the kernel ever allows us to disable these prints, we should go back to
+ * using __ratelimit() instead.
+ *
+ * Return values are the same as __ratelimit():
+ *
+ * 0: If we're rate limiting
+ * 1: If we're not rate limiting.
+ */
+int
+zfs_ratelimit(zfs_ratelimit_t *rl)
+{
+ hrtime_t now;
+
+ hrtime_t elapsed;
+ int error = 1;
+
+ mutex_enter(&rl->lock);
+
+ now = gethrtime();
+ elapsed = now - rl->start;
+
+ rl->count++;
+ if (NSEC2SEC(elapsed) >= rl->interval) {
+ rl->start = now;
+ rl->count = 0;
+ } else {
+ if (rl->count >= rl->burst) {
+ error = 0; /* We're ratelimiting */
+ }
+ }
+ mutex_exit(&rl->lock);
+
+ return (error);
+}
diff --git a/scripts/zfs2zol-patch.sed b/scripts/zfs2zol-patch.sed
index d4def4429..99824d6dd 100755
--- a/scripts/zfs2zol-patch.sed
+++ b/scripts/zfs2zol-patch.sed
@@ -19,14 +19,6 @@ s:usr/src/test/zfs-tests/runfiles:tests/runfiles:g
s:usr/src/test/zfs-tests/tests/functional:tests/zfs-tests/tests/functional:g
s:usr/src/test/zfs-tests/tests/perf:tests/zfs-tests/tests/perf:g
s:usr/src/test/test-runner/cmd/run.py:tests/test-runner/cmd/test-runner.py:g
-
-#
-# The usr/src/common/zfs/ files go in a couple different dirs.
-# usr/src/common/zfs/zfeature_common.c goes in module/zfs
-#
-s:usr/src/common/zfs/zfeature_common.c:module/zfs/zfeature_common.c:g
-
-# ...but most of the rest of the C files go in module/zcommon
s/usr\/src\/common\/zfs\/\(.*\)\.c/module\/zcommon\/\1.c/g
# crypto framework
diff --git a/tests/zfs-tests/tests/functional/libzfs/Makefile.am b/tests/zfs-tests/tests/functional/libzfs/Makefile.am
index 811f09452..d885bc1ab 100644
--- a/tests/zfs-tests/tests/functional/libzfs/Makefile.am
+++ b/tests/zfs-tests/tests/functional/libzfs/Makefile.am
@@ -13,11 +13,7 @@ DEFAULT_INCLUDES += \
-I$(top_srcdir)/lib/libspl/include
many_fds_LDADD = \
- $(top_builddir)/lib/libnvpair/libnvpair.la \
- $(top_builddir)/lib/libuutil/libuutil.la \
- $(top_builddir)/lib/libzpool/libzpool.la \
- $(top_builddir)/lib/libzfs/libzfs.la \
- $(top_builddir)/lib/libzfs_core/libzfs_core.la
+ $(top_builddir)/lib/libzfs/libzfs.la
pkgexec_PROGRAMS = many_fds
many_fds_SOURCES = many_fds.c