aboutsummaryrefslogtreecommitdiffstats
path: root/module/splat
diff options
context:
space:
mode:
Diffstat (limited to 'module/splat')
-rw-r--r--module/splat/Makefile.in28
-rw-r--r--module/splat/splat-atomic.c233
-rw-r--r--module/splat/splat-condvar.c511
-rw-r--r--module/splat/splat-cred.c299
-rw-r--r--module/splat/splat-ctl.c753
-rw-r--r--module/splat/splat-generic.c367
-rw-r--r--module/splat/splat-internal.h150
-rw-r--r--module/splat/splat-kmem.c1410
-rw-r--r--module/splat/splat-kobj.c166
-rw-r--r--module/splat/splat-linux.c237
-rw-r--r--module/splat/splat-list.c475
-rw-r--r--module/splat/splat-mutex.c447
-rw-r--r--module/splat/splat-random.c130
-rw-r--r--module/splat/splat-rwlock.c747
-rw-r--r--module/splat/splat-taskq.c1548
-rw-r--r--module/splat/splat-thread.c390
-rw-r--r--module/splat/splat-time.c119
-rw-r--r--module/splat/splat-vnode.c355
-rw-r--r--module/splat/splat-zlib.c166
19 files changed, 0 insertions, 8531 deletions
diff --git a/module/splat/Makefile.in b/module/splat/Makefile.in
deleted file mode 100644
index 680f28492..000000000
--- a/module/splat/Makefile.in
+++ /dev/null
@@ -1,28 +0,0 @@
-# Makefile.in for splat kernel module
-
-src = @abs_top_srcdir@/module/splat
-obj = @abs_builddir@
-
-MODULE := splat
-EXTRA_CFLAGS = $(SPL_MODULE_CFLAGS) @KERNELCPPFLAGS@
-
-# Solaris Porting LAyer Tests
-obj-$(CONFIG_SPL) := $(MODULE).o
-
-$(MODULE)-objs += splat-ctl.o
-$(MODULE)-objs += splat-kmem.o
-$(MODULE)-objs += splat-taskq.o
-$(MODULE)-objs += splat-random.o
-$(MODULE)-objs += splat-mutex.o
-$(MODULE)-objs += splat-condvar.o
-$(MODULE)-objs += splat-thread.o
-$(MODULE)-objs += splat-rwlock.o
-$(MODULE)-objs += splat-time.o
-$(MODULE)-objs += splat-vnode.o
-$(MODULE)-objs += splat-kobj.o
-$(MODULE)-objs += splat-atomic.o
-$(MODULE)-objs += splat-list.o
-$(MODULE)-objs += splat-generic.o
-$(MODULE)-objs += splat-cred.o
-$(MODULE)-objs += splat-zlib.o
-$(MODULE)-objs += splat-linux.o
diff --git a/module/splat/splat-atomic.c b/module/splat/splat-atomic.c
deleted file mode 100644
index 8aaa0835d..000000000
--- a/module/splat/splat-atomic.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Atomic Tests.
- */
-
-#include <sys/atomic.h>
-#include <sys/thread.h>
-#include <sys/mutex.h>
-#include <linux/mm_compat.h>
-#include <linux/wait_compat.h>
-#include <linux/slab.h>
-#include "splat-internal.h"
-
-#define SPLAT_ATOMIC_NAME "atomic"
-#define SPLAT_ATOMIC_DESC "Kernel Atomic Tests"
-
-#define SPLAT_ATOMIC_TEST1_ID 0x0b01
-#define SPLAT_ATOMIC_TEST1_NAME "64-bit"
-#define SPLAT_ATOMIC_TEST1_DESC "Validate 64-bit atomic ops"
-
-#define SPLAT_ATOMIC_TEST_MAGIC 0x43435454UL
-#define SPLAT_ATOMIC_INIT_VALUE 10000000UL
-
-typedef enum {
- SPLAT_ATOMIC_INC_64 = 0,
- SPLAT_ATOMIC_DEC_64 = 1,
- SPLAT_ATOMIC_ADD_64 = 2,
- SPLAT_ATOMIC_SUB_64 = 3,
- SPLAT_ATOMIC_ADD_64_NV = 4,
- SPLAT_ATOMIC_SUB_64_NV = 5,
- SPLAT_ATOMIC_COUNT_64 = 6
-} atomic_op_t;
-
-typedef struct atomic_priv {
- unsigned long ap_magic;
- struct file *ap_file;
- kmutex_t ap_lock;
- spl_wait_queue_head_t ap_waitq;
- volatile uint64_t ap_atomic;
- volatile uint64_t ap_atomic_exited;
- atomic_op_t ap_op;
-
-} atomic_priv_t;
-
-static void
-splat_atomic_work(void *priv)
-{
- atomic_priv_t *ap;
- atomic_op_t op;
- int i;
-
- ap = (atomic_priv_t *)priv;
- ASSERT(ap->ap_magic == SPLAT_ATOMIC_TEST_MAGIC);
-
- mutex_enter(&ap->ap_lock);
- op = ap->ap_op;
- wake_up(&ap->ap_waitq);
- mutex_exit(&ap->ap_lock);
-
- splat_vprint(ap->ap_file, SPLAT_ATOMIC_TEST1_NAME,
- "Thread %d successfully started: %lu/%lu\n", op,
- (long unsigned)ap->ap_atomic,
- (long unsigned)ap->ap_atomic_exited);
-
- for (i = 0; i < SPLAT_ATOMIC_INIT_VALUE / 10; i++) {
-
- /* Periodically sleep to mix up the ordering */
- if ((i % (SPLAT_ATOMIC_INIT_VALUE / 100)) == 0) {
- splat_vprint(ap->ap_file, SPLAT_ATOMIC_TEST1_NAME,
- "Thread %d sleeping: %lu/%lu\n", op,
- (long unsigned)ap->ap_atomic,
- (long unsigned)ap->ap_atomic_exited);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 100);
- }
-
- switch (op) {
- case SPLAT_ATOMIC_INC_64:
- atomic_inc_64(&ap->ap_atomic);
- break;
- case SPLAT_ATOMIC_DEC_64:
- atomic_dec_64(&ap->ap_atomic);
- break;
- case SPLAT_ATOMIC_ADD_64:
- atomic_add_64(&ap->ap_atomic, 3);
- break;
- case SPLAT_ATOMIC_SUB_64:
- atomic_sub_64(&ap->ap_atomic, 3);
- break;
- case SPLAT_ATOMIC_ADD_64_NV:
- atomic_add_64_nv(&ap->ap_atomic, 5);
- break;
- case SPLAT_ATOMIC_SUB_64_NV:
- atomic_sub_64_nv(&ap->ap_atomic, 5);
- break;
- default:
- PANIC("Undefined op %d\n", op);
- }
- }
-
- atomic_inc_64(&ap->ap_atomic_exited);
-
- splat_vprint(ap->ap_file, SPLAT_ATOMIC_TEST1_NAME,
- "Thread %d successfully exited: %lu/%lu\n", op,
- (long unsigned)ap->ap_atomic,
- (long unsigned)ap->ap_atomic_exited);
-
- wake_up(&ap->ap_waitq);
- thread_exit();
-}
-
-static int
-splat_atomic_test1_cond(atomic_priv_t *ap, int started)
-{
- return (ap->ap_atomic_exited == started);
-}
-
-static int
-splat_atomic_test1(struct file *file, void *arg)
-{
- atomic_priv_t ap;
- DEFINE_WAIT(wait);
- kthread_t *thr;
- int i, rc = 0;
-
- ap.ap_magic = SPLAT_ATOMIC_TEST_MAGIC;
- ap.ap_file = file;
- mutex_init(&ap.ap_lock, SPLAT_ATOMIC_TEST1_NAME, MUTEX_DEFAULT, NULL);
- init_waitqueue_head(&ap.ap_waitq);
- ap.ap_atomic = SPLAT_ATOMIC_INIT_VALUE;
- ap.ap_atomic_exited = 0;
-
- for (i = 0; i < SPLAT_ATOMIC_COUNT_64; i++) {
- mutex_enter(&ap.ap_lock);
- ap.ap_op = i;
-
- thr = (kthread_t *)thread_create(NULL, 0, splat_atomic_work,
- &ap, 0, &p0, TS_RUN,
- defclsyspri);
- if (thr == NULL) {
- rc = -ESRCH;
- mutex_exit(&ap.ap_lock);
- break;
- }
-
- /* Prepare to wait, the new thread will wake us once it
- * has made a copy of the unique private passed data */
- prepare_to_wait(&ap.ap_waitq, &wait, TASK_UNINTERRUPTIBLE);
- mutex_exit(&ap.ap_lock);
- schedule();
- }
-
- wait_event(ap.ap_waitq, splat_atomic_test1_cond(&ap, i));
-
- if (rc) {
- splat_vprint(file, SPLAT_ATOMIC_TEST1_NAME, "Only started "
- "%d/%d test threads\n", i, SPLAT_ATOMIC_COUNT_64);
- return rc;
- }
-
- if (ap.ap_atomic != SPLAT_ATOMIC_INIT_VALUE) {
- splat_vprint(file, SPLAT_ATOMIC_TEST1_NAME,
- "Final value %lu does not match initial value %lu\n",
- (long unsigned)ap.ap_atomic, SPLAT_ATOMIC_INIT_VALUE);
- return -EINVAL;
- }
-
- splat_vprint(file, SPLAT_ATOMIC_TEST1_NAME,
- "Success initial and final values match, %lu == %lu\n",
- (long unsigned)ap.ap_atomic, SPLAT_ATOMIC_INIT_VALUE);
-
- mutex_destroy(&ap.ap_lock);
-
- return 0;
-}
-
-splat_subsystem_t *
-splat_atomic_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_ATOMIC_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_ATOMIC_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_ATOMIC;
-
- splat_test_init(sub, SPLAT_ATOMIC_TEST1_NAME, SPLAT_ATOMIC_TEST1_DESC,
- SPLAT_ATOMIC_TEST1_ID, splat_atomic_test1);
-
- return sub;
-}
-
-void
-splat_atomic_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
- splat_test_fini(sub, SPLAT_ATOMIC_TEST1_ID);
-
- kfree(sub);
-}
-
-int
-splat_atomic_id(void) {
- return SPLAT_SUBSYSTEM_ATOMIC;
-}
diff --git a/module/splat/splat-condvar.c b/module/splat/splat-condvar.c
deleted file mode 100644
index 0804baf50..000000000
--- a/module/splat/splat-condvar.c
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Condition Variable Tests.
- */
-
-#include <sys/condvar.h>
-#include <sys/timer.h>
-#include <sys/thread.h>
-#include "splat-internal.h"
-
-#define SPLAT_CONDVAR_NAME "condvar"
-#define SPLAT_CONDVAR_DESC "Kernel Condition Variable Tests"
-
-#define SPLAT_CONDVAR_TEST1_ID 0x0501
-#define SPLAT_CONDVAR_TEST1_NAME "signal1"
-#define SPLAT_CONDVAR_TEST1_DESC "Wake a single thread, cv_wait()/cv_signal()"
-
-#define SPLAT_CONDVAR_TEST2_ID 0x0502
-#define SPLAT_CONDVAR_TEST2_NAME "broadcast1"
-#define SPLAT_CONDVAR_TEST2_DESC "Wake all threads, cv_wait()/cv_broadcast()"
-
-#define SPLAT_CONDVAR_TEST3_ID 0x0503
-#define SPLAT_CONDVAR_TEST3_NAME "signal2"
-#define SPLAT_CONDVAR_TEST3_DESC "Wake a single thread, cv_wait_timeout()/cv_signal()"
-
-#define SPLAT_CONDVAR_TEST4_ID 0x0504
-#define SPLAT_CONDVAR_TEST4_NAME "broadcast2"
-#define SPLAT_CONDVAR_TEST4_DESC "Wake all threads, cv_wait_timeout()/cv_broadcast()"
-
-#define SPLAT_CONDVAR_TEST5_ID 0x0505
-#define SPLAT_CONDVAR_TEST5_NAME "timeout"
-#define SPLAT_CONDVAR_TEST5_DESC "Timeout thread, cv_wait_timeout()"
-
-#define SPLAT_CONDVAR_TEST_MAGIC 0x115599DDUL
-#define SPLAT_CONDVAR_TEST_NAME "condvar"
-#define SPLAT_CONDVAR_TEST_COUNT 8
-
-typedef struct condvar_priv {
- unsigned long cv_magic;
- struct file *cv_file;
- kcondvar_t cv_condvar;
- kmutex_t cv_mtx;
-} condvar_priv_t;
-
-typedef struct condvar_thr {
- const char *ct_name;
- condvar_priv_t *ct_cvp;
- struct task_struct *ct_thread;
- int ct_rc;
-} condvar_thr_t;
-
-int
-splat_condvar_test12_thread(void *arg)
-{
- condvar_thr_t *ct = (condvar_thr_t *)arg;
- condvar_priv_t *cv = ct->ct_cvp;
-
- ASSERT(cv->cv_magic == SPLAT_CONDVAR_TEST_MAGIC);
-
- mutex_enter(&cv->cv_mtx);
- splat_vprint(cv->cv_file, ct->ct_name,
- "%s thread sleeping with %d waiters\n",
- ct->ct_thread->comm, atomic_read(&cv->cv_condvar.cv_waiters));
- cv_wait(&cv->cv_condvar, &cv->cv_mtx);
- splat_vprint(cv->cv_file, ct->ct_name,
- "%s thread woken %d waiters remain\n",
- ct->ct_thread->comm, atomic_read(&cv->cv_condvar.cv_waiters));
- mutex_exit(&cv->cv_mtx);
-
- /* wait for main thread reap us */
- while (!kthread_should_stop())
- schedule();
- return 0;
-}
-
-static int
-splat_condvar_test1(struct file *file, void *arg)
-{
- int i, count = 0, rc = 0;
- condvar_thr_t ct[SPLAT_CONDVAR_TEST_COUNT];
- condvar_priv_t cv;
-
- cv.cv_magic = SPLAT_CONDVAR_TEST_MAGIC;
- cv.cv_file = file;
- mutex_init(&cv.cv_mtx, SPLAT_CONDVAR_TEST_NAME, MUTEX_DEFAULT, NULL);
- cv_init(&cv.cv_condvar, NULL, CV_DEFAULT, NULL);
-
- /* Create some threads, the exact number isn't important just as
- * long as we know how many we managed to create and should expect. */
- for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
- ct[i].ct_cvp = &cv;
- ct[i].ct_name = SPLAT_CONDVAR_TEST1_NAME;
- ct[i].ct_rc = 0;
- ct[i].ct_thread = spl_kthread_create(splat_condvar_test12_thread,
- &ct[i], "%s/%d", SPLAT_CONDVAR_TEST_NAME, i);
-
- if (!IS_ERR(ct[i].ct_thread)) {
- wake_up_process(ct[i].ct_thread);
- count++;
- }
- }
-
- /* Wait until all threads are waiting on the condition variable */
- while (atomic_read(&cv.cv_condvar.cv_waiters) != count)
- schedule();
-
- /* Wake a single thread at a time, wait until it exits */
- for (i = 1; i <= count; i++) {
- cv_signal(&cv.cv_condvar);
-
- while (atomic_read(&cv.cv_condvar.cv_waiters) > (count - i))
- schedule();
-
- /* Correct behavior 1 thread woken */
- if (atomic_read(&cv.cv_condvar.cv_waiters) == (count - i))
- continue;
-
- splat_vprint(file, SPLAT_CONDVAR_TEST1_NAME, "Attempted to "
- "wake %d thread but work %d threads woke\n",
- 1, count - atomic_read(&cv.cv_condvar.cv_waiters));
- rc = -EINVAL;
- break;
- }
-
- if (!rc)
- splat_vprint(file, SPLAT_CONDVAR_TEST1_NAME, "Correctly woke "
- "%d sleeping threads %d at a time\n", count, 1);
-
- /* Wait until that last nutex is dropped */
- while (mutex_owner(&cv.cv_mtx))
- schedule();
-
- /* Wake everything for the failure case */
- cv_broadcast(&cv.cv_condvar);
- cv_destroy(&cv.cv_condvar);
-
- /* wait for threads to exit */
- for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
- if (!IS_ERR(ct[i].ct_thread))
- kthread_stop(ct[i].ct_thread);
- }
- mutex_destroy(&cv.cv_mtx);
-
- return rc;
-}
-
-static int
-splat_condvar_test2(struct file *file, void *arg)
-{
- int i, count = 0, rc = 0;
- condvar_thr_t ct[SPLAT_CONDVAR_TEST_COUNT];
- condvar_priv_t cv;
-
- cv.cv_magic = SPLAT_CONDVAR_TEST_MAGIC;
- cv.cv_file = file;
- mutex_init(&cv.cv_mtx, SPLAT_CONDVAR_TEST_NAME, MUTEX_DEFAULT, NULL);
- cv_init(&cv.cv_condvar, NULL, CV_DEFAULT, NULL);
-
- /* Create some threads, the exact number isn't important just as
- * long as we know how many we managed to create and should expect. */
- for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
- ct[i].ct_cvp = &cv;
- ct[i].ct_name = SPLAT_CONDVAR_TEST2_NAME;
- ct[i].ct_rc = 0;
- ct[i].ct_thread = spl_kthread_create(splat_condvar_test12_thread,
- &ct[i], "%s/%d", SPLAT_CONDVAR_TEST_NAME, i);
-
- if (!IS_ERR(ct[i].ct_thread)) {
- wake_up_process(ct[i].ct_thread);
- count++;
- }
- }
-
- /* Wait until all threads are waiting on the condition variable */
- while (atomic_read(&cv.cv_condvar.cv_waiters) != count)
- schedule();
-
- /* Wake all threads waiting on the condition variable */
- cv_broadcast(&cv.cv_condvar);
-
- /* Wait until all threads have exited */
- while ((atomic_read(&cv.cv_condvar.cv_waiters) > 0) || mutex_owner(&cv.cv_mtx))
- schedule();
-
- splat_vprint(file, SPLAT_CONDVAR_TEST2_NAME, "Correctly woke all "
- "%d sleeping threads at once\n", count);
-
- /* Wake everything for the failure case */
- cv_destroy(&cv.cv_condvar);
-
- /* wait for threads to exit */
- for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
- if (!IS_ERR(ct[i].ct_thread))
- kthread_stop(ct[i].ct_thread);
- }
- mutex_destroy(&cv.cv_mtx);
-
- return rc;
-}
-
-int
-splat_condvar_test34_thread(void *arg)
-{
- condvar_thr_t *ct = (condvar_thr_t *)arg;
- condvar_priv_t *cv = ct->ct_cvp;
- clock_t rc;
-
- ASSERT(cv->cv_magic == SPLAT_CONDVAR_TEST_MAGIC);
-
- mutex_enter(&cv->cv_mtx);
- splat_vprint(cv->cv_file, ct->ct_name,
- "%s thread sleeping with %d waiters\n",
- ct->ct_thread->comm, atomic_read(&cv->cv_condvar.cv_waiters));
-
- /* Sleep no longer than 3 seconds, for this test we should
- * actually never sleep that long without being woken up. */
- rc = cv_timedwait(&cv->cv_condvar, &cv->cv_mtx, lbolt + HZ * 3);
- if (rc == -1) {
- ct->ct_rc = -ETIMEDOUT;
- splat_vprint(cv->cv_file, ct->ct_name, "%s thread timed out, "
- "should have been woken\n", ct->ct_thread->comm);
- } else {
- splat_vprint(cv->cv_file, ct->ct_name,
- "%s thread woken %d waiters remain\n",
- ct->ct_thread->comm,
- atomic_read(&cv->cv_condvar.cv_waiters));
- }
-
- mutex_exit(&cv->cv_mtx);
-
- /* wait for main thread reap us */
- while (!kthread_should_stop())
- schedule();
- return 0;
-}
-
-static int
-splat_condvar_test3(struct file *file, void *arg)
-{
- int i, count = 0, rc = 0;
- condvar_thr_t ct[SPLAT_CONDVAR_TEST_COUNT];
- condvar_priv_t cv;
-
- cv.cv_magic = SPLAT_CONDVAR_TEST_MAGIC;
- cv.cv_file = file;
- mutex_init(&cv.cv_mtx, SPLAT_CONDVAR_TEST_NAME, MUTEX_DEFAULT, NULL);
- cv_init(&cv.cv_condvar, NULL, CV_DEFAULT, NULL);
-
- /* Create some threads, the exact number isn't important just as
- * long as we know how many we managed to create and should expect. */
- for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
- ct[i].ct_cvp = &cv;
- ct[i].ct_name = SPLAT_CONDVAR_TEST3_NAME;
- ct[i].ct_rc = 0;
- ct[i].ct_thread = spl_kthread_create(splat_condvar_test34_thread,
- &ct[i], "%s/%d", SPLAT_CONDVAR_TEST_NAME, i);
-
- if (!IS_ERR(ct[i].ct_thread)) {
- wake_up_process(ct[i].ct_thread);
- count++;
- }
- }
-
- /* Wait until all threads are waiting on the condition variable */
- while (atomic_read(&cv.cv_condvar.cv_waiters) != count)
- schedule();
-
- /* Wake a single thread at a time, wait until it exits */
- for (i = 1; i <= count; i++) {
- cv_signal(&cv.cv_condvar);
-
- while (atomic_read(&cv.cv_condvar.cv_waiters) > (count - i))
- schedule();
-
- /* Correct behavior 1 thread woken */
- if (atomic_read(&cv.cv_condvar.cv_waiters) == (count - i))
- continue;
-
- splat_vprint(file, SPLAT_CONDVAR_TEST3_NAME, "Attempted to "
- "wake %d thread but work %d threads woke\n",
- 1, count - atomic_read(&cv.cv_condvar.cv_waiters));
- rc = -EINVAL;
- break;
- }
-
- /* Validate no waiting thread timed out early */
- for (i = 0; i < count; i++)
- if (ct[i].ct_rc)
- rc = ct[i].ct_rc;
-
- if (!rc)
- splat_vprint(file, SPLAT_CONDVAR_TEST3_NAME, "Correctly woke "
- "%d sleeping threads %d at a time\n", count, 1);
-
- /* Wait until that last nutex is dropped */
- while (mutex_owner(&cv.cv_mtx))
- schedule();
-
- /* Wake everything for the failure case */
- cv_broadcast(&cv.cv_condvar);
- cv_destroy(&cv.cv_condvar);
-
- /* wait for threads to exit */
- for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
- if (!IS_ERR(ct[i].ct_thread))
- kthread_stop(ct[i].ct_thread);
- }
- mutex_destroy(&cv.cv_mtx);
-
- return rc;
-}
-
-static int
-splat_condvar_test4(struct file *file, void *arg)
-{
- int i, count = 0, rc = 0;
- condvar_thr_t ct[SPLAT_CONDVAR_TEST_COUNT];
- condvar_priv_t cv;
-
- cv.cv_magic = SPLAT_CONDVAR_TEST_MAGIC;
- cv.cv_file = file;
- mutex_init(&cv.cv_mtx, SPLAT_CONDVAR_TEST_NAME, MUTEX_DEFAULT, NULL);
- cv_init(&cv.cv_condvar, NULL, CV_DEFAULT, NULL);
-
- /* Create some threads, the exact number isn't important just as
- * long as we know how many we managed to create and should expect. */
- for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
- ct[i].ct_cvp = &cv;
- ct[i].ct_name = SPLAT_CONDVAR_TEST3_NAME;
- ct[i].ct_rc = 0;
- ct[i].ct_thread = spl_kthread_create(splat_condvar_test34_thread,
- &ct[i], "%s/%d", SPLAT_CONDVAR_TEST_NAME, i);
-
- if (!IS_ERR(ct[i].ct_thread)) {
- wake_up_process(ct[i].ct_thread);
- count++;
- }
- }
-
- /* Wait until all threads are waiting on the condition variable */
- while (atomic_read(&cv.cv_condvar.cv_waiters) != count)
- schedule();
-
- /* Wake a single thread at a time, wait until it exits */
- for (i = 1; i <= count; i++) {
- cv_signal(&cv.cv_condvar);
-
- while (atomic_read(&cv.cv_condvar.cv_waiters) > (count - i))
- schedule();
-
- /* Correct behavior 1 thread woken */
- if (atomic_read(&cv.cv_condvar.cv_waiters) == (count - i))
- continue;
-
- splat_vprint(file, SPLAT_CONDVAR_TEST3_NAME, "Attempted to "
- "wake %d thread but work %d threads woke\n",
- 1, count - atomic_read(&cv.cv_condvar.cv_waiters));
- rc = -EINVAL;
- break;
- }
-
- /* Validate no waiting thread timed out early */
- for (i = 0; i < count; i++)
- if (ct[i].ct_rc)
- rc = ct[i].ct_rc;
-
- if (!rc)
- splat_vprint(file, SPLAT_CONDVAR_TEST3_NAME, "Correctly woke "
- "%d sleeping threads %d at a time\n", count, 1);
-
- /* Wait until that last nutex is dropped */
- while (mutex_owner(&cv.cv_mtx))
- schedule();
-
- /* Wake everything for the failure case */
- cv_broadcast(&cv.cv_condvar);
- cv_destroy(&cv.cv_condvar);
-
- /* wait for threads to exit */
- for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
- if (!IS_ERR(ct[i].ct_thread))
- kthread_stop(ct[i].ct_thread);
- }
- mutex_destroy(&cv.cv_mtx);
-
- return rc;
-}
-
-static int
-splat_condvar_test5(struct file *file, void *arg)
-{
- kcondvar_t condvar;
- kmutex_t mtx;
- clock_t time_left, time_before, time_after, time_delta;
- uint64_t whole_delta;
- uint32_t remain_delta;
- int rc = 0;
-
- mutex_init(&mtx, SPLAT_CONDVAR_TEST_NAME, MUTEX_DEFAULT, NULL);
- cv_init(&condvar, NULL, CV_DEFAULT, NULL);
-
- splat_vprint(file, SPLAT_CONDVAR_TEST5_NAME, "Thread going to sleep for "
- "%d second and expecting to be woken by timeout\n", 1);
-
- /* Allow a 1 second timeout, plenty long to validate correctness. */
- time_before = lbolt;
- mutex_enter(&mtx);
- time_left = cv_timedwait(&condvar, &mtx, lbolt + HZ);
- mutex_exit(&mtx);
- time_after = lbolt;
- time_delta = time_after - time_before; /* XXX - Handle jiffie wrap */
- whole_delta = time_delta;
- remain_delta = do_div(whole_delta, HZ);
-
- if (time_left == -1) {
- if (time_delta >= HZ) {
- splat_vprint(file, SPLAT_CONDVAR_TEST5_NAME,
- "Thread correctly timed out and was asleep "
- "for %d.%d seconds (%d second min)\n",
- (int)whole_delta, (int)remain_delta, 1);
- } else {
- splat_vprint(file, SPLAT_CONDVAR_TEST5_NAME,
- "Thread correctly timed out but was only "
- "asleep for %d.%d seconds (%d second "
- "min)\n", (int)whole_delta,
- (int)remain_delta, 1);
- rc = -ETIMEDOUT;
- }
- } else {
- splat_vprint(file, SPLAT_CONDVAR_TEST5_NAME,
- "Thread exited after only %d.%d seconds, it "
- "did not hit the %d second timeout\n",
- (int)whole_delta, (int)remain_delta, 1);
- rc = -ETIMEDOUT;
- }
-
- cv_destroy(&condvar);
- mutex_destroy(&mtx);
-
- return rc;
-}
-
-splat_subsystem_t *
-splat_condvar_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_CONDVAR_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_CONDVAR_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_CONDVAR;
-
- splat_test_init(sub, SPLAT_CONDVAR_TEST1_NAME, SPLAT_CONDVAR_TEST1_DESC,
- SPLAT_CONDVAR_TEST1_ID, splat_condvar_test1);
- splat_test_init(sub, SPLAT_CONDVAR_TEST2_NAME, SPLAT_CONDVAR_TEST2_DESC,
- SPLAT_CONDVAR_TEST2_ID, splat_condvar_test2);
- splat_test_init(sub, SPLAT_CONDVAR_TEST3_NAME, SPLAT_CONDVAR_TEST3_DESC,
- SPLAT_CONDVAR_TEST3_ID, splat_condvar_test3);
- splat_test_init(sub, SPLAT_CONDVAR_TEST4_NAME, SPLAT_CONDVAR_TEST4_DESC,
- SPLAT_CONDVAR_TEST4_ID, splat_condvar_test4);
- splat_test_init(sub, SPLAT_CONDVAR_TEST5_NAME, SPLAT_CONDVAR_TEST5_DESC,
- SPLAT_CONDVAR_TEST5_ID, splat_condvar_test5);
-
- return sub;
-}
-
-void
-splat_condvar_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
- splat_test_fini(sub, SPLAT_CONDVAR_TEST5_ID);
- splat_test_fini(sub, SPLAT_CONDVAR_TEST4_ID);
- splat_test_fini(sub, SPLAT_CONDVAR_TEST3_ID);
- splat_test_fini(sub, SPLAT_CONDVAR_TEST2_ID);
- splat_test_fini(sub, SPLAT_CONDVAR_TEST1_ID);
-
- kfree(sub);
-}
-
-int
-splat_condvar_id(void) {
- return SPLAT_SUBSYSTEM_CONDVAR;
-}
diff --git a/module/splat/splat-cred.c b/module/splat/splat-cred.c
deleted file mode 100644
index f13c0f752..000000000
--- a/module/splat/splat-cred.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Credential Tests.
- */
-
-#include <sys/cred.h>
-#include <sys/random.h>
-#include "splat-internal.h"
-
-#define SPLAT_CRED_NAME "cred"
-#define SPLAT_CRED_DESC "Kernel Cred Tests"
-
-#define SPLAT_CRED_TEST1_ID 0x0e01
-#define SPLAT_CRED_TEST1_NAME "cred"
-#define SPLAT_CRED_TEST1_DESC "Task Credential Test"
-
-#define SPLAT_CRED_TEST2_ID 0x0e02
-#define SPLAT_CRED_TEST2_NAME "kcred"
-#define SPLAT_CRED_TEST2_DESC "Kernel Credential Test"
-
-#define SPLAT_CRED_TEST3_ID 0x0e03
-#define SPLAT_CRED_TEST3_NAME "groupmember"
-#define SPLAT_CRED_TEST3_DESC "Group Member Test"
-
-#define GROUP_STR_SIZE 128
-#define GROUP_STR_REDZONE 16
-
-static int
-splat_cred_test1(struct file *file, void *arg)
-{
- char str[GROUP_STR_SIZE];
- uid_t uid, ruid, suid;
- gid_t gid, rgid, sgid, *groups;
- int ngroups, i, count = 0;
- cred_t *cr = CRED();
-
- uid = crgetuid(cr);
- ruid = crgetruid(cr);
- suid = crgetsuid(cr);
-
- gid = crgetgid(cr);
- rgid = crgetrgid(cr);
- sgid = crgetsgid(cr);
-
- ngroups = crgetngroups(cr);
- groups = crgetgroups(cr);
-
- memset(str, 0, GROUP_STR_SIZE);
- for (i = 0; i < ngroups; i++) {
- count += sprintf(str + count, "%d ", groups[i]);
-
- if (count > (GROUP_STR_SIZE - GROUP_STR_REDZONE)) {
- splat_vprint(file, SPLAT_CRED_TEST1_NAME,
- "Failed too many group entries for temp "
- "buffer: %d, %s\n", ngroups, str);
- return -ENOSPC;
- }
- }
-
- splat_vprint(file, SPLAT_CRED_TEST1_NAME,
- "uid: %d ruid: %d suid: %d "
- "gid: %d rgid: %d sgid: %d\n",
- uid, ruid, suid, gid, rgid, sgid);
- splat_vprint(file, SPLAT_CRED_TEST1_NAME,
- "ngroups: %d groups: %s\n", ngroups, str);
-
- if (uid || ruid || suid || gid || rgid || sgid) {
- splat_vprint(file, SPLAT_CRED_TEST1_NAME,
- "Failed expected all uids+gids to be %d\n", 0);
- return -EIDRM;
- }
-
- if (ngroups > NGROUPS_MAX) {
- splat_vprint(file, SPLAT_CRED_TEST1_NAME,
- "Failed ngroups must not exceed NGROUPS_MAX: "
- "%d > %d\n", ngroups, NGROUPS_MAX);
- return -EIDRM;
- }
-
- splat_vprint(file, SPLAT_CRED_TEST1_NAME,
- "Success sane CRED(): %d\n", 0);
-
- return 0;
-} /* splat_cred_test1() */
-
-static int
-splat_cred_test2(struct file *file, void *arg)
-{
- char str[GROUP_STR_SIZE];
- uid_t uid, ruid, suid;
- gid_t gid, rgid, sgid, *groups;
- int ngroups, i, count = 0;
-
- crhold(kcred);
-
- uid = crgetuid(kcred);
- ruid = crgetruid(kcred);
- suid = crgetsuid(kcred);
-
- gid = crgetgid(kcred);
- rgid = crgetrgid(kcred);
- sgid = crgetsgid(kcred);
-
- ngroups = crgetngroups(kcred);
- groups = crgetgroups(kcred);
-
- memset(str, 0, GROUP_STR_SIZE);
- for (i = 0; i < ngroups; i++) {
- count += sprintf(str + count, "%d ", groups[i]);
-
- if (count > (GROUP_STR_SIZE - GROUP_STR_REDZONE)) {
- splat_vprint(file, SPLAT_CRED_TEST2_NAME,
- "Failed too many group entries for temp "
- "buffer: %d, %s\n", ngroups, str);
- crfree(kcred);
- return -ENOSPC;
- }
- }
-
- crfree(kcred);
-
- splat_vprint(file, SPLAT_CRED_TEST2_NAME,
- "uid: %d ruid: %d suid: %d "
- "gid: %d rgid: %d sgid: %d\n",
- uid, ruid, suid, gid, rgid, sgid);
- splat_vprint(file, SPLAT_CRED_TEST2_NAME,
- "ngroups: %d groups: %s\n", ngroups, str);
-
- if (uid || ruid || suid || gid || rgid || sgid) {
- splat_vprint(file, SPLAT_CRED_TEST2_NAME,
- "Failed expected all uids+gids to be %d\n", 0);
- return -EIDRM;
- }
-
- if (ngroups > NGROUPS_MAX) {
- splat_vprint(file, SPLAT_CRED_TEST2_NAME,
- "Failed ngroups must not exceed NGROUPS_MAX: "
- "%d > %d\n", ngroups, NGROUPS_MAX);
- return -EIDRM;
- }
-
- splat_vprint(file, SPLAT_CRED_TEST2_NAME,
- "Success sane kcred: %d\n", 0);
-
- return 0;
-} /* splat_cred_test2() */
-
-#define SPLAT_NGROUPS 32
-/*
- * Verify the groupmember() works correctly by constructing an interesting
- * CRED() and checking that the expected gids are part of it.
- */
-static int
-splat_cred_test3(struct file *file, void *arg)
-{
- gid_t known_gid, missing_gid, tmp_gid;
- unsigned char rnd;
- struct group_info *gi;
- int i, rc;
-
- get_random_bytes((void *)&rnd, 1);
- known_gid = (rnd > 0) ? rnd : 1;
- missing_gid = 0;
-
- /*
- * Create an interesting known set of gids for test purposes. The
- * gids are pseudo randomly selected are will be in the range of
- * 1:(NGROUPS_MAX-1). Gid 0 is explicitly avoided so we can reliably
- * test for its absence in the test cases.
- */
- gi = groups_alloc(SPLAT_NGROUPS);
- if (gi == NULL) {
- splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed create "
- "group_info for known gids: %d\n", -ENOMEM);
- rc = -ENOMEM;
- goto show_groups;
- }
-
- for (i = 0, tmp_gid = known_gid; i < SPLAT_NGROUPS; i++) {
- splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Adding gid %d "
- "to current CRED() (%d/%d)\n", tmp_gid, i, gi->ngroups);
-#ifdef HAVE_KUIDGID_T
- GROUP_AT(gi, i) = make_kgid(current_user_ns(), tmp_gid);
-#else
- GROUP_AT(gi, i) = tmp_gid;
-#endif /* HAVE_KUIDGID_T */
- tmp_gid = ((tmp_gid * 17) % (NGROUPS_MAX - 1)) + 1;
- }
-
- /* Set the new groups in the CRED() and release our reference. */
- rc = set_current_groups(gi);
- put_group_info(gi);
-
- if (rc) {
- splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed to add "
- "gid %d to current group: %d\n", known_gid, rc);
- goto show_groups;
- }
-
- /* Verify groupmember() finds the known_gid in the CRED() */
- rc = groupmember(known_gid, CRED());
- if (!rc) {
- splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed to find "
- "known gid %d in CRED()'s groups.\n", known_gid);
- rc = -EIDRM;
- goto show_groups;
- }
-
- /* Verify groupmember() does NOT finds the missing gid in the CRED() */
- rc = groupmember(missing_gid, CRED());
- if (rc) {
- splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed missing "
- "gid %d was found in CRED()'s groups.\n", missing_gid);
- rc = -EIDRM;
- goto show_groups;
- }
-
- splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Success groupmember() "
- "correctly detects expected gids in CRED(): %d\n", rc);
-
-show_groups:
- if (rc) {
- int i, grps = crgetngroups(CRED());
-
- splat_vprint(file, SPLAT_CRED_TEST3_NAME, "%d groups: ", grps);
- for (i = 0; i < grps; i++)
- splat_print(file, "%d ", crgetgroups(CRED())[i]);
- splat_print(file, "%s", "\n");
- }
-
-
- return (rc);
-} /* splat_cred_test3() */
-
-splat_subsystem_t *
-splat_cred_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_CRED_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_CRED_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_CRED;
-
- splat_test_init(sub, SPLAT_CRED_TEST1_NAME, SPLAT_CRED_TEST1_DESC,
- SPLAT_CRED_TEST1_ID, splat_cred_test1);
- splat_test_init(sub, SPLAT_CRED_TEST2_NAME, SPLAT_CRED_TEST2_DESC,
- SPLAT_CRED_TEST2_ID, splat_cred_test2);
- splat_test_init(sub, SPLAT_CRED_TEST3_NAME, SPLAT_CRED_TEST3_DESC,
- SPLAT_CRED_TEST3_ID, splat_cred_test3);
-
- return sub;
-} /* splat_cred_init() */
-
-void
-splat_cred_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
-
- splat_test_fini(sub, SPLAT_CRED_TEST3_ID);
- splat_test_fini(sub, SPLAT_CRED_TEST2_ID);
- splat_test_fini(sub, SPLAT_CRED_TEST1_ID);
-
- kfree(sub);
-} /* splat_cred_fini() */
-
-int
-splat_cred_id(void)
-{
- return SPLAT_SUBSYSTEM_CRED;
-} /* splat_cred_id() */
diff --git a/module/splat/splat-ctl.c b/module/splat/splat-ctl.c
deleted file mode 100644
index cf6850100..000000000
--- a/module/splat/splat-ctl.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Test Control Interface.
- *
- * The 'splat' (Solaris Porting LAyer Tests) module is designed as a
- * framework which runs various in kernel regression tests to validate
- * the SPL primitives honor the Solaris ABI.
- *
- * The splat module is constructed of various splat_* source files each
- * of which contain regression tests for a particular subsystem. For
- * example, the splat_kmem.c file contains all the tests for validating
- * the kmem interfaces have been implemented correctly. When the splat
- * module is loaded splat_*_init() will be called for each subsystems
- * tests. It is the responsibility of splat_*_init() to register all
- * the tests for this subsystem using the splat_test_init().
- * Similarly splat_*_fini() is called when the splat module is removed
- * and is responsible for unregistering its tests via the splat_test_fini.
- * Once a test is registered it can then be run with an ioctl()
- * call which specifies the subsystem and test to be run. The provided
- * splat command line tool can be used to display all available
- * subsystems and tests. It can also be used to run the full suite
- * of regression tests or particular tests.
- */
-
-#include <sys/debug.h>
-#include <sys/mutex.h>
-#include <sys/types.h>
-#include <linux/cdev.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-#include "splat-internal.h"
-
-static struct list_head splat_module_list;
-static spinlock_t splat_module_lock;
-
-static int
-splat_open(struct inode *inode, struct file *file)
-{
- splat_info_t *info;
-
- info = (splat_info_t *)kmalloc(sizeof(*info), GFP_KERNEL);
- if (info == NULL)
- return -ENOMEM;
-
- mutex_init(&info->info_lock, SPLAT_NAME, MUTEX_DEFAULT, NULL);
- info->info_size = SPLAT_INFO_BUFFER_SIZE;
- info->info_buffer = (char *)vmalloc(SPLAT_INFO_BUFFER_SIZE);
- if (info->info_buffer == NULL) {
- kfree(info);
- return -ENOMEM;
- }
- memset(info->info_buffer, 0, info->info_size);
-
- info->info_head = info->info_buffer;
- file->private_data = (void *)info;
-
- splat_print(file, "%s\n", spl_version);
-
- return 0;
-}
-
-static int
-splat_release(struct inode *inode, struct file *file)
-{
- splat_info_t *info = (splat_info_t *)file->private_data;
-
- ASSERT(info);
- ASSERT(info->info_buffer);
-
- mutex_destroy(&info->info_lock);
- vfree(info->info_buffer);
- kfree(info);
-
- return 0;
-}
-
-static int
-splat_buffer_clear(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
-{
- splat_info_t *info = (splat_info_t *)file->private_data;
-
- ASSERT(info);
- ASSERT(info->info_buffer);
-
- mutex_enter(&info->info_lock);
- memset(info->info_buffer, 0, info->info_size);
- info->info_head = info->info_buffer;
- mutex_exit(&info->info_lock);
-
- return 0;
-}
-
-static int
-splat_buffer_size(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
-{
- splat_info_t *info = (splat_info_t *)file->private_data;
- char *buf;
- int min, size, rc = 0;
-
- ASSERT(info);
- ASSERT(info->info_buffer);
-
- mutex_enter(&info->info_lock);
- if (kcfg->cfg_arg1 > 0) {
-
- size = kcfg->cfg_arg1;
- buf = (char *)vmalloc(size);
- if (buf == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- /* Zero fill and truncate contents when coping buffer */
- min = ((size < info->info_size) ? size : info->info_size);
- memset(buf, 0, size);
- memcpy(buf, info->info_buffer, min);
- vfree(info->info_buffer);
- info->info_size = size;
- info->info_buffer = buf;
- info->info_head = info->info_buffer;
- }
-
- kcfg->cfg_rc1 = info->info_size;
-
- if (copy_to_user((struct splat_cfg_t __user *)arg, kcfg, sizeof(*kcfg)))
- rc = -EFAULT;
-out:
- mutex_exit(&info->info_lock);
-
- return rc;
-}
-
-
-static splat_subsystem_t *
-splat_subsystem_find(int id) {
- splat_subsystem_t *sub;
-
- spin_lock(&splat_module_lock);
- list_for_each_entry(sub, &splat_module_list, subsystem_list) {
- if (id == sub->desc.id) {
- spin_unlock(&splat_module_lock);
- return sub;
- }
- }
- spin_unlock(&splat_module_lock);
-
- return NULL;
-}
-
-static int
-splat_subsystem_count(splat_cfg_t *kcfg, unsigned long arg)
-{
- splat_subsystem_t *sub;
- int i = 0;
-
- spin_lock(&splat_module_lock);
- list_for_each_entry(sub, &splat_module_list, subsystem_list)
- i++;
-
- spin_unlock(&splat_module_lock);
- kcfg->cfg_rc1 = i;
-
- if (copy_to_user((struct splat_cfg_t __user *)arg, kcfg, sizeof(*kcfg)))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-splat_subsystem_list(splat_cfg_t *kcfg, unsigned long arg)
-{
- splat_subsystem_t *sub;
- splat_cfg_t *tmp;
- int size, i = 0;
-
- /* Structure will be sized large enough for N subsystem entries
- * which is passed in by the caller. On exit the number of
- * entries filled in with valid subsystems will be stored in
- * cfg_rc1. If the caller does not provide enough entries
- * for all subsystems we will truncate the list to avoid overrun.
- */
- size = sizeof(*tmp) + kcfg->cfg_data.splat_subsystems.size *
- sizeof(splat_user_t);
- tmp = kmalloc(size, GFP_KERNEL);
- if (tmp == NULL)
- return -ENOMEM;
-
- /* Local 'tmp' is used as the structure copied back to user space */
- memset(tmp, 0, size);
- memcpy(tmp, kcfg, sizeof(*kcfg));
-
- spin_lock(&splat_module_lock);
- list_for_each_entry(sub, &splat_module_list, subsystem_list) {
- strncpy(tmp->cfg_data.splat_subsystems.descs[i].name,
- sub->desc.name, SPLAT_NAME_SIZE);
- strncpy(tmp->cfg_data.splat_subsystems.descs[i].desc,
- sub->desc.desc, SPLAT_DESC_SIZE);
- tmp->cfg_data.splat_subsystems.descs[i].id = sub->desc.id;
-
- /* Truncate list if we are about to overrun alloc'ed memory */
- if ((i++) == kcfg->cfg_data.splat_subsystems.size)
- break;
- }
- spin_unlock(&splat_module_lock);
- tmp->cfg_rc1 = i;
-
- if (copy_to_user((struct splat_cfg_t __user *)arg, tmp, size)) {
- kfree(tmp);
- return -EFAULT;
- }
-
- kfree(tmp);
- return 0;
-}
-
-static int
-splat_test_count(splat_cfg_t *kcfg, unsigned long arg)
-{
- splat_subsystem_t *sub;
- splat_test_t *test;
- int i = 0;
-
- /* Subsystem ID passed as arg1 */
- sub = splat_subsystem_find(kcfg->cfg_arg1);
- if (sub == NULL)
- return -EINVAL;
-
- spin_lock(&(sub->test_lock));
- list_for_each_entry(test, &(sub->test_list), test_list)
- i++;
-
- spin_unlock(&(sub->test_lock));
- kcfg->cfg_rc1 = i;
-
- if (copy_to_user((struct splat_cfg_t __user *)arg, kcfg, sizeof(*kcfg)))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-splat_test_list(splat_cfg_t *kcfg, unsigned long arg)
-{
- splat_subsystem_t *sub;
- splat_test_t *test;
- splat_cfg_t *tmp;
- int size, i = 0;
-
- /* Subsystem ID passed as arg1 */
- sub = splat_subsystem_find(kcfg->cfg_arg1);
- if (sub == NULL)
- return -EINVAL;
-
- /* Structure will be sized large enough for N test entries
- * which is passed in by the caller. On exit the number of
- * entries filled in with valid tests will be stored in
- * cfg_rc1. If the caller does not provide enough entries
- * for all tests we will truncate the list to avoid overrun.
- */
- size = sizeof(*tmp)+kcfg->cfg_data.splat_tests.size*sizeof(splat_user_t);
- tmp = kmalloc(size, GFP_KERNEL);
- if (tmp == NULL)
- return -ENOMEM;
-
- /* Local 'tmp' is used as the structure copied back to user space */
- memset(tmp, 0, size);
- memcpy(tmp, kcfg, sizeof(*kcfg));
-
- spin_lock(&(sub->test_lock));
- list_for_each_entry(test, &(sub->test_list), test_list) {
- strncpy(tmp->cfg_data.splat_tests.descs[i].name,
- test->desc.name, SPLAT_NAME_SIZE);
- strncpy(tmp->cfg_data.splat_tests.descs[i].desc,
- test->desc.desc, SPLAT_DESC_SIZE);
- tmp->cfg_data.splat_tests.descs[i].id = test->desc.id;
-
- /* Truncate list if we are about to overrun alloc'ed memory */
- if ((i++) == kcfg->cfg_data.splat_tests.size)
- break;
- }
- spin_unlock(&(sub->test_lock));
- tmp->cfg_rc1 = i;
-
- if (copy_to_user((struct splat_cfg_t __user *)arg, tmp, size)) {
- kfree(tmp);
- return -EFAULT;
- }
-
- kfree(tmp);
- return 0;
-}
-
-static int
-splat_validate(struct file *file, splat_subsystem_t *sub, int cmd, void *arg)
-{
- splat_test_t *test;
-
- spin_lock(&(sub->test_lock));
- list_for_each_entry(test, &(sub->test_list), test_list) {
- if (test->desc.id == cmd) {
- spin_unlock(&(sub->test_lock));
- return test->test(file, arg);
- }
- }
- spin_unlock(&(sub->test_lock));
-
- return -EINVAL;
-}
-
-static int
-splat_ioctl_cfg(struct file *file, unsigned int cmd, unsigned long arg)
-{
- splat_cfg_t kcfg;
- int rc = 0;
-
- /* User and kernel space agree about arg size */
- if (_IOC_SIZE(cmd) != sizeof(kcfg))
- return -EBADMSG;
-
- if (copy_from_user(&kcfg, (splat_cfg_t *)arg, sizeof(kcfg)))
- return -EFAULT;
-
- if (kcfg.cfg_magic != SPLAT_CFG_MAGIC) {
- splat_print(file, "Bad config magic 0x%x != 0x%x\n",
- kcfg.cfg_magic, SPLAT_CFG_MAGIC);
- return -EINVAL;
- }
-
- switch (kcfg.cfg_cmd) {
- case SPLAT_CFG_BUFFER_CLEAR:
- /* cfg_arg1 - Unused
- * cfg_rc1 - Unused
- */
- rc = splat_buffer_clear(file, &kcfg, arg);
- break;
- case SPLAT_CFG_BUFFER_SIZE:
- /* cfg_arg1 - 0 - query size; >0 resize
- * cfg_rc1 - Set to current buffer size
- */
- rc = splat_buffer_size(file, &kcfg, arg);
- break;
- case SPLAT_CFG_SUBSYSTEM_COUNT:
- /* cfg_arg1 - Unused
- * cfg_rc1 - Set to number of subsystems
- */
- rc = splat_subsystem_count(&kcfg, arg);
- break;
- case SPLAT_CFG_SUBSYSTEM_LIST:
- /* cfg_arg1 - Unused
- * cfg_rc1 - Set to number of subsystems
- * cfg_data.splat_subsystems - Set with subsystems
- */
- rc = splat_subsystem_list(&kcfg, arg);
- break;
- case SPLAT_CFG_TEST_COUNT:
- /* cfg_arg1 - Set to a target subsystem
- * cfg_rc1 - Set to number of tests
- */
- rc = splat_test_count(&kcfg, arg);
- break;
- case SPLAT_CFG_TEST_LIST:
- /* cfg_arg1 - Set to a target subsystem
- * cfg_rc1 - Set to number of tests
- * cfg_data.splat_subsystems - Populated with tests
- */
- rc = splat_test_list(&kcfg, arg);
- break;
- default:
- splat_print(file, "Bad config command %d\n",
- kcfg.cfg_cmd);
- rc = -EINVAL;
- break;
- }
-
- return rc;
-}
-
-static int
-splat_ioctl_cmd(struct file *file, unsigned int cmd, unsigned long arg)
-{
- splat_subsystem_t *sub;
- splat_cmd_t kcmd;
- int rc = -EINVAL;
- void *data = NULL;
-
- /* User and kernel space agree about arg size */
- if (_IOC_SIZE(cmd) != sizeof(kcmd))
- return -EBADMSG;
-
- if (copy_from_user(&kcmd, (splat_cfg_t *)arg, sizeof(kcmd)))
- return -EFAULT;
-
- if (kcmd.cmd_magic != SPLAT_CMD_MAGIC) {
- splat_print(file, "Bad command magic 0x%x != 0x%x\n",
- kcmd.cmd_magic, SPLAT_CFG_MAGIC);
- return -EINVAL;
- }
-
- /* Allocate memory for any opaque data the caller needed to pass on */
- if (kcmd.cmd_data_size > 0) {
- data = (void *)kmalloc(kcmd.cmd_data_size, GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(data, (void *)(arg + offsetof(splat_cmd_t,
- cmd_data_str)), kcmd.cmd_data_size)) {
- kfree(data);
- return -EFAULT;
- }
- }
-
- sub = splat_subsystem_find(kcmd.cmd_subsystem);
- if (sub != NULL)
- rc = splat_validate(file, sub, kcmd.cmd_test, data);
- else
- rc = -EINVAL;
-
- if (data != NULL)
- kfree(data);
-
- return rc;
-}
-
-static long
-splat_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- int rc = 0;
-
- /* Ignore tty ioctls */
- if ((cmd & 0xffffff00) == ((int)'T') << 8)
- return -ENOTTY;
-
- switch (cmd) {
- case SPLAT_CFG:
- rc = splat_ioctl_cfg(file, cmd, arg);
- break;
- case SPLAT_CMD:
- rc = splat_ioctl_cmd(file, cmd, arg);
- break;
- default:
- splat_print(file, "Bad ioctl command %d\n", cmd);
- rc = -EINVAL;
- break;
- }
-
- return rc;
-}
-
-#ifdef CONFIG_COMPAT
-/* Compatibility handler for ioctls from 32-bit ELF binaries */
-static long
-splat_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- return splat_unlocked_ioctl(file, cmd, arg);
-}
-#endif /* CONFIG_COMPAT */
-
-/* I'm not sure why you would want to write in to this buffer from
- * user space since its principle use is to pass test status info
- * back to the user space, but I don't see any reason to prevent it.
- */
-static ssize_t splat_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- splat_info_t *info = (splat_info_t *)file->private_data;
- int rc = 0;
-
- ASSERT(info);
- ASSERT(info->info_buffer);
-
- mutex_enter(&info->info_lock);
-
- /* Write beyond EOF */
- if (*ppos >= info->info_size) {
- rc = -EFBIG;
- goto out;
- }
-
- /* Resize count if beyond EOF */
- if (*ppos + count > info->info_size)
- count = info->info_size - *ppos;
-
- if (copy_from_user(info->info_buffer, buf, count)) {
- rc = -EFAULT;
- goto out;
- }
-
- *ppos += count;
- rc = count;
-out:
- mutex_exit(&info->info_lock);
- return rc;
-}
-
-static ssize_t splat_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- splat_info_t *info = (splat_info_t *)file->private_data;
- int rc = 0;
-
- ASSERT(info);
- ASSERT(info->info_buffer);
-
- mutex_enter(&info->info_lock);
-
- /* Read beyond EOF */
- if (*ppos >= info->info_size)
- goto out;
-
- /* Resize count if beyond EOF */
- if (*ppos + count > info->info_size)
- count = info->info_size - *ppos;
-
- if (copy_to_user(buf, info->info_buffer + *ppos, count)) {
- rc = -EFAULT;
- goto out;
- }
-
- *ppos += count;
- rc = count;
-out:
- mutex_exit(&info->info_lock);
- return rc;
-}
-
-static loff_t splat_seek(struct file *file, loff_t offset, int origin)
-{
- splat_info_t *info = (splat_info_t *)file->private_data;
- int rc = -EINVAL;
-
- ASSERT(info);
- ASSERT(info->info_buffer);
-
- mutex_enter(&info->info_lock);
-
- switch (origin) {
- case 0: /* SEEK_SET - No-op just do it */
- break;
- case 1: /* SEEK_CUR - Seek from current */
- offset = file->f_pos + offset;
- break;
- case 2: /* SEEK_END - Seek from end */
- offset = info->info_size + offset;
- break;
- }
-
- if (offset >= 0) {
- file->f_pos = offset;
- file->f_version = 0;
- rc = offset;
- }
-
- mutex_exit(&info->info_lock);
-
- return rc;
-}
-
-static struct file_operations splat_fops = {
- .owner = THIS_MODULE,
- .open = splat_open,
- .release = splat_release,
- .unlocked_ioctl = splat_unlocked_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = splat_compat_ioctl,
-#endif
- .read = splat_read,
- .write = splat_write,
- .llseek = splat_seek,
-};
-
-static struct miscdevice splat_misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = SPLAT_NAME,
- .fops = &splat_fops,
-};
-
-static void splat_subsystem_init(const char *name,
- splat_subsystem_t *(*init)(void))
-{
- splat_subsystem_t *sub;
- sub = init();
- if (sub == NULL) {
- printk(KERN_ERR "splat: Error initializing: %s\n", name);
- return;
- }
- spin_lock(&splat_module_lock);
- list_add_tail(&sub->subsystem_list, &splat_module_list);
- spin_unlock(&splat_module_lock);
-}
-
-static void splat_subsystem_fini(const char *name,
- int (*id_func)(void), void (*fini)(splat_subsystem_t *))
-{
- splat_subsystem_t *sub, *tmp;
- int id, flag = 0;
-
- id = id_func();
- spin_lock(&splat_module_lock);
- list_for_each_entry_safe(sub, tmp, &splat_module_list, subsystem_list) {
- if (sub->desc.id == id) {
- list_del_init(&sub->subsystem_list);
- flag = 1;
- break;
- }
- }
- spin_unlock(&splat_module_lock);
- if (flag == 0)
- printk(KERN_ERR "splat: Error finalizing: %s\n", name);
- else
- fini(sub);
-}
-
-#define SPLAT_SUBSYSTEM_INIT(type) \
- splat_subsystem_init(#type, splat_##type##_init)
-#define SPLAT_SUBSYSTEM_FINI(type) \
- splat_subsystem_fini(#type, splat_##type##_id, splat_##type##_fini)
-
-void splat_test_init(splat_subsystem_t *sub, const char *name,
- const char *desc, unsigned int tid, splat_test_func_t func)
-{
- splat_test_t *test;
- test = kmalloc(sizeof (splat_test_t), GFP_KERNEL);
- if (test == NULL) {
- printk(KERN_ERR "splat: Error initializing: %s/%u\n",
- name, tid);
- return;
- }
- memset(test, 0, sizeof (splat_test_t));
- strncpy(test->desc.name, name, SPLAT_NAME_SIZE-1);
- strncpy(test->desc.desc, desc, SPLAT_DESC_SIZE-1);
- test->desc.id = tid;
- test->test = func;
- INIT_LIST_HEAD(&test->test_list);
- spin_lock(&sub->test_lock);
- list_add_tail(&test->test_list, &sub->test_list);
- spin_unlock(&sub->test_lock);
-}
-
-void splat_test_fini(splat_subsystem_t *sub, unsigned int tid)
-{
- splat_test_t *test, *tmp;
- int flag = 0;
-
- spin_lock(&sub->test_lock);
- list_for_each_entry_safe(test, tmp, &sub->test_list, test_list) {
- if (test->desc.id == tid) {
- list_del_init(&test->test_list);
- kfree(test);
- flag = 1;
- break;
- }
- }
- spin_unlock(&sub->test_lock);
-
- if (flag == 0)
- printk(KERN_ERR "splat: Error finalizing: %u\n", tid);
-}
-
-static int __init
-splat_init(void)
-{
- int error;
-
- spin_lock_init(&splat_module_lock);
- INIT_LIST_HEAD(&splat_module_list);
-
- SPLAT_SUBSYSTEM_INIT(kmem);
- SPLAT_SUBSYSTEM_INIT(taskq);
- SPLAT_SUBSYSTEM_INIT(krng);
- SPLAT_SUBSYSTEM_INIT(mutex);
- SPLAT_SUBSYSTEM_INIT(condvar);
- SPLAT_SUBSYSTEM_INIT(thread);
- SPLAT_SUBSYSTEM_INIT(rwlock);
- SPLAT_SUBSYSTEM_INIT(time);
- SPLAT_SUBSYSTEM_INIT(vnode);
- SPLAT_SUBSYSTEM_INIT(kobj);
- SPLAT_SUBSYSTEM_INIT(atomic);
- SPLAT_SUBSYSTEM_INIT(list);
- SPLAT_SUBSYSTEM_INIT(generic);
- SPLAT_SUBSYSTEM_INIT(cred);
- SPLAT_SUBSYSTEM_INIT(zlib);
- SPLAT_SUBSYSTEM_INIT(linux);
-
- error = misc_register(&splat_misc);
- if (error) {
- printk(KERN_INFO "SPLAT: misc_register() failed %d\n", error);
- } else {
- printk(KERN_INFO "SPLAT: Loaded module v%s-%s%s\n",
- SPL_META_VERSION, SPL_META_RELEASE, SPL_DEBUG_STR);
- }
-
- return (error);
-}
-
-static void __exit
-splat_fini(void)
-{
- misc_deregister(&splat_misc);
-
- SPLAT_SUBSYSTEM_FINI(linux);
- SPLAT_SUBSYSTEM_FINI(zlib);
- SPLAT_SUBSYSTEM_FINI(cred);
- SPLAT_SUBSYSTEM_FINI(generic);
- SPLAT_SUBSYSTEM_FINI(list);
- SPLAT_SUBSYSTEM_FINI(atomic);
- SPLAT_SUBSYSTEM_FINI(kobj);
- SPLAT_SUBSYSTEM_FINI(vnode);
- SPLAT_SUBSYSTEM_FINI(time);
- SPLAT_SUBSYSTEM_FINI(rwlock);
- SPLAT_SUBSYSTEM_FINI(thread);
- SPLAT_SUBSYSTEM_FINI(condvar);
- SPLAT_SUBSYSTEM_FINI(mutex);
- SPLAT_SUBSYSTEM_FINI(krng);
- SPLAT_SUBSYSTEM_FINI(taskq);
- SPLAT_SUBSYSTEM_FINI(kmem);
-
- ASSERT(list_empty(&splat_module_list));
- printk(KERN_INFO "SPLAT: Unloaded module v%s-%s%s\n",
- SPL_META_VERSION, SPL_META_RELEASE, SPL_DEBUG_STR);
-}
-
-module_init(splat_init);
-module_exit(splat_fini);
-
-MODULE_DESCRIPTION("Solaris Porting LAyer Tests");
-MODULE_AUTHOR(SPL_META_AUTHOR);
-MODULE_LICENSE(SPL_META_LICENSE);
-MODULE_VERSION(SPL_META_VERSION "-" SPL_META_RELEASE);
diff --git a/module/splat/splat-generic.c b/module/splat/splat-generic.c
deleted file mode 100644
index e256c83f0..000000000
--- a/module/splat/splat-generic.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Generic Tests.
- */
-
-#include <sys/sunddi.h>
-#include <linux/math64_compat.h>
-#include "splat-internal.h"
-
-#define SPLAT_GENERIC_NAME "generic"
-#define SPLAT_GENERIC_DESC "Kernel Generic Tests"
-
-#define SPLAT_GENERIC_TEST1_ID 0x0d01
-#define SPLAT_GENERIC_TEST1_NAME "ddi_strtoul"
-#define SPLAT_GENERIC_TEST1_DESC "ddi_strtoul Test"
-
-#define SPLAT_GENERIC_TEST2_ID 0x0d02
-#define SPLAT_GENERIC_TEST2_NAME "ddi_strtol"
-#define SPLAT_GENERIC_TEST2_DESC "ddi_strtol Test"
-
-#define SPLAT_GENERIC_TEST3_ID 0x0d03
-#define SPLAT_GENERIC_TEST3_NAME "ddi_strtoull"
-#define SPLAT_GENERIC_TEST3_DESC "ddi_strtoull Test"
-
-#define SPLAT_GENERIC_TEST4_ID 0x0d04
-#define SPLAT_GENERIC_TEST4_NAME "ddi_strtoll"
-#define SPLAT_GENERIC_TEST4_DESC "ddi_strtoll Test"
-
-# define SPLAT_GENERIC_TEST5_ID 0x0d05
-# define SPLAT_GENERIC_TEST5_NAME "udivdi3"
-# define SPLAT_GENERIC_TEST5_DESC "Unsigned Div-64 Test"
-
-# define SPLAT_GENERIC_TEST6_ID 0x0d06
-# define SPLAT_GENERIC_TEST6_NAME "divdi3"
-# define SPLAT_GENERIC_TEST6_DESC "Signed Div-64 Test"
-
-#define STR_POS "123456789"
-#define STR_NEG "-123456789"
-#define STR_BASE "0xabcdef"
-#define STR_RANGE_MAX "10000000000000000"
-#define STR_RANGE_MIN "-10000000000000000"
-#define STR_INVAL1 "12345U"
-#define STR_INVAL2 "invald"
-
-#define VAL_POS 123456789
-#define VAL_NEG -123456789
-#define VAL_BASE 0xabcdef
-#define VAL_INVAL1 12345U
-
-#define define_generic_msg_strtox(type, valtype) \
-static void \
-generic_msg_strto##type(struct file *file, char *msg, int rc, int *err, \
- const char *s, valtype d, char *endptr) \
-{ \
- splat_vprint(file, SPLAT_GENERIC_TEST1_NAME, \
- "%s (%d) %s: %s == %lld, 0x%p\n", \
- rc ? "Fail" : "Pass", *err, msg, s, \
- (unsigned long long)d, endptr); \
- *err = rc; \
-}
-
-define_generic_msg_strtox(ul, unsigned long);
-define_generic_msg_strtox(l, long);
-define_generic_msg_strtox(ull, unsigned long long);
-define_generic_msg_strtox(ll, long long);
-
-#define define_splat_generic_test_strtox(type, valtype) \
-static int \
-splat_generic_test_strto##type(struct file *file, void *arg) \
-{ \
- int rc, rc1, rc2, rc3, rc4, rc5, rc6, rc7; \
- char str[20], *endptr; \
- valtype r; \
- \
- /* Positive value: expect success */ \
- r = 0; \
- rc = 1; \
- endptr = NULL; \
- rc1 = ddi_strto##type(STR_POS, &endptr, 10, &r); \
- if (rc1 == 0 && r == VAL_POS && endptr && *endptr == '\0') \
- rc = 0; \
- \
- generic_msg_strto##type(file, "positive", rc , &rc1, \
- STR_POS, r, endptr); \
- \
- /* Negative value: expect success */ \
- r = 0; \
- rc = 1; \
- endptr = NULL; \
- strcpy(str, STR_NEG); \
- rc2 = ddi_strto##type(str, &endptr, 10, &r); \
- if (#type[0] == 'u') { \
- if (rc2 == 0 && r == 0 && endptr == str) \
- rc = 0; \
- } else { \
- if (rc2 == 0 && r == VAL_NEG && \
- endptr && *endptr == '\0') \
- rc = 0; \
- } \
- \
- generic_msg_strto##type(file, "negative", rc, &rc2, \
- STR_NEG, r, endptr); \
- \
- /* Non decimal base: expect sucess */ \
- r = 0; \
- rc = 1; \
- endptr = NULL; \
- rc3 = ddi_strto##type(STR_BASE, &endptr, 0, &r); \
- if (rc3 == 0 && r == VAL_BASE && endptr && *endptr == '\0') \
- rc = 0; \
- \
- generic_msg_strto##type(file, "base", rc, &rc3, \
- STR_BASE, r, endptr); \
- \
- /* Max out of range: failure expected, r unchanged */ \
- r = 0; \
- rc = 1; \
- endptr = NULL; \
- rc4 = ddi_strto##type(STR_RANGE_MAX, &endptr, 16, &r); \
- if (rc4 == ERANGE && r == 0 && endptr == NULL) \
- rc = 0; \
- \
- generic_msg_strto##type(file, "max", rc, &rc4, \
- STR_RANGE_MAX, r, endptr); \
- \
- /* Min out of range: failure expected, r unchanged */ \
- r = 0; \
- rc = 1; \
- endptr = NULL; \
- strcpy(str, STR_RANGE_MIN); \
- rc5 = ddi_strto##type(str, &endptr, 16, &r); \
- if (#type[0] == 'u') { \
- if (rc5 == 0 && r == 0 && endptr == str) \
- rc = 0; \
- } else { \
- if (rc5 == ERANGE && r == 0 && endptr == NULL) \
- rc = 0; \
- } \
- \
- generic_msg_strto##type(file, "min", rc, &rc5, \
- STR_RANGE_MIN, r, endptr); \
- \
- /* Invalid string: success expected, endptr == 'U' */ \
- r = 0; \
- rc = 1; \
- endptr = NULL; \
- rc6 = ddi_strto##type(STR_INVAL1, &endptr, 10, &r); \
- if (rc6 == 0 && r == VAL_INVAL1 && endptr && *endptr == 'U') \
- rc = 0; \
- \
- generic_msg_strto##type(file, "invalid", rc, &rc6, \
- STR_INVAL1, r, endptr); \
- \
- /* Invalid string: failure expected, endptr == str */ \
- r = 0; \
- rc = 1; \
- endptr = NULL; \
- strcpy(str, STR_INVAL2); \
- rc7 = ddi_strto##type(str, &endptr, 10, &r); \
- if (rc7 == 0 && r == 0 && endptr == str) \
- rc = 0; \
- \
- generic_msg_strto##type(file, "invalid", rc, &rc7, \
- STR_INVAL2, r, endptr); \
- \
- return (rc1 || rc2 || rc3 || rc4 || rc5 || rc6 || rc7) ? \
- -EINVAL : 0; \
-}
-
-define_splat_generic_test_strtox(ul, unsigned long);
-define_splat_generic_test_strtox(l, long);
-define_splat_generic_test_strtox(ull, unsigned long long);
-define_splat_generic_test_strtox(ll, long long);
-
-/*
- * The entries in the table are used in all combinations and the
- * return value is checked to ensure it is range. On 32-bit
- * systems __udivdi3 will be invoked for the 64-bit division.
- * On 64-bit system the native 64-bit divide will be used so
- * __udivdi3 isn't used but we might as well stil run the test.
- */
-static int
-splat_generic_test_udivdi3(struct file *file, void *arg)
-{
- const uint64_t tabu[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 1000, 2003,
- 32765, 32766, 32767, 32768, 32769, 32760,
- 65533, 65534, 65535, 65536, 65537, 65538,
- 0x7ffffffeULL, 0x7fffffffULL, 0x80000000ULL, 0x80000001ULL,
- 0x7000000000000000ULL, 0x7000000080000000ULL, 0x7000000080000001ULL,
- 0x7fffffffffffffffULL, 0x7fffffff8fffffffULL, 0x7fffffff8ffffff1ULL,
- 0x7fffffff00000000ULL, 0x7fffffff80000000ULL, 0x7fffffff00000001ULL,
- 0x8000000000000000ULL, 0x8000000080000000ULL, 0x8000000080000001ULL,
- 0xc000000000000000ULL, 0xc000000080000000ULL, 0xc000000080000001ULL,
- 0xfffffffffffffffdULL, 0xfffffffffffffffeULL, 0xffffffffffffffffULL,
- };
- uint64_t uu, vu, qu, ru;
- int n, i, j, errors = 0;
-
- splat_vprint(file, SPLAT_GENERIC_TEST5_NAME, "%s",
- "Testing unsigned 64-bit division.\n");
- n = sizeof(tabu) / sizeof(tabu[0]);
- for (i = 0; i < n; i++) {
- for (j = 1; j < n; j++) {
- uu = tabu[i];
- vu = tabu[j];
- qu = uu / vu; /* __udivdi3 */
- ru = uu - qu * vu;
- if (qu > uu || ru >= vu) {
- splat_vprint(file, SPLAT_GENERIC_TEST5_NAME,
- "%016llx/%016llx != %016llx rem %016llx\n",
- uu, vu, qu, ru);
- errors++;
- }
- }
- }
-
- if (errors) {
- splat_vprint(file, SPLAT_GENERIC_TEST5_NAME,
- "Failed %d/%d tests\n", errors, n * (n - 1));
- return -ERANGE;
- }
-
- splat_vprint(file, SPLAT_GENERIC_TEST5_NAME,
- "Passed all %d tests\n", n * (n - 1));
-
- return 0;
-}
-
-/*
- * The entries the table are used in all combinations, with + and - signs
- * preceding them. The return value is checked to ensure it is range.
- * On 32-bit systems __divdi3 will be invoked for the 64-bit division.
- * On 64-bit system the native 64-bit divide will be used so __divdi3
- * isn't used but we might as well stil run the test.
- */
-static int
-splat_generic_test_divdi3(struct file *file, void *arg)
-{
- const int64_t tabs[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 1000, 2003,
- 32765, 32766, 32767, 32768, 32769, 32760,
- 65533, 65534, 65535, 65536, 65537, 65538,
- 0x7ffffffeLL, 0x7fffffffLL, 0x80000000LL, 0x80000001LL,
- 0x7000000000000000LL, 0x7000000080000000LL, 0x7000000080000001LL,
- 0x7fffffffffffffffLL, 0x7fffffff8fffffffLL, 0x7fffffff8ffffff1LL,
- 0x7fffffff00000000LL, 0x7fffffff80000000LL, 0x7fffffff00000001LL,
- 0x0123456789abcdefLL, 0x00000000abcdef01LL, 0x0000000012345678LL,
-#if BITS_PER_LONG == 32
- 0x8000000000000000LL, 0x8000000080000000LL, 0x8000000080000001LL,
-#endif
- };
- int64_t u, v, q, r;
- int n, i, j, k, errors = 0;
-
- splat_vprint(file, SPLAT_GENERIC_TEST6_NAME, "%s",
- "Testing signed 64-bit division.\n");
- n = sizeof(tabs) / sizeof(tabs[0]);
- for (i = 0; i < n; i++) {
- for (j = 1; j < n; j++) {
- for (k = 0; k <= 3; k++) {
- u = (k & 1) ? -tabs[i] : tabs[i];
- v = (k >= 2) ? -tabs[j] : tabs[j];
-
- q = u / v; /* __divdi3 */
- r = u - q * v;
- if (abs64(q) > abs64(u) ||
- abs64(r) >= abs64(v) ||
- (r != 0 && (r ^ u) < 0)) {
- splat_vprint(file,
- SPLAT_GENERIC_TEST6_NAME,
- "%016llx/%016llx != %016llx "
- "rem %016llx\n", u, v, q, r);
- errors++;
- }
- }
- }
- }
-
- if (errors) {
- splat_vprint(file, SPLAT_GENERIC_TEST6_NAME,
- "Failed %d/%d tests\n", errors, n * (n - 1));
- return -ERANGE;
- }
-
- splat_vprint(file, SPLAT_GENERIC_TEST6_NAME,
- "Passed all %d tests\n", n * (n - 1));
-
- return 0;
-}
-
-splat_subsystem_t *
-splat_generic_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_GENERIC_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_GENERIC_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_GENERIC;
-
- splat_test_init(sub, SPLAT_GENERIC_TEST1_NAME, SPLAT_GENERIC_TEST1_DESC,
- SPLAT_GENERIC_TEST1_ID, splat_generic_test_strtoul);
- splat_test_init(sub, SPLAT_GENERIC_TEST2_NAME, SPLAT_GENERIC_TEST2_DESC,
- SPLAT_GENERIC_TEST2_ID, splat_generic_test_strtol);
- splat_test_init(sub, SPLAT_GENERIC_TEST3_NAME, SPLAT_GENERIC_TEST3_DESC,
- SPLAT_GENERIC_TEST3_ID, splat_generic_test_strtoull);
- splat_test_init(sub, SPLAT_GENERIC_TEST4_NAME, SPLAT_GENERIC_TEST4_DESC,
- SPLAT_GENERIC_TEST4_ID, splat_generic_test_strtoll);
- splat_test_init(sub, SPLAT_GENERIC_TEST5_NAME, SPLAT_GENERIC_TEST5_DESC,
- SPLAT_GENERIC_TEST5_ID, splat_generic_test_udivdi3);
- splat_test_init(sub, SPLAT_GENERIC_TEST6_NAME, SPLAT_GENERIC_TEST6_DESC,
- SPLAT_GENERIC_TEST6_ID, splat_generic_test_divdi3);
-
- return sub;
-}
-
-void
-splat_generic_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
-
- splat_test_fini(sub, SPLAT_GENERIC_TEST6_ID);
- splat_test_fini(sub, SPLAT_GENERIC_TEST5_ID);
- splat_test_fini(sub, SPLAT_GENERIC_TEST4_ID);
- splat_test_fini(sub, SPLAT_GENERIC_TEST3_ID);
- splat_test_fini(sub, SPLAT_GENERIC_TEST2_ID);
- splat_test_fini(sub, SPLAT_GENERIC_TEST1_ID);
-
- kfree(sub);
-}
-
-int
-splat_generic_id(void)
-{
- return SPLAT_SUBSYSTEM_GENERIC;
-}
diff --git a/module/splat/splat-internal.h b/module/splat/splat-internal.h
deleted file mode 100644
index 97c10acfd..000000000
--- a/module/splat/splat-internal.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _SPLAT_INTERNAL_H
-#define _SPLAT_INTERNAL_H
-
-#include "splat-ctl.h"
-#include <sys/mutex.h>
-#include <linux/file_compat.h>
-#include <linux/version.h>
-
-typedef int (*splat_test_func_t)(struct file *, void *);
-
-typedef struct splat_test {
- struct list_head test_list;
- splat_user_t desc;
- splat_test_func_t test;
-} splat_test_t;
-
-typedef struct splat_subsystem {
- struct list_head subsystem_list;/* List had to chain entries */
- splat_user_t desc;
- spinlock_t test_lock;
- struct list_head test_list;
-} splat_subsystem_t;
-
-void splat_test_init(splat_subsystem_t *sub, const char *name,
- const char *desc, unsigned int tid, splat_test_func_t func);
-void splat_test_fini(splat_subsystem_t *sub, unsigned int tid);
-
-#define SPLAT_INFO_BUFFER_SIZE 65536
-#define SPLAT_INFO_BUFFER_REDZONE 256
-
-typedef struct splat_info {
- kmutex_t info_lock;
- int info_size;
- char *info_buffer;
- char *info_head; /* Internal kernel use only */
-} splat_info_t;
-
-#define sym2str(sym) (char *)(#sym)
-
-#define splat_print(file, format, args...) \
-({ splat_info_t *_info_ = (splat_info_t *)file->private_data; \
- int _rc_; \
- \
- ASSERT(_info_); \
- ASSERT(_info_->info_buffer); \
- \
- mutex_enter(&_info_->info_lock); \
- \
- /* Don't allow the kernel to start a write in the red zone */ \
- if ((int)(_info_->info_head - _info_->info_buffer) > \
- (SPLAT_INFO_BUFFER_SIZE - SPLAT_INFO_BUFFER_REDZONE)) { \
- _rc_ = -EOVERFLOW; \
- } else { \
- _rc_ = sprintf(_info_->info_head, format, args); \
- if (_rc_ >= 0) \
- _info_->info_head += _rc_; \
- } \
- \
- mutex_exit(&_info_->info_lock); \
- _rc_; \
-})
-
-#define splat_vprint(file, test, format, args...) \
- splat_print(file, "%*s: " format, SPLAT_NAME_SIZE, test, args)
-
-#define splat_locked_test(lock, test) \
-({ \
- int _rc_; \
- spin_lock(lock); \
- _rc_ = (test) ? 1 : 0; \
- spin_unlock(lock); \
- _rc_; \
-})
-
-splat_subsystem_t *splat_condvar_init(void);
-splat_subsystem_t *splat_kmem_init(void);
-splat_subsystem_t *splat_mutex_init(void);
-splat_subsystem_t *splat_krng_init(void);
-splat_subsystem_t *splat_rwlock_init(void);
-splat_subsystem_t *splat_taskq_init(void);
-splat_subsystem_t *splat_thread_init(void);
-splat_subsystem_t *splat_time_init(void);
-splat_subsystem_t *splat_vnode_init(void);
-splat_subsystem_t *splat_kobj_init(void);
-splat_subsystem_t *splat_atomic_init(void);
-splat_subsystem_t *splat_list_init(void);
-splat_subsystem_t *splat_generic_init(void);
-splat_subsystem_t *splat_cred_init(void);
-splat_subsystem_t *splat_zlib_init(void);
-splat_subsystem_t *splat_linux_init(void);
-
-void splat_condvar_fini(splat_subsystem_t *);
-void splat_kmem_fini(splat_subsystem_t *);
-void splat_mutex_fini(splat_subsystem_t *);
-void splat_krng_fini(splat_subsystem_t *);
-void splat_rwlock_fini(splat_subsystem_t *);
-void splat_taskq_fini(splat_subsystem_t *);
-void splat_thread_fini(splat_subsystem_t *);
-void splat_time_fini(splat_subsystem_t *);
-void splat_vnode_fini(splat_subsystem_t *);
-void splat_kobj_fini(splat_subsystem_t *);
-void splat_atomic_fini(splat_subsystem_t *);
-void splat_list_fini(splat_subsystem_t *);
-void splat_generic_fini(splat_subsystem_t *);
-void splat_cred_fini(splat_subsystem_t *);
-void splat_zlib_fini(splat_subsystem_t *);
-void splat_linux_fini(splat_subsystem_t *);
-
-int splat_condvar_id(void);
-int splat_kmem_id(void);
-int splat_mutex_id(void);
-int splat_krng_id(void);
-int splat_rwlock_id(void);
-int splat_taskq_id(void);
-int splat_thread_id(void);
-int splat_time_id(void);
-int splat_vnode_id(void);
-int splat_kobj_id(void);
-int splat_atomic_id(void);
-int splat_list_id(void);
-int splat_generic_id(void);
-int splat_cred_id(void);
-int splat_zlib_id(void);
-int splat_linux_id(void);
-
-#endif /* _SPLAT_INTERNAL_H */
diff --git a/module/splat/splat-kmem.c b/module/splat/splat-kmem.c
deleted file mode 100644
index 282f42d77..000000000
--- a/module/splat/splat-kmem.c
+++ /dev/null
@@ -1,1410 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Kmem Tests.
- */
-
-#include <sys/kmem.h>
-#include <sys/kmem_cache.h>
-#include <sys/vmem.h>
-#include <sys/random.h>
-#include <sys/thread.h>
-#include <sys/vmsystm.h>
-#include "splat-internal.h"
-
-#define SPLAT_KMEM_NAME "kmem"
-#define SPLAT_KMEM_DESC "Kernel Malloc/Slab Tests"
-
-#define SPLAT_KMEM_TEST1_ID 0x0101
-#define SPLAT_KMEM_TEST1_NAME "kmem_alloc"
-#define SPLAT_KMEM_TEST1_DESC "Memory allocation test (kmem_alloc)"
-
-#define SPLAT_KMEM_TEST2_ID 0x0102
-#define SPLAT_KMEM_TEST2_NAME "kmem_zalloc"
-#define SPLAT_KMEM_TEST2_DESC "Memory allocation test (kmem_zalloc)"
-
-#define SPLAT_KMEM_TEST3_ID 0x0103
-#define SPLAT_KMEM_TEST3_NAME "vmem_alloc"
-#define SPLAT_KMEM_TEST3_DESC "Memory allocation test (vmem_alloc)"
-
-#define SPLAT_KMEM_TEST4_ID 0x0104
-#define SPLAT_KMEM_TEST4_NAME "vmem_zalloc"
-#define SPLAT_KMEM_TEST4_DESC "Memory allocation test (vmem_zalloc)"
-
-#define SPLAT_KMEM_TEST5_ID 0x0105
-#define SPLAT_KMEM_TEST5_NAME "slab_small"
-#define SPLAT_KMEM_TEST5_DESC "Slab ctor/dtor test (small)"
-
-#define SPLAT_KMEM_TEST6_ID 0x0106
-#define SPLAT_KMEM_TEST6_NAME "slab_large"
-#define SPLAT_KMEM_TEST6_DESC "Slab ctor/dtor test (large)"
-
-#define SPLAT_KMEM_TEST7_ID 0x0107
-#define SPLAT_KMEM_TEST7_NAME "slab_align"
-#define SPLAT_KMEM_TEST7_DESC "Slab alignment test"
-
-#define SPLAT_KMEM_TEST8_ID 0x0108
-#define SPLAT_KMEM_TEST8_NAME "slab_reap"
-#define SPLAT_KMEM_TEST8_DESC "Slab reaping test"
-
-#define SPLAT_KMEM_TEST9_ID 0x0109
-#define SPLAT_KMEM_TEST9_NAME "slab_age"
-#define SPLAT_KMEM_TEST9_DESC "Slab aging test"
-
-#define SPLAT_KMEM_TEST10_ID 0x010a
-#define SPLAT_KMEM_TEST10_NAME "slab_lock"
-#define SPLAT_KMEM_TEST10_DESC "Slab locking test"
-
-#if 0
-#define SPLAT_KMEM_TEST11_ID 0x010b
-#define SPLAT_KMEM_TEST11_NAME "slab_overcommit"
-#define SPLAT_KMEM_TEST11_DESC "Slab memory overcommit test"
-#endif
-
-#define SPLAT_KMEM_TEST13_ID 0x010d
-#define SPLAT_KMEM_TEST13_NAME "slab_reclaim"
-#define SPLAT_KMEM_TEST13_DESC "Slab direct memory reclaim test"
-
-#define SPLAT_KMEM_ALLOC_COUNT 10
-#define SPLAT_VMEM_ALLOC_COUNT 10
-
-
-static int
-splat_kmem_test1(struct file *file, void *arg)
-{
- void *ptr[SPLAT_KMEM_ALLOC_COUNT];
- int size = PAGE_SIZE;
- int i, count, rc = 0;
-
- while ((!rc) && (size <= spl_kmem_alloc_warn)) {
- count = 0;
-
- for (i = 0; i < SPLAT_KMEM_ALLOC_COUNT; i++) {
- ptr[i] = kmem_alloc(size, KM_SLEEP);
- if (ptr[i])
- count++;
- }
-
- for (i = 0; i < SPLAT_KMEM_ALLOC_COUNT; i++)
- if (ptr[i])
- kmem_free(ptr[i], size);
-
- splat_vprint(file, SPLAT_KMEM_TEST1_NAME,
- "%d byte allocations, %d/%d successful\n",
- size, count, SPLAT_KMEM_ALLOC_COUNT);
- if (count != SPLAT_KMEM_ALLOC_COUNT)
- rc = -ENOMEM;
-
- size *= 2;
- }
-
- return rc;
-}
-
-static int
-splat_kmem_test2(struct file *file, void *arg)
-{
- void *ptr[SPLAT_KMEM_ALLOC_COUNT];
- int size = PAGE_SIZE;
- int i, j, count, rc = 0;
-
- while ((!rc) && (size <= spl_kmem_alloc_warn)) {
- count = 0;
-
- for (i = 0; i < SPLAT_KMEM_ALLOC_COUNT; i++) {
- ptr[i] = kmem_zalloc(size, KM_SLEEP);
- if (ptr[i])
- count++;
- }
-
- /* Ensure buffer has been zero filled */
- for (i = 0; i < SPLAT_KMEM_ALLOC_COUNT; i++) {
- for (j = 0; j < size; j++) {
- if (((char *)ptr[i])[j] != '\0') {
- splat_vprint(file,SPLAT_KMEM_TEST2_NAME,
- "%d-byte allocation was "
- "not zeroed\n", size);
- rc = -EFAULT;
- }
- }
- }
-
- for (i = 0; i < SPLAT_KMEM_ALLOC_COUNT; i++)
- if (ptr[i])
- kmem_free(ptr[i], size);
-
- splat_vprint(file, SPLAT_KMEM_TEST2_NAME,
- "%d byte allocations, %d/%d successful\n",
- size, count, SPLAT_KMEM_ALLOC_COUNT);
- if (count != SPLAT_KMEM_ALLOC_COUNT)
- rc = -ENOMEM;
-
- size *= 2;
- }
-
- return rc;
-}
-
-static int
-splat_kmem_test3(struct file *file, void *arg)
-{
- void *ptr[SPLAT_VMEM_ALLOC_COUNT];
- int size = PAGE_SIZE;
- int i, count, rc = 0;
-
- /*
- * Test up to 4x the maximum kmem_alloc() size to ensure both
- * the kmem_alloc() and vmem_alloc() call paths are used.
- */
- while ((!rc) && (size <= (4 * spl_kmem_alloc_max))) {
- count = 0;
-
- for (i = 0; i < SPLAT_VMEM_ALLOC_COUNT; i++) {
- ptr[i] = vmem_alloc(size, KM_SLEEP);
- if (ptr[i])
- count++;
- }
-
- for (i = 0; i < SPLAT_VMEM_ALLOC_COUNT; i++)
- if (ptr[i])
- vmem_free(ptr[i], size);
-
- splat_vprint(file, SPLAT_KMEM_TEST3_NAME,
- "%d byte allocations, %d/%d successful\n",
- size, count, SPLAT_VMEM_ALLOC_COUNT);
- if (count != SPLAT_VMEM_ALLOC_COUNT)
- rc = -ENOMEM;
-
- size *= 2;
- }
-
- return rc;
-}
-
-static int
-splat_kmem_test4(struct file *file, void *arg)
-{
- void *ptr[SPLAT_VMEM_ALLOC_COUNT];
- int size = PAGE_SIZE;
- int i, j, count, rc = 0;
-
- /*
- * Test up to 4x the maximum kmem_zalloc() size to ensure both
- * the kmem_zalloc() and vmem_zalloc() call paths are used.
- */
- while ((!rc) && (size <= (4 * spl_kmem_alloc_max))) {
- count = 0;
-
- for (i = 0; i < SPLAT_VMEM_ALLOC_COUNT; i++) {
- ptr[i] = vmem_zalloc(size, KM_SLEEP);
- if (ptr[i])
- count++;
- }
-
- /* Ensure buffer has been zero filled */
- for (i = 0; i < SPLAT_VMEM_ALLOC_COUNT; i++) {
- for (j = 0; j < size; j++) {
- if (((char *)ptr[i])[j] != '\0') {
- splat_vprint(file, SPLAT_KMEM_TEST4_NAME,
- "%d-byte allocation was "
- "not zeroed\n", size);
- rc = -EFAULT;
- }
- }
- }
-
- for (i = 0; i < SPLAT_VMEM_ALLOC_COUNT; i++)
- if (ptr[i])
- vmem_free(ptr[i], size);
-
- splat_vprint(file, SPLAT_KMEM_TEST4_NAME,
- "%d byte allocations, %d/%d successful\n",
- size, count, SPLAT_VMEM_ALLOC_COUNT);
- if (count != SPLAT_VMEM_ALLOC_COUNT)
- rc = -ENOMEM;
-
- size *= 2;
- }
-
- return rc;
-}
-
-#define SPLAT_KMEM_TEST_MAGIC 0x004488CCUL
-#define SPLAT_KMEM_CACHE_NAME "kmem_test"
-#define SPLAT_KMEM_OBJ_COUNT 1024
-#define SPLAT_KMEM_OBJ_RECLAIM 32 /* objects */
-#define SPLAT_KMEM_THREADS 32
-
-#define KCP_FLAG_READY 0x01
-
-typedef struct kmem_cache_data {
- unsigned long kcd_magic;
- struct list_head kcd_node;
- int kcd_flag;
- char kcd_buf[0];
-} kmem_cache_data_t;
-
-typedef struct kmem_cache_thread {
- spinlock_t kct_lock;
- int kct_id;
- struct list_head kct_list;
-} kmem_cache_thread_t;
-
-typedef struct kmem_cache_priv {
- unsigned long kcp_magic;
- struct file *kcp_file;
- kmem_cache_t *kcp_cache;
- spinlock_t kcp_lock;
- spl_wait_queue_head_t kcp_ctl_waitq;
- spl_wait_queue_head_t kcp_thr_waitq;
- int kcp_flags;
- int kcp_kct_count;
- kmem_cache_thread_t *kcp_kct[SPLAT_KMEM_THREADS];
- int kcp_size;
- int kcp_align;
- int kcp_count;
- int kcp_alloc;
- int kcp_rc;
-} kmem_cache_priv_t;
-
-static kmem_cache_priv_t *
-splat_kmem_cache_test_kcp_alloc(struct file *file, char *name,
- int size, int align, int alloc)
-{
- kmem_cache_priv_t *kcp;
-
- kcp = kmem_zalloc(sizeof(kmem_cache_priv_t), KM_SLEEP);
- if (!kcp)
- return NULL;
-
- kcp->kcp_magic = SPLAT_KMEM_TEST_MAGIC;
- kcp->kcp_file = file;
- kcp->kcp_cache = NULL;
- spin_lock_init(&kcp->kcp_lock);
- init_waitqueue_head(&kcp->kcp_ctl_waitq);
- init_waitqueue_head(&kcp->kcp_thr_waitq);
- kcp->kcp_flags = 0;
- kcp->kcp_kct_count = -1;
- kcp->kcp_size = size;
- kcp->kcp_align = align;
- kcp->kcp_count = 0;
- kcp->kcp_alloc = alloc;
- kcp->kcp_rc = 0;
-
- return kcp;
-}
-
-static void
-splat_kmem_cache_test_kcp_free(kmem_cache_priv_t *kcp)
-{
- kmem_free(kcp, sizeof(kmem_cache_priv_t));
-}
-
-static kmem_cache_thread_t *
-splat_kmem_cache_test_kct_alloc(kmem_cache_priv_t *kcp, int id)
-{
- kmem_cache_thread_t *kct;
-
- ASSERT3S(id, <, SPLAT_KMEM_THREADS);
- ASSERT(kcp->kcp_kct[id] == NULL);
-
- kct = kmem_zalloc(sizeof(kmem_cache_thread_t), KM_SLEEP);
- if (!kct)
- return NULL;
-
- spin_lock_init(&kct->kct_lock);
- kct->kct_id = id;
- INIT_LIST_HEAD(&kct->kct_list);
-
- spin_lock(&kcp->kcp_lock);
- kcp->kcp_kct[id] = kct;
- spin_unlock(&kcp->kcp_lock);
-
- return kct;
-}
-
-static void
-splat_kmem_cache_test_kct_free(kmem_cache_priv_t *kcp,
- kmem_cache_thread_t *kct)
-{
- spin_lock(&kcp->kcp_lock);
- kcp->kcp_kct[kct->kct_id] = NULL;
- spin_unlock(&kcp->kcp_lock);
-
- kmem_free(kct, sizeof(kmem_cache_thread_t));
-}
-
-static void
-splat_kmem_cache_test_kcd_free(kmem_cache_priv_t *kcp,
- kmem_cache_thread_t *kct)
-{
- kmem_cache_data_t *kcd;
-
- spin_lock(&kct->kct_lock);
- while (!list_empty(&kct->kct_list)) {
- kcd = list_entry(kct->kct_list.next,
- kmem_cache_data_t, kcd_node);
- list_del(&kcd->kcd_node);
- spin_unlock(&kct->kct_lock);
-
- kmem_cache_free(kcp->kcp_cache, kcd);
-
- spin_lock(&kct->kct_lock);
- }
- spin_unlock(&kct->kct_lock);
-}
-
-static int
-splat_kmem_cache_test_kcd_alloc(kmem_cache_priv_t *kcp,
- kmem_cache_thread_t *kct, int count)
-{
- kmem_cache_data_t *kcd;
- int i;
-
- for (i = 0; i < count; i++) {
- kcd = kmem_cache_alloc(kcp->kcp_cache, KM_SLEEP);
- if (kcd == NULL) {
- splat_kmem_cache_test_kcd_free(kcp, kct);
- return -ENOMEM;
- }
-
- spin_lock(&kct->kct_lock);
- list_add_tail(&kcd->kcd_node, &kct->kct_list);
- spin_unlock(&kct->kct_lock);
- }
-
- return 0;
-}
-
-static void
-splat_kmem_cache_test_debug(struct file *file, char *name,
- kmem_cache_priv_t *kcp)
-{
- int j;
-
- splat_vprint(file, name, "%s cache objects %d",
- kcp->kcp_cache->skc_name, kcp->kcp_count);
-
- if (kcp->kcp_cache->skc_flags & (KMC_KMEM | KMC_VMEM)) {
- splat_vprint(file, name, ", slabs %u/%u objs %u/%u",
- (unsigned)kcp->kcp_cache->skc_slab_alloc,
- (unsigned)kcp->kcp_cache->skc_slab_total,
- (unsigned)kcp->kcp_cache->skc_obj_alloc,
- (unsigned)kcp->kcp_cache->skc_obj_total);
-
- if (!(kcp->kcp_cache->skc_flags & KMC_NOMAGAZINE)) {
- splat_vprint(file, name, "%s", "mags");
-
- for_each_online_cpu(j)
- splat_print(file, "%u/%u ",
- kcp->kcp_cache->skc_mag[j]->skm_avail,
- kcp->kcp_cache->skc_mag[j]->skm_size);
- }
- }
-
- splat_print(file, "%s\n", "");
-}
-
-static int
-splat_kmem_cache_test_constructor(void *ptr, void *priv, int flags)
-{
- kmem_cache_priv_t *kcp = (kmem_cache_priv_t *)priv;
- kmem_cache_data_t *kcd = (kmem_cache_data_t *)ptr;
-
- if (kcd && kcp) {
- kcd->kcd_magic = kcp->kcp_magic;
- INIT_LIST_HEAD(&kcd->kcd_node);
- kcd->kcd_flag = 1;
- memset(kcd->kcd_buf, 0xaa, kcp->kcp_size - (sizeof *kcd));
- kcp->kcp_count++;
- }
-
- return 0;
-}
-
-static void
-splat_kmem_cache_test_destructor(void *ptr, void *priv)
-{
- kmem_cache_priv_t *kcp = (kmem_cache_priv_t *)priv;
- kmem_cache_data_t *kcd = (kmem_cache_data_t *)ptr;
-
- if (kcd && kcp) {
- kcd->kcd_magic = 0;
- kcd->kcd_flag = 0;
- memset(kcd->kcd_buf, 0xbb, kcp->kcp_size - (sizeof *kcd));
- kcp->kcp_count--;
- }
-
- return;
-}
-
-/*
- * Generic reclaim function which assumes that all objects may
- * be reclaimed at any time. We free a small percentage of the
- * objects linked off the kcp or kct[] every time we are called.
- */
-static void
-splat_kmem_cache_test_reclaim(void *priv)
-{
- kmem_cache_priv_t *kcp = (kmem_cache_priv_t *)priv;
- kmem_cache_thread_t *kct;
- kmem_cache_data_t *kcd;
- LIST_HEAD(reclaim);
- int i, count;
-
- ASSERT(kcp->kcp_magic == SPLAT_KMEM_TEST_MAGIC);
-
- /* For each kct thread reclaim some objects */
- spin_lock(&kcp->kcp_lock);
- for (i = 0; i < SPLAT_KMEM_THREADS; i++) {
- kct = kcp->kcp_kct[i];
- if (!kct)
- continue;
-
- spin_unlock(&kcp->kcp_lock);
- spin_lock(&kct->kct_lock);
-
- count = SPLAT_KMEM_OBJ_RECLAIM;
- while (count > 0 && !list_empty(&kct->kct_list)) {
- kcd = list_entry(kct->kct_list.next,
- kmem_cache_data_t, kcd_node);
- list_del(&kcd->kcd_node);
- list_add(&kcd->kcd_node, &reclaim);
- count--;
- }
-
- spin_unlock(&kct->kct_lock);
- spin_lock(&kcp->kcp_lock);
- }
- spin_unlock(&kcp->kcp_lock);
-
- /* Freed outside the spin lock */
- while (!list_empty(&reclaim)) {
- kcd = list_entry(reclaim.next, kmem_cache_data_t, kcd_node);
- list_del(&kcd->kcd_node);
- kmem_cache_free(kcp->kcp_cache, kcd);
- }
-
- return;
-}
-
-static int
-splat_kmem_cache_test_threads(kmem_cache_priv_t *kcp, int threads)
-{
- int rc;
-
- spin_lock(&kcp->kcp_lock);
- rc = (kcp->kcp_kct_count == threads);
- spin_unlock(&kcp->kcp_lock);
-
- return rc;
-}
-
-static int
-splat_kmem_cache_test_flags(kmem_cache_priv_t *kcp, int flags)
-{
- int rc;
-
- spin_lock(&kcp->kcp_lock);
- rc = (kcp->kcp_flags & flags);
- spin_unlock(&kcp->kcp_lock);
-
- return rc;
-}
-
-static void
-splat_kmem_cache_test_thread(void *arg)
-{
- kmem_cache_priv_t *kcp = (kmem_cache_priv_t *)arg;
- kmem_cache_thread_t *kct;
- int rc = 0, id;
-
- ASSERT(kcp->kcp_magic == SPLAT_KMEM_TEST_MAGIC);
-
- /* Assign thread ids */
- spin_lock(&kcp->kcp_lock);
- if (kcp->kcp_kct_count == -1)
- kcp->kcp_kct_count = 0;
-
- id = kcp->kcp_kct_count;
- kcp->kcp_kct_count++;
- spin_unlock(&kcp->kcp_lock);
-
- kct = splat_kmem_cache_test_kct_alloc(kcp, id);
- if (!kct) {
- rc = -ENOMEM;
- goto out;
- }
-
- /* Wait for all threads to have started and report they are ready */
- if (kcp->kcp_kct_count == SPLAT_KMEM_THREADS)
- wake_up(&kcp->kcp_ctl_waitq);
-
- wait_event(kcp->kcp_thr_waitq,
- splat_kmem_cache_test_flags(kcp, KCP_FLAG_READY));
-
- /* Create and destroy objects */
- rc = splat_kmem_cache_test_kcd_alloc(kcp, kct, kcp->kcp_alloc);
- splat_kmem_cache_test_kcd_free(kcp, kct);
-out:
- if (kct)
- splat_kmem_cache_test_kct_free(kcp, kct);
-
- spin_lock(&kcp->kcp_lock);
- if (!kcp->kcp_rc)
- kcp->kcp_rc = rc;
-
- if ((--kcp->kcp_kct_count) == 0)
- wake_up(&kcp->kcp_ctl_waitq);
-
- spin_unlock(&kcp->kcp_lock);
-
- thread_exit();
-}
-
-static int
-splat_kmem_cache_test(struct file *file, void *arg, char *name,
- int size, int align, int flags)
-{
- kmem_cache_priv_t *kcp = NULL;
- kmem_cache_data_t **kcd = NULL;
- int i, rc = 0, objs = 0;
-
- /* Limit size for low memory machines (1/128 of memory) */
- size = MIN(size, (physmem * PAGE_SIZE) >> 7);
-
- splat_vprint(file, name,
- "Testing size=%d, align=%d, flags=0x%04x\n",
- size, align, flags);
-
- kcp = splat_kmem_cache_test_kcp_alloc(file, name, size, align, 0);
- if (!kcp) {
- splat_vprint(file, name, "Unable to create '%s'\n", "kcp");
- return (-ENOMEM);
- }
-
- kcp->kcp_cache = kmem_cache_create(SPLAT_KMEM_CACHE_NAME,
- kcp->kcp_size, kcp->kcp_align,
- splat_kmem_cache_test_constructor,
- splat_kmem_cache_test_destructor,
- NULL, kcp, NULL, flags);
- if (kcp->kcp_cache == NULL) {
- splat_vprint(file, name, "Unable to create "
- "name='%s', size=%d, align=%d, flags=0x%x\n",
- SPLAT_KMEM_CACHE_NAME, size, align, flags);
- rc = -ENOMEM;
- goto out_free;
- }
-
- /*
- * Allocate several slabs worth of objects to verify functionality.
- * However, on 32-bit systems with limited address space constrain
- * it to a single slab for the purposes of this test.
- */
-#ifdef _LP64
- objs = kcp->kcp_cache->skc_slab_objs * 4;
-#else
- objs = 1;
-#endif
- kcd = kmem_zalloc(sizeof (kmem_cache_data_t *) * objs, KM_SLEEP);
- if (kcd == NULL) {
- splat_vprint(file, name, "Unable to allocate pointers "
- "for %d objects\n", objs);
- rc = -ENOMEM;
- goto out_free;
- }
-
- for (i = 0; i < objs; i++) {
- kcd[i] = kmem_cache_alloc(kcp->kcp_cache, KM_SLEEP);
- if (kcd[i] == NULL) {
- splat_vprint(file, name, "Unable to allocate "
- "from '%s'\n", SPLAT_KMEM_CACHE_NAME);
- rc = -EINVAL;
- goto out_free;
- }
-
- if (!kcd[i]->kcd_flag) {
- splat_vprint(file, name, "Failed to run constructor "
- "for '%s'\n", SPLAT_KMEM_CACHE_NAME);
- rc = -EINVAL;
- goto out_free;
- }
-
- if (kcd[i]->kcd_magic != kcp->kcp_magic) {
- splat_vprint(file, name,
- "Failed to pass private data to constructor "
- "for '%s'\n", SPLAT_KMEM_CACHE_NAME);
- rc = -EINVAL;
- goto out_free;
- }
- }
-
- for (i = 0; i < objs; i++) {
- kmem_cache_free(kcp->kcp_cache, kcd[i]);
-
- /* Destructors are run for every kmem_cache_free() */
- if (kcd[i]->kcd_flag) {
- splat_vprint(file, name,
- "Failed to run destructor for '%s'\n",
- SPLAT_KMEM_CACHE_NAME);
- rc = -EINVAL;
- goto out_free;
- }
- }
-
- if (kcp->kcp_count) {
- splat_vprint(file, name,
- "Failed to run destructor on all slab objects for '%s'\n",
- SPLAT_KMEM_CACHE_NAME);
- rc = -EINVAL;
- }
-
- kmem_free(kcd, sizeof (kmem_cache_data_t *) * objs);
- kmem_cache_destroy(kcp->kcp_cache);
-
- splat_kmem_cache_test_kcp_free(kcp);
- splat_vprint(file, name,
- "Success ran alloc'd/free'd %d objects of size %d\n",
- objs, size);
-
- return (rc);
-
-out_free:
- if (kcd) {
- for (i = 0; i < objs; i++) {
- if (kcd[i] != NULL)
- kmem_cache_free(kcp->kcp_cache, kcd[i]);
- }
-
- kmem_free(kcd, sizeof (kmem_cache_data_t *) * objs);
- }
-
- if (kcp->kcp_cache)
- kmem_cache_destroy(kcp->kcp_cache);
-
- splat_kmem_cache_test_kcp_free(kcp);
-
- return (rc);
-}
-
-static int
-splat_kmem_cache_thread_test(struct file *file, void *arg, char *name,
- int size, int alloc, int max_time)
-{
- kmem_cache_priv_t *kcp;
- kthread_t *thr;
- struct timespec start, stop, delta;
- char cache_name[32];
- int i, rc = 0;
-
- kcp = splat_kmem_cache_test_kcp_alloc(file, name, size, 0, alloc);
- if (!kcp) {
- splat_vprint(file, name, "Unable to create '%s'\n", "kcp");
- return -ENOMEM;
- }
-
- (void)snprintf(cache_name, 32, "%s-%d-%d",
- SPLAT_KMEM_CACHE_NAME, size, alloc);
- kcp->kcp_cache =
- kmem_cache_create(cache_name, kcp->kcp_size, 0,
- splat_kmem_cache_test_constructor,
- splat_kmem_cache_test_destructor,
- splat_kmem_cache_test_reclaim,
- kcp, NULL, 0);
- if (!kcp->kcp_cache) {
- splat_vprint(file, name, "Unable to create '%s'\n", cache_name);
- rc = -ENOMEM;
- goto out_kcp;
- }
-
- getnstimeofday(&start);
-
- for (i = 0; i < SPLAT_KMEM_THREADS; i++) {
- thr = thread_create(NULL, 0,
- splat_kmem_cache_test_thread,
- kcp, 0, &p0, TS_RUN, defclsyspri);
- if (thr == NULL) {
- rc = -ESRCH;
- goto out_cache;
- }
- }
-
- /* Sleep until all threads have started, then set the ready
- * flag and wake them all up for maximum concurrency. */
- wait_event(kcp->kcp_ctl_waitq,
- splat_kmem_cache_test_threads(kcp, SPLAT_KMEM_THREADS));
-
- spin_lock(&kcp->kcp_lock);
- kcp->kcp_flags |= KCP_FLAG_READY;
- spin_unlock(&kcp->kcp_lock);
- wake_up_all(&kcp->kcp_thr_waitq);
-
- /* Sleep until all thread have finished */
- wait_event(kcp->kcp_ctl_waitq, splat_kmem_cache_test_threads(kcp, 0));
-
- getnstimeofday(&stop);
- delta = timespec_sub(stop, start);
-
- splat_vprint(file, name,
- "%-22s %2ld.%09ld\t"
- "%lu/%lu/%lu\t%lu/%lu/%lu\n",
- kcp->kcp_cache->skc_name,
- delta.tv_sec, delta.tv_nsec,
- (unsigned long)kcp->kcp_cache->skc_slab_total,
- (unsigned long)kcp->kcp_cache->skc_slab_max,
- (unsigned long)(kcp->kcp_alloc *
- SPLAT_KMEM_THREADS /
- SPL_KMEM_CACHE_OBJ_PER_SLAB),
- (unsigned long)kcp->kcp_cache->skc_obj_total,
- (unsigned long)kcp->kcp_cache->skc_obj_max,
- (unsigned long)(kcp->kcp_alloc *
- SPLAT_KMEM_THREADS));
-
- if (delta.tv_sec >= max_time)
- rc = -ETIME;
-
- if (!rc && kcp->kcp_rc)
- rc = kcp->kcp_rc;
-
-out_cache:
- kmem_cache_destroy(kcp->kcp_cache);
-out_kcp:
- splat_kmem_cache_test_kcp_free(kcp);
- return rc;
-}
-
-/* Validate small object cache behavior for dynamic/kmem/vmem caches */
-static int
-splat_kmem_test5(struct file *file, void *arg)
-{
- char *name = SPLAT_KMEM_TEST5_NAME;
- int i, rc = 0;
-
- /* Randomly pick small object sizes and alignments. */
- for (i = 0; i < 100; i++) {
- int size, align, flags = 0;
- uint32_t rnd;
-
- /* Evenly distribute tests over all value cache types */
- get_random_bytes((void *)&rnd, sizeof (uint32_t));
- switch (rnd & 0x03) {
- default:
- case 0x00:
- flags = 0;
- break;
- case 0x01:
- flags = KMC_KMEM;
- break;
- case 0x02:
- flags = KMC_VMEM;
- break;
- case 0x03:
- flags = KMC_SLAB;
- break;
- }
-
- /* The following flags are set with a 1/10 chance */
- flags |= ((((rnd >> 8) % 10) == 0) ? KMC_OFFSLAB : 0);
- flags |= ((((rnd >> 16) % 10) == 0) ? KMC_NOEMERGENCY : 0);
-
- /* 32b - PAGE_SIZE */
- get_random_bytes((void *)&rnd, sizeof (uint32_t));
- size = MAX(rnd % (PAGE_SIZE + 1), 32);
-
- /* 2^N where (3 <= N <= PAGE_SHIFT) */
- get_random_bytes((void *)&rnd, sizeof (uint32_t));
- align = (1 << MAX(3, rnd % (PAGE_SHIFT + 1)));
-
- rc = splat_kmem_cache_test(file, arg, name, size, align, flags);
- if (rc)
- return (rc);
- }
-
- return (rc);
-}
-
-/*
- * Validate large object cache behavior for dynamic/kmem/vmem caches
- */
-static int
-splat_kmem_test6(struct file *file, void *arg)
-{
- char *name = SPLAT_KMEM_TEST6_NAME;
- int i, max_size, rc = 0;
-
- /* Randomly pick large object sizes and alignments. */
- for (i = 0; i < 100; i++) {
- int size, align, flags = 0;
- uint32_t rnd;
-
- /* Evenly distribute tests over all value cache types */
- get_random_bytes((void *)&rnd, sizeof (uint32_t));
- switch (rnd & 0x03) {
- default:
- case 0x00:
- flags = 0;
- max_size = (SPL_KMEM_CACHE_MAX_SIZE * 1024 * 1024) / 2;
- break;
- case 0x01:
- flags = KMC_KMEM;
- max_size = (SPL_MAX_ORDER_NR_PAGES - 2) * PAGE_SIZE;
- break;
- case 0x02:
- flags = KMC_VMEM;
- max_size = (SPL_KMEM_CACHE_MAX_SIZE * 1024 * 1024) / 2;
- break;
- case 0x03:
- flags = KMC_SLAB;
- max_size = SPL_MAX_KMEM_ORDER_NR_PAGES * PAGE_SIZE;
- break;
- }
-
- /* The following flags are set with a 1/10 chance */
- flags |= ((((rnd >> 8) % 10) == 0) ? KMC_OFFSLAB : 0);
- flags |= ((((rnd >> 16) % 10) == 0) ? KMC_NOEMERGENCY : 0);
-
- /* PAGE_SIZE - max_size */
- get_random_bytes((void *)&rnd, sizeof (uint32_t));
- size = MAX(rnd % (max_size + 1), PAGE_SIZE),
-
- /* 2^N where (3 <= N <= PAGE_SHIFT) */
- get_random_bytes((void *)&rnd, sizeof (uint32_t));
- align = (1 << MAX(3, rnd % (PAGE_SHIFT + 1)));
-
- rc = splat_kmem_cache_test(file, arg, name, size, align, flags);
- if (rc)
- return (rc);
- }
-
- return (rc);
-}
-
-/*
- * Validate object alignment cache behavior for caches
- */
-static int
-splat_kmem_test7(struct file *file, void *arg)
-{
- char *name = SPLAT_KMEM_TEST7_NAME;
- int max_size = (SPL_KMEM_CACHE_MAX_SIZE * 1024 * 1024) / 2;
- int i, rc;
-
- for (i = SPL_KMEM_CACHE_ALIGN; i <= PAGE_SIZE; i *= 2) {
- uint32_t size;
-
- get_random_bytes((void *)&size, sizeof (uint32_t));
- size = MAX(size % (max_size + 1), 32);
-
- rc = splat_kmem_cache_test(file, arg, name, size, i, 0);
- if (rc)
- return rc;
-
- rc = splat_kmem_cache_test(file, arg, name, size, i,
- KMC_OFFSLAB);
- if (rc)
- return rc;
- }
-
- return rc;
-}
-
-/*
- * Validate kmem_cache_reap() by requesting the slab cache free any objects
- * it can. For a few reasons this may not immediately result in more free
- * memory even if objects are freed. First off, due to fragmentation we
- * may not be able to reclaim any slabs. Secondly, even if we do we fully
- * clear some slabs we will not want to immediately reclaim all of them
- * because we may contend with cache allocations and thrash. What we want
- * to see is the slab size decrease more gradually as it becomes clear they
- * will not be needed. This should be achievable in less than a minute.
- * If it takes longer than this something has gone wrong.
- */
-static int
-splat_kmem_test8(struct file *file, void *arg)
-{
- kmem_cache_priv_t *kcp;
- kmem_cache_thread_t *kct;
- unsigned int spl_kmem_cache_expire_old;
- int i, rc = 0;
-
- /* Enable cache aging just for this test if it is disabled */
- spl_kmem_cache_expire_old = spl_kmem_cache_expire;
- spl_kmem_cache_expire = KMC_EXPIRE_AGE;
-
- kcp = splat_kmem_cache_test_kcp_alloc(file, SPLAT_KMEM_TEST8_NAME,
- 256, 0, 0);
- if (!kcp) {
- splat_vprint(file, SPLAT_KMEM_TEST8_NAME,
- "Unable to create '%s'\n", "kcp");
- rc = -ENOMEM;
- goto out;
- }
-
- kcp->kcp_cache =
- kmem_cache_create(SPLAT_KMEM_CACHE_NAME, kcp->kcp_size, 0,
- splat_kmem_cache_test_constructor,
- splat_kmem_cache_test_destructor,
- splat_kmem_cache_test_reclaim,
- kcp, NULL, 0);
- if (!kcp->kcp_cache) {
- splat_vprint(file, SPLAT_KMEM_TEST8_NAME,
- "Unable to create '%s'\n", SPLAT_KMEM_CACHE_NAME);
- rc = -ENOMEM;
- goto out_kcp;
- }
-
- kct = splat_kmem_cache_test_kct_alloc(kcp, 0);
- if (!kct) {
- splat_vprint(file, SPLAT_KMEM_TEST8_NAME,
- "Unable to create '%s'\n", "kct");
- rc = -ENOMEM;
- goto out_cache;
- }
-
- rc = splat_kmem_cache_test_kcd_alloc(kcp, kct, SPLAT_KMEM_OBJ_COUNT);
- if (rc) {
- splat_vprint(file, SPLAT_KMEM_TEST8_NAME, "Unable to "
- "allocate from '%s'\n", SPLAT_KMEM_CACHE_NAME);
- goto out_kct;
- }
-
- /* Force reclaim every 1/10 a second for 60 seconds. */
- for (i = 0; i < 600; i++) {
- kmem_cache_reap_now(kcp->kcp_cache);
- splat_kmem_cache_test_debug(file, SPLAT_KMEM_TEST8_NAME, kcp);
-
- if (kcp->kcp_count == 0)
- break;
-
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 10);
- }
-
- if (kcp->kcp_count == 0) {
- splat_vprint(file, SPLAT_KMEM_TEST8_NAME,
- "Successfully created %d objects "
- "in cache %s and reclaimed them\n",
- SPLAT_KMEM_OBJ_COUNT, SPLAT_KMEM_CACHE_NAME);
- } else {
- splat_vprint(file, SPLAT_KMEM_TEST8_NAME,
- "Failed to reclaim %u/%d objects from cache %s\n",
- (unsigned)kcp->kcp_count,
- SPLAT_KMEM_OBJ_COUNT, SPLAT_KMEM_CACHE_NAME);
- rc = -ENOMEM;
- }
-
- /* Cleanup our mess (for failure case of time expiring) */
- splat_kmem_cache_test_kcd_free(kcp, kct);
-out_kct:
- splat_kmem_cache_test_kct_free(kcp, kct);
-out_cache:
- kmem_cache_destroy(kcp->kcp_cache);
-out_kcp:
- splat_kmem_cache_test_kcp_free(kcp);
-out:
- spl_kmem_cache_expire = spl_kmem_cache_expire_old;
-
- return rc;
-}
-
-/* Test cache aging, we have allocated a large number of objects thus
- * creating a large number of slabs and then free'd them all. However,
- * since there should be little memory pressure at the moment those
- * slabs have not been freed. What we want to see is the slab size
- * decrease gradually as it becomes clear they will not be be needed.
- * This should be achievable in less than minute. If it takes longer
- * than this something has gone wrong.
- */
-static int
-splat_kmem_test9(struct file *file, void *arg)
-{
- kmem_cache_priv_t *kcp;
- kmem_cache_thread_t *kct;
- unsigned int spl_kmem_cache_expire_old;
- int i, rc = 0, count = SPLAT_KMEM_OBJ_COUNT * 128;
-
- /* Enable cache aging just for this test if it is disabled */
- spl_kmem_cache_expire_old = spl_kmem_cache_expire;
- spl_kmem_cache_expire = KMC_EXPIRE_AGE;
-
- kcp = splat_kmem_cache_test_kcp_alloc(file, SPLAT_KMEM_TEST9_NAME,
- 256, 0, 0);
- if (!kcp) {
- splat_vprint(file, SPLAT_KMEM_TEST9_NAME,
- "Unable to create '%s'\n", "kcp");
- rc = -ENOMEM;
- goto out;
- }
-
- kcp->kcp_cache =
- kmem_cache_create(SPLAT_KMEM_CACHE_NAME, kcp->kcp_size, 0,
- splat_kmem_cache_test_constructor,
- splat_kmem_cache_test_destructor,
- NULL, kcp, NULL, 0);
- if (!kcp->kcp_cache) {
- splat_vprint(file, SPLAT_KMEM_TEST9_NAME,
- "Unable to create '%s'\n", SPLAT_KMEM_CACHE_NAME);
- rc = -ENOMEM;
- goto out_kcp;
- }
-
- kct = splat_kmem_cache_test_kct_alloc(kcp, 0);
- if (!kct) {
- splat_vprint(file, SPLAT_KMEM_TEST8_NAME,
- "Unable to create '%s'\n", "kct");
- rc = -ENOMEM;
- goto out_cache;
- }
-
- rc = splat_kmem_cache_test_kcd_alloc(kcp, kct, count);
- if (rc) {
- splat_vprint(file, SPLAT_KMEM_TEST9_NAME, "Unable to "
- "allocate from '%s'\n", SPLAT_KMEM_CACHE_NAME);
- goto out_kct;
- }
-
- splat_kmem_cache_test_kcd_free(kcp, kct);
-
- for (i = 0; i < 60; i++) {
- splat_kmem_cache_test_debug(file, SPLAT_KMEM_TEST9_NAME, kcp);
-
- if (kcp->kcp_count == 0)
- break;
-
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ);
- }
-
- if (kcp->kcp_count == 0) {
- splat_vprint(file, SPLAT_KMEM_TEST9_NAME,
- "Successfully created %d objects "
- "in cache %s and reclaimed them\n",
- count, SPLAT_KMEM_CACHE_NAME);
- } else {
- splat_vprint(file, SPLAT_KMEM_TEST9_NAME,
- "Failed to reclaim %u/%d objects from cache %s\n",
- (unsigned)kcp->kcp_count, count,
- SPLAT_KMEM_CACHE_NAME);
- rc = -ENOMEM;
- }
-
-out_kct:
- splat_kmem_cache_test_kct_free(kcp, kct);
-out_cache:
- kmem_cache_destroy(kcp->kcp_cache);
-out_kcp:
- splat_kmem_cache_test_kcp_free(kcp);
-out:
- spl_kmem_cache_expire = spl_kmem_cache_expire_old;
-
- return rc;
-}
-
-/*
- * This test creates N threads with a shared kmem cache. They then all
- * concurrently allocate and free from the cache to stress the locking and
- * concurrent cache performance. If any one test takes longer than 5
- * seconds to complete it is treated as a failure and may indicate a
- * performance regression. On my test system no one test takes more
- * than 1 second to complete so a 5x slowdown likely a problem.
- */
-static int
-splat_kmem_test10(struct file *file, void *arg)
-{
- uint64_t size, alloc, maxsize, limit, rc = 0;
-
-#if defined(CONFIG_64BIT)
- maxsize = (1024 * 1024);
-#else
- maxsize = (128 * 1024);
-#endif
-
- for (size = 32; size <= maxsize; size *= 2) {
-
- splat_vprint(file, SPLAT_KMEM_TEST10_NAME, "%-22s %s", "name",
- "time (sec)\tslabs \tobjs \thash\n");
- splat_vprint(file, SPLAT_KMEM_TEST10_NAME, "%-22s %s", "",
- " \ttot/max/calc\ttot/max/calc\n");
-
- for (alloc = 1; alloc <= 1024; alloc *= 2) {
-
- /* Skip tests which exceed 1/2 of memory. */
- limit = MIN(physmem * PAGE_SIZE,
- vmem_size(NULL, VMEM_ALLOC | VMEM_FREE)) / 2;
- if (size * alloc * SPLAT_KMEM_THREADS > limit)
- continue;
-
- rc = splat_kmem_cache_thread_test(file, arg,
- SPLAT_KMEM_TEST10_NAME, size, alloc, 5);
- if (rc)
- break;
- }
- }
-
- return rc;
-}
-
-#if 0
-/*
- * This test creates N threads with a shared kmem cache which overcommits
- * memory by 4x. This makes it impossible for the slab to satify the
- * thread requirements without having its reclaim hook run which will
- * free objects back for use. This behavior is triggered by the linum VM
- * detecting a low memory condition on the node and invoking the shrinkers.
- * This should allow all the threads to complete while avoiding deadlock
- * and for the most part out of memory events. This is very tough on the
- * system so it is possible the test app may get oom'ed. This particular
- * test has proven troublesome on 32-bit archs with limited virtual
- * address space so it only run on 64-bit systems.
- */
-static int
-splat_kmem_test11(struct file *file, void *arg)
-{
- uint64_t size, alloc, rc;
-
- size = 8 * 1024;
- alloc = ((4 * physmem * PAGE_SIZE) / size) / SPLAT_KMEM_THREADS;
-
- splat_vprint(file, SPLAT_KMEM_TEST11_NAME, "%-22s %s", "name",
- "time (sec)\tslabs \tobjs \thash\n");
- splat_vprint(file, SPLAT_KMEM_TEST11_NAME, "%-22s %s", "",
- " \ttot/max/calc\ttot/max/calc\n");
-
- rc = splat_kmem_cache_thread_test(file, arg,
- SPLAT_KMEM_TEST11_NAME, size, alloc, 60);
-
- return rc;
-}
-#endif
-
-typedef struct dummy_page {
- struct list_head dp_list;
- char dp_pad[PAGE_SIZE - sizeof(struct list_head)];
-} dummy_page_t;
-
-/*
- * This test is designed to verify that direct reclaim is functioning as
- * expected. We allocate a large number of objects thus creating a large
- * number of slabs. We then apply memory pressure and expect that the
- * direct reclaim path can easily recover those slabs. The registered
- * reclaim function will free the objects and the slab shrinker will call
- * it repeatedly until at least a single slab can be freed.
- *
- * Note it may not be possible to reclaim every last slab via direct reclaim
- * without a failure because the shrinker_rwsem may be contended. For this
- * reason, quickly reclaiming 3/4 of the slabs is considered a success.
- *
- * This should all be possible within 10 seconds. For reference, on a
- * system with 2G of memory this test takes roughly 0.2 seconds to run.
- * It may take longer on larger memory systems but should still easily
- * complete in the alloted 10 seconds.
- */
-static int
-splat_kmem_test13(struct file *file, void *arg)
-{
- kmem_cache_priv_t *kcp;
- kmem_cache_thread_t *kct;
- dummy_page_t *dp;
- struct list_head list;
- struct timespec start, stop, delta = { 0, 0 };
- int size, count, slabs, fails = 0;
- int i, rc = 0, max_time = 10;
-
- size = 128 * 1024;
- count = MIN(physmem * PAGE_SIZE, vmem_size(NULL,
- VMEM_ALLOC | VMEM_FREE)) / 4 / size;
-
- kcp = splat_kmem_cache_test_kcp_alloc(file, SPLAT_KMEM_TEST13_NAME,
- size, 0, 0);
- if (!kcp) {
- splat_vprint(file, SPLAT_KMEM_TEST13_NAME,
- "Unable to create '%s'\n", "kcp");
- rc = -ENOMEM;
- goto out;
- }
-
- kcp->kcp_cache =
- kmem_cache_create(SPLAT_KMEM_CACHE_NAME, kcp->kcp_size, 0,
- splat_kmem_cache_test_constructor,
- splat_kmem_cache_test_destructor,
- splat_kmem_cache_test_reclaim,
- kcp, NULL, 0);
- if (!kcp->kcp_cache) {
- splat_vprint(file, SPLAT_KMEM_TEST13_NAME,
- "Unable to create '%s'\n", SPLAT_KMEM_CACHE_NAME);
- rc = -ENOMEM;
- goto out_kcp;
- }
-
- kct = splat_kmem_cache_test_kct_alloc(kcp, 0);
- if (!kct) {
- splat_vprint(file, SPLAT_KMEM_TEST13_NAME,
- "Unable to create '%s'\n", "kct");
- rc = -ENOMEM;
- goto out_cache;
- }
-
- rc = splat_kmem_cache_test_kcd_alloc(kcp, kct, count);
- if (rc) {
- splat_vprint(file, SPLAT_KMEM_TEST13_NAME, "Unable to "
- "allocate from '%s'\n", SPLAT_KMEM_CACHE_NAME);
- goto out_kct;
- }
-
- i = 0;
- slabs = kcp->kcp_cache->skc_slab_total;
- INIT_LIST_HEAD(&list);
- getnstimeofday(&start);
-
- /* Apply memory pressure */
- while (kcp->kcp_cache->skc_slab_total > (slabs >> 2)) {
-
- if ((i % 10000) == 0)
- splat_kmem_cache_test_debug(
- file, SPLAT_KMEM_TEST13_NAME, kcp);
-
- getnstimeofday(&stop);
- delta = timespec_sub(stop, start);
- if (delta.tv_sec >= max_time) {
- splat_vprint(file, SPLAT_KMEM_TEST13_NAME,
- "Failed to reclaim 3/4 of cache in %ds, "
- "%u/%u slabs remain\n", max_time,
- (unsigned)kcp->kcp_cache->skc_slab_total,
- slabs);
- rc = -ETIME;
- break;
- }
-
- dp = (dummy_page_t *)__get_free_page(GFP_KERNEL);
- if (!dp) {
- fails++;
- splat_vprint(file, SPLAT_KMEM_TEST13_NAME,
- "Failed (%d) to allocate page with %u "
- "slabs still in the cache\n", fails,
- (unsigned)kcp->kcp_cache->skc_slab_total);
- continue;
- }
-
- list_add(&dp->dp_list, &list);
- i++;
- }
-
- if (rc == 0)
- splat_vprint(file, SPLAT_KMEM_TEST13_NAME,
- "Successfully created %u slabs and with %d alloc "
- "failures reclaimed 3/4 of them in %d.%03ds\n",
- slabs, fails,
- (int)delta.tv_sec, (int)delta.tv_nsec / 1000000);
-
- /* Release memory pressure pages */
- while (!list_empty(&list)) {
- dp = list_entry(list.next, dummy_page_t, dp_list);
- list_del_init(&dp->dp_list);
- free_page((unsigned long)dp);
- }
-
- /* Release remaining kmem cache objects */
- splat_kmem_cache_test_kcd_free(kcp, kct);
-out_kct:
- splat_kmem_cache_test_kct_free(kcp, kct);
-out_cache:
- kmem_cache_destroy(kcp->kcp_cache);
-out_kcp:
- splat_kmem_cache_test_kcp_free(kcp);
-out:
- return rc;
-}
-
-splat_subsystem_t *
-splat_kmem_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_KMEM_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_KMEM_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_KMEM;
-
- splat_test_init(sub, SPLAT_KMEM_TEST1_NAME, SPLAT_KMEM_TEST1_DESC,
- SPLAT_KMEM_TEST1_ID, splat_kmem_test1);
- splat_test_init(sub, SPLAT_KMEM_TEST2_NAME, SPLAT_KMEM_TEST2_DESC,
- SPLAT_KMEM_TEST2_ID, splat_kmem_test2);
- splat_test_init(sub, SPLAT_KMEM_TEST3_NAME, SPLAT_KMEM_TEST3_DESC,
- SPLAT_KMEM_TEST3_ID, splat_kmem_test3);
- splat_test_init(sub, SPLAT_KMEM_TEST4_NAME, SPLAT_KMEM_TEST4_DESC,
- SPLAT_KMEM_TEST4_ID, splat_kmem_test4);
- splat_test_init(sub, SPLAT_KMEM_TEST5_NAME, SPLAT_KMEM_TEST5_DESC,
- SPLAT_KMEM_TEST5_ID, splat_kmem_test5);
- splat_test_init(sub, SPLAT_KMEM_TEST6_NAME, SPLAT_KMEM_TEST6_DESC,
- SPLAT_KMEM_TEST6_ID, splat_kmem_test6);
- splat_test_init(sub, SPLAT_KMEM_TEST7_NAME, SPLAT_KMEM_TEST7_DESC,
- SPLAT_KMEM_TEST7_ID, splat_kmem_test7);
- splat_test_init(sub, SPLAT_KMEM_TEST8_NAME, SPLAT_KMEM_TEST8_DESC,
- SPLAT_KMEM_TEST8_ID, splat_kmem_test8);
- splat_test_init(sub, SPLAT_KMEM_TEST9_NAME, SPLAT_KMEM_TEST9_DESC,
- SPLAT_KMEM_TEST9_ID, splat_kmem_test9);
- splat_test_init(sub, SPLAT_KMEM_TEST10_NAME, SPLAT_KMEM_TEST10_DESC,
- SPLAT_KMEM_TEST10_ID, splat_kmem_test10);
-#if 0
- splat_test_init(sub, SPLAT_KMEM_TEST11_NAME, SPLAT_KMEM_TEST11_DESC,
- SPLAT_KMEM_TEST11_ID, splat_kmem_test11);
-#endif
- splat_test_init(sub, SPLAT_KMEM_TEST13_NAME, SPLAT_KMEM_TEST13_DESC,
- SPLAT_KMEM_TEST13_ID, splat_kmem_test13);
-
- return sub;
-}
-
-void
-splat_kmem_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
- splat_test_fini(sub, SPLAT_KMEM_TEST13_ID);
-#if 0
- splat_test_fini(sub, SPLAT_KMEM_TEST11_ID);
-#endif
- splat_test_fini(sub, SPLAT_KMEM_TEST10_ID);
- splat_test_fini(sub, SPLAT_KMEM_TEST9_ID);
- splat_test_fini(sub, SPLAT_KMEM_TEST8_ID);
- splat_test_fini(sub, SPLAT_KMEM_TEST7_ID);
- splat_test_fini(sub, SPLAT_KMEM_TEST6_ID);
- splat_test_fini(sub, SPLAT_KMEM_TEST5_ID);
- splat_test_fini(sub, SPLAT_KMEM_TEST4_ID);
- splat_test_fini(sub, SPLAT_KMEM_TEST3_ID);
- splat_test_fini(sub, SPLAT_KMEM_TEST2_ID);
- splat_test_fini(sub, SPLAT_KMEM_TEST1_ID);
-
- kfree(sub);
-}
-
-int
-splat_kmem_id(void) {
- return SPLAT_SUBSYSTEM_KMEM;
-}
diff --git a/module/splat/splat-kobj.c b/module/splat/splat-kobj.c
deleted file mode 100644
index bd44de395..000000000
--- a/module/splat/splat-kobj.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Kobj Tests.
- */
-
-#include <sys/kobj.h>
-#include "splat-internal.h"
-
-#define SPLAT_KOBJ_NAME "kobj"
-#define SPLAT_KOBJ_DESC "Kernel Kobj Tests"
-
-#define SPLAT_KOBJ_TEST1_ID 0x0a01
-#define SPLAT_KOBJ_TEST1_NAME "open"
-#define SPLAT_KOBJ_TEST1_DESC "Kobj Open/Close Test"
-
-#define SPLAT_KOBJ_TEST2_ID 0x0a02
-#define SPLAT_KOBJ_TEST2_NAME "size/read"
-#define SPLAT_KOBJ_TEST2_DESC "Kobj Size/Read Test"
-
-#define SPLAT_KOBJ_TEST_FILE "/etc/fstab"
-
-static int
-splat_kobj_test1(struct file *file, void *arg)
-{
- struct _buf *f;
-
- f = kobj_open_file(SPLAT_KOBJ_TEST_FILE);
- if (f == (struct _buf *)-1) {
- splat_vprint(file, SPLAT_KOBJ_TEST1_NAME, "Failed to open "
- "test file: %s\n", SPLAT_KOBJ_TEST_FILE);
- return -ENOENT;
- }
-
- kobj_close_file(f);
- splat_vprint(file, SPLAT_KOBJ_TEST1_NAME, "Successfully opened and "
- "closed test file: %s\n", SPLAT_KOBJ_TEST_FILE);
-
- return 0;
-} /* splat_kobj_test1() */
-
-static int
-splat_kobj_test2(struct file *file, void *arg)
-{
- struct _buf *f;
- char *buf;
- uint64_t size;
- int rc;
-
- f = kobj_open_file(SPLAT_KOBJ_TEST_FILE);
- if (f == (struct _buf *)-1) {
- splat_vprint(file, SPLAT_KOBJ_TEST2_NAME, "Failed to open "
- "test file: %s\n", SPLAT_KOBJ_TEST_FILE);
- return -ENOENT;
- }
-
- rc = kobj_get_filesize(f, &size);
- if (rc) {
- splat_vprint(file, SPLAT_KOBJ_TEST2_NAME, "Failed stat of "
- "test file: %s (%d)\n", SPLAT_KOBJ_TEST_FILE, rc);
- goto out;
- }
-
- buf = kmalloc(size + 1, GFP_KERNEL);
- if (!buf) {
- rc = -ENOMEM;
- splat_vprint(file, SPLAT_KOBJ_TEST2_NAME, "Failed to alloc "
- "%lld bytes for tmp buffer (%d)\n",
- (long long)size, rc);
- goto out;
- }
-
- memset(buf, 0, size + 1);
- rc = kobj_read_file(f, buf, size, 0);
- if (rc < 0) {
- splat_vprint(file, SPLAT_KOBJ_TEST2_NAME, "Failed read of "
- "test file: %s (%d)\n", SPLAT_KOBJ_TEST_FILE, rc);
- goto out2;
- }
-
- /* Validate we read as many bytes as expected based on the stat. This
- * isn't a perfect test since we didn't create the file however it is
- * pretty unlikely there are garbage characters in your /etc/fstab */
- if (size != (uint64_t)strlen(buf)) {
- rc = -EFBIG;
- splat_vprint(file, SPLAT_KOBJ_TEST2_NAME, "Stat'ed size "
- "(%lld) does not match number of bytes read "
- "(%lld)\n", (long long)size,
- (long long)strlen(buf));
- goto out2;
- }
-
- rc = 0;
- splat_vprint(file, SPLAT_KOBJ_TEST2_NAME, "\n%s\n", buf);
- splat_vprint(file, SPLAT_KOBJ_TEST2_NAME, "Successfully stat'ed "
- "and read expected number of bytes (%lld) from test "
- "file: %s\n", (long long)size, SPLAT_KOBJ_TEST_FILE);
-out2:
- kfree(buf);
-out:
- kobj_close_file(f);
-
- return rc;
-} /* splat_kobj_test2() */
-
-splat_subsystem_t *
-splat_kobj_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_KOBJ_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_KOBJ_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_KOBJ;
-
- splat_test_init(sub, SPLAT_KOBJ_TEST1_NAME, SPLAT_KOBJ_TEST1_DESC,
- SPLAT_KOBJ_TEST1_ID, splat_kobj_test1);
- splat_test_init(sub, SPLAT_KOBJ_TEST2_NAME, SPLAT_KOBJ_TEST2_DESC,
- SPLAT_KOBJ_TEST2_ID, splat_kobj_test2);
-
- return sub;
-} /* splat_kobj_init() */
-
-void
-splat_kobj_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
-
- splat_test_fini(sub, SPLAT_KOBJ_TEST2_ID);
- splat_test_fini(sub, SPLAT_KOBJ_TEST1_ID);
-
- kfree(sub);
-} /* splat_kobj_fini() */
-
-int
-splat_kobj_id(void)
-{
- return SPLAT_SUBSYSTEM_KOBJ;
-} /* splat_kobj_id() */
diff --git a/module/splat/splat-linux.c b/module/splat/splat-linux.c
deleted file mode 100644
index 1565d74a3..000000000
--- a/module/splat/splat-linux.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2011 Lawrence Livermore National Security, LLC.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Kernel Compatibility Tests.
- */
-
-#include <sys/kmem.h>
-#include <linux/mm_compat.h>
-#include "splat-internal.h"
-
-#define SPLAT_LINUX_NAME "linux"
-#define SPLAT_LINUX_DESC "Kernel Compatibility Tests"
-
-#define SPLAT_LINUX_TEST1_ID 0x1001
-#define SPLAT_LINUX_TEST1_NAME "shrinker"
-#define SPLAT_LINUX_TEST1_DESC "Shrinker test"
-
-/*
- * Wait queue used to eliminate race between dropping of slab
- * and execution of the shrinker callback
- */
-DECLARE_WAIT_QUEUE_HEAD(shrinker_wait);
-
-SPL_SHRINKER_CALLBACK_FWD_DECLARE(splat_linux_shrinker_fn);
-SPL_SHRINKER_DECLARE(splat_linux_shrinker, splat_linux_shrinker_fn, 1);
-static unsigned long splat_linux_shrinker_size = 0;
-static struct file *splat_linux_shrinker_file = NULL;
-
-static spl_shrinker_t
-__splat_linux_shrinker_fn(struct shrinker *shrink, struct shrink_control *sc)
-{
- static int failsafe = 0;
- static unsigned long last_splat_linux_shrinker_size = 0;
- unsigned long size;
- spl_shrinker_t count;
-
- /*
- * shrinker_size can only decrease or stay the same between callbacks
- * in the same run, so Reset failsafe whenever shrinker increases
- * as this indicates a new run.
- */
- if (last_splat_linux_shrinker_size < splat_linux_shrinker_size)
- failsafe = 0;
-
- last_splat_linux_shrinker_size = splat_linux_shrinker_size;
-
- if (sc->nr_to_scan) {
- size = MIN(sc->nr_to_scan, splat_linux_shrinker_size);
- splat_linux_shrinker_size -= size;
-
- splat_vprint(splat_linux_shrinker_file, SPLAT_LINUX_TEST1_NAME,
- "Reclaimed %lu objects, size now %lu\n",
- size, splat_linux_shrinker_size);
-
-#ifdef HAVE_SPLIT_SHRINKER_CALLBACK
- count = size;
-#else
- count = splat_linux_shrinker_size;
-#endif /* HAVE_SPLIT_SHRINKER_CALLBACK */
-
- } else {
- count = splat_linux_shrinker_size;
- splat_vprint(splat_linux_shrinker_file, SPLAT_LINUX_TEST1_NAME,
- "Cache size is %lu\n", splat_linux_shrinker_size);
- }
-
- /* Far more calls than expected abort drop_slab as a failsafe */
- if (failsafe > 100) {
- splat_vprint(splat_linux_shrinker_file, SPLAT_LINUX_TEST1_NAME,
- "Far more calls than expected (%d), size now %lu\n",
- failsafe, splat_linux_shrinker_size);
- return (SHRINK_STOP);
- } else {
- /*
- * We only increment failsafe if it doesn't trigger. This
- * makes any failsafe failure persistent until the next test.
- */
- failsafe++;
- }
-
- /* Shrinker has run, so signal back to test. */
- wake_up(&shrinker_wait);
-
- return (count);
-}
-
-SPL_SHRINKER_CALLBACK_WRAPPER(splat_linux_shrinker_fn);
-
-#define DROP_SLAB_CMD \
- "exec 0</dev/null " \
- " 1>/proc/sys/vm/drop_caches " \
- " 2>/dev/null; " \
- "echo 2"
-
-static int
-splat_linux_drop_slab(struct file *file)
-{
- char *argv[] = { "/bin/sh",
- "-c",
- DROP_SLAB_CMD,
- NULL };
- char *envp[] = { "HOME=/",
- "TERM=linux",
- "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
- NULL };
- int rc;
-
- rc = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
- if (rc)
- splat_vprint(file, SPLAT_LINUX_TEST1_NAME,
- "Failed user helper '%s %s %s', rc = %d\n",
- argv[0], argv[1], argv[2], rc);
-
- return rc;
-}
-
-/*
- * Verify correct shrinker functionality by registering a shrinker
- * with the required compatibility macros. We then use a simulated
- * cache and force the systems caches to be dropped. The shrinker
- * should be repeatedly called until it reports that the cache is
- * empty. It is then cleanly unregistered and correct behavior is
- * verified. There are now four slightly different supported shrinker
- * API and this test ensures the compatibility code is correct.
- */
-static int
-splat_linux_test1(struct file *file, void *arg)
-{
- int rc = -EINVAL;
-
- /*
- * Globals used by the shrinker, it is not safe to run this
- * test concurrently this is a safe assumption for SPLAT tests.
- * Regardless we do some minimal checking a bail if concurrent
- * use is detected.
- */
- if (splat_linux_shrinker_size || splat_linux_shrinker_file) {
- splat_vprint(file, SPLAT_LINUX_TEST1_NAME,
- "Failed due to concurrent shrinker test, rc = %d\n", rc);
- return (rc);
- }
-
- splat_linux_shrinker_size = 1024;
- splat_linux_shrinker_file = file;
-
- spl_register_shrinker(&splat_linux_shrinker);
- rc = splat_linux_drop_slab(file);
- if (rc)
- goto out;
-
- /*
- * By the time we get here, it is possible that the shrinker has not
- * yet run. splat_linux_drop_slab sends a signal for it to run, but
- * there is no guarantee of when it will actually run. We wait for it
- * to run here, terminating when either the shrinker size is now 0 or
- * we timeout after 1 second, which should be an eternity (error).
- */
- rc = wait_event_timeout(shrinker_wait, !splat_linux_shrinker_size, HZ);
- if (!rc) {
- splat_vprint(file, SPLAT_LINUX_TEST1_NAME,
- "Failed cache shrinking timed out, size now %lu",
- splat_linux_shrinker_size);
- rc = -ETIMEDOUT;
- } else {
- rc = 0;
- }
-
- if (!rc && splat_linux_shrinker_size != 0) {
- splat_vprint(file, SPLAT_LINUX_TEST1_NAME,
- "Failed cache was not shrunk to 0, size now %lu",
- splat_linux_shrinker_size);
- rc = -EDOM;
- }
-out:
- spl_unregister_shrinker(&splat_linux_shrinker);
-
- splat_linux_shrinker_size = 0;
- splat_linux_shrinker_file = NULL;
-
- return rc;
-}
-
-splat_subsystem_t *
-splat_linux_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_LINUX_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_LINUX_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_LINUX;
-
- splat_test_init(sub, SPLAT_LINUX_TEST1_NAME, SPLAT_LINUX_TEST1_DESC,
- SPLAT_LINUX_TEST1_ID, splat_linux_test1);
-
- return sub;
-}
-
-void
-splat_linux_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
- splat_test_fini(sub, SPLAT_LINUX_TEST1_ID);
-
- kfree(sub);
-}
-
-int
-splat_linux_id(void) {
- return SPLAT_SUBSYSTEM_LINUX;
-}
diff --git a/module/splat/splat-list.c b/module/splat/splat-list.c
deleted file mode 100644
index 8a5f3c937..000000000
--- a/module/splat/splat-list.c
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) List Tests.
- */
-
-#include <sys/list.h>
-#include <sys/kmem.h>
-#include "splat-internal.h"
-
-#define SPLAT_LIST_NAME "list"
-#define SPLAT_LIST_DESC "Kernel List Tests"
-
-#define SPLAT_LIST_TEST1_ID 0x0c01
-#define SPLAT_LIST_TEST1_NAME "create/destroy"
-#define SPLAT_LIST_TEST1_DESC "Create/destroy Test"
-
-#define SPLAT_LIST_TEST2_ID 0x0c02
-#define SPLAT_LIST_TEST2_NAME "ins/rm head"
-#define SPLAT_LIST_TEST2_DESC "Insert/remove head Test"
-
-#define SPLAT_LIST_TEST3_ID 0x0c03
-#define SPLAT_LIST_TEST3_NAME "ins/rm tail"
-#define SPLAT_LIST_TEST3_DESC "Insert/remove tail Test"
-
-#define SPLAT_LIST_TEST4_ID 0x0c04
-#define SPLAT_LIST_TEST4_NAME "insert_after"
-#define SPLAT_LIST_TEST4_DESC "Insert_after Test"
-
-#define SPLAT_LIST_TEST5_ID 0x0c05
-#define SPLAT_LIST_TEST5_NAME "insert_before"
-#define SPLAT_LIST_TEST5_DESC "Insert_before Test"
-
-#define SPLAT_LIST_TEST6_ID 0x0c06
-#define SPLAT_LIST_TEST6_NAME "remove"
-#define SPLAT_LIST_TEST6_DESC "Remove Test"
-
-#define SPLAT_LIST_TEST7_ID 0x0c7
-#define SPLAT_LIST_TEST7_NAME "active"
-#define SPLAT_LIST_TEST7_DESC "Active Test"
-
-/* It is important that li_node is not the first element, this
- * ensures the list_d2l/list_object macros are working correctly. */
-typedef struct list_item {
- int li_data;
- list_node_t li_node;
-} list_item_t;
-
-#define LIST_ORDER_STACK 0
-#define LIST_ORDER_QUEUE 1
-
-static int
-splat_list_test1(struct file *file, void *arg)
-{
- list_t list;
-
- splat_vprint(file, SPLAT_LIST_TEST1_NAME, "Creating list\n%s", "");
- list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
-
- if (!list_is_empty(&list)) {
- splat_vprint(file, SPLAT_LIST_TEST1_NAME,
- "New list NOT empty%s\n", "");
- /* list_destroy() intentionally skipped to avoid assert */
- return -EEXIST;
- }
-
- splat_vprint(file, SPLAT_LIST_TEST1_NAME, "Destroying list\n%s", "");
- list_destroy(&list);
-
- /* Validate the list has been destroyed */
- if (list_link_active(&list.list_head)) {
- splat_vprint(file, SPLAT_LIST_TEST1_NAME,
- "Destroyed list still active%s", "");
- return -EIO;
- }
-
- return 0;
-}
-
-static int
-splat_list_validate(list_t *list, int size, int order, int mult)
-{
- list_item_t *li;
- int i;
-
- /* Walk all items in list from head to verify stack or queue
- * ordering. We bound the for loop by size+1 to ensure that
- * we still terminate if there is list corruption. We also
- * intentionally make things a little more complex than they
- * need to be by using list_head/list_next for queues, and
- * list_tail/list_prev for stacks. This is simply done for
- * coverage and to ensure these function are working right.
- */
- for (i = 0, li = (order ? list_head(list) : list_tail(list));
- i < size + 1 && li != NULL;
- i++, li = (order ? list_next(list, li) : list_prev(list, li)))
- if (li->li_data != i * mult)
- return -EIDRM;
-
- if (i != size)
- return -E2BIG;
-
- return 0;
-}
-
-static int
-splat_list_test2(struct file *file, void *arg)
-{
- list_t list;
- list_item_t *li;
- int i, list_size = 8, rc = 0;
-
- splat_vprint(file, SPLAT_LIST_TEST2_NAME, "Creating list\n%s", "");
- list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
-
- /* Insert all items at the list head to form a stack */
- splat_vprint(file, SPLAT_LIST_TEST2_NAME,
- "Adding %d items to list head\n", list_size);
- for (i = 0; i < list_size; i++) {
- li = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
- if (li == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- list_link_init(&li->li_node);
- li->li_data = i;
- list_insert_head(&list, li);
- }
-
- splat_vprint(file, SPLAT_LIST_TEST2_NAME,
- "Validating %d item list is a stack\n", list_size);
- rc = splat_list_validate(&list, list_size, LIST_ORDER_STACK, 1);
- if (rc)
- splat_vprint(file, SPLAT_LIST_TEST2_NAME,
- "List validation failed, %d\n", rc);
-out:
- /* Remove all items */
- splat_vprint(file, SPLAT_LIST_TEST2_NAME,
- "Removing %d items from list head\n", list_size);
- while ((li = list_remove_head(&list)))
- kmem_free(li, sizeof(list_item_t));
-
- splat_vprint(file, SPLAT_LIST_TEST2_NAME, "Destroying list\n%s", "");
- list_destroy(&list);
-
- return rc;
-}
-
-static int
-splat_list_test3(struct file *file, void *arg)
-{
- list_t list;
- list_item_t *li;
- int i, list_size = 8, rc = 0;
-
- splat_vprint(file, SPLAT_LIST_TEST3_NAME, "Creating list\n%s", "");
- list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
-
- /* Insert all items at the list tail to form a queue */
- splat_vprint(file, SPLAT_LIST_TEST3_NAME,
- "Adding %d items to list tail\n", list_size);
- for (i = 0; i < list_size; i++) {
- li = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
- if (li == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- list_link_init(&li->li_node);
- li->li_data = i;
- list_insert_tail(&list, li);
- }
-
- splat_vprint(file, SPLAT_LIST_TEST3_NAME,
- "Validating %d item list is a queue\n", list_size);
- rc = splat_list_validate(&list, list_size, LIST_ORDER_QUEUE, 1);
- if (rc)
- splat_vprint(file, SPLAT_LIST_TEST3_NAME,
- "List validation failed, %d\n", rc);
-out:
- /* Remove all items */
- splat_vprint(file, SPLAT_LIST_TEST3_NAME,
- "Removing %d items from list tail\n", list_size);
- while ((li = list_remove_tail(&list)))
- kmem_free(li, sizeof(list_item_t));
-
- splat_vprint(file, SPLAT_LIST_TEST3_NAME, "Destroying list\n%s", "");
- list_destroy(&list);
-
- return rc;
-}
-
-static int
-splat_list_test4(struct file *file, void *arg)
-{
- list_t list;
- list_item_t *li_new, *li_last = NULL;
- int i, list_size = 8, rc = 0;
-
- splat_vprint(file, SPLAT_LIST_TEST4_NAME, "Creating list\n%s", "");
- list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
-
- /* Insert all items after the last item to form a queue */
- splat_vprint(file, SPLAT_LIST_TEST4_NAME,
- "Adding %d items each after the last item\n", list_size);
- for (i = 0; i < list_size; i++) {
- li_new = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
- if (li_new == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- list_link_init(&li_new->li_node);
- li_new->li_data = i;
- list_insert_after(&list, li_last, li_new);
- li_last = li_new;
- }
-
- splat_vprint(file, SPLAT_LIST_TEST4_NAME,
- "Validating %d item list is a queue\n", list_size);
- rc = splat_list_validate(&list, list_size, LIST_ORDER_QUEUE, 1);
- if (rc)
- splat_vprint(file, SPLAT_LIST_TEST4_NAME,
- "List validation failed, %d\n", rc);
-out:
- /* Remove all items */
- splat_vprint(file, SPLAT_LIST_TEST4_NAME,
- "Removing %d items from list tail\n", list_size);
- while ((li_new = list_remove_head(&list)))
- kmem_free(li_new, sizeof(list_item_t));
-
- splat_vprint(file, SPLAT_LIST_TEST4_NAME, "Destroying list\n%s", "");
- list_destroy(&list);
-
- return rc;
-}
-
-static int
-splat_list_test5(struct file *file, void *arg)
-{
- list_t list;
- list_item_t *li_new, *li_last = NULL;
- int i, list_size = 8, rc = 0;
-
- splat_vprint(file, SPLAT_LIST_TEST5_NAME, "Creating list\n%s", "");
- list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
-
- /* Insert all items before the last item to form a stack */
- splat_vprint(file, SPLAT_LIST_TEST5_NAME,
- "Adding %d items each before the last item\n", list_size);
- for (i = 0; i < list_size; i++) {
- li_new = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
- if (li_new == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- list_link_init(&li_new->li_node);
- li_new->li_data = i;
- list_insert_before(&list, li_last, li_new);
- li_last = li_new;
- }
-
- splat_vprint(file, SPLAT_LIST_TEST5_NAME,
- "Validating %d item list is a queue\n", list_size);
- rc = splat_list_validate(&list, list_size, LIST_ORDER_STACK, 1);
- if (rc)
- splat_vprint(file, SPLAT_LIST_TEST5_NAME,
- "List validation failed, %d\n", rc);
-out:
- /* Remove all items */
- splat_vprint(file, SPLAT_LIST_TEST5_NAME,
- "Removing %d items from list tail\n", list_size);
- while ((li_new = list_remove_tail(&list)))
- kmem_free(li_new, sizeof(list_item_t));
-
- splat_vprint(file, SPLAT_LIST_TEST5_NAME, "Destroying list\n%s", "");
- list_destroy(&list);
-
- return rc;
-}
-
-static int
-splat_list_test6(struct file *file, void *arg)
-{
- list_t list;
- list_item_t *li, *li_prev;
- int i, list_size = 8, rc = 0;
-
- splat_vprint(file, SPLAT_LIST_TEST6_NAME, "Creating list\n%s", "");
- list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
-
- /* Insert all items at the list tail to form a queue */
- splat_vprint(file, SPLAT_LIST_TEST6_NAME,
- "Adding %d items to list tail\n", list_size);
- for (i = 0; i < list_size; i++) {
- li = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
- if (li == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- list_link_init(&li->li_node);
- li->li_data = i;
- list_insert_tail(&list, li);
- }
-
- /* Remove all odd items from the queue */
- splat_vprint(file, SPLAT_LIST_TEST6_NAME,
- "Removing %d odd items from the list\n", list_size >> 1);
- for (li = list_head(&list); li != NULL; li = list_next(&list, li)) {
- if (li->li_data % 2 == 1) {
- li_prev = list_prev(&list, li);
- list_remove(&list, li);
- kmem_free(li, sizeof(list_item_t));
- li = li_prev;
- }
- }
-
- splat_vprint(file, SPLAT_LIST_TEST6_NAME, "Validating %d item "
- "list is a queue of only even elements\n", list_size / 2);
- rc = splat_list_validate(&list, list_size / 2, LIST_ORDER_QUEUE, 2);
- if (rc)
- splat_vprint(file, SPLAT_LIST_TEST6_NAME,
- "List validation failed, %d\n", rc);
-out:
- /* Remove all items */
- splat_vprint(file, SPLAT_LIST_TEST6_NAME,
- "Removing %d items from list tail\n", list_size / 2);
- while ((li = list_remove_tail(&list)))
- kmem_free(li, sizeof(list_item_t));
-
- splat_vprint(file, SPLAT_LIST_TEST6_NAME, "Destroying list\n%s", "");
- list_destroy(&list);
-
- return rc;
-}
-
-static int
-splat_list_test7(struct file *file, void *arg)
-{
- list_t list;
- list_item_t *li;
- int rc = 0;
-
- splat_vprint(file, SPLAT_LIST_TEST7_NAME, "Creating list\n%s", "");
- list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
-
- li = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
- if (li == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- /* Validate newly initialized node is inactive */
- splat_vprint(file, SPLAT_LIST_TEST7_NAME, "Init list node\n%s", "");
- list_link_init(&li->li_node);
- if (list_link_active(&li->li_node)) {
- splat_vprint(file, SPLAT_LIST_TEST7_NAME, "Newly initialized "
- "list node should inactive %p/%p\n",
- li->li_node.prev, li->li_node.next);
- rc = -EINVAL;
- goto out_li;
- }
-
- /* Validate node is active when linked in to a list */
- splat_vprint(file, SPLAT_LIST_TEST7_NAME, "Insert list node\n%s", "");
- list_insert_head(&list, li);
- if (!list_link_active(&li->li_node)) {
- splat_vprint(file, SPLAT_LIST_TEST7_NAME, "List node "
- "inserted in list should be active %p/%p\n",
- li->li_node.prev, li->li_node.next);
- rc = -EINVAL;
- goto out;
- }
-
- /* Validate node is inactive when removed from list */
- splat_vprint(file, SPLAT_LIST_TEST7_NAME, "Remove list node\n%s", "");
- list_remove(&list, li);
- if (list_link_active(&li->li_node)) {
- splat_vprint(file, SPLAT_LIST_TEST7_NAME, "List node "
- "removed from list should be inactive %p/%p\n",
- li->li_node.prev, li->li_node.next);
- rc = -EINVAL;
- }
-out_li:
- kmem_free(li, sizeof(list_item_t));
-out:
- /* Remove all items */
- while ((li = list_remove_head(&list)))
- kmem_free(li, sizeof(list_item_t));
-
- splat_vprint(file, SPLAT_LIST_TEST7_NAME, "Destroying list\n%s", "");
- list_destroy(&list);
-
- return rc;
-}
-
-splat_subsystem_t *
-splat_list_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_LIST_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_LIST_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_LIST;
-
- splat_test_init(sub, SPLAT_LIST_TEST1_NAME, SPLAT_LIST_TEST1_DESC,
- SPLAT_LIST_TEST1_ID, splat_list_test1);
- splat_test_init(sub, SPLAT_LIST_TEST2_NAME, SPLAT_LIST_TEST2_DESC,
- SPLAT_LIST_TEST2_ID, splat_list_test2);
- splat_test_init(sub, SPLAT_LIST_TEST3_NAME, SPLAT_LIST_TEST3_DESC,
- SPLAT_LIST_TEST3_ID, splat_list_test3);
- splat_test_init(sub, SPLAT_LIST_TEST4_NAME, SPLAT_LIST_TEST4_DESC,
- SPLAT_LIST_TEST4_ID, splat_list_test4);
- splat_test_init(sub, SPLAT_LIST_TEST5_NAME, SPLAT_LIST_TEST5_DESC,
- SPLAT_LIST_TEST5_ID, splat_list_test5);
- splat_test_init(sub, SPLAT_LIST_TEST6_NAME, SPLAT_LIST_TEST6_DESC,
- SPLAT_LIST_TEST6_ID, splat_list_test6);
- splat_test_init(sub, SPLAT_LIST_TEST7_NAME, SPLAT_LIST_TEST7_DESC,
- SPLAT_LIST_TEST7_ID, splat_list_test7);
-
- return sub;
-}
-
-void
-splat_list_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
-
- splat_test_fini(sub, SPLAT_LIST_TEST7_ID);
- splat_test_fini(sub, SPLAT_LIST_TEST6_ID);
- splat_test_fini(sub, SPLAT_LIST_TEST5_ID);
- splat_test_fini(sub, SPLAT_LIST_TEST4_ID);
- splat_test_fini(sub, SPLAT_LIST_TEST3_ID);
- splat_test_fini(sub, SPLAT_LIST_TEST2_ID);
- splat_test_fini(sub, SPLAT_LIST_TEST1_ID);
-
- kfree(sub);
-}
-
-int
-splat_list_id(void)
-{
- return SPLAT_SUBSYSTEM_LIST;
-}
diff --git a/module/splat/splat-mutex.c b/module/splat/splat-mutex.c
deleted file mode 100644
index 202e6c0f6..000000000
--- a/module/splat/splat-mutex.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Mutex Tests.
- */
-
-#include <sys/mutex.h>
-#include <sys/taskq.h>
-#include <linux/delay.h>
-#include <linux/mm_compat.h>
-#include "splat-internal.h"
-
-#define SPLAT_MUTEX_NAME "mutex"
-#define SPLAT_MUTEX_DESC "Kernel Mutex Tests"
-
-#define SPLAT_MUTEX_TEST1_ID 0x0401
-#define SPLAT_MUTEX_TEST1_NAME "tryenter"
-#define SPLAT_MUTEX_TEST1_DESC "Validate mutex_tryenter() correctness"
-
-#define SPLAT_MUTEX_TEST2_ID 0x0402
-#define SPLAT_MUTEX_TEST2_NAME "race"
-#define SPLAT_MUTEX_TEST2_DESC "Many threads entering/exiting the mutex"
-
-#define SPLAT_MUTEX_TEST3_ID 0x0403
-#define SPLAT_MUTEX_TEST3_NAME "owned"
-#define SPLAT_MUTEX_TEST3_DESC "Validate mutex_owned() correctness"
-
-#define SPLAT_MUTEX_TEST4_ID 0x0404
-#define SPLAT_MUTEX_TEST4_NAME "owner"
-#define SPLAT_MUTEX_TEST4_DESC "Validate mutex_owner() correctness"
-
-#define SPLAT_MUTEX_TEST_MAGIC 0x115599DDUL
-#define SPLAT_MUTEX_TEST_NAME "mutex_test"
-#define SPLAT_MUTEX_TEST_TASKQ "mutex_taskq"
-#define SPLAT_MUTEX_TEST_COUNT 128
-
-typedef struct mutex_priv {
- unsigned long mp_magic;
- struct file *mp_file;
- kmutex_t mp_mtx;
- int mp_rc;
- int mp_rc2;
-} mutex_priv_t;
-
-static void
-splat_mutex_test1_func(void *arg)
-{
- mutex_priv_t *mp = (mutex_priv_t *)arg;
- ASSERT(mp->mp_magic == SPLAT_MUTEX_TEST_MAGIC);
-
- if (mutex_tryenter(&mp->mp_mtx)) {
- mp->mp_rc = 0;
- mutex_exit(&mp->mp_mtx);
- } else {
- mp->mp_rc = -EBUSY;
- }
-}
-
-static int
-splat_mutex_test1(struct file *file, void *arg)
-{
- mutex_priv_t *mp;
- taskq_t *tq;
- taskqid_t id;
- int rc = 0;
-
- mp = (mutex_priv_t *)kmalloc(sizeof(*mp), GFP_KERNEL);
- if (mp == NULL)
- return -ENOMEM;
-
- tq = taskq_create(SPLAT_MUTEX_TEST_TASKQ, 1, defclsyspri,
- 50, INT_MAX, TASKQ_PREPOPULATE);
- if (tq == NULL) {
- rc = -ENOMEM;
- goto out2;
- }
-
- mp->mp_magic = SPLAT_MUTEX_TEST_MAGIC;
- mp->mp_file = file;
- mutex_init(&mp->mp_mtx, SPLAT_MUTEX_TEST_NAME, MUTEX_DEFAULT, NULL);
- mutex_enter(&mp->mp_mtx);
-
- /*
- * Schedule a task function which will try and acquire the mutex via
- * mutex_tryenter() while it's held. This should fail and the task
- * function will indicate this status in the passed private data.
- */
- mp->mp_rc = -EINVAL;
- id = taskq_dispatch(tq, splat_mutex_test1_func, mp, TQ_SLEEP);
- if (id == TASKQID_INVALID) {
- mutex_exit(&mp->mp_mtx);
- splat_vprint(file, SPLAT_MUTEX_TEST1_NAME, "%s",
- "taskq_dispatch() failed\n");
- rc = -EINVAL;
- goto out;
- }
-
- taskq_wait_id(tq, id);
- mutex_exit(&mp->mp_mtx);
-
- /* Task function successfully acquired mutex, very bad! */
- if (mp->mp_rc != -EBUSY) {
- splat_vprint(file, SPLAT_MUTEX_TEST1_NAME,
- "mutex_trylock() incorrectly succeeded when "
- "the mutex was held, %d/%d\n", (int)id, mp->mp_rc);
- rc = -EINVAL;
- goto out;
- } else {
- splat_vprint(file, SPLAT_MUTEX_TEST1_NAME, "%s",
- "mutex_trylock() correctly failed when "
- "the mutex was held\n");
- }
-
- /*
- * Schedule a task function which will try and acquire the mutex via
- * mutex_tryenter() while it is not held. This should succeed and
- * can be verified by checking the private data.
- */
- mp->mp_rc = -EINVAL;
- id = taskq_dispatch(tq, splat_mutex_test1_func, mp, TQ_SLEEP);
- if (id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_MUTEX_TEST1_NAME, "%s",
- "taskq_dispatch() failed\n");
- rc = -EINVAL;
- goto out;
- }
-
- taskq_wait_id(tq, id);
-
- /* Task function failed to acquire mutex, very bad! */
- if (mp->mp_rc != 0) {
- splat_vprint(file, SPLAT_MUTEX_TEST1_NAME,
- "mutex_trylock() incorrectly failed when the mutex "
- "was not held, %d/%d\n", (int)id, mp->mp_rc);
- rc = -EINVAL;
- } else {
- splat_vprint(file, SPLAT_MUTEX_TEST1_NAME, "%s",
- "mutex_trylock() correctly succeeded "
- "when the mutex was not held\n");
- }
-out:
- taskq_destroy(tq);
- mutex_destroy(&(mp->mp_mtx));
-out2:
- kfree(mp);
- return rc;
-}
-
-static void
-splat_mutex_test2_func(void *arg)
-{
- mutex_priv_t *mp = (mutex_priv_t *)arg;
- int rc;
- ASSERT(mp->mp_magic == SPLAT_MUTEX_TEST_MAGIC);
-
- /* Read the value before sleeping and write it after we wake up to
- * maximize the chance of a race if mutexs are not working properly */
- mutex_enter(&mp->mp_mtx);
- rc = mp->mp_rc;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 100); /* 1/100 of a second */
- VERIFY(mp->mp_rc == rc);
- mp->mp_rc = rc + 1;
- mutex_exit(&mp->mp_mtx);
-}
-
-static int
-splat_mutex_test2(struct file *file, void *arg)
-{
- mutex_priv_t *mp;
- taskq_t *tq;
- taskqid_t id;
- int i, rc = 0;
-
- mp = (mutex_priv_t *)kmalloc(sizeof(*mp), GFP_KERNEL);
- if (mp == NULL)
- return -ENOMEM;
-
- /* Create several threads allowing tasks to race with each other */
- tq = taskq_create(SPLAT_MUTEX_TEST_TASKQ, num_online_cpus(),
- defclsyspri, 50, INT_MAX, TASKQ_PREPOPULATE);
- if (tq == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- mp->mp_magic = SPLAT_MUTEX_TEST_MAGIC;
- mp->mp_file = file;
- mutex_init(&(mp->mp_mtx), SPLAT_MUTEX_TEST_NAME, MUTEX_DEFAULT, NULL);
- mp->mp_rc = 0;
-
- /*
- * Schedule N work items to the work queue each of which enters the
- * mutex, sleeps briefly, then exits the mutex. On a multiprocessor
- * box these work items will be handled by all available CPUs. The
- * task function checks to ensure the tracked shared variable is
- * always only incremented by one. Additionally, the mutex itself
- * is instrumented such that if any two processors are in the
- * critical region at the same time the system will panic. If the
- * mutex is implemented right this will never happy, that's a pass.
- */
- for (i = 0; i < SPLAT_MUTEX_TEST_COUNT; i++) {
- id = taskq_dispatch(tq, splat_mutex_test2_func, mp, TQ_SLEEP);
- if (id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_MUTEX_TEST2_NAME,
- "Failed to queue task %d\n", i);
- rc = -EINVAL;
- }
- }
-
- taskq_wait(tq);
-
- if (mp->mp_rc == SPLAT_MUTEX_TEST_COUNT) {
- splat_vprint(file, SPLAT_MUTEX_TEST2_NAME, "%d racing threads "
- "correctly entered/exited the mutex %d times\n",
- num_online_cpus(), mp->mp_rc);
- } else {
- splat_vprint(file, SPLAT_MUTEX_TEST2_NAME, "%d racing threads "
- "only processed %d/%d mutex work items\n",
- num_online_cpus(),mp->mp_rc,SPLAT_MUTEX_TEST_COUNT);
- rc = -EINVAL;
- }
-
- taskq_destroy(tq);
- mutex_destroy(&(mp->mp_mtx));
-out:
- kfree(mp);
- return rc;
-}
-
-static void
-splat_mutex_owned(void *priv)
-{
- mutex_priv_t *mp = (mutex_priv_t *)priv;
-
- ASSERT(mp->mp_magic == SPLAT_MUTEX_TEST_MAGIC);
- mp->mp_rc = mutex_owned(&mp->mp_mtx);
- mp->mp_rc2 = MUTEX_HELD(&mp->mp_mtx);
-}
-
-static int
-splat_mutex_test3(struct file *file, void *arg)
-{
- mutex_priv_t mp;
- taskq_t *tq;
- taskqid_t id;
- int rc = 0;
-
- mp.mp_magic = SPLAT_MUTEX_TEST_MAGIC;
- mp.mp_file = file;
- mutex_init(&mp.mp_mtx, SPLAT_MUTEX_TEST_NAME, MUTEX_DEFAULT, NULL);
-
- if ((tq = taskq_create(SPLAT_MUTEX_TEST_NAME, 1, defclsyspri,
- 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) {
- splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Taskq '%s' "
- "create failed\n", SPLAT_MUTEX_TEST3_NAME);
- return -EINVAL;
- }
-
- mutex_enter(&mp.mp_mtx);
-
- /* Mutex should be owned by current */
- if (!mutex_owned(&mp.mp_mtx)) {
- splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Unowned mutex "
- "should be owned by pid %d\n", current->pid);
- rc = -EINVAL;
- goto out_exit;
- }
-
- id = taskq_dispatch(tq, splat_mutex_owned, &mp, TQ_SLEEP);
- if (id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Failed to "
- "dispatch function '%s' to taskq\n",
- sym2str(splat_mutex_owned));
- rc = -EINVAL;
- goto out_exit;
- }
- taskq_wait(tq);
-
- /* Mutex should not be owned which checked from a different thread */
- if (mp.mp_rc || mp.mp_rc2) {
- splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Mutex owned by "
- "pid %d not by taskq\n", current->pid);
- rc = -EINVAL;
- goto out_exit;
- }
-
- mutex_exit(&mp.mp_mtx);
-
- /* Mutex should not be owned by current */
- if (mutex_owned(&mp.mp_mtx)) {
- splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Mutex owned by "
- "pid %d it should be unowned\b", current->pid);
- rc = -EINVAL;
- goto out;
- }
-
- id = taskq_dispatch(tq, splat_mutex_owned, &mp, TQ_SLEEP);
- if (id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Failed to "
- "dispatch function '%s' to taskq\n",
- sym2str(splat_mutex_owned));
- rc = -EINVAL;
- goto out;
- }
- taskq_wait(tq);
-
- /* Mutex should be owned by no one */
- if (mp.mp_rc || mp.mp_rc2) {
- splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Mutex owned by "
- "no one, %d/%d disagrees\n", mp.mp_rc, mp.mp_rc2);
- rc = -EINVAL;
- goto out;
- }
-
- splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "%s",
- "Correct mutex_owned() behavior\n");
- goto out;
-out_exit:
- mutex_exit(&mp.mp_mtx);
-out:
- mutex_destroy(&mp.mp_mtx);
- taskq_destroy(tq);
-
- return rc;
-}
-
-static int
-splat_mutex_test4(struct file *file, void *arg)
-{
- kmutex_t mtx;
- kthread_t *owner;
- int rc = 0;
-
- mutex_init(&mtx, SPLAT_MUTEX_TEST_NAME, MUTEX_DEFAULT, NULL);
-
- /*
- * Verify mutex owner is cleared after being dropped. Depending
- * on how you build your kernel this behavior changes, ensure the
- * SPL mutex implementation is properly detecting this.
- */
- mutex_enter(&mtx);
- msleep(100);
- mutex_exit(&mtx);
- if (MUTEX_HELD(&mtx)) {
- splat_vprint(file, SPLAT_MUTEX_TEST4_NAME, "Mutex should "
- "not be held, bit is by %p\n", mutex_owner(&mtx));
- rc = -EINVAL;
- goto out;
- }
-
- mutex_enter(&mtx);
-
- /* Mutex should be owned by current */
- owner = mutex_owner(&mtx);
- if (current != owner) {
- splat_vprint(file, SPLAT_MUTEX_TEST4_NAME, "Mutex should "
- "be owned by pid %d but is owned by pid %d\n",
- current->pid, owner ? owner->pid : -1);
- rc = -EINVAL;
- goto out;
- }
-
- mutex_exit(&mtx);
-
- /* Mutex should not be owned by any task */
- owner = mutex_owner(&mtx);
- if (owner) {
- splat_vprint(file, SPLAT_MUTEX_TEST4_NAME, "Mutex should not "
- "be owned but is owned by pid %d\n", owner->pid);
- rc = -EINVAL;
- goto out;
- }
-
- splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "%s",
- "Correct mutex_owner() behavior\n");
-out:
- mutex_destroy(&mtx);
-
- return rc;
-}
-
-splat_subsystem_t *
-splat_mutex_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_MUTEX_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_MUTEX_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_MUTEX;
-
- splat_test_init(sub, SPLAT_MUTEX_TEST1_NAME, SPLAT_MUTEX_TEST1_DESC,
- SPLAT_MUTEX_TEST1_ID, splat_mutex_test1);
- splat_test_init(sub, SPLAT_MUTEX_TEST2_NAME, SPLAT_MUTEX_TEST2_DESC,
- SPLAT_MUTEX_TEST2_ID, splat_mutex_test2);
- splat_test_init(sub, SPLAT_MUTEX_TEST3_NAME, SPLAT_MUTEX_TEST3_DESC,
- SPLAT_MUTEX_TEST3_ID, splat_mutex_test3);
- splat_test_init(sub, SPLAT_MUTEX_TEST4_NAME, SPLAT_MUTEX_TEST4_DESC,
- SPLAT_MUTEX_TEST4_ID, splat_mutex_test4);
-
- return sub;
-}
-
-void
-splat_mutex_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
- splat_test_fini(sub, SPLAT_MUTEX_TEST4_ID);
- splat_test_fini(sub, SPLAT_MUTEX_TEST3_ID);
- splat_test_fini(sub, SPLAT_MUTEX_TEST2_ID);
- splat_test_fini(sub, SPLAT_MUTEX_TEST1_ID);
-
- kfree(sub);
-}
-
-int
-splat_mutex_id(void) {
- return SPLAT_SUBSYSTEM_MUTEX;
-}
diff --git a/module/splat/splat-random.c b/module/splat/splat-random.c
deleted file mode 100644
index 2ddb823fc..000000000
--- a/module/splat/splat-random.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Random Number Generator Tests.
- */
-
-#include <sys/random.h>
-#include <sys/kmem.h>
-#include "splat-internal.h"
-
-#define SPLAT_KRNG_NAME "krng"
-#define SPLAT_KRNG_DESC "Kernel Random Number Generator Tests"
-
-#define SPLAT_KRNG_TEST1_ID 0x0301
-#define SPLAT_KRNG_TEST1_NAME "freq"
-#define SPLAT_KRNG_TEST1_DESC "Frequency Test"
-
-#define KRNG_NUM_BITS 1048576
-#define KRNG_NUM_BYTES (KRNG_NUM_BITS >> 3)
-#define KRNG_NUM_BITS_DIV2 (KRNG_NUM_BITS >> 1)
-#define KRNG_ERROR_RANGE 2097
-
-/* Random Number Generator Tests
- There can be meny more tests on quality of the
- random number generator. For now we are only
- testing the frequency of particular bits.
- We could also test consecutive sequences,
- randomness within a particular block, etc.
- but is probably not necessary for our purposes */
-
-static int
-splat_krng_test1(struct file *file, void *arg)
-{
- uint8_t *buf;
- int i, j, diff, num = 0, rc = 0;
-
- buf = kmalloc(sizeof(*buf) * KRNG_NUM_BYTES, GFP_KERNEL);
- if (buf == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- memset(buf, 0, sizeof(*buf) * KRNG_NUM_BYTES);
-
- /* Always succeeds */
- random_get_pseudo_bytes(buf, sizeof(uint8_t) * KRNG_NUM_BYTES);
-
- for (i = 0; i < KRNG_NUM_BYTES; i++) {
- uint8_t tmp = buf[i];
- for (j = 0; j < 8; j++) {
- uint8_t tmp2 = ((tmp >> j) & 0x01);
- if (tmp2 == 1) {
- num++;
- }
- }
- }
-
- kfree(buf);
-
- diff = KRNG_NUM_BITS_DIV2 - num;
- if (diff < 0)
- diff *= -1;
-
- splat_print(file, "Test 1 Number of ones: %d\n", num);
- splat_print(file, "Test 1 Difference from expected: %d Allowed: %d\n",
- diff, KRNG_ERROR_RANGE);
-
- if (diff > KRNG_ERROR_RANGE)
- rc = -ERANGE;
-out:
- return rc;
-}
-
-splat_subsystem_t *
-splat_krng_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_KRNG_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_KRNG_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_KRNG;
-
- splat_test_init(sub, SPLAT_KRNG_TEST1_NAME, SPLAT_KRNG_TEST1_DESC,
- SPLAT_KRNG_TEST1_ID, splat_krng_test1);
-
- return sub;
-}
-
-void
-splat_krng_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
-
- splat_test_fini(sub, SPLAT_KRNG_TEST1_ID);
-
- kfree(sub);
-}
-
-int
-splat_krng_id(void) {
- return SPLAT_SUBSYSTEM_KRNG;
-}
diff --git a/module/splat/splat-rwlock.c b/module/splat/splat-rwlock.c
deleted file mode 100644
index 562a5f047..000000000
--- a/module/splat/splat-rwlock.c
+++ /dev/null
@@ -1,747 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Read/Writer Lock Tests.
- */
-
-#include <sys/random.h>
-#include <sys/rwlock.h>
-#include <sys/taskq.h>
-#include <linux/delay.h>
-#include <linux/mm_compat.h>
-#include "splat-internal.h"
-
-#define SPLAT_RWLOCK_NAME "rwlock"
-#define SPLAT_RWLOCK_DESC "Kernel RW Lock Tests"
-
-#define SPLAT_RWLOCK_TEST1_ID 0x0701
-#define SPLAT_RWLOCK_TEST1_NAME "N-rd/1-wr"
-#define SPLAT_RWLOCK_TEST1_DESC "Multiple readers one writer"
-
-#define SPLAT_RWLOCK_TEST2_ID 0x0702
-#define SPLAT_RWLOCK_TEST2_NAME "0-rd/N-wr"
-#define SPLAT_RWLOCK_TEST2_DESC "Multiple writers"
-
-#define SPLAT_RWLOCK_TEST3_ID 0x0703
-#define SPLAT_RWLOCK_TEST3_NAME "held"
-#define SPLAT_RWLOCK_TEST3_DESC "RW_{LOCK|READ|WRITE}_HELD"
-
-#define SPLAT_RWLOCK_TEST4_ID 0x0704
-#define SPLAT_RWLOCK_TEST4_NAME "tryenter"
-#define SPLAT_RWLOCK_TEST4_DESC "Tryenter"
-
-#define SPLAT_RWLOCK_TEST5_ID 0x0705
-#define SPLAT_RWLOCK_TEST5_NAME "rw_downgrade"
-#define SPLAT_RWLOCK_TEST5_DESC "Write downgrade"
-
-#define SPLAT_RWLOCK_TEST6_ID 0x0706
-#define SPLAT_RWLOCK_TEST6_NAME "rw_tryupgrade-1"
-#define SPLAT_RWLOCK_TEST6_DESC "rwsem->count value"
-
-#define SPLAT_RWLOCK_TEST7_ID 0x0707
-#define SPLAT_RWLOCK_TEST7_NAME "rw_tryupgrade-2"
-#define SPLAT_RWLOCK_TEST7_DESC "Read upgrade"
-
-#define SPLAT_RWLOCK_TEST_MAGIC 0x115599DDUL
-#define SPLAT_RWLOCK_TEST_NAME "rwlock_test"
-#define SPLAT_RWLOCK_TEST_TASKQ "rwlock_taskq"
-#define SPLAT_RWLOCK_TEST_COUNT 8
-
-#define SPLAT_RWLOCK_RELEASE_INIT 0
-#define SPLAT_RWLOCK_RELEASE_WR 1
-#define SPLAT_RWLOCK_RELEASE_RD 2
-
-typedef struct rw_priv {
- unsigned long rw_magic;
- struct file *rw_file;
- krwlock_t rw_rwlock;
- spinlock_t rw_lock;
- spl_wait_queue_head_t rw_waitq;
- int rw_completed;
- int rw_holders;
- int rw_waiters;
- int rw_release;
- int rw_rc;
- krw_t rw_type;
-} rw_priv_t;
-
-typedef struct rw_thr {
- const char *rwt_name;
- rw_priv_t *rwt_rwp;
- struct task_struct *rwt_thread;
-} rw_thr_t;
-
-void splat_init_rw_priv(rw_priv_t *rwp, struct file *file)
-{
- rwp->rw_magic = SPLAT_RWLOCK_TEST_MAGIC;
- rwp->rw_file = file;
- rw_init(&rwp->rw_rwlock, SPLAT_RWLOCK_TEST_NAME, RW_DEFAULT, NULL);
- spin_lock_init(&rwp->rw_lock);
- init_waitqueue_head(&rwp->rw_waitq);
- rwp->rw_completed = 0;
- rwp->rw_holders = 0;
- rwp->rw_waiters = 0;
- rwp->rw_release = SPLAT_RWLOCK_RELEASE_INIT;
- rwp->rw_rc = 0;
- rwp->rw_type = 0;
-}
-
-#if defined(CONFIG_PREEMPT_RT_FULL)
-static int
-splat_rwlock_test1(struct file *file, void *arg)
-{
- /*
- * This test will never succeed on PREEMPT_RT_FULL because these
- * kernels only allow a single thread to hold the lock.
- */
- return 0;
-}
-#else
-static int
-splat_rwlock_wr_thr(void *arg)
-{
- rw_thr_t *rwt = (rw_thr_t *)arg;
- rw_priv_t *rwp = rwt->rwt_rwp;
- uint8_t rnd;
-
- ASSERT(rwp->rw_magic == SPLAT_RWLOCK_TEST_MAGIC);
-
- get_random_bytes((void *)&rnd, 1);
- msleep((unsigned int)rnd);
-
- splat_vprint(rwp->rw_file, rwt->rwt_name,
- "%s trying to acquire rwlock (%d holding/%d waiting)\n",
- rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
- spin_lock(&rwp->rw_lock);
- rwp->rw_waiters++;
- spin_unlock(&rwp->rw_lock);
- rw_enter(&rwp->rw_rwlock, RW_WRITER);
-
- spin_lock(&rwp->rw_lock);
- rwp->rw_waiters--;
- rwp->rw_holders++;
- spin_unlock(&rwp->rw_lock);
- splat_vprint(rwp->rw_file, rwt->rwt_name,
- "%s acquired rwlock (%d holding/%d waiting)\n",
- rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
-
- /* Wait for control thread to signal we can release the write lock */
- wait_event_interruptible(rwp->rw_waitq, splat_locked_test(&rwp->rw_lock,
- rwp->rw_release == SPLAT_RWLOCK_RELEASE_WR));
-
- spin_lock(&rwp->rw_lock);
- rwp->rw_completed++;
- rwp->rw_holders--;
- spin_unlock(&rwp->rw_lock);
- splat_vprint(rwp->rw_file, rwt->rwt_name,
- "%s dropped rwlock (%d holding/%d waiting)\n",
- rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
-
- rw_exit(&rwp->rw_rwlock);
-
- return 0;
-}
-
-static int
-splat_rwlock_rd_thr(void *arg)
-{
- rw_thr_t *rwt = (rw_thr_t *)arg;
- rw_priv_t *rwp = rwt->rwt_rwp;
- uint8_t rnd;
-
- ASSERT(rwp->rw_magic == SPLAT_RWLOCK_TEST_MAGIC);
-
- get_random_bytes((void *)&rnd, 1);
- msleep((unsigned int)rnd);
-
- /* Don't try and take the semaphore until after someone has it */
- wait_event_interruptible(rwp->rw_waitq,
- splat_locked_test(&rwp->rw_lock, rwp->rw_holders > 0));
-
- splat_vprint(rwp->rw_file, rwt->rwt_name,
- "%s trying to acquire rwlock (%d holding/%d waiting)\n",
- rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
- spin_lock(&rwp->rw_lock);
- rwp->rw_waiters++;
- spin_unlock(&rwp->rw_lock);
- rw_enter(&rwp->rw_rwlock, RW_READER);
-
- spin_lock(&rwp->rw_lock);
- rwp->rw_waiters--;
- rwp->rw_holders++;
- spin_unlock(&rwp->rw_lock);
- splat_vprint(rwp->rw_file, rwt->rwt_name,
- "%s acquired rwlock (%d holding/%d waiting)\n",
- rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
-
- /* Wait for control thread to signal we can release the read lock */
- wait_event_interruptible(rwp->rw_waitq, splat_locked_test(&rwp->rw_lock,
- rwp->rw_release == SPLAT_RWLOCK_RELEASE_RD));
-
- spin_lock(&rwp->rw_lock);
- rwp->rw_completed++;
- rwp->rw_holders--;
- spin_unlock(&rwp->rw_lock);
- splat_vprint(rwp->rw_file, rwt->rwt_name,
- "%s dropped rwlock (%d holding/%d waiting)\n",
- rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
-
- rw_exit(&rwp->rw_rwlock);
-
- return 0;
-}
-
-static int
-splat_rwlock_test1(struct file *file, void *arg)
-{
- int i, count = 0, rc = 0;
- rw_thr_t rwt[SPLAT_RWLOCK_TEST_COUNT];
- rw_priv_t *rwp;
-
- rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
- if (rwp == NULL)
- return -ENOMEM;
-
- splat_init_rw_priv(rwp, file);
-
- /* Create some threads, the exact number isn't important just as
- * long as we know how many we managed to create and should expect. */
- for (i = 0; i < SPLAT_RWLOCK_TEST_COUNT; i++) {
- rwt[i].rwt_rwp = rwp;
- rwt[i].rwt_name = SPLAT_RWLOCK_TEST1_NAME;
-
- /* The first thread will be the writer */
- if (i == 0)
- rwt[i].rwt_thread = spl_kthread_create(splat_rwlock_wr_thr,
- &rwt[i], "%s/%d", SPLAT_RWLOCK_TEST_NAME, i);
- else
- rwt[i].rwt_thread = spl_kthread_create(splat_rwlock_rd_thr,
- &rwt[i], "%s/%d", SPLAT_RWLOCK_TEST_NAME, i);
-
- if (!IS_ERR(rwt[i].rwt_thread)) {
- wake_up_process(rwt[i].rwt_thread);
- count++;
- }
- }
-
- /* Wait for the writer */
- while (splat_locked_test(&rwp->rw_lock, rwp->rw_holders == 0)) {
- wake_up_interruptible(&rwp->rw_waitq);
- msleep(100);
- }
-
- /* Wait for 'count-1' readers */
- while (splat_locked_test(&rwp->rw_lock, rwp->rw_waiters < count - 1)) {
- wake_up_interruptible(&rwp->rw_waitq);
- msleep(100);
- }
-
- /* Verify there is only one lock holder */
- if (splat_locked_test(&rwp->rw_lock, rwp->rw_holders) != 1) {
- splat_vprint(file, SPLAT_RWLOCK_TEST1_NAME, "Only 1 holder "
- "expected for rwlock (%d holding/%d waiting)\n",
- rwp->rw_holders, rwp->rw_waiters);
- rc = -EINVAL;
- }
-
- /* Verify 'count-1' readers */
- if (splat_locked_test(&rwp->rw_lock, rwp->rw_waiters != count - 1)) {
- splat_vprint(file, SPLAT_RWLOCK_TEST1_NAME, "Only %d waiters "
- "expected for rwlock (%d holding/%d waiting)\n",
- count - 1, rwp->rw_holders, rwp->rw_waiters);
- rc = -EINVAL;
- }
-
- /* Signal the writer to release, allows readers to acquire */
- spin_lock(&rwp->rw_lock);
- rwp->rw_release = SPLAT_RWLOCK_RELEASE_WR;
- wake_up_interruptible(&rwp->rw_waitq);
- spin_unlock(&rwp->rw_lock);
-
- /* Wait for 'count-1' readers to hold the lock */
- while (splat_locked_test(&rwp->rw_lock, rwp->rw_holders < count - 1)) {
- wake_up_interruptible(&rwp->rw_waitq);
- msleep(100);
- }
-
- /* Verify there are 'count-1' readers */
- if (splat_locked_test(&rwp->rw_lock, rwp->rw_holders != count - 1)) {
- splat_vprint(file, SPLAT_RWLOCK_TEST1_NAME, "Only %d holders "
- "expected for rwlock (%d holding/%d waiting)\n",
- count - 1, rwp->rw_holders, rwp->rw_waiters);
- rc = -EINVAL;
- }
-
- /* Release 'count-1' readers */
- spin_lock(&rwp->rw_lock);
- rwp->rw_release = SPLAT_RWLOCK_RELEASE_RD;
- wake_up_interruptible(&rwp->rw_waitq);
- spin_unlock(&rwp->rw_lock);
-
- /* Wait for the test to complete */
- while (splat_locked_test(&rwp->rw_lock,
- rwp->rw_holders>0 || rwp->rw_waiters>0))
- msleep(100);
-
- rw_destroy(&(rwp->rw_rwlock));
- kfree(rwp);
-
- return rc;
-}
-#endif
-
-static void
-splat_rwlock_test2_func(void *arg)
-{
- rw_priv_t *rwp = (rw_priv_t *)arg;
- int rc;
- ASSERT(rwp->rw_magic == SPLAT_RWLOCK_TEST_MAGIC);
-
- /* Read the value before sleeping and write it after we wake up to
- * maximize the chance of a race if rwlocks are not working properly */
- rw_enter(&rwp->rw_rwlock, RW_WRITER);
- rc = rwp->rw_rc;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 100); /* 1/100 of a second */
- VERIFY(rwp->rw_rc == rc);
- rwp->rw_rc = rc + 1;
- rw_exit(&rwp->rw_rwlock);
-}
-
-static int
-splat_rwlock_test2(struct file *file, void *arg)
-{
- rw_priv_t *rwp;
- taskq_t *tq;
- int i, rc = 0, tq_count = 256;
-
- rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
- if (rwp == NULL)
- return -ENOMEM;
-
- splat_init_rw_priv(rwp, file);
-
- /* Create several threads allowing tasks to race with each other */
- tq = taskq_create(SPLAT_RWLOCK_TEST_TASKQ, num_online_cpus(),
- defclsyspri, 50, INT_MAX, TASKQ_PREPOPULATE);
- if (tq == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- /*
- * Schedule N work items to the work queue each of which enters the
- * writer rwlock, sleeps briefly, then exits the writer rwlock. On a
- * multiprocessor box these work items will be handled by all available
- * CPUs. The task function checks to ensure the tracked shared variable
- * is always only incremented by one. Additionally, the rwlock itself
- * is instrumented such that if any two processors are in the
- * critical region at the same time the system will panic. If the
- * rwlock is implemented right this will never happy, that's a pass.
- */
- for (i = 0; i < tq_count; i++) {
- if (taskq_dispatch(tq, splat_rwlock_test2_func, rwp,
- TQ_SLEEP) == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_RWLOCK_TEST2_NAME,
- "Failed to queue task %d\n", i);
- rc = -EINVAL;
- }
- }
-
- taskq_wait(tq);
-
- if (rwp->rw_rc == tq_count) {
- splat_vprint(file, SPLAT_RWLOCK_TEST2_NAME, "%d racing threads "
- "correctly entered/exited the rwlock %d times\n",
- num_online_cpus(), rwp->rw_rc);
- } else {
- splat_vprint(file, SPLAT_RWLOCK_TEST2_NAME, "%d racing threads "
- "only processed %d/%d w rwlock work items\n",
- num_online_cpus(), rwp->rw_rc, tq_count);
- rc = -EINVAL;
- }
-
- taskq_destroy(tq);
- rw_destroy(&(rwp->rw_rwlock));
-out:
- kfree(rwp);
- return rc;
-}
-
-#define splat_rwlock_test3_helper(rwp,rex1,rex2,wex1,wex2,held_func,rc) \
-do { \
- int result, _rc1_, _rc2_, _rc3_, _rc4_; \
- \
- rc = 0; \
- rw_enter(&(rwp)->rw_rwlock, RW_READER); \
- _rc1_ = ((result = held_func(&(rwp)->rw_rwlock)) != rex1); \
- splat_vprint(file, SPLAT_RWLOCK_TEST3_NAME, "%s" #held_func \
- " returned %d (expected %d) when RW_READER\n", \
- _rc1_ ? "Fail " : "", result, rex1); \
- rw_exit(&(rwp)->rw_rwlock); \
- _rc2_ = ((result = held_func(&(rwp)->rw_rwlock)) != rex2); \
- splat_vprint(file, SPLAT_RWLOCK_TEST3_NAME, "%s" #held_func \
- " returned %d (expected %d) when !RW_READER\n", \
- _rc2_ ? "Fail " : "", result, rex2); \
- \
- rw_enter(&(rwp)->rw_rwlock, RW_WRITER); \
- _rc3_ = ((result = held_func(&(rwp)->rw_rwlock)) != wex1); \
- splat_vprint(file, SPLAT_RWLOCK_TEST3_NAME, "%s" #held_func \
- " returned %d (expected %d) when RW_WRITER\n", \
- _rc3_ ? "Fail " : "", result, wex1); \
- rw_exit(&(rwp)->rw_rwlock); \
- _rc4_ = ((result = held_func(&(rwp)->rw_rwlock)) != wex2); \
- splat_vprint(file, SPLAT_RWLOCK_TEST3_NAME, "%s" #held_func \
- " returned %d (expected %d) when !RW_WRITER\n", \
- _rc4_ ? "Fail " : "", result, wex2); \
- \
- rc = ((_rc1_ || _rc2_ || _rc3_ || _rc4_) ? -EINVAL : 0); \
-} while(0);
-
-static int
-splat_rwlock_test3(struct file *file, void *arg)
-{
- rw_priv_t *rwp;
- int rc1, rc2, rc3;
-
- rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
- if (rwp == NULL)
- return -ENOMEM;
-
- splat_init_rw_priv(rwp, file);
-
- splat_rwlock_test3_helper(rwp, 1, 0, 1, 0, RW_LOCK_HELD, rc1);
- splat_rwlock_test3_helper(rwp, 1, 0, 0, 0, RW_READ_HELD, rc2);
- splat_rwlock_test3_helper(rwp, 0, 0, 1, 0, RW_WRITE_HELD, rc3);
-
- rw_destroy(&rwp->rw_rwlock);
- kfree(rwp);
-
- return ((rc1 || rc2 || rc3) ? -EINVAL : 0);
-}
-
-static void
-splat_rwlock_test4_func(void *arg)
-{
- rw_priv_t *rwp = (rw_priv_t *)arg;
- ASSERT(rwp->rw_magic == SPLAT_RWLOCK_TEST_MAGIC);
-
- if (rw_tryenter(&rwp->rw_rwlock, rwp->rw_type)) {
- rwp->rw_rc = 0;
- rw_exit(&rwp->rw_rwlock);
- } else {
- rwp->rw_rc = -EBUSY;
- }
-}
-
-static char *
-splat_rwlock_test4_name(krw_t type)
-{
- switch (type) {
- case RW_NONE: return "RW_NONE";
- case RW_WRITER: return "RW_WRITER";
- case RW_READER: return "RW_READER";
- }
-
- return NULL;
-}
-
-static int
-splat_rwlock_test4_type(taskq_t *tq, rw_priv_t *rwp, int expected_rc,
- krw_t holder_type, krw_t try_type)
-{
- int id, rc = 0;
-
- /* Schedule a task function which will try and acquire the rwlock
- * using type try_type while the rwlock is being held as holder_type.
- * The result must match expected_rc for the test to pass */
- rwp->rw_rc = -EINVAL;
- rwp->rw_type = try_type;
-
- if (holder_type == RW_WRITER || holder_type == RW_READER)
- rw_enter(&rwp->rw_rwlock, holder_type);
-
- id = taskq_dispatch(tq, splat_rwlock_test4_func, rwp, TQ_SLEEP);
- if (id == TASKQID_INVALID) {
- splat_vprint(rwp->rw_file, SPLAT_RWLOCK_TEST4_NAME, "%s",
- "taskq_dispatch() failed\n");
- rc = -EINVAL;
- goto out;
- }
-
- taskq_wait_id(tq, id);
-
- if (rwp->rw_rc != expected_rc)
- rc = -EINVAL;
-
- splat_vprint(rwp->rw_file, SPLAT_RWLOCK_TEST4_NAME,
- "%srw_tryenter(%s) returned %d (expected %d) when %s\n",
- rc ? "Fail " : "", splat_rwlock_test4_name(try_type),
- rwp->rw_rc, expected_rc,
- splat_rwlock_test4_name(holder_type));
-out:
- if (holder_type == RW_WRITER || holder_type == RW_READER)
- rw_exit(&rwp->rw_rwlock);
-
- return rc;
-}
-
-static int
-splat_rwlock_test4(struct file *file, void *arg)
-{
- rw_priv_t *rwp;
- taskq_t *tq;
- int rc = 0, rc1, rc2, rc3, rc4, rc5, rc6;
-
- rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
- if (rwp == NULL)
- return -ENOMEM;
-
- tq = taskq_create(SPLAT_RWLOCK_TEST_TASKQ, 1, defclsyspri,
- 50, INT_MAX, TASKQ_PREPOPULATE);
- if (tq == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- splat_init_rw_priv(rwp, file);
-
- /*
- * Validate all combinations of rw_tryenter() contention.
- *
- * The concurrent reader test is modified for PREEMPT_RT_FULL
- * kernels which do not permit concurrent read locks to be taken
- * from different threads. The same thread is allowed to take
- * the read lock multiple times.
- */
- rc1 = splat_rwlock_test4_type(tq, rwp, -EBUSY, RW_WRITER, RW_WRITER);
- rc2 = splat_rwlock_test4_type(tq, rwp, -EBUSY, RW_WRITER, RW_READER);
- rc3 = splat_rwlock_test4_type(tq, rwp, -EBUSY, RW_READER, RW_WRITER);
-#if defined(CONFIG_PREEMPT_RT_FULL)
- rc4 = splat_rwlock_test4_type(tq, rwp, -EBUSY, RW_READER, RW_READER);
-#else
- rc4 = splat_rwlock_test4_type(tq, rwp, 0, RW_READER, RW_READER);
-#endif
- rc5 = splat_rwlock_test4_type(tq, rwp, 0, RW_NONE, RW_WRITER);
- rc6 = splat_rwlock_test4_type(tq, rwp, 0, RW_NONE, RW_READER);
-
- if (rc1 || rc2 || rc3 || rc4 || rc5 || rc6)
- rc = -EINVAL;
-
- taskq_destroy(tq);
-out:
- rw_destroy(&(rwp->rw_rwlock));
- kfree(rwp);
-
- return rc;
-}
-
-static int
-splat_rwlock_test5(struct file *file, void *arg)
-{
- rw_priv_t *rwp;
- int rc = -EINVAL;
-
- rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
- if (rwp == NULL)
- return -ENOMEM;
-
- splat_init_rw_priv(rwp, file);
-
- rw_enter(&rwp->rw_rwlock, RW_WRITER);
- if (!RW_WRITE_HELD(&rwp->rw_rwlock)) {
- splat_vprint(file, SPLAT_RWLOCK_TEST5_NAME,
- "rwlock should be write lock: %d\n",
- RW_WRITE_HELD(&rwp->rw_rwlock));
- goto out;
- }
-
- rw_downgrade(&rwp->rw_rwlock);
- if (!RW_READ_HELD(&rwp->rw_rwlock)) {
- splat_vprint(file, SPLAT_RWLOCK_TEST5_NAME,
- "rwlock should be read lock: %d\n",
- RW_READ_HELD(&rwp->rw_rwlock));
- goto out;
- }
-
- rc = 0;
- splat_vprint(file, SPLAT_RWLOCK_TEST5_NAME, "%s",
- "rwlock properly downgraded\n");
-out:
- rw_exit(&rwp->rw_rwlock);
- rw_destroy(&rwp->rw_rwlock);
- kfree(rwp);
-
- return rc;
-}
-
-static int
-splat_rwlock_test6(struct file *file, void *arg)
-{
- rw_priv_t *rwp;
- int rc;
-
- rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
- if (rwp == NULL)
- return -ENOMEM;
-
- splat_init_rw_priv(rwp, file);
-
- rw_enter(&rwp->rw_rwlock, RW_READER);
- if (RWSEM_COUNT(SEM(&rwp->rw_rwlock)) !=
- SPL_RWSEM_SINGLE_READER_VALUE) {
- splat_vprint(file, SPLAT_RWLOCK_TEST6_NAME,
- "We assumed single reader rwsem->count "
- "should be %ld, but is %ld\n",
- (long int)SPL_RWSEM_SINGLE_READER_VALUE,
- (long int)RWSEM_COUNT(SEM(&rwp->rw_rwlock)));
- rc = -ENOLCK;
- goto out;
- }
- rw_exit(&rwp->rw_rwlock);
-
- rw_enter(&rwp->rw_rwlock, RW_WRITER);
- if (RWSEM_COUNT(SEM(&rwp->rw_rwlock)) !=
- SPL_RWSEM_SINGLE_WRITER_VALUE) {
- splat_vprint(file, SPLAT_RWLOCK_TEST6_NAME,
- "We assumed single writer rwsem->count "
- "should be %ld, but is %ld\n",
- (long int)SPL_RWSEM_SINGLE_WRITER_VALUE,
- (long int)RWSEM_COUNT(SEM(&rwp->rw_rwlock)));
- rc = -ENOLCK;
- goto out;
- }
- rc = 0;
- splat_vprint(file, SPLAT_RWLOCK_TEST6_NAME, "%s",
- "rwsem->count same as we assumed\n");
-out:
- rw_exit(&rwp->rw_rwlock);
- rw_destroy(&rwp->rw_rwlock);
- kfree(rwp);
-
- return rc;
-}
-
-static int
-splat_rwlock_test7(struct file *file, void *arg)
-{
- rw_priv_t *rwp;
- int rc;
-
- rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
- if (rwp == NULL)
- return -ENOMEM;
-
- splat_init_rw_priv(rwp, file);
-
- rw_enter(&rwp->rw_rwlock, RW_READER);
- if (!RW_READ_HELD(&rwp->rw_rwlock)) {
- splat_vprint(file, SPLAT_RWLOCK_TEST7_NAME,
- "rwlock should be read lock: %d\n",
- RW_READ_HELD(&rwp->rw_rwlock));
- rc = -ENOLCK;
- goto out;
- }
-
- /* With one reader upgrade should never fail. */
- rc = rw_tryupgrade(&rwp->rw_rwlock);
- if (!rc) {
- splat_vprint(file, SPLAT_RWLOCK_TEST7_NAME,
- "rwlock failed upgrade from reader: %d\n",
- RW_READ_HELD(&rwp->rw_rwlock));
- rc = -ENOLCK;
- goto out;
- }
-
- if (RW_READ_HELD(&rwp->rw_rwlock) || !RW_WRITE_HELD(&rwp->rw_rwlock)) {
- splat_vprint(file, SPLAT_RWLOCK_TEST7_NAME, "rwlock should "
- "have 0 (not %d) reader and 1 (not %d) writer\n",
- RW_READ_HELD(&rwp->rw_rwlock),
- RW_WRITE_HELD(&rwp->rw_rwlock));
- goto out;
- }
-
- rc = 0;
- splat_vprint(file, SPLAT_RWLOCK_TEST7_NAME, "%s",
- "rwlock properly upgraded\n");
-out:
- rw_exit(&rwp->rw_rwlock);
- rw_destroy(&rwp->rw_rwlock);
- kfree(rwp);
-
- return rc;
-}
-
-splat_subsystem_t *
-splat_rwlock_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_RWLOCK_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_RWLOCK_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_RWLOCK;
-
- splat_test_init(sub, SPLAT_RWLOCK_TEST1_NAME, SPLAT_RWLOCK_TEST1_DESC,
- SPLAT_RWLOCK_TEST1_ID, splat_rwlock_test1);
- splat_test_init(sub, SPLAT_RWLOCK_TEST2_NAME, SPLAT_RWLOCK_TEST2_DESC,
- SPLAT_RWLOCK_TEST2_ID, splat_rwlock_test2);
- splat_test_init(sub, SPLAT_RWLOCK_TEST3_NAME, SPLAT_RWLOCK_TEST3_DESC,
- SPLAT_RWLOCK_TEST3_ID, splat_rwlock_test3);
- splat_test_init(sub, SPLAT_RWLOCK_TEST4_NAME, SPLAT_RWLOCK_TEST4_DESC,
- SPLAT_RWLOCK_TEST4_ID, splat_rwlock_test4);
- splat_test_init(sub, SPLAT_RWLOCK_TEST5_NAME, SPLAT_RWLOCK_TEST5_DESC,
- SPLAT_RWLOCK_TEST5_ID, splat_rwlock_test5);
- splat_test_init(sub, SPLAT_RWLOCK_TEST6_NAME, SPLAT_RWLOCK_TEST6_DESC,
- SPLAT_RWLOCK_TEST6_ID, splat_rwlock_test6);
- splat_test_init(sub, SPLAT_RWLOCK_TEST7_NAME, SPLAT_RWLOCK_TEST7_DESC,
- SPLAT_RWLOCK_TEST7_ID, splat_rwlock_test7);
-
- return sub;
-}
-
-void
-splat_rwlock_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
- splat_test_fini(sub, SPLAT_RWLOCK_TEST7_ID);
- splat_test_fini(sub, SPLAT_RWLOCK_TEST6_ID);
- splat_test_fini(sub, SPLAT_RWLOCK_TEST5_ID);
- splat_test_fini(sub, SPLAT_RWLOCK_TEST4_ID);
- splat_test_fini(sub, SPLAT_RWLOCK_TEST3_ID);
- splat_test_fini(sub, SPLAT_RWLOCK_TEST2_ID);
- splat_test_fini(sub, SPLAT_RWLOCK_TEST1_ID);
- kfree(sub);
-}
-
-int
-splat_rwlock_id(void) {
- return SPLAT_SUBSYSTEM_RWLOCK;
-}
diff --git a/module/splat/splat-taskq.c b/module/splat/splat-taskq.c
deleted file mode 100644
index ff73e103a..000000000
--- a/module/splat/splat-taskq.c
+++ /dev/null
@@ -1,1548 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Task Queue Tests.
- */
-
-#include <sys/kmem.h>
-#include <sys/vmem.h>
-#include <sys/random.h>
-#include <sys/taskq.h>
-#include <sys/time.h>
-#include <sys/timer.h>
-#include <linux/delay.h>
-#include "splat-internal.h"
-
-#define SPLAT_TASKQ_NAME "taskq"
-#define SPLAT_TASKQ_DESC "Kernel Task Queue Tests"
-
-#define SPLAT_TASKQ_TEST1_ID 0x0201
-#define SPLAT_TASKQ_TEST1_NAME "single"
-#define SPLAT_TASKQ_TEST1_DESC "Single task queue, single task"
-
-#define SPLAT_TASKQ_TEST2_ID 0x0202
-#define SPLAT_TASKQ_TEST2_NAME "multiple"
-#define SPLAT_TASKQ_TEST2_DESC "Multiple task queues, multiple tasks"
-
-#define SPLAT_TASKQ_TEST3_ID 0x0203
-#define SPLAT_TASKQ_TEST3_NAME "system"
-#define SPLAT_TASKQ_TEST3_DESC "System task queue, multiple tasks"
-
-#define SPLAT_TASKQ_TEST4_ID 0x0204
-#define SPLAT_TASKQ_TEST4_NAME "wait"
-#define SPLAT_TASKQ_TEST4_DESC "Multiple task waiting"
-
-#define SPLAT_TASKQ_TEST5_ID 0x0205
-#define SPLAT_TASKQ_TEST5_NAME "order"
-#define SPLAT_TASKQ_TEST5_DESC "Correct task ordering"
-
-#define SPLAT_TASKQ_TEST6_ID 0x0206
-#define SPLAT_TASKQ_TEST6_NAME "front"
-#define SPLAT_TASKQ_TEST6_DESC "Correct ordering with TQ_FRONT flag"
-
-#define SPLAT_TASKQ_TEST7_ID 0x0207
-#define SPLAT_TASKQ_TEST7_NAME "recurse"
-#define SPLAT_TASKQ_TEST7_DESC "Single task queue, recursive dispatch"
-
-#define SPLAT_TASKQ_TEST8_ID 0x0208
-#define SPLAT_TASKQ_TEST8_NAME "contention"
-#define SPLAT_TASKQ_TEST8_DESC "1 queue, 100 threads, 131072 tasks"
-
-#define SPLAT_TASKQ_TEST9_ID 0x0209
-#define SPLAT_TASKQ_TEST9_NAME "delay"
-#define SPLAT_TASKQ_TEST9_DESC "Delayed task execution"
-
-#define SPLAT_TASKQ_TEST10_ID 0x020a
-#define SPLAT_TASKQ_TEST10_NAME "cancel"
-#define SPLAT_TASKQ_TEST10_DESC "Cancel task execution"
-
-#define SPLAT_TASKQ_TEST11_ID 0x020b
-#define SPLAT_TASKQ_TEST11_NAME "dynamic"
-#define SPLAT_TASKQ_TEST11_DESC "Dynamic task queue thread creation"
-
-#define SPLAT_TASKQ_ORDER_MAX 8
-#define SPLAT_TASKQ_DEPTH_MAX 16
-
-
-typedef struct splat_taskq_arg {
- int flag;
- int id;
- atomic_t *count;
- int order[SPLAT_TASKQ_ORDER_MAX];
- unsigned int depth;
- clock_t expire;
- taskq_t *tq;
- taskq_ent_t *tqe;
- spinlock_t lock;
- struct file *file;
- const char *name;
-} splat_taskq_arg_t;
-
-typedef struct splat_taskq_id {
- int id;
- splat_taskq_arg_t *arg;
-} splat_taskq_id_t;
-
-/*
- * Create a taskq, queue a task, wait until task completes, ensure
- * task ran properly, cleanup taskq.
- */
-static void
-splat_taskq_test13_func(void *arg)
-{
- splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
-
- ASSERT(tq_arg);
- splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST1_NAME,
- "Taskq '%s' function '%s' setting flag\n",
- tq_arg->name, sym2str(splat_taskq_test13_func));
- tq_arg->flag = 1;
-}
-
-static int
-splat_taskq_test1_impl(struct file *file, void *arg, boolean_t prealloc)
-{
- taskq_t *tq;
- taskqid_t id;
- splat_taskq_arg_t tq_arg;
- taskq_ent_t *tqe;
-
- tqe = kmem_alloc(sizeof (taskq_ent_t), KM_SLEEP);
- taskq_init_ent(tqe);
-
- splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
- "Taskq '%s' creating (%s dispatch)\n",
- SPLAT_TASKQ_TEST1_NAME,
- prealloc ? "prealloc" : "dynamic");
- if ((tq = taskq_create(SPLAT_TASKQ_TEST1_NAME, 1, defclsyspri,
- 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) {
- splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
- "Taskq '%s' create failed\n",
- SPLAT_TASKQ_TEST1_NAME);
- kmem_free(tqe, sizeof (taskq_ent_t));
- return -EINVAL;
- }
-
- tq_arg.flag = 0;
- tq_arg.id = 0;
- tq_arg.file = file;
- tq_arg.name = SPLAT_TASKQ_TEST1_NAME;
-
- splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
- "Taskq '%s' function '%s' dispatching\n",
- tq_arg.name, sym2str(splat_taskq_test13_func));
- if (prealloc) {
- taskq_dispatch_ent(tq, splat_taskq_test13_func,
- &tq_arg, TQ_SLEEP, tqe);
- id = tqe->tqent_id;
- } else {
- id = taskq_dispatch(tq, splat_taskq_test13_func,
- &tq_arg, TQ_SLEEP);
- }
-
- if (id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
- "Taskq '%s' function '%s' dispatch failed\n",
- tq_arg.name, sym2str(splat_taskq_test13_func));
- kmem_free(tqe, sizeof (taskq_ent_t));
- taskq_destroy(tq);
- return -EINVAL;
- }
-
- splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' waiting\n",
- tq_arg.name);
- taskq_wait(tq);
- splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' destroying\n",
- tq_arg.name);
-
- kmem_free(tqe, sizeof (taskq_ent_t));
- taskq_destroy(tq);
-
- return (tq_arg.flag) ? 0 : -EINVAL;
-}
-
-static int
-splat_taskq_test1(struct file *file, void *arg)
-{
- int rc;
-
- rc = splat_taskq_test1_impl(file, arg, B_FALSE);
- if (rc)
- return rc;
-
- rc = splat_taskq_test1_impl(file, arg, B_TRUE);
-
- return rc;
-}
-
-/*
- * Create multiple taskq's, each with multiple tasks, wait until
- * all tasks complete, ensure all tasks ran properly and in the
- * correct order. Run order must be the same as the order submitted
- * because we only have 1 thread per taskq. Finally cleanup the taskq.
- */
-static void
-splat_taskq_test2_func1(void *arg)
-{
- splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
-
- ASSERT(tq_arg);
- splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST2_NAME,
- "Taskq '%s/%d' function '%s' flag = %d = %d * 2\n",
- tq_arg->name, tq_arg->id,
- sym2str(splat_taskq_test2_func1),
- tq_arg->flag * 2, tq_arg->flag);
- tq_arg->flag *= 2;
-}
-
-static void
-splat_taskq_test2_func2(void *arg)
-{
- splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
-
- ASSERT(tq_arg);
- splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST2_NAME,
- "Taskq '%s/%d' function '%s' flag = %d = %d + 1\n",
- tq_arg->name, tq_arg->id,
- sym2str(splat_taskq_test2_func2),
- tq_arg->flag + 1, tq_arg->flag);
- tq_arg->flag += 1;
-}
-
-#define TEST2_TASKQS 8
-#define TEST2_THREADS_PER_TASKQ 1
-
-static int
-splat_taskq_test2_impl(struct file *file, void *arg, boolean_t prealloc) {
- taskq_t *tq[TEST2_TASKQS] = { NULL };
- taskqid_t id;
- splat_taskq_arg_t *tq_args[TEST2_TASKQS] = { NULL };
- taskq_ent_t *func1_tqes = NULL;
- taskq_ent_t *func2_tqes = NULL;
- int i, rc = 0;
-
- func1_tqes = kmalloc(sizeof(*func1_tqes) * TEST2_TASKQS, GFP_KERNEL);
- if (func1_tqes == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- func2_tqes = kmalloc(sizeof(*func2_tqes) * TEST2_TASKQS, GFP_KERNEL);
- if (func2_tqes == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- for (i = 0; i < TEST2_TASKQS; i++) {
- taskq_init_ent(&func1_tqes[i]);
- taskq_init_ent(&func2_tqes[i]);
-
- tq_args[i] = kmalloc(sizeof (splat_taskq_arg_t), GFP_KERNEL);
- if (tq_args[i] == NULL) {
- rc = -ENOMEM;
- break;
- }
-
- splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
- "Taskq '%s/%d' creating (%s dispatch)\n",
- SPLAT_TASKQ_TEST2_NAME, i,
- prealloc ? "prealloc" : "dynamic");
- if ((tq[i] = taskq_create(SPLAT_TASKQ_TEST2_NAME,
- TEST2_THREADS_PER_TASKQ,
- defclsyspri, 50, INT_MAX,
- TASKQ_PREPOPULATE)) == NULL) {
- splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
- "Taskq '%s/%d' create failed\n",
- SPLAT_TASKQ_TEST2_NAME, i);
- rc = -EINVAL;
- break;
- }
-
- tq_args[i]->flag = i;
- tq_args[i]->id = i;
- tq_args[i]->file = file;
- tq_args[i]->name = SPLAT_TASKQ_TEST2_NAME;
-
- splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
- "Taskq '%s/%d' function '%s' dispatching\n",
- tq_args[i]->name, tq_args[i]->id,
- sym2str(splat_taskq_test2_func1));
- if (prealloc) {
- taskq_dispatch_ent(tq[i], splat_taskq_test2_func1,
- tq_args[i], TQ_SLEEP, &func1_tqes[i]);
- id = func1_tqes[i].tqent_id;
- } else {
- id = taskq_dispatch(tq[i], splat_taskq_test2_func1,
- tq_args[i], TQ_SLEEP);
- }
-
- if (id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
- "Taskq '%s/%d' function '%s' dispatch "
- "failed\n", tq_args[i]->name, tq_args[i]->id,
- sym2str(splat_taskq_test2_func1));
- rc = -EINVAL;
- break;
- }
-
- splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
- "Taskq '%s/%d' function '%s' dispatching\n",
- tq_args[i]->name, tq_args[i]->id,
- sym2str(splat_taskq_test2_func2));
- if (prealloc) {
- taskq_dispatch_ent(tq[i], splat_taskq_test2_func2,
- tq_args[i], TQ_SLEEP, &func2_tqes[i]);
- id = func2_tqes[i].tqent_id;
- } else {
- id = taskq_dispatch(tq[i], splat_taskq_test2_func2,
- tq_args[i], TQ_SLEEP);
- }
-
- if (id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq "
- "'%s/%d' function '%s' dispatch failed\n",
- tq_args[i]->name, tq_args[i]->id,
- sym2str(splat_taskq_test2_func2));
- rc = -EINVAL;
- break;
- }
- }
-
- /* When rc is set we're effectively just doing cleanup here, so
- * ignore new errors in that case. They just cause noise. */
- for (i = 0; i < TEST2_TASKQS; i++) {
- if (tq_args[i] == NULL)
- continue;
-
- if (tq[i] != NULL) {
- splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
- "Taskq '%s/%d' waiting\n",
- tq_args[i]->name, tq_args[i]->id);
- taskq_wait(tq[i]);
- splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
- "Taskq '%s/%d; destroying\n",
- tq_args[i]->name, tq_args[i]->id);
-
- taskq_destroy(tq[i]);
-
- if (!rc && tq_args[i]->flag != ((i * 2) + 1)) {
- splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
- "Taskq '%s/%d' processed tasks "
- "out of order; %d != %d\n",
- tq_args[i]->name, tq_args[i]->id,
- tq_args[i]->flag, i * 2 + 1);
- rc = -EINVAL;
- } else {
- splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
- "Taskq '%s/%d' processed tasks "
- "in the correct order; %d == %d\n",
- tq_args[i]->name, tq_args[i]->id,
- tq_args[i]->flag, i * 2 + 1);
- }
-
- kfree(tq_args[i]);
- }
- }
-out:
- if (func1_tqes)
- kfree(func1_tqes);
-
- if (func2_tqes)
- kfree(func2_tqes);
-
- return rc;
-}
-
-static int
-splat_taskq_test2(struct file *file, void *arg) {
- int rc;
-
- rc = splat_taskq_test2_impl(file, arg, B_FALSE);
- if (rc)
- return rc;
-
- rc = splat_taskq_test2_impl(file, arg, B_TRUE);
-
- return rc;
-}
-
-/*
- * Use the global system task queue with a single task, wait until task
- * completes, ensure task ran properly.
- */
-static int
-splat_taskq_test3_impl(struct file *file, void *arg, boolean_t prealloc)
-{
- taskqid_t id;
- splat_taskq_arg_t *tq_arg;
- taskq_ent_t *tqe;
- int error;
-
- tq_arg = kmem_alloc(sizeof (splat_taskq_arg_t), KM_SLEEP);
- tqe = kmem_alloc(sizeof (taskq_ent_t), KM_SLEEP);
- taskq_init_ent(tqe);
-
- tq_arg->flag = 0;
- tq_arg->id = 0;
- tq_arg->file = file;
- tq_arg->name = SPLAT_TASKQ_TEST3_NAME;
-
- splat_vprint(file, SPLAT_TASKQ_TEST3_NAME,
- "Taskq '%s' function '%s' %s dispatch\n",
- tq_arg->name, sym2str(splat_taskq_test13_func),
- prealloc ? "prealloc" : "dynamic");
- if (prealloc) {
- taskq_dispatch_ent(system_taskq, splat_taskq_test13_func,
- tq_arg, TQ_SLEEP, tqe);
- id = tqe->tqent_id;
- } else {
- id = taskq_dispatch(system_taskq, splat_taskq_test13_func,
- tq_arg, TQ_SLEEP);
- }
-
- if (id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_TASKQ_TEST3_NAME,
- "Taskq '%s' function '%s' dispatch failed\n",
- tq_arg->name, sym2str(splat_taskq_test13_func));
- kmem_free(tqe, sizeof (taskq_ent_t));
- kmem_free(tq_arg, sizeof (splat_taskq_arg_t));
- return -EINVAL;
- }
-
- splat_vprint(file, SPLAT_TASKQ_TEST3_NAME, "Taskq '%s' waiting\n",
- tq_arg->name);
- taskq_wait(system_taskq);
-
- error = (tq_arg->flag) ? 0 : -EINVAL;
-
- kmem_free(tqe, sizeof (taskq_ent_t));
- kmem_free(tq_arg, sizeof (splat_taskq_arg_t));
-
- return (error);
-}
-
-static int
-splat_taskq_test3(struct file *file, void *arg)
-{
- int rc;
-
- rc = splat_taskq_test3_impl(file, arg, B_FALSE);
- if (rc)
- return rc;
-
- rc = splat_taskq_test3_impl(file, arg, B_TRUE);
-
- return rc;
-}
-
-/*
- * Create a taskq and dispatch a large number of tasks to the queue.
- * Then use taskq_wait() to block until all the tasks complete, then
- * cross check that all the tasks ran by checking the shared atomic
- * counter which is incremented in the task function.
- *
- * First we try with a large 'maxalloc' value, then we try with a small one.
- * We should not drop tasks when TQ_SLEEP is used in taskq_dispatch(), even
- * if the number of pending tasks is above maxalloc.
- */
-static void
-splat_taskq_test4_func(void *arg)
-{
- splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
- ASSERT(tq_arg);
-
- atomic_inc(tq_arg->count);
-}
-
-static int
-splat_taskq_test4_common(struct file *file, void *arg, int minalloc,
- int maxalloc, int nr_tasks, boolean_t prealloc)
-{
- taskq_t *tq;
- taskqid_t id;
- splat_taskq_arg_t tq_arg;
- taskq_ent_t *tqes;
- atomic_t count;
- int i, j, rc = 0;
-
- tqes = kmalloc(sizeof(*tqes) * nr_tasks, GFP_KERNEL);
- if (tqes == NULL)
- return -ENOMEM;
-
- splat_vprint(file, SPLAT_TASKQ_TEST4_NAME,
- "Taskq '%s' creating (%s dispatch) (%d/%d/%d)\n",
- SPLAT_TASKQ_TEST4_NAME,
- prealloc ? "prealloc" : "dynamic",
- minalloc, maxalloc, nr_tasks);
- if ((tq = taskq_create(SPLAT_TASKQ_TEST4_NAME, 1, defclsyspri,
- minalloc, maxalloc, TASKQ_PREPOPULATE)) == NULL) {
- splat_vprint(file, SPLAT_TASKQ_TEST4_NAME,
- "Taskq '%s' create failed\n",
- SPLAT_TASKQ_TEST4_NAME);
- rc = -EINVAL;
- goto out_free;
- }
-
- tq_arg.file = file;
- tq_arg.name = SPLAT_TASKQ_TEST4_NAME;
- tq_arg.count = &count;
-
- for (i = 1; i <= nr_tasks; i *= 2) {
- atomic_set(tq_arg.count, 0);
- splat_vprint(file, SPLAT_TASKQ_TEST4_NAME,
- "Taskq '%s' function '%s' dispatched %d times\n",
- tq_arg.name, sym2str(splat_taskq_test4_func), i);
-
- for (j = 0; j < i; j++) {
- taskq_init_ent(&tqes[j]);
-
- if (prealloc) {
- taskq_dispatch_ent(tq, splat_taskq_test4_func,
- &tq_arg, TQ_SLEEP, &tqes[j]);
- id = tqes[j].tqent_id;
- } else {
- id = taskq_dispatch(tq, splat_taskq_test4_func,
- &tq_arg, TQ_SLEEP);
- }
-
- if (id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_TASKQ_TEST4_NAME,
- "Taskq '%s' function '%s' dispatch "
- "%d failed\n", tq_arg.name,
- sym2str(splat_taskq_test4_func), j);
- rc = -EINVAL;
- goto out;
- }
- }
-
- splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' "
- "waiting for %d dispatches\n", tq_arg.name, i);
- taskq_wait(tq);
- splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' "
- "%d/%d dispatches finished\n", tq_arg.name,
- atomic_read(&count), i);
- if (atomic_read(&count) != i) {
- rc = -ERANGE;
- goto out;
-
- }
- }
-out:
- splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' destroying\n",
- tq_arg.name);
- taskq_destroy(tq);
-
-out_free:
- kfree(tqes);
-
- return rc;
-}
-
-static int
-splat_taskq_test4_impl(struct file *file, void *arg, boolean_t prealloc)
-{
- int rc;
-
- rc = splat_taskq_test4_common(file, arg, 50, INT_MAX, 1024, prealloc);
- if (rc)
- return rc;
-
- rc = splat_taskq_test4_common(file, arg, 1, 1, 32, prealloc);
-
- return rc;
-}
-
-static int
-splat_taskq_test4(struct file *file, void *arg)
-{
- int rc;
-
- rc = splat_taskq_test4_impl(file, arg, B_FALSE);
- if (rc)
- return rc;
-
- rc = splat_taskq_test4_impl(file, arg, B_TRUE);
-
- return rc;
-}
-
-/*
- * Create a taskq and dispatch a specific sequence of tasks carefully
- * crafted to validate the order in which tasks are processed. When
- * there are multiple worker threads each thread will process the
- * next pending task as soon as it completes its current task. This
- * means that tasks do not strictly complete in order in which they
- * were dispatched (increasing task id). This is fine but we need to
- * verify taskq_wait_outstanding() blocks until the passed task id and
- * all lower task ids complete. We do this by dispatching the following
- * specific sequence of tasks each of which block for N time units.
- * We then use taskq_wait_outstanding() to unblock at specific task id and
- * verify the only the expected task ids have completed and in the
- * correct order. The two cases of interest are:
- *
- * 1) Task ids larger than the waited for task id can run and
- * complete as long as there is an available worker thread.
- * 2) All task ids lower than the waited one must complete before
- * unblocking even if the waited task id itself has completed.
- *
- * The following table shows each task id and how they will be
- * scheduled. Each rows represent one time unit and each column
- * one of the three worker threads. The places taskq_wait_outstanding()
- * must unblock for a specific id are identified as well as the
- * task ids which must have completed and their order.
- *
- * +-----+ <--- taskq_wait_outstanding(tq, 8) unblocks
- * | | Required Completion Order: 1,2,4,5,3,8,6,7
- * +-----+ |
- * | | |
- * | | +-----+
- * | | | 8 |
- * | | +-----+ <--- taskq_wait_outstanding(tq, 3) unblocks
- * | | 7 | | Required Completion Order: 1,2,4,5,3
- * | +-----+ |
- * | 6 | | |
- * +-----+ | |
- * | | 5 | |
- * | +-----+ |
- * | 4 | | |
- * +-----+ | |
- * | 1 | 2 | 3 |
- * +-----+-----+-----+
- *
- */
-static void
-splat_taskq_test5_func(void *arg)
-{
- splat_taskq_id_t *tq_id = (splat_taskq_id_t *)arg;
- splat_taskq_arg_t *tq_arg = tq_id->arg;
- int factor;
-
- /* Delays determined by above table */
- switch (tq_id->id) {
- default: factor = 0; break;
- case 1: case 8: factor = 1; break;
- case 2: case 4: case 5: factor = 2; break;
- case 6: case 7: factor = 4; break;
- case 3: factor = 5; break;
- }
-
- msleep(factor * 100);
- splat_vprint(tq_arg->file, tq_arg->name,
- "Taskqid %d complete for taskq '%s'\n",
- tq_id->id, tq_arg->name);
-
- spin_lock(&tq_arg->lock);
- tq_arg->order[tq_arg->flag] = tq_id->id;
- tq_arg->flag++;
- spin_unlock(&tq_arg->lock);
-}
-
-static int
-splat_taskq_test_order(splat_taskq_arg_t *tq_arg, int *order)
-{
- int i, j;
-
- for (i = 0; i < SPLAT_TASKQ_ORDER_MAX; i++) {
- if (tq_arg->order[i] != order[i]) {
- splat_vprint(tq_arg->file, tq_arg->name,
- "Taskq '%s' incorrect completion "
- "order\n", tq_arg->name);
- splat_vprint(tq_arg->file, tq_arg->name,
- "%s", "Expected { ");
-
- for (j = 0; j < SPLAT_TASKQ_ORDER_MAX; j++)
- splat_print(tq_arg->file, "%d ", order[j]);
-
- splat_print(tq_arg->file, "%s", "}\n");
- splat_vprint(tq_arg->file, tq_arg->name,
- "%s", "Got { ");
-
- for (j = 0; j < SPLAT_TASKQ_ORDER_MAX; j++)
- splat_print(tq_arg->file, "%d ",
- tq_arg->order[j]);
-
- splat_print(tq_arg->file, "%s", "}\n");
- return -EILSEQ;
- }
- }
-
- splat_vprint(tq_arg->file, tq_arg->name,
- "Taskq '%s' validated correct completion order\n",
- tq_arg->name);
-
- return 0;
-}
-
-static int
-splat_taskq_test5_impl(struct file *file, void *arg, boolean_t prealloc)
-{
- taskq_t *tq;
- taskqid_t id;
- splat_taskq_id_t tq_id[SPLAT_TASKQ_ORDER_MAX];
- splat_taskq_arg_t tq_arg;
- int order1[SPLAT_TASKQ_ORDER_MAX] = { 1,2,4,5,3,0,0,0 };
- int order2[SPLAT_TASKQ_ORDER_MAX] = { 1,2,4,5,3,8,6,7 };
- taskq_ent_t *tqes;
- int i, rc = 0;
-
- tqes = kmem_alloc(sizeof(*tqes) * SPLAT_TASKQ_ORDER_MAX, KM_SLEEP);
- memset(tqes, 0, sizeof(*tqes) * SPLAT_TASKQ_ORDER_MAX);
-
- splat_vprint(file, SPLAT_TASKQ_TEST5_NAME,
- "Taskq '%s' creating (%s dispatch)\n",
- SPLAT_TASKQ_TEST5_NAME,
- prealloc ? "prealloc" : "dynamic");
- if ((tq = taskq_create(SPLAT_TASKQ_TEST5_NAME, 3, defclsyspri,
- 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) {
- splat_vprint(file, SPLAT_TASKQ_TEST5_NAME,
- "Taskq '%s' create failed\n",
- SPLAT_TASKQ_TEST5_NAME);
- return -EINVAL;
- }
-
- tq_arg.flag = 0;
- memset(&tq_arg.order, 0, sizeof(int) * SPLAT_TASKQ_ORDER_MAX);
- spin_lock_init(&tq_arg.lock);
- tq_arg.file = file;
- tq_arg.name = SPLAT_TASKQ_TEST5_NAME;
-
- for (i = 0; i < SPLAT_TASKQ_ORDER_MAX; i++) {
- taskq_init_ent(&tqes[i]);
-
- tq_id[i].id = i + 1;
- tq_id[i].arg = &tq_arg;
-
- if (prealloc) {
- taskq_dispatch_ent(tq, splat_taskq_test5_func,
- &tq_id[i], TQ_SLEEP, &tqes[i]);
- id = tqes[i].tqent_id;
- } else {
- id = taskq_dispatch(tq, splat_taskq_test5_func,
- &tq_id[i], TQ_SLEEP);
- }
-
- if (id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_TASKQ_TEST5_NAME,
- "Taskq '%s' function '%s' dispatch failed\n",
- tq_arg.name, sym2str(splat_taskq_test5_func));
- rc = -EINVAL;
- goto out;
- }
-
- if (tq_id[i].id != id) {
- splat_vprint(file, SPLAT_TASKQ_TEST5_NAME,
- "Taskq '%s' expected taskqid %d got %d\n",
- tq_arg.name, (int)tq_id[i].id, (int)id);
- rc = -EINVAL;
- goto out;
- }
- }
-
- splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' "
- "waiting for taskqid %d completion\n", tq_arg.name, 3);
- taskq_wait_outstanding(tq, 3);
- if ((rc = splat_taskq_test_order(&tq_arg, order1)))
- goto out;
-
- splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' "
- "waiting for taskqid %d completion\n", tq_arg.name, 8);
- taskq_wait_outstanding(tq, 8);
- rc = splat_taskq_test_order(&tq_arg, order2);
-
-out:
- splat_vprint(file, SPLAT_TASKQ_TEST5_NAME,
- "Taskq '%s' destroying\n", tq_arg.name);
- taskq_destroy(tq);
-
- kmem_free(tqes, sizeof(*tqes) * SPLAT_TASKQ_ORDER_MAX);
-
- return rc;
-}
-
-static int
-splat_taskq_test5(struct file *file, void *arg)
-{
- int rc;
-
- rc = splat_taskq_test5_impl(file, arg, B_FALSE);
- if (rc)
- return rc;
-
- rc = splat_taskq_test5_impl(file, arg, B_TRUE);
-
- return rc;
-}
-
-/*
- * Create a single task queue with three threads. Dispatch 8 tasks,
- * setting TQ_FRONT on only the last three. Sleep after
- * dispatching tasks 1-3 to ensure they will run and hold the threads
- * busy while we dispatch the remaining tasks. Verify that tasks 6-8
- * run before task 4-5.
- *
- * The following table shows each task id and how they will be
- * scheduled. Each rows represent one time unit and each column
- * one of the three worker threads.
- *
- * NB: The Horizontal Line is the LAST Time unit consumed by the Task,
- * and must be included in the factor calculation.
- * T
- * 17-> +-----+
- * 16 | T6 |
- * 15-> +-----+ |
- * 14 | T6 | |
- * 13-> | | 5 +-----+
- * 12 | | | T6 |
- * 11-> | +-----| |
- * 10 | 4 | T6 | |
- * 9-> +-----+ | 8 |
- * 8 | T5 | | |
- * 7-> | | 7 +-----+
- * 6 | | | T7 |
- * 5-> | +-----+ |
- * 4 | 6 | T5 | |
- * 3-> +-----+ | |
- * 2 | T3 | | |
- * 1 | 1 | 2 | 3 |
- * 0 +-----+-----+-----+
- *
- */
-static void
-splat_taskq_test6_func(void *arg)
-{
- /* Delays determined by above table */
- static const int factor[SPLAT_TASKQ_ORDER_MAX+1] = {0,3,5,7,6,6,5,6,6};
-
- splat_taskq_id_t *tq_id = (splat_taskq_id_t *)arg;
- splat_taskq_arg_t *tq_arg = tq_id->arg;
-
- splat_vprint(tq_arg->file, tq_arg->name,
- "Taskqid %d starting for taskq '%s'\n",
- tq_id->id, tq_arg->name);
-
- if (tq_id->id < SPLAT_TASKQ_ORDER_MAX+1) {
- msleep(factor[tq_id->id] * 50);
- }
-
- spin_lock(&tq_arg->lock);
- tq_arg->order[tq_arg->flag] = tq_id->id;
- tq_arg->flag++;
- spin_unlock(&tq_arg->lock);
-
- splat_vprint(tq_arg->file, tq_arg->name,
- "Taskqid %d complete for taskq '%s'\n",
- tq_id->id, tq_arg->name);
-}
-
-static int
-splat_taskq_test6_impl(struct file *file, void *arg, boolean_t prealloc)
-{
- taskq_t *tq;
- taskqid_t id;
- splat_taskq_id_t tq_id[SPLAT_TASKQ_ORDER_MAX];
- splat_taskq_arg_t tq_arg;
- int order[SPLAT_TASKQ_ORDER_MAX] = { 1,2,3,6,7,8,4,5 };
- taskq_ent_t *tqes;
- int i, rc = 0;
- uint_t tflags;
-
- tqes = kmem_alloc(sizeof(*tqes) * SPLAT_TASKQ_ORDER_MAX, KM_SLEEP);
- memset(tqes, 0, sizeof(*tqes) * SPLAT_TASKQ_ORDER_MAX);
-
- splat_vprint(file, SPLAT_TASKQ_TEST6_NAME,
- "Taskq '%s' creating (%s dispatch)\n",
- SPLAT_TASKQ_TEST6_NAME,
- prealloc ? "prealloc" : "dynamic");
- if ((tq = taskq_create(SPLAT_TASKQ_TEST6_NAME, 3, defclsyspri,
- 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) {
- splat_vprint(file, SPLAT_TASKQ_TEST6_NAME,
- "Taskq '%s' create failed\n",
- SPLAT_TASKQ_TEST6_NAME);
- return -EINVAL;
- }
-
- tq_arg.flag = 0;
- memset(&tq_arg.order, 0, sizeof(int) * SPLAT_TASKQ_ORDER_MAX);
- spin_lock_init(&tq_arg.lock);
- tq_arg.file = file;
- tq_arg.name = SPLAT_TASKQ_TEST6_NAME;
-
- for (i = 0; i < SPLAT_TASKQ_ORDER_MAX; i++) {
- taskq_init_ent(&tqes[i]);
-
- tq_id[i].id = i + 1;
- tq_id[i].arg = &tq_arg;
- tflags = TQ_SLEEP;
- if (i > 4)
- tflags |= TQ_FRONT;
-
- if (prealloc) {
- taskq_dispatch_ent(tq, splat_taskq_test6_func,
- &tq_id[i], tflags, &tqes[i]);
- id = tqes[i].tqent_id;
- } else {
- id = taskq_dispatch(tq, splat_taskq_test6_func,
- &tq_id[i], tflags);
- }
-
- if (id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_TASKQ_TEST6_NAME,
- "Taskq '%s' function '%s' dispatch failed\n",
- tq_arg.name, sym2str(splat_taskq_test6_func));
- rc = -EINVAL;
- goto out;
- }
-
- if (tq_id[i].id != id) {
- splat_vprint(file, SPLAT_TASKQ_TEST6_NAME,
- "Taskq '%s' expected taskqid %d got %d\n",
- tq_arg.name, (int)tq_id[i].id, (int)id);
- rc = -EINVAL;
- goto out;
- }
- /* Sleep to let tasks 1-3 start executing. */
- if ( i == 2 )
- msleep(100);
- }
-
- splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' "
- "waiting for taskqid %d completion\n", tq_arg.name,
- SPLAT_TASKQ_ORDER_MAX);
- taskq_wait_outstanding(tq, SPLAT_TASKQ_ORDER_MAX);
- rc = splat_taskq_test_order(&tq_arg, order);
-
-out:
- splat_vprint(file, SPLAT_TASKQ_TEST6_NAME,
- "Taskq '%s' destroying\n", tq_arg.name);
- taskq_destroy(tq);
-
- kmem_free(tqes, sizeof(*tqes) * SPLAT_TASKQ_ORDER_MAX);
-
- return rc;
-}
-
-static int
-splat_taskq_test6(struct file *file, void *arg)
-{
- int rc;
-
- rc = splat_taskq_test6_impl(file, arg, B_FALSE);
- if (rc)
- return rc;
-
- rc = splat_taskq_test6_impl(file, arg, B_TRUE);
-
- return rc;
-}
-
-static void
-splat_taskq_test7_func(void *arg)
-{
- splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
- taskqid_t id;
-
- ASSERT(tq_arg);
-
- if (tq_arg->depth >= SPLAT_TASKQ_DEPTH_MAX)
- return;
-
- tq_arg->depth++;
-
- splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST7_NAME,
- "Taskq '%s' function '%s' dispatching (depth = %u)\n",
- tq_arg->name, sym2str(splat_taskq_test7_func),
- tq_arg->depth);
-
- if (tq_arg->tqe) {
- VERIFY(taskq_empty_ent(tq_arg->tqe));
- taskq_dispatch_ent(tq_arg->tq, splat_taskq_test7_func,
- tq_arg, TQ_SLEEP, tq_arg->tqe);
- id = tq_arg->tqe->tqent_id;
- } else {
- id = taskq_dispatch(tq_arg->tq, splat_taskq_test7_func,
- tq_arg, TQ_SLEEP);
- }
-
- if (id == TASKQID_INVALID) {
- splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST7_NAME,
- "Taskq '%s' function '%s' dispatch failed "
- "(depth = %u)\n", tq_arg->name,
- sym2str(splat_taskq_test7_func), tq_arg->depth);
- tq_arg->flag = -EINVAL;
- return;
- }
-}
-
-static int
-splat_taskq_test7_impl(struct file *file, void *arg, boolean_t prealloc)
-{
- taskq_t *tq;
- splat_taskq_arg_t *tq_arg;
- taskq_ent_t *tqe;
- int error;
-
- splat_vprint(file, SPLAT_TASKQ_TEST7_NAME,
- "Taskq '%s' creating (%s dispatch)\n",
- SPLAT_TASKQ_TEST7_NAME,
- prealloc ? "prealloc" : "dynamic");
- if ((tq = taskq_create(SPLAT_TASKQ_TEST7_NAME, 1, defclsyspri,
- 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) {
- splat_vprint(file, SPLAT_TASKQ_TEST7_NAME,
- "Taskq '%s' create failed\n",
- SPLAT_TASKQ_TEST7_NAME);
- return -EINVAL;
- }
-
- tq_arg = kmem_alloc(sizeof (splat_taskq_arg_t), KM_SLEEP);
- tqe = kmem_alloc(sizeof (taskq_ent_t), KM_SLEEP);
-
- tq_arg->depth = 0;
- tq_arg->flag = 0;
- tq_arg->id = 0;
- tq_arg->file = file;
- tq_arg->name = SPLAT_TASKQ_TEST7_NAME;
- tq_arg->tq = tq;
-
- if (prealloc) {
- taskq_init_ent(tqe);
- tq_arg->tqe = tqe;
- } else {
- tq_arg->tqe = NULL;
- }
-
- splat_taskq_test7_func(tq_arg);
-
- if (tq_arg->flag == 0) {
- splat_vprint(file, SPLAT_TASKQ_TEST7_NAME,
- "Taskq '%s' waiting\n", tq_arg->name);
- taskq_wait_outstanding(tq, SPLAT_TASKQ_DEPTH_MAX);
- }
-
- error = (tq_arg->depth == SPLAT_TASKQ_DEPTH_MAX ? 0 : -EINVAL);
-
- splat_vprint(file, SPLAT_TASKQ_TEST7_NAME,
- "Taskq '%s' destroying\n", tq_arg->name);
-
- kmem_free(tqe, sizeof (taskq_ent_t));
- kmem_free(tq_arg, sizeof (splat_taskq_arg_t));
-
- taskq_destroy(tq);
-
- return (error);
-}
-
-static int
-splat_taskq_test7(struct file *file, void *arg)
-{
- int rc;
-
- rc = splat_taskq_test7_impl(file, arg, B_FALSE);
- if (rc)
- return (rc);
-
- rc = splat_taskq_test7_impl(file, arg, B_TRUE);
-
- return (rc);
-}
-
-static void
-splat_taskq_throughput_func(void *arg)
-{
- splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
- ASSERT(tq_arg);
-
- atomic_inc(tq_arg->count);
-}
-
-static int
-splat_taskq_throughput(struct file *file, void *arg, const char *name,
- int nthreads, int minalloc, int maxalloc, int flags, int tasks,
- struct timespec *delta)
-{
- taskq_t *tq;
- taskqid_t id;
- splat_taskq_arg_t tq_arg;
- taskq_ent_t **tqes;
- atomic_t count;
- struct timespec start, stop;
- int i, j, rc = 0;
-
- tqes = vmalloc(sizeof (*tqes) * tasks);
- if (tqes == NULL)
- return (-ENOMEM);
-
- memset(tqes, 0, sizeof (*tqes) * tasks);
-
- splat_vprint(file, name, "Taskq '%s' creating (%d/%d/%d/%d)\n",
- name, nthreads, minalloc, maxalloc, tasks);
- if ((tq = taskq_create(name, nthreads, defclsyspri,
- minalloc, maxalloc, flags)) == NULL) {
- splat_vprint(file, name, "Taskq '%s' create failed\n", name);
- rc = -EINVAL;
- goto out_free;
- }
-
- tq_arg.file = file;
- tq_arg.name = name;
- tq_arg.count = &count;
- atomic_set(tq_arg.count, 0);
-
- getnstimeofday(&start);
-
- for (i = 0; i < tasks; i++) {
- tqes[i] = kmalloc(sizeof (taskq_ent_t), GFP_KERNEL);
- if (tqes[i] == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- taskq_init_ent(tqes[i]);
- taskq_dispatch_ent(tq, splat_taskq_throughput_func,
- &tq_arg, TQ_SLEEP, tqes[i]);
- id = tqes[i]->tqent_id;
-
- if (id == TASKQID_INVALID) {
- splat_vprint(file, name, "Taskq '%s' function '%s' "
- "dispatch %d failed\n", tq_arg.name,
- sym2str(splat_taskq_throughput_func), i);
- rc = -EINVAL;
- goto out;
- }
- }
-
- splat_vprint(file, name, "Taskq '%s' waiting for %d dispatches\n",
- tq_arg.name, tasks);
-
- taskq_wait(tq);
-
- if (delta != NULL) {
- getnstimeofday(&stop);
- *delta = timespec_sub(stop, start);
- }
-
- splat_vprint(file, name, "Taskq '%s' %d/%d dispatches finished\n",
- tq_arg.name, atomic_read(tq_arg.count), tasks);
-
- if (atomic_read(tq_arg.count) != tasks)
- rc = -ERANGE;
-
-out:
- splat_vprint(file, name, "Taskq '%s' destroying\n", tq_arg.name);
- taskq_destroy(tq);
-out_free:
- for (j = 0; j < tasks && tqes[j] != NULL; j++)
- kfree(tqes[j]);
-
- vfree(tqes);
-
- return (rc);
-}
-
-/*
- * Create a taskq with 100 threads and dispatch a huge number of trivial
- * tasks to generate contention on tq->tq_lock. This test should always
- * pass. The purpose is to provide a benchmark for measuring the
- * effectiveness of taskq optimizations.
- */
-#define TEST8_NUM_TASKS 0x20000
-#define TEST8_THREADS_PER_TASKQ 100
-
-static int
-splat_taskq_test8(struct file *file, void *arg)
-{
- return (splat_taskq_throughput(file, arg,
- SPLAT_TASKQ_TEST8_NAME, TEST8_THREADS_PER_TASKQ,
- 1, INT_MAX, TASKQ_PREPOPULATE, TEST8_NUM_TASKS, NULL));
-}
-
-/*
- * Create a taskq and dispatch a number of delayed tasks to the queue.
- * For each task verify that it was run no early than requested.
- */
-static void
-splat_taskq_test9_func(void *arg)
-{
- splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
- ASSERT(tq_arg);
-
- if (ddi_time_after_eq(ddi_get_lbolt(), tq_arg->expire))
- atomic_inc(tq_arg->count);
-
- kmem_free(tq_arg, sizeof(splat_taskq_arg_t));
-}
-
-static int
-splat_taskq_test9(struct file *file, void *arg)
-{
- taskq_t *tq;
- atomic_t count;
- int i, rc = 0;
- int minalloc = 1;
- int maxalloc = 10;
- int nr_tasks = 100;
-
- splat_vprint(file, SPLAT_TASKQ_TEST9_NAME,
- "Taskq '%s' creating (%s dispatch) (%d/%d/%d)\n",
- SPLAT_TASKQ_TEST9_NAME, "delay", minalloc, maxalloc, nr_tasks);
- if ((tq = taskq_create(SPLAT_TASKQ_TEST9_NAME, 3, defclsyspri,
- minalloc, maxalloc, TASKQ_PREPOPULATE)) == NULL) {
- splat_vprint(file, SPLAT_TASKQ_TEST9_NAME,
- "Taskq '%s' create failed\n", SPLAT_TASKQ_TEST9_NAME);
- return -EINVAL;
- }
-
- atomic_set(&count, 0);
-
- for (i = 1; i <= nr_tasks; i++) {
- splat_taskq_arg_t *tq_arg;
- taskqid_t id;
- uint32_t rnd;
-
- /* A random timeout in jiffies of at most 5 seconds */
- get_random_bytes((void *)&rnd, 4);
- rnd = rnd % (5 * HZ);
-
- tq_arg = kmem_alloc(sizeof(splat_taskq_arg_t), KM_SLEEP);
- tq_arg->file = file;
- tq_arg->name = SPLAT_TASKQ_TEST9_NAME;
- tq_arg->expire = ddi_get_lbolt() + rnd;
- tq_arg->count = &count;
-
- splat_vprint(file, SPLAT_TASKQ_TEST9_NAME,
- "Taskq '%s' delay dispatch %u jiffies\n",
- SPLAT_TASKQ_TEST9_NAME, rnd);
-
- id = taskq_dispatch_delay(tq, splat_taskq_test9_func,
- tq_arg, TQ_SLEEP, ddi_get_lbolt() + rnd);
-
- if (id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_TASKQ_TEST9_NAME,
- "Taskq '%s' delay dispatch failed\n",
- SPLAT_TASKQ_TEST9_NAME);
- kmem_free(tq_arg, sizeof(splat_taskq_arg_t));
- taskq_wait(tq);
- rc = -EINVAL;
- goto out;
- }
- }
-
- splat_vprint(file, SPLAT_TASKQ_TEST9_NAME, "Taskq '%s' waiting for "
- "%d delay dispatches\n", SPLAT_TASKQ_TEST9_NAME, nr_tasks);
-
- taskq_wait(tq);
- if (atomic_read(&count) != nr_tasks)
- rc = -ERANGE;
-
- splat_vprint(file, SPLAT_TASKQ_TEST9_NAME, "Taskq '%s' %d/%d delay "
- "dispatches finished on time\n", SPLAT_TASKQ_TEST9_NAME,
- atomic_read(&count), nr_tasks);
- splat_vprint(file, SPLAT_TASKQ_TEST9_NAME, "Taskq '%s' destroying\n",
- SPLAT_TASKQ_TEST9_NAME);
-out:
- taskq_destroy(tq);
-
- return rc;
-}
-
-/*
- * Create a taskq and dispatch then cancel tasks in the queue.
- */
-static void
-splat_taskq_test10_func(void *arg)
-{
- splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
- uint8_t rnd;
-
- if (ddi_time_after_eq(ddi_get_lbolt(), tq_arg->expire))
- atomic_inc(tq_arg->count);
-
- /* Randomly sleep to further perturb the system */
- get_random_bytes((void *)&rnd, 1);
- msleep(1 + (rnd % 9));
-}
-
-static int
-splat_taskq_test10(struct file *file, void *arg)
-{
- taskq_t *tq;
- splat_taskq_arg_t **tqas;
- atomic_t count;
- int i, j, rc = 0;
- int minalloc = 1;
- int maxalloc = 10;
- int nr_tasks = 100;
- int canceled = 0;
- int completed = 0;
- int blocked = 0;
- clock_t start, cancel;
-
- tqas = vmalloc(sizeof(*tqas) * nr_tasks);
- if (tqas == NULL)
- return -ENOMEM;
- memset(tqas, 0, sizeof(*tqas) * nr_tasks);
-
- splat_vprint(file, SPLAT_TASKQ_TEST10_NAME,
- "Taskq '%s' creating (%s dispatch) (%d/%d/%d)\n",
- SPLAT_TASKQ_TEST10_NAME, "delay", minalloc, maxalloc, nr_tasks);
- if ((tq = taskq_create(SPLAT_TASKQ_TEST10_NAME, 3, defclsyspri,
- minalloc, maxalloc, TASKQ_PREPOPULATE)) == NULL) {
- splat_vprint(file, SPLAT_TASKQ_TEST10_NAME,
- "Taskq '%s' create failed\n", SPLAT_TASKQ_TEST10_NAME);
- rc = -EINVAL;
- goto out_free;
- }
-
- atomic_set(&count, 0);
-
- for (i = 0; i < nr_tasks; i++) {
- splat_taskq_arg_t *tq_arg;
- uint32_t rnd;
-
- /* A random timeout in jiffies of at most 5 seconds */
- get_random_bytes((void *)&rnd, 4);
- rnd = rnd % (5 * HZ);
-
- tq_arg = kmem_alloc(sizeof(splat_taskq_arg_t), KM_SLEEP);
- tq_arg->file = file;
- tq_arg->name = SPLAT_TASKQ_TEST10_NAME;
- tq_arg->count = &count;
- tqas[i] = tq_arg;
-
- /*
- * Dispatch every 1/3 one immediately to mix it up, the cancel
- * code is inherently racy and we want to try and provoke any
- * subtle concurrently issues.
- */
- if ((i % 3) == 0) {
- tq_arg->expire = ddi_get_lbolt();
- tq_arg->id = taskq_dispatch(tq, splat_taskq_test10_func,
- tq_arg, TQ_SLEEP);
- } else {
- tq_arg->expire = ddi_get_lbolt() + rnd;
- tq_arg->id = taskq_dispatch_delay(tq,
- splat_taskq_test10_func,
- tq_arg, TQ_SLEEP, ddi_get_lbolt() + rnd);
- }
-
- if (tq_arg->id == TASKQID_INVALID) {
- splat_vprint(file, SPLAT_TASKQ_TEST10_NAME,
- "Taskq '%s' dispatch failed\n",
- SPLAT_TASKQ_TEST10_NAME);
- kmem_free(tq_arg, sizeof(splat_taskq_arg_t));
- taskq_wait(tq);
- rc = -EINVAL;
- goto out;
- } else {
- splat_vprint(file, SPLAT_TASKQ_TEST10_NAME,
- "Taskq '%s' dispatch %lu in %lu jiffies\n",
- SPLAT_TASKQ_TEST10_NAME, (unsigned long)tq_arg->id,
- !(i % 3) ? 0 : tq_arg->expire - ddi_get_lbolt());
- }
- }
-
- /*
- * Start randomly canceling tasks for the duration of the test. We
- * happen to know the valid task id's will be in the range 1..nr_tasks
- * because the taskq is private and was just created. However, we
- * have no idea of a particular task has already executed or not.
- */
- splat_vprint(file, SPLAT_TASKQ_TEST10_NAME, "Taskq '%s' randomly "
- "canceling task ids\n", SPLAT_TASKQ_TEST10_NAME);
-
- start = ddi_get_lbolt();
- i = 0;
-
- while (ddi_time_before(ddi_get_lbolt(), start + 5 * HZ)) {
- taskqid_t id;
- uint32_t rnd;
-
- i++;
- cancel = ddi_get_lbolt();
- get_random_bytes((void *)&rnd, 4);
- id = 1 + (rnd % nr_tasks);
- rc = taskq_cancel_id(tq, id);
-
- /*
- * Keep track of the results of the random cancels.
- */
- if (rc == 0) {
- canceled++;
- } else if (rc == ENOENT) {
- completed++;
- } else if (rc == EBUSY) {
- blocked++;
- } else {
- rc = -EINVAL;
- break;
- }
-
- /*
- * Verify we never get blocked to long in taskq_cancel_id().
- * The worst case is 10ms if we happen to cancel the task
- * which is currently executing. We allow a factor of 2x.
- */
- if (ddi_get_lbolt() - cancel > HZ / 50) {
- splat_vprint(file, SPLAT_TASKQ_TEST10_NAME,
- "Taskq '%s' cancel for %lu took %lu\n",
- SPLAT_TASKQ_TEST10_NAME, (unsigned long)id,
- ddi_get_lbolt() - cancel);
- rc = -ETIMEDOUT;
- break;
- }
-
- get_random_bytes((void *)&rnd, 4);
- msleep(1 + (rnd % 100));
- rc = 0;
- }
-
- taskq_wait(tq);
-
- /*
- * Cross check the results of taskq_cancel_id() with the number of
- * times the dispatched function actually ran successfully.
- */
- if ((rc == 0) && (nr_tasks - canceled != atomic_read(&count)))
- rc = -EDOM;
-
- splat_vprint(file, SPLAT_TASKQ_TEST10_NAME, "Taskq '%s' %d attempts, "
- "%d canceled, %d completed, %d blocked, %d/%d tasks run\n",
- SPLAT_TASKQ_TEST10_NAME, i, canceled, completed, blocked,
- atomic_read(&count), nr_tasks);
- splat_vprint(file, SPLAT_TASKQ_TEST10_NAME, "Taskq '%s' destroying %d\n",
- SPLAT_TASKQ_TEST10_NAME, rc);
-out:
- taskq_destroy(tq);
-out_free:
- for (j = 0; j < nr_tasks && tqas[j] != NULL; j++)
- kmem_free(tqas[j], sizeof(splat_taskq_arg_t));
- vfree(tqas);
-
- return rc;
-}
-
-/*
- * Create a dynamic taskq with 100 threads and dispatch a huge number of
- * trivial tasks. This will cause the taskq to grow quickly to its max
- * thread count. This test should always pass. The purpose is to provide
- * a benchmark for measuring the performance of dynamic taskqs.
- */
-#define TEST11_NUM_TASKS 100000
-#define TEST11_THREADS_PER_TASKQ 100
-
-static int
-splat_taskq_test11(struct file *file, void *arg)
-{
- struct timespec normal, dynamic;
- int error;
-
- error = splat_taskq_throughput(file, arg, SPLAT_TASKQ_TEST11_NAME,
- TEST11_THREADS_PER_TASKQ, 1, INT_MAX,
- TASKQ_PREPOPULATE, TEST11_NUM_TASKS, &normal);
- if (error)
- return (error);
-
- error = splat_taskq_throughput(file, arg, SPLAT_TASKQ_TEST11_NAME,
- TEST11_THREADS_PER_TASKQ, 1, INT_MAX,
- TASKQ_PREPOPULATE | TASKQ_DYNAMIC, TEST11_NUM_TASKS, &dynamic);
- if (error)
- return (error);
-
- splat_vprint(file, SPLAT_TASKQ_TEST11_NAME,
- "Timing taskq_wait(): normal=%ld.%09lds, dynamic=%ld.%09lds\n",
- normal.tv_sec, normal.tv_nsec,
- dynamic.tv_sec, dynamic.tv_nsec);
-
- /* A 10x increase in runtime is used to indicate a core problem. */
- if (((int64_t)dynamic.tv_sec * NANOSEC + (int64_t)dynamic.tv_nsec) >
- (((int64_t)normal.tv_sec * NANOSEC + (int64_t)normal.tv_nsec) * 10))
- error = -ETIME;
-
- return (error);
-}
-
-splat_subsystem_t *
-splat_taskq_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_TASKQ_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_TASKQ_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_TASKQ;
-
- splat_test_init(sub, SPLAT_TASKQ_TEST1_NAME, SPLAT_TASKQ_TEST1_DESC,
- SPLAT_TASKQ_TEST1_ID, splat_taskq_test1);
- splat_test_init(sub, SPLAT_TASKQ_TEST2_NAME, SPLAT_TASKQ_TEST2_DESC,
- SPLAT_TASKQ_TEST2_ID, splat_taskq_test2);
- splat_test_init(sub, SPLAT_TASKQ_TEST3_NAME, SPLAT_TASKQ_TEST3_DESC,
- SPLAT_TASKQ_TEST3_ID, splat_taskq_test3);
- splat_test_init(sub, SPLAT_TASKQ_TEST4_NAME, SPLAT_TASKQ_TEST4_DESC,
- SPLAT_TASKQ_TEST4_ID, splat_taskq_test4);
- splat_test_init(sub, SPLAT_TASKQ_TEST5_NAME, SPLAT_TASKQ_TEST5_DESC,
- SPLAT_TASKQ_TEST5_ID, splat_taskq_test5);
- splat_test_init(sub, SPLAT_TASKQ_TEST6_NAME, SPLAT_TASKQ_TEST6_DESC,
- SPLAT_TASKQ_TEST6_ID, splat_taskq_test6);
- splat_test_init(sub, SPLAT_TASKQ_TEST7_NAME, SPLAT_TASKQ_TEST7_DESC,
- SPLAT_TASKQ_TEST7_ID, splat_taskq_test7);
- splat_test_init(sub, SPLAT_TASKQ_TEST8_NAME, SPLAT_TASKQ_TEST8_DESC,
- SPLAT_TASKQ_TEST8_ID, splat_taskq_test8);
- splat_test_init(sub, SPLAT_TASKQ_TEST9_NAME, SPLAT_TASKQ_TEST9_DESC,
- SPLAT_TASKQ_TEST9_ID, splat_taskq_test9);
- splat_test_init(sub, SPLAT_TASKQ_TEST10_NAME, SPLAT_TASKQ_TEST10_DESC,
- SPLAT_TASKQ_TEST10_ID, splat_taskq_test10);
- splat_test_init(sub, SPLAT_TASKQ_TEST11_NAME, SPLAT_TASKQ_TEST11_DESC,
- SPLAT_TASKQ_TEST11_ID, splat_taskq_test11);
-
- return sub;
-}
-
-void
-splat_taskq_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
- splat_test_fini(sub, SPLAT_TASKQ_TEST11_ID);
- splat_test_fini(sub, SPLAT_TASKQ_TEST10_ID);
- splat_test_fini(sub, SPLAT_TASKQ_TEST9_ID);
- splat_test_fini(sub, SPLAT_TASKQ_TEST8_ID);
- splat_test_fini(sub, SPLAT_TASKQ_TEST7_ID);
- splat_test_fini(sub, SPLAT_TASKQ_TEST6_ID);
- splat_test_fini(sub, SPLAT_TASKQ_TEST5_ID);
- splat_test_fini(sub, SPLAT_TASKQ_TEST4_ID);
- splat_test_fini(sub, SPLAT_TASKQ_TEST3_ID);
- splat_test_fini(sub, SPLAT_TASKQ_TEST2_ID);
- splat_test_fini(sub, SPLAT_TASKQ_TEST1_ID);
-
- kfree(sub);
-}
-
-int
-splat_taskq_id(void) {
- return SPLAT_SUBSYSTEM_TASKQ;
-}
diff --git a/module/splat/splat-thread.c b/module/splat/splat-thread.c
deleted file mode 100644
index f2e6bf15e..000000000
--- a/module/splat/splat-thread.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Thread Tests.
- */
-
-#include <sys/thread.h>
-#include <sys/random.h>
-#include <linux/delay.h>
-#include <linux/mm_compat.h>
-#include <linux/wait_compat.h>
-#include <linux/slab.h>
-#include "splat-internal.h"
-
-#define SPLAT_THREAD_NAME "thread"
-#define SPLAT_THREAD_DESC "Kernel Thread Tests"
-
-#define SPLAT_THREAD_TEST1_ID 0x0601
-#define SPLAT_THREAD_TEST1_NAME "create"
-#define SPLAT_THREAD_TEST1_DESC "Validate thread creation"
-
-#define SPLAT_THREAD_TEST2_ID 0x0602
-#define SPLAT_THREAD_TEST2_NAME "exit"
-#define SPLAT_THREAD_TEST2_DESC "Validate thread exit"
-
-#define SPLAT_THREAD_TEST3_ID 0x6003
-#define SPLAT_THREAD_TEST3_NAME "tsd"
-#define SPLAT_THREAD_TEST3_DESC "Validate thread specific data"
-
-#define SPLAT_THREAD_TEST_MAGIC 0x4488CC00UL
-#define SPLAT_THREAD_TEST_KEYS 32
-#define SPLAT_THREAD_TEST_THREADS 16
-
-typedef struct thread_priv {
- unsigned long tp_magic;
- struct file *tp_file;
- spinlock_t tp_lock;
- spl_wait_queue_head_t tp_waitq;
- uint_t tp_keys[SPLAT_THREAD_TEST_KEYS];
- int tp_rc;
- int tp_count;
- int tp_dtor_count;
-} thread_priv_t;
-
-static int
-splat_thread_rc(thread_priv_t *tp, int rc)
-{
- int ret;
-
- spin_lock(&tp->tp_lock);
- ret = (tp->tp_rc == rc);
- spin_unlock(&tp->tp_lock);
-
- return ret;
-}
-
-static int
-splat_thread_count(thread_priv_t *tp, int count)
-{
- int ret;
-
- spin_lock(&tp->tp_lock);
- ret = (tp->tp_count == count);
- spin_unlock(&tp->tp_lock);
-
- return ret;
-}
-
-static void
-splat_thread_work1(void *priv)
-{
- thread_priv_t *tp = (thread_priv_t *)priv;
-
- spin_lock(&tp->tp_lock);
- ASSERT(tp->tp_magic == SPLAT_THREAD_TEST_MAGIC);
- tp->tp_rc = 1;
- wake_up(&tp->tp_waitq);
- spin_unlock(&tp->tp_lock);
-
- thread_exit();
-}
-
-static int
-splat_thread_test1(struct file *file, void *arg)
-{
- thread_priv_t tp;
- kthread_t *thr;
-
- tp.tp_magic = SPLAT_THREAD_TEST_MAGIC;
- tp.tp_file = file;
- spin_lock_init(&tp.tp_lock);
- init_waitqueue_head(&tp.tp_waitq);
- tp.tp_rc = 0;
-
- thr = (kthread_t *)thread_create(NULL, 0, splat_thread_work1, &tp, 0,
- &p0, TS_RUN, defclsyspri);
- /* Must never fail under Solaris, but we check anyway since this
- * can happen in the linux SPL, we may want to change this behavior */
- if (thr == NULL)
- return -ESRCH;
-
- /* Sleep until the thread sets tp.tp_rc == 1 */
- wait_event(tp.tp_waitq, splat_thread_rc(&tp, 1));
-
- splat_vprint(file, SPLAT_THREAD_TEST1_NAME, "%s",
- "Thread successfully started properly\n");
- return 0;
-}
-
-static void
-splat_thread_work2(void *priv)
-{
- thread_priv_t *tp = (thread_priv_t *)priv;
-
- spin_lock(&tp->tp_lock);
- ASSERT(tp->tp_magic == SPLAT_THREAD_TEST_MAGIC);
- tp->tp_rc = 1;
- wake_up(&tp->tp_waitq);
- spin_unlock(&tp->tp_lock);
-
- thread_exit();
-
- /* The following code is unreachable when thread_exit() is
- * working properly, which is exactly what we're testing */
- spin_lock(&tp->tp_lock);
- tp->tp_rc = 2;
- wake_up(&tp->tp_waitq);
- spin_unlock(&tp->tp_lock);
-}
-
-static int
-splat_thread_test2(struct file *file, void *arg)
-{
- thread_priv_t tp;
- kthread_t *thr;
- int rc = 0;
-
- tp.tp_magic = SPLAT_THREAD_TEST_MAGIC;
- tp.tp_file = file;
- spin_lock_init(&tp.tp_lock);
- init_waitqueue_head(&tp.tp_waitq);
- tp.tp_rc = 0;
-
- thr = (kthread_t *)thread_create(NULL, 0, splat_thread_work2, &tp, 0,
- &p0, TS_RUN, defclsyspri);
- /* Must never fail under Solaris, but we check anyway since this
- * can happen in the linux SPL, we may want to change this behavior */
- if (thr == NULL)
- return -ESRCH;
-
- /* Sleep until the thread sets tp.tp_rc == 1 */
- wait_event(tp.tp_waitq, splat_thread_rc(&tp, 1));
-
- /* Sleep until the thread sets tp.tp_rc == 2, or until we hit
- * the timeout. If thread exit is working properly we should
- * hit the timeout and never see to.tp_rc == 2. */
- rc = wait_event_timeout(tp.tp_waitq, splat_thread_rc(&tp, 2), HZ / 10);
- if (rc > 0) {
- rc = -EINVAL;
- splat_vprint(file, SPLAT_THREAD_TEST2_NAME, "%s",
- "Thread did not exit properly at thread_exit()\n");
- } else {
- splat_vprint(file, SPLAT_THREAD_TEST2_NAME, "%s",
- "Thread successfully exited at thread_exit()\n");
- }
-
- return rc;
-}
-
-static void
-splat_thread_work3_common(thread_priv_t *tp)
-{
- ulong_t rnd;
- int i, rc = 0;
-
- /* set a unique value for each key using a random value */
- get_random_bytes((void *)&rnd, 4);
- for (i = 0; i < SPLAT_THREAD_TEST_KEYS; i++)
- tsd_set(tp->tp_keys[i], (void *)(i + rnd));
-
- /* verify the unique value for each key */
- for (i = 0; i < SPLAT_THREAD_TEST_KEYS; i++)
- if (tsd_get(tp->tp_keys[i]) != (void *)(i + rnd))
- rc = -EINVAL;
-
- /* set the value to thread_priv_t for use by the destructor */
- for (i = 0; i < SPLAT_THREAD_TEST_KEYS; i++)
- tsd_set(tp->tp_keys[i], (void *)tp);
-
- spin_lock(&tp->tp_lock);
- if (rc && !tp->tp_rc)
- tp->tp_rc = rc;
-
- tp->tp_count++;
- wake_up_all(&tp->tp_waitq);
- spin_unlock(&tp->tp_lock);
-}
-
-static void
-splat_thread_work3_wait(void *priv)
-{
- thread_priv_t *tp = (thread_priv_t *)priv;
-
- ASSERT(tp->tp_magic == SPLAT_THREAD_TEST_MAGIC);
- splat_thread_work3_common(tp);
- wait_event(tp->tp_waitq, splat_thread_count(tp, 0));
- thread_exit();
-}
-
-static void
-splat_thread_work3_exit(void *priv)
-{
- thread_priv_t *tp = (thread_priv_t *)priv;
-
- ASSERT(tp->tp_magic == SPLAT_THREAD_TEST_MAGIC);
- splat_thread_work3_common(tp);
- thread_exit();
-}
-
-static void
-splat_thread_dtor3(void *priv)
-{
- thread_priv_t *tp = (thread_priv_t *)priv;
-
- ASSERT(tp->tp_magic == SPLAT_THREAD_TEST_MAGIC);
- spin_lock(&tp->tp_lock);
- tp->tp_dtor_count++;
- spin_unlock(&tp->tp_lock);
-}
-
-/*
- * Create threads which set and verify SPLAT_THREAD_TEST_KEYS number of
- * keys. These threads may then exit by calling thread_exit() which calls
- * tsd_exit() resulting in all their thread specific data being reclaimed.
- * Alternately, the thread may block in which case the thread specific
- * data will be reclaimed as part of tsd_destroy(). In either case all
- * thread specific data must be reclaimed, this is verified by ensuring
- * the registered destructor is called the correct number of times.
- */
-static int
-splat_thread_test3(struct file *file, void *arg)
-{
- int i, rc = 0, expected, wait_count = 0, exit_count = 0;
- thread_priv_t tp;
-
- tp.tp_magic = SPLAT_THREAD_TEST_MAGIC;
- tp.tp_file = file;
- spin_lock_init(&tp.tp_lock);
- init_waitqueue_head(&tp.tp_waitq);
- tp.tp_rc = 0;
- tp.tp_count = 0;
- tp.tp_dtor_count = 0;
-
- for (i = 0; i < SPLAT_THREAD_TEST_KEYS; i++) {
- tp.tp_keys[i] = 0;
- tsd_create(&tp.tp_keys[i], splat_thread_dtor3);
- }
-
- /* Start tsd wait threads */
- for (i = 0; i < SPLAT_THREAD_TEST_THREADS; i++) {
- if (thread_create(NULL, 0, splat_thread_work3_wait,
- &tp, 0, &p0, TS_RUN, defclsyspri))
- wait_count++;
- }
-
- /* All wait threads have setup their tsd and are blocking. */
- wait_event(tp.tp_waitq, splat_thread_count(&tp, wait_count));
-
- if (tp.tp_dtor_count != 0) {
- splat_vprint(file, SPLAT_THREAD_TEST3_NAME,
- "Prematurely ran %d tsd destructors\n", tp.tp_dtor_count);
- if (!rc)
- rc = -ERANGE;
- }
-
- /* Start tsd exit threads */
- for (i = 0; i < SPLAT_THREAD_TEST_THREADS; i++) {
- if (thread_create(NULL, 0, splat_thread_work3_exit,
- &tp, 0, &p0, TS_RUN, defclsyspri))
- exit_count++;
- }
-
- /* All exit threads verified tsd and are in the process of exiting */
- wait_event(tp.tp_waitq,splat_thread_count(&tp, wait_count+exit_count));
- msleep(500);
-
- expected = (SPLAT_THREAD_TEST_KEYS * exit_count);
- if (tp.tp_dtor_count != expected) {
- splat_vprint(file, SPLAT_THREAD_TEST3_NAME,
- "Expected %d exit tsd destructors but saw %d\n",
- expected, tp.tp_dtor_count);
- if (!rc)
- rc = -ERANGE;
- }
-
- /* Destroy all keys and associated tsd in blocked threads */
- for (i = 0; i < SPLAT_THREAD_TEST_KEYS; i++)
- tsd_destroy(&tp.tp_keys[i]);
-
- expected = (SPLAT_THREAD_TEST_KEYS * (exit_count + wait_count));
- if (tp.tp_dtor_count != expected) {
- splat_vprint(file, SPLAT_THREAD_TEST3_NAME,
- "Expected %d wait+exit tsd destructors but saw %d\n",
- expected, tp.tp_dtor_count);
- if (!rc)
- rc = -ERANGE;
- }
-
- /* Release the remaining wait threads, sleep briefly while they exit */
- spin_lock(&tp.tp_lock);
- tp.tp_count = 0;
- wake_up_all(&tp.tp_waitq);
- spin_unlock(&tp.tp_lock);
- msleep(500);
-
- if (tp.tp_rc) {
- splat_vprint(file, SPLAT_THREAD_TEST3_NAME,
- "Thread tsd_get()/tsd_set() error %d\n", tp.tp_rc);
- if (!rc)
- rc = tp.tp_rc;
- } else if (!rc) {
- splat_vprint(file, SPLAT_THREAD_TEST3_NAME, "%s",
- "Thread specific data verified\n");
- }
-
- return rc;
-}
-
-splat_subsystem_t *
-splat_thread_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_THREAD_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_THREAD_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_THREAD;
-
- splat_test_init(sub, SPLAT_THREAD_TEST1_NAME, SPLAT_THREAD_TEST1_DESC,
- SPLAT_THREAD_TEST1_ID, splat_thread_test1);
- splat_test_init(sub, SPLAT_THREAD_TEST2_NAME, SPLAT_THREAD_TEST2_DESC,
- SPLAT_THREAD_TEST2_ID, splat_thread_test2);
- splat_test_init(sub, SPLAT_THREAD_TEST3_NAME, SPLAT_THREAD_TEST3_DESC,
- SPLAT_THREAD_TEST3_ID, splat_thread_test3);
-
- return sub;
-}
-
-void
-splat_thread_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
- splat_test_fini(sub, SPLAT_THREAD_TEST3_ID);
- splat_test_fini(sub, SPLAT_THREAD_TEST2_ID);
- splat_test_fini(sub, SPLAT_THREAD_TEST1_ID);
-
- kfree(sub);
-}
-
-int
-splat_thread_id(void) {
- return SPLAT_SUBSYSTEM_THREAD;
-}
diff --git a/module/splat/splat-time.c b/module/splat/splat-time.c
deleted file mode 100644
index a0e261956..000000000
--- a/module/splat/splat-time.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Time Tests.
- */
-
-#include <sys/time.h>
-#include <linux/mm_compat.h>
-#include <linux/slab.h>
-#include "splat-internal.h"
-
-#define SPLAT_TIME_NAME "time"
-#define SPLAT_TIME_DESC "Kernel Time Tests"
-
-#define SPLAT_TIME_TEST1_ID 0x0801
-#define SPLAT_TIME_TEST1_NAME "time1"
-#define SPLAT_TIME_TEST1_DESC "HZ Test"
-
-#define SPLAT_TIME_TEST2_ID 0x0802
-#define SPLAT_TIME_TEST2_NAME "time2"
-#define SPLAT_TIME_TEST2_DESC "Monotonic Test"
-
-static int
-splat_time_test1(struct file *file, void *arg)
-{
- int myhz = hz;
- splat_vprint(file, SPLAT_TIME_TEST1_NAME, "hz is %d\n", myhz);
- return 0;
-}
-
-static int
-splat_time_test2(struct file *file, void *arg)
-{
- hrtime_t tm1, tm2;
- int i;
-
- tm1 = gethrtime();
- splat_vprint(file, SPLAT_TIME_TEST2_NAME, "time is %lld\n", tm1);
-
- for(i = 0; i < 100; i++) {
- tm2 = gethrtime();
- splat_vprint(file, SPLAT_TIME_TEST2_NAME, "time is %lld\n", tm2);
-
- if(tm1 > tm2) {
- splat_print(file, "%s: gethrtime() is not giving "
- "monotonically increasing values\n",
- SPLAT_TIME_TEST2_NAME);
- return 1;
- }
- tm1 = tm2;
-
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(10);
- }
-
- return 0;
-}
-
-splat_subsystem_t *
-splat_time_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_TIME_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_TIME_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_TIME;
-
- splat_test_init(sub, SPLAT_TIME_TEST1_NAME, SPLAT_TIME_TEST1_DESC,
- SPLAT_TIME_TEST1_ID, splat_time_test1);
- splat_test_init(sub, SPLAT_TIME_TEST2_NAME, SPLAT_TIME_TEST2_DESC,
- SPLAT_TIME_TEST2_ID, splat_time_test2);
-
- return sub;
-}
-
-void
-splat_time_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
-
- splat_test_fini(sub, SPLAT_TIME_TEST2_ID);
- splat_test_fini(sub, SPLAT_TIME_TEST1_ID);
-
- kfree(sub);
-}
-
-int
-splat_time_id(void)
-{
- return SPLAT_SUBSYSTEM_TIME;
-}
diff --git a/module/splat/splat-vnode.c b/module/splat/splat-vnode.c
deleted file mode 100644
index 4ccf24f1e..000000000
--- a/module/splat/splat-vnode.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Vnode Tests.
- */
-
-#include <sys/vnode.h>
-#include "splat-internal.h"
-
-#define SPLAT_VNODE_NAME "vnode"
-#define SPLAT_VNODE_DESC "Kernel Vnode Tests"
-
-#define SPLAT_VNODE_TEST1_ID 0x0901
-#define SPLAT_VNODE_TEST1_NAME "vn_open"
-#define SPLAT_VNODE_TEST1_DESC "Vn_open Test"
-
-#define SPLAT_VNODE_TEST2_ID 0x0902
-#define SPLAT_VNODE_TEST2_NAME "vn_openat"
-#define SPLAT_VNODE_TEST2_DESC "Vn_openat Test"
-
-#define SPLAT_VNODE_TEST3_ID 0x0903
-#define SPLAT_VNODE_TEST3_NAME "vn_rdwr"
-#define SPLAT_VNODE_TEST3_DESC "Vn_rdwrt Test"
-
-#define SPLAT_VNODE_TEST5_ID 0x0905
-#define SPLAT_VNODE_TEST5_NAME "vn_getattr"
-#define SPLAT_VNODE_TEST5_DESC "Vn_getattr Test"
-
-#define SPLAT_VNODE_TEST6_ID 0x0906
-#define SPLAT_VNODE_TEST6_NAME "vn_sync"
-#define SPLAT_VNODE_TEST6_DESC "Vn_sync Test"
-
-#define SPLAT_VNODE_TEST_FILE "/etc/fstab"
-#define SPLAT_VNODE_TEST_FILE_AT "etc/fstab"
-#define SPLAT_VNODE_TEST_FILE_RW "/tmp/spl.vnode.tmp"
-#define SPLAT_VNODE_TEST_FILE_RW1 "/tmp/spl.vnode.tmp.1"
-#define SPLAT_VNODE_TEST_FILE_RW2 "/tmp/spl.vnode.tmp.2"
-
-static int
-splat_vnode_user_cmd(struct file *file, void *arg,
- char *name, char *cmd)
-{
- char sh_path[] = "/bin/sh";
- char *argv[] = { sh_path,
- "-c",
- cmd,
- NULL };
- char *envp[] = { "HOME=/",
- "TERM=linux",
- "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
- NULL };
- int rc;
-
- rc = call_usermodehelper(sh_path, argv, envp, UMH_WAIT_PROC);
- if (rc) {
- splat_vprint(file, name,
- "Failed command: %s %s %s (%d)\n",
- argv[0], argv[1], cmd, rc);
- return -EPERM;
- }
-
- return 0;
-}
-
-static int
-splat_vnode_unlink_all(struct file *file, void *arg, char *name)
-{
- char *cmds[] = { "rm -f " SPLAT_VNODE_TEST_FILE_RW,
- "rm -f " SPLAT_VNODE_TEST_FILE_RW1,
- "rm -f " SPLAT_VNODE_TEST_FILE_RW2,
- NULL };
- int i = 0, rc = 0;
-
- while (cmds[i] != NULL) {
- if ((rc = splat_vnode_user_cmd(file, arg, name, cmds[i])))
- return rc;
-
- i++;
- }
-
- return rc;
-}
-
-static int
-splat_vnode_test1(struct file *file, void *arg)
-{
- vnode_t *vp;
- int rc;
-
- if ((rc = vn_open(SPLAT_VNODE_TEST_FILE, UIO_SYSSPACE,
- FREAD, 0644, &vp, 0, 0))) {
- splat_vprint(file, SPLAT_VNODE_TEST1_NAME,
- "Failed to vn_open test file: %s (%d)\n",
- SPLAT_VNODE_TEST_FILE, rc);
- return -rc;
- }
-
- rc = VOP_CLOSE(vp, 0, 0, 0, 0, 0);
-
- if (rc) {
- splat_vprint(file, SPLAT_VNODE_TEST1_NAME,
- "Failed to vn_close test file: %s (%d)\n",
- SPLAT_VNODE_TEST_FILE, rc);
- return -rc;
- }
-
- splat_vprint(file, SPLAT_VNODE_TEST1_NAME, "Successfully vn_open'ed "
- "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE);
-
- return -rc;
-} /* splat_vnode_test1() */
-
-static int
-splat_vnode_test2(struct file *file, void *arg)
-{
- vnode_t *vp;
- int rc;
-
- if ((rc = vn_openat(SPLAT_VNODE_TEST_FILE_AT, UIO_SYSSPACE,
- FREAD, 0644, &vp, 0, 0, rootdir, 0))) {
- splat_vprint(file, SPLAT_VNODE_TEST2_NAME,
- "Failed to vn_openat test file: %s (%d)\n",
- SPLAT_VNODE_TEST_FILE, rc);
- return -rc;
- }
-
- rc = VOP_CLOSE(vp, 0, 0, 0, 0, 0);
-
- if (rc) {
- splat_vprint(file, SPLAT_VNODE_TEST2_NAME,
- "Failed to vn_close test file: %s (%d)\n",
- SPLAT_VNODE_TEST_FILE, rc);
- return -rc;
- }
-
- splat_vprint(file, SPLAT_VNODE_TEST2_NAME, "Successfully vn_openat'ed "
- "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE);
-
- return -rc;
-} /* splat_vnode_test2() */
-
-static int
-splat_vnode_test3(struct file *file, void *arg)
-{
- vnode_t *vp;
- char buf1[32] = "SPL VNode Interface Test File\n";
- char buf2[32] = "";
- int rc;
-
- if ((rc = splat_vnode_unlink_all(file, arg, SPLAT_VNODE_TEST3_NAME)))
- return rc;
-
- if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE,
- FWRITE | FREAD | FCREAT | FEXCL,
- 0644, &vp, 0, 0))) {
- splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
- "Failed to vn_open test file: %s (%d)\n",
- SPLAT_VNODE_TEST_FILE_RW, rc);
- return -rc;
- }
-
- rc = vn_rdwr(UIO_WRITE, vp, buf1, strlen(buf1), 0,
- UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
- if (rc) {
- splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
- "Failed vn_rdwr write of test file: %s (%d)\n",
- SPLAT_VNODE_TEST_FILE_RW, rc);
- goto out;
- }
-
- rc = vn_rdwr(UIO_READ, vp, buf2, strlen(buf1), 0,
- UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
- if (rc) {
- splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
- "Failed vn_rdwr read of test file: %s (%d)\n",
- SPLAT_VNODE_TEST_FILE_RW, rc);
- goto out;
- }
-
- if (strncmp(buf1, buf2, strlen(buf1))) {
- rc = EINVAL;
- splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
- "Failed strncmp data written does not match "
- "data read\nWrote: %sRead: %s\n", buf1, buf2);
- goto out;
- }
-
- rc = 0;
- splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Wrote: %s", buf1);
- splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Read: %s", buf2);
- splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Successfully wrote and "
- "read expected data pattern to test file: %s\n",
- SPLAT_VNODE_TEST_FILE_RW);
-
-out:
- VOP_CLOSE(vp, 0, 0, 0, 0, 0);
-
- return -rc;
-} /* splat_vnode_test3() */
-
-static int
-splat_vnode_test5(struct file *file, void *arg)
-{
- vnode_t *vp;
- vattr_t vap;
- int rc;
-
- if ((rc = vn_open(SPLAT_VNODE_TEST_FILE, UIO_SYSSPACE,
- FREAD, 0644, &vp, 0, 0))) {
- splat_vprint(file, SPLAT_VNODE_TEST5_NAME,
- "Failed to vn_open test file: %s (%d)\n",
- SPLAT_VNODE_TEST_FILE, rc);
- return -rc;
- }
-
- rc = VOP_GETATTR(vp, &vap, 0, 0, NULL);
- if (rc) {
- splat_vprint(file, SPLAT_VNODE_TEST5_NAME,
- "Failed to vn_getattr test file: %s (%d)\n",
- SPLAT_VNODE_TEST_FILE, rc);
- goto out;
- }
-
- if (vap.va_type != VREG) {
- rc = EINVAL;
- splat_vprint(file, SPLAT_VNODE_TEST5_NAME,
- "Failed expected regular file type "
- "(%d != VREG): %s (%d)\n", vap.va_type,
- SPLAT_VNODE_TEST_FILE, rc);
- goto out;
- }
-
- splat_vprint(file, SPLAT_VNODE_TEST1_NAME, "Successfully "
- "vn_getattr'ed test file: %s\n", SPLAT_VNODE_TEST_FILE);
-
-out:
- VOP_CLOSE(vp, 0, 0, 0, 0, 0);
-
- return -rc;
-} /* splat_vnode_test5() */
-
-static int
-splat_vnode_test6(struct file *file, void *arg)
-{
- vnode_t *vp;
- char buf[32] = "SPL VNode Interface Test File\n";
- int rc;
-
- if ((rc = splat_vnode_unlink_all(file, arg, SPLAT_VNODE_TEST6_NAME)))
- return rc;
-
- if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE,
- FWRITE | FCREAT | FEXCL, 0644, &vp, 0, 0))) {
- splat_vprint(file, SPLAT_VNODE_TEST6_NAME,
- "Failed to vn_open test file: %s (%d)\n",
- SPLAT_VNODE_TEST_FILE_RW, rc);
- return -rc;
- }
-
- rc = vn_rdwr(UIO_WRITE, vp, buf, strlen(buf), 0,
- UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
- if (rc) {
- splat_vprint(file, SPLAT_VNODE_TEST6_NAME,
- "Failed vn_rdwr write of test file: %s (%d)\n",
- SPLAT_VNODE_TEST_FILE_RW, rc);
- goto out;
- }
-
- rc = vn_fsync(vp, 0, 0, 0);
- if (rc) {
- splat_vprint(file, SPLAT_VNODE_TEST6_NAME,
- "Failed vn_fsync of test file: %s (%d)\n",
- SPLAT_VNODE_TEST_FILE_RW, rc);
- goto out;
- }
-
- rc = 0;
- splat_vprint(file, SPLAT_VNODE_TEST6_NAME, "Successfully "
- "fsync'ed test file %s\n", SPLAT_VNODE_TEST_FILE_RW);
-out:
- VOP_CLOSE(vp, 0, 0, 0, 0, 0);
-
- return -rc;
-} /* splat_vnode_test6() */
-
-splat_subsystem_t *
-splat_vnode_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_VNODE_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_VNODE_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_VNODE;
-
- splat_test_init(sub, SPLAT_VNODE_TEST1_NAME, SPLAT_VNODE_TEST1_DESC,
- SPLAT_VNODE_TEST1_ID, splat_vnode_test1);
- splat_test_init(sub, SPLAT_VNODE_TEST2_NAME, SPLAT_VNODE_TEST2_DESC,
- SPLAT_VNODE_TEST2_ID, splat_vnode_test2);
- splat_test_init(sub, SPLAT_VNODE_TEST3_NAME, SPLAT_VNODE_TEST3_DESC,
- SPLAT_VNODE_TEST3_ID, splat_vnode_test3);
- splat_test_init(sub, SPLAT_VNODE_TEST5_NAME, SPLAT_VNODE_TEST5_DESC,
- SPLAT_VNODE_TEST5_ID, splat_vnode_test5);
- splat_test_init(sub, SPLAT_VNODE_TEST6_NAME, SPLAT_VNODE_TEST6_DESC,
- SPLAT_VNODE_TEST6_ID, splat_vnode_test6);
-
- return sub;
-} /* splat_vnode_init() */
-
-void
-splat_vnode_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
-
- splat_test_fini(sub, SPLAT_VNODE_TEST6_ID);
- splat_test_fini(sub, SPLAT_VNODE_TEST5_ID);
- splat_test_fini(sub, SPLAT_VNODE_TEST3_ID);
- splat_test_fini(sub, SPLAT_VNODE_TEST2_ID);
- splat_test_fini(sub, SPLAT_VNODE_TEST1_ID);
-
- kfree(sub);
-} /* splat_vnode_fini() */
-
-int
-splat_vnode_id(void)
-{
- return SPLAT_SUBSYSTEM_VNODE;
-} /* splat_vnode_id() */
diff --git a/module/splat/splat-zlib.c b/module/splat/splat-zlib.c
deleted file mode 100644
index 28e521c82..000000000
--- a/module/splat/splat-zlib.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <[email protected]>.
- * UCRL-CODE-235197
- *
- * This file is part of the SPL, Solaris Porting Layer.
- * For details, see <http://zfsonlinux.org/>.
- *
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- * Solaris Porting LAyer Tests (SPLAT) Zlib Compression Tests.
- */
-
-#include <sys/zmod.h>
-#include <sys/random.h>
-#include <sys/kmem.h>
-#include <sys/vmem.h>
-#include "splat-internal.h"
-
-#define SPLAT_ZLIB_NAME "zlib"
-#define SPLAT_ZLIB_DESC "Zlib Compression Tests"
-
-#define SPLAT_ZLIB_TEST1_ID 0x0f01
-#define SPLAT_ZLIB_TEST1_NAME "compress/uncompress"
-#define SPLAT_ZLIB_TEST1_DESC "Compress/Uncompress Test"
-
-#define BUFFER_SIZE (128 * 1024)
-
-static int
-splat_zlib_test1_check(struct file *file, void *src, void *dst, void *chk,
- int level)
-{
- size_t dst_len = BUFFER_SIZE;
- size_t chk_len = BUFFER_SIZE;
- int rc;
-
- memset(dst, 0, BUFFER_SIZE);
- memset(chk, 0, BUFFER_SIZE);
-
- rc = z_compress_level(dst, &dst_len, src, BUFFER_SIZE, level);
- if (rc != Z_OK) {
- splat_vprint(file, SPLAT_ZLIB_TEST1_NAME,
- "Failed level %d z_compress_level(), %d\n", level, rc);
- return -EINVAL;
- }
-
- rc = z_uncompress(chk, &chk_len, dst, dst_len);
- if (rc != Z_OK) {
- splat_vprint(file, SPLAT_ZLIB_TEST1_NAME,
- "Failed level %d z_uncompress(), %d\n", level, rc);
- return -EINVAL;
- }
-
- rc = memcmp(src, chk, BUFFER_SIZE);
- if (rc) {
- splat_vprint(file, SPLAT_ZLIB_TEST1_NAME,
- "Failed level %d memcmp()), %d\n", level, rc);
- return -EINVAL;
- }
-
- splat_vprint(file, SPLAT_ZLIB_TEST1_NAME,
- "Passed level %d, compressed %d bytes to %d bytes\n",
- level, BUFFER_SIZE, (int)dst_len);
-
- return 0;
-}
-
-/*
- * Compress a buffer, uncompress the newly compressed buffer, then
- * compare it to the original. Do this for all 9 compression levels.
- */
-static int
-splat_zlib_test1(struct file *file, void *arg)
-{
- void *src = NULL, *dst = NULL, *chk = NULL;
- int i, rc, level;
-
- src = vmalloc(BUFFER_SIZE);
- if (src == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- dst = vmalloc(BUFFER_SIZE);
- if (dst == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- chk = vmalloc(BUFFER_SIZE);
- if (chk == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- /* Source buffer is a repeating 1024 byte random pattern. */
- random_get_pseudo_bytes(src, sizeof(uint8_t) * 1024);
- for (i = 1; i < 128; i++)
- memcpy(src + (i * 1024), src, 1024);
-
- for (level = 1; level <= 9; level++)
- if ((rc = splat_zlib_test1_check(file, src, dst, chk, level)))
- break;
-out:
- if (src)
- vfree(src);
-
- if (dst)
- vfree(dst);
-
- if (chk)
- vfree(chk);
-
- return rc;
-}
-
-splat_subsystem_t *
-splat_zlib_init(void)
-{
- splat_subsystem_t *sub;
-
- sub = kmalloc(sizeof(*sub), GFP_KERNEL);
- if (sub == NULL)
- return NULL;
-
- memset(sub, 0, sizeof(*sub));
- strncpy(sub->desc.name, SPLAT_ZLIB_NAME, SPLAT_NAME_SIZE);
- strncpy(sub->desc.desc, SPLAT_ZLIB_DESC, SPLAT_DESC_SIZE);
- INIT_LIST_HEAD(&sub->subsystem_list);
- INIT_LIST_HEAD(&sub->test_list);
- spin_lock_init(&sub->test_lock);
- sub->desc.id = SPLAT_SUBSYSTEM_ZLIB;
-
- splat_test_init(sub, SPLAT_ZLIB_TEST1_NAME, SPLAT_ZLIB_TEST1_DESC,
- SPLAT_ZLIB_TEST1_ID, splat_zlib_test1);
-
- return sub;
-}
-
-void
-splat_zlib_fini(splat_subsystem_t *sub)
-{
- ASSERT(sub);
-
- splat_test_fini(sub, SPLAT_ZLIB_TEST1_ID);
-
- kfree(sub);
-}
-
-int
-splat_zlib_id(void) {
- return SPLAT_SUBSYSTEM_ZLIB;
-}