Merge branch 'splat'

Additional debugging, some cleanup, and an assortment of fixes
to the SPLAT tests and infrastructure.  Full details in the
individual patches.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
Brian Behlendorf 2012-11-06 14:49:11 -08:00
commit 65c2fc5a2e
22 changed files with 93 additions and 81 deletions

View File

@ -35,12 +35,13 @@
* calling any of the wait/signal funs, and passed into the wait funs.
*/
#define CV_MAGIC 0x346545f4
#define CV_POISON 0x95
#define CV_DESTROY 0x346545f5
typedef struct {
int cv_magic;
wait_queue_head_t cv_event;
wait_queue_head_t cv_destroy;
atomic_t cv_refs;
atomic_t cv_waiters;
kmutex_t *cv_mutex;
} kcondvar_t;

View File

@ -28,7 +28,6 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mm_compat.h>
#include <linux/spinlock.h>
#include <linux/rwsem.h>
#include <linux/hash.h>

View File

@ -42,6 +42,8 @@
#include <linux/proc_compat.h>
#include <linux/math64_compat.h>
#include <linux/zlib_compat.h>
#include <linux/mm_compat.h>
#include <linux/delay.h>
#ifndef HAVE_UINTPTR_T
typedef unsigned long uintptr_t;

View File

@ -48,6 +48,7 @@ __cv_init(kcondvar_t *cvp, char *name, kcv_type_t type, void *arg)
init_waitqueue_head(&cvp->cv_event);
init_waitqueue_head(&cvp->cv_destroy);
atomic_set(&cvp->cv_waiters, 0);
atomic_set(&cvp->cv_refs, 1);
cvp->cv_mutex = NULL;
/* We may be called when there is a non-zero preempt_count or
@ -63,12 +64,13 @@ EXPORT_SYMBOL(__cv_init);
static int
cv_destroy_wakeup(kcondvar_t *cvp)
{
if ((cvp->cv_mutex != NULL) ||
(waitqueue_active(&cvp->cv_event)) ||
(atomic_read(&cvp->cv_waiters) > 0))
return 0;
if (!atomic_read(&cvp->cv_waiters) && !atomic_read(&cvp->cv_refs)) {
ASSERT(cvp->cv_mutex == NULL);
ASSERT(!waitqueue_active(&cvp->cv_event));
return 1;
}
return 0;
}
void
@ -78,11 +80,15 @@ __cv_destroy(kcondvar_t *cvp)
ASSERT(cvp);
ASSERT(cvp->cv_magic == CV_MAGIC);
/* Block until all waiters have woken */
cvp->cv_magic = CV_DESTROY;
atomic_dec(&cvp->cv_refs);
/* Block until all waiters are woken and references dropped. */
while (cv_destroy_wakeup(cvp) == 0)
wait_event_timeout(cvp->cv_destroy, cv_destroy_wakeup(cvp), 1);
ASSERT3P(cvp->cv_mutex, ==, NULL);
ASSERT3S(atomic_read(&cvp->cv_refs), ==, 0);
ASSERT3S(atomic_read(&cvp->cv_waiters), ==, 0);
ASSERT3S(waitqueue_active(&cvp->cv_event), ==, 0);
@ -100,6 +106,7 @@ cv_wait_common(kcondvar_t *cvp, kmutex_t *mp, int state)
ASSERT(mp);
ASSERT(cvp->cv_magic == CV_MAGIC);
ASSERT(mutex_owned(mp));
atomic_inc(&cvp->cv_refs);
if (cvp->cv_mutex == NULL)
cvp->cv_mutex = mp;
@ -124,6 +131,7 @@ cv_wait_common(kcondvar_t *cvp, kmutex_t *mp, int state)
}
finish_wait(&cvp->cv_event, &wait);
atomic_dec(&cvp->cv_refs);
SEXIT;
}
@ -157,6 +165,7 @@ __cv_timedwait_common(kcondvar_t *cvp, kmutex_t *mp,
ASSERT(mp);
ASSERT(cvp->cv_magic == CV_MAGIC);
ASSERT(mutex_owned(mp));
atomic_inc(&cvp->cv_refs);
if (cvp->cv_mutex == NULL)
cvp->cv_mutex = mp;
@ -166,8 +175,10 @@ __cv_timedwait_common(kcondvar_t *cvp, kmutex_t *mp,
/* XXX - Does not handle jiffie wrap properly */
time_left = expire_time - jiffies;
if (time_left <= 0)
if (time_left <= 0) {
atomic_dec(&cvp->cv_refs);
SRETURN(-1);
}
prepare_to_wait_exclusive(&cvp->cv_event, &wait, state);
atomic_inc(&cvp->cv_waiters);
@ -186,6 +197,7 @@ __cv_timedwait_common(kcondvar_t *cvp, kmutex_t *mp,
}
finish_wait(&cvp->cv_event, &wait);
atomic_dec(&cvp->cv_refs);
SRETURN(time_left > 0 ? time_left : -1);
}
@ -210,6 +222,7 @@ __cv_signal(kcondvar_t *cvp)
SENTRY;
ASSERT(cvp);
ASSERT(cvp->cv_magic == CV_MAGIC);
atomic_inc(&cvp->cv_refs);
/* All waiters are added with WQ_FLAG_EXCLUSIVE so only one
* waiter will be set runable with each call to wake_up().
@ -218,6 +231,7 @@ __cv_signal(kcondvar_t *cvp)
if (atomic_read(&cvp->cv_waiters) > 0)
wake_up(&cvp->cv_event);
atomic_dec(&cvp->cv_refs);
SEXIT;
}
EXPORT_SYMBOL(__cv_signal);
@ -225,15 +239,17 @@ EXPORT_SYMBOL(__cv_signal);
void
__cv_broadcast(kcondvar_t *cvp)
{
SENTRY;
ASSERT(cvp);
ASSERT(cvp->cv_magic == CV_MAGIC);
SENTRY;
atomic_inc(&cvp->cv_refs);
/* Wake_up_all() will wake up all waiters even those which
* have the WQ_FLAG_EXCLUSIVE flag set. */
if (atomic_read(&cvp->cv_waiters) > 0)
wake_up_all(&cvp->cv_event);
atomic_dec(&cvp->cv_refs);
SEXIT;
}
EXPORT_SYMBOL(__cv_broadcast);

View File

@ -24,6 +24,8 @@
* Solaris Porting LAyer Tests (SPLAT) Atomic Tests.
\*****************************************************************************/
#include <sys/atomic.h>
#include <sys/thread.h>
#include "splat-internal.h"
#define SPLAT_ATOMIC_NAME "atomic"
@ -49,7 +51,7 @@ typedef enum {
typedef struct atomic_priv {
unsigned long ap_magic;
struct file *ap_file;
spinlock_t ap_lock;
struct mutex ap_lock;
wait_queue_head_t ap_waitq;
volatile uint64_t ap_atomic;
volatile uint64_t ap_atomic_exited;
@ -67,10 +69,10 @@ splat_atomic_work(void *priv)
ap = (atomic_priv_t *)priv;
ASSERT(ap->ap_magic == SPLAT_ATOMIC_TEST_MAGIC);
spin_lock(&ap->ap_lock);
mutex_lock(&ap->ap_lock);
op = ap->ap_op;
wake_up(&ap->ap_waitq);
spin_unlock(&ap->ap_lock);
mutex_unlock(&ap->ap_lock);
splat_vprint(ap->ap_file, SPLAT_ATOMIC_TEST1_NAME,
"Thread %d successfully started: %lu/%lu\n", op,
@ -140,13 +142,13 @@ splat_atomic_test1(struct file *file, void *arg)
ap.ap_magic = SPLAT_ATOMIC_TEST_MAGIC;
ap.ap_file = file;
spin_lock_init(&ap.ap_lock);
mutex_init(&ap.ap_lock);
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++) {
spin_lock(&ap.ap_lock);
mutex_lock(&ap.ap_lock);
ap.ap_op = i;
thr = (kthread_t *)thread_create(NULL, 0, splat_atomic_work,
@ -154,14 +156,14 @@ splat_atomic_test1(struct file *file, void *arg)
minclsyspri);
if (thr == NULL) {
rc = -ESRCH;
spin_unlock(&ap.ap_lock);
mutex_unlock(&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);
spin_unlock(&ap.ap_lock);
mutex_unlock(&ap.ap_lock);
schedule();
}

View File

@ -24,6 +24,7 @@
* Solaris Porting LAyer Tests (SPLAT) Condition Variable Tests.
\*****************************************************************************/
#include <sys/condvar.h>
#include "splat-internal.h"
#define SPLAT_CONDVAR_NAME "condvar"

View File

@ -24,6 +24,7 @@
* Solaris Porting LAyer Tests (SPLAT) Credential Tests.
\*****************************************************************************/
#include <sys/cred.h>
#include "splat-internal.h"
#define SPLAT_CRED_NAME "cred"

View File

@ -43,6 +43,14 @@
* of regression tests or particular tests.
\*****************************************************************************/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <sys/types.h>
#include <sys/debug.h>
#include "splat-internal.h"
static spl_class *splat_class;
@ -63,7 +71,7 @@ splat_open(struct inode *inode, struct file *file)
if (info == NULL)
return -ENOMEM;
spin_lock_init(&info->info_lock);
mutex_init(&info->info_lock);
info->info_size = SPLAT_INFO_BUFFER_SIZE;
info->info_buffer = (char *)vmalloc(SPLAT_INFO_BUFFER_SIZE);
if (info->info_buffer == NULL) {
@ -92,6 +100,7 @@ splat_release(struct inode *inode, struct file *file)
ASSERT(info);
ASSERT(info->info_buffer);
mutex_destroy(&info->info_lock);
vfree(info->info_buffer);
kfree(info);
@ -106,10 +115,10 @@ splat_buffer_clear(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
ASSERT(info);
ASSERT(info->info_buffer);
spin_lock(&info->info_lock);
mutex_lock(&info->info_lock);
memset(info->info_buffer, 0, info->info_size);
info->info_head = info->info_buffer;
spin_unlock(&info->info_lock);
mutex_unlock(&info->info_lock);
return 0;
}
@ -124,7 +133,7 @@ splat_buffer_size(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
ASSERT(info);
ASSERT(info->info_buffer);
spin_lock(&info->info_lock);
mutex_lock(&info->info_lock);
if (kcfg->cfg_arg1 > 0) {
size = kcfg->cfg_arg1;
@ -149,7 +158,7 @@ splat_buffer_size(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
if (copy_to_user((struct splat_cfg_t __user *)arg, kcfg, sizeof(*kcfg)))
rc = -EFAULT;
out:
spin_unlock(&info->info_lock);
mutex_unlock(&info->info_lock);
return rc;
}
@ -500,7 +509,7 @@ static ssize_t splat_write(struct file *file, const char __user *buf,
ASSERT(info);
ASSERT(info->info_buffer);
spin_lock(&info->info_lock);
mutex_lock(&info->info_lock);
/* Write beyond EOF */
if (*ppos >= info->info_size) {
@ -520,7 +529,7 @@ static ssize_t splat_write(struct file *file, const char __user *buf,
*ppos += count;
rc = count;
out:
spin_unlock(&info->info_lock);
mutex_unlock(&info->info_lock);
return rc;
}
@ -537,7 +546,7 @@ static ssize_t splat_read(struct file *file, char __user *buf,
ASSERT(info);
ASSERT(info->info_buffer);
spin_lock(&info->info_lock);
mutex_lock(&info->info_lock);
/* Read beyond EOF */
if (*ppos >= info->info_size)
@ -555,7 +564,7 @@ static ssize_t splat_read(struct file *file, char __user *buf,
*ppos += count;
rc = count;
out:
spin_unlock(&info->info_lock);
mutex_unlock(&info->info_lock);
return rc;
}
@ -571,7 +580,7 @@ static loff_t splat_seek(struct file *file, loff_t offset, int origin)
ASSERT(info);
ASSERT(info->info_buffer);
spin_lock(&info->info_lock);
mutex_lock(&info->info_lock);
switch (origin) {
case 0: /* SEEK_SET - No-op just do it */
@ -590,7 +599,7 @@ static loff_t splat_seek(struct file *file, loff_t offset, int origin)
rc = offset;
}
spin_unlock(&info->info_lock);
mutex_unlock(&info->info_lock);
return rc;
}

View File

@ -24,6 +24,7 @@
* Solaris Porting LAyer Tests (SPLAT) Generic Tests.
\*****************************************************************************/
#include <sys/sunddi.h>
#include "splat-internal.h"
#define SPLAT_GENERIC_NAME "generic"

View File

@ -25,47 +25,6 @@
#ifndef _SPLAT_INTERNAL_H
#define _SPLAT_INTERNAL_H
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/elf.h>
#include <linux/limits.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/swap.h>
#include <linux/delay.h>
#include <asm/ioctls.h>
#include <asm/uaccess.h>
#include <stdarg.h>
#include <sys/callb.h>
#include <sys/condvar.h>
#include <sys/cred.h>
#include <sys/sysmacros.h>
#include <sys/kmem.h>
#include <sys/kstat.h>
#include <sys/mutex.h>
#include <sys/random.h>
#include <sys/rwlock.h>
#include <sys/taskq.h>
#include <sys/thread.h>
#include <sys/time.h>
#include <sys/timer.h>
#include <sys/types.h>
#include <sys/kobj.h>
#include <sys/atomic.h>
#include <sys/list.h>
#include <sys/sunddi.h>
#include <sys/zmod.h>
#include <linux/cdev.h>
#include "spl-device.h"
#include "spl-debug.h"
#include "splat-ctl.h"
@ -162,7 +121,7 @@ typedef struct splat_subsystem {
#define SPLAT_INFO_BUFFER_REDZONE 256
typedef struct splat_info {
spinlock_t info_lock;
struct mutex info_lock;
int info_size;
char *info_buffer;
char *info_head; /* Internal kernel use only */
@ -177,7 +136,7 @@ typedef struct splat_info {
ASSERT(_info_); \
ASSERT(_info_->info_buffer); \
\
spin_lock(&_info_->info_lock); \
mutex_lock(&_info_->info_lock); \
\
/* Don't allow the kernel to start a write in the red zone */ \
if ((int)(_info_->info_head - _info_->info_buffer) > \
@ -189,7 +148,7 @@ typedef struct splat_info {
_info_->info_head += _rc_; \
} \
\
spin_unlock(&_info_->info_lock); \
mutex_unlock(&_info_->info_lock); \
_rc_; \
})

View File

@ -24,6 +24,8 @@
* Solaris Porting LAyer Tests (SPLAT) Kmem Tests.
\*****************************************************************************/
#include <sys/kmem.h>
#include <sys/thread.h>
#include "splat-internal.h"
#define SPLAT_KMEM_NAME "kmem"
@ -69,11 +71,11 @@
#define SPLAT_KMEM_TEST10_NAME "slab_lock"
#define SPLAT_KMEM_TEST10_DESC "Slab locking test"
#ifdef _LP64
#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 /* _LP64 */
#endif
#define SPLAT_KMEM_TEST12_ID 0x010c
#define SPLAT_KMEM_TEST12_NAME "vmem_size"
@ -1006,7 +1008,7 @@ splat_kmem_test10(struct file *file, void *arg)
return rc;
}
#ifdef _LP64
#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
@ -1037,7 +1039,7 @@ splat_kmem_test11(struct file *file, void *arg)
return rc;
}
#endif /* _LP64 */
#endif
/*
* Check vmem_size() behavior by acquiring the alloc/free/total vmem
@ -1290,10 +1292,10 @@ splat_kmem_init(void)
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);
#ifdef _LP64
#if 0
SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST11_NAME, SPLAT_KMEM_TEST11_DESC,
SPLAT_KMEM_TEST11_ID, splat_kmem_test11);
#endif /* _LP64 */
#endif
SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST12_NAME, SPLAT_KMEM_TEST12_DESC,
SPLAT_KMEM_TEST12_ID, splat_kmem_test12);
SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST13_NAME, SPLAT_KMEM_TEST13_DESC,
@ -1308,9 +1310,9 @@ splat_kmem_fini(splat_subsystem_t *sub)
ASSERT(sub);
SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST13_ID);
SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST12_ID);
#ifdef _LP64
#if 0
SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST11_ID);
#endif /* _LP64 */
#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);

View File

@ -24,6 +24,7 @@
* Solaris Porting LAyer Tests (SPLAT) Kobj Tests.
\*****************************************************************************/
#include <sys/kobj.h>
#include "splat-internal.h"
#define SPLAT_KOBJ_NAME "kobj"

View File

@ -23,6 +23,7 @@
* Solaris Porting LAyer Tests (SPLAT) Kernel Compatibility Tests.
\*****************************************************************************/
#include <sys/kmem.h>
#include "splat-internal.h"
#define SPLAT_LINUX_NAME "linux"

View File

@ -24,6 +24,8 @@
* Solaris Porting LAyer Tests (SPLAT) List Tests.
\*****************************************************************************/
#include <sys/list.h>
#include <sys/kmem.h>
#include "splat-internal.h"
#define SPLAT_LIST_NAME "list"

View File

@ -24,6 +24,8 @@
* Solaris Porting LAyer Tests (SPLAT) Mutex Tests.
\*****************************************************************************/
#include <sys/mutex.h>
#include <sys/taskq.h>
#include "splat-internal.h"
#define SPLAT_MUTEX_NAME "mutex"

View File

@ -24,6 +24,8 @@
* 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"

View File

@ -24,6 +24,9 @@
* Solaris Porting LAyer Tests (SPLAT) Read/Writer Lock Tests.
\*****************************************************************************/
#include <sys/rwlock.h>
#include <sys/taskq.h>
#include <sys/random.h>
#include "splat-internal.h"
#define SPLAT_RWLOCK_NAME "rwlock"

View File

@ -24,6 +24,8 @@
* Solaris Porting LAyer Tests (SPLAT) Task Queue Tests.
\*****************************************************************************/
#include <sys/taskq.h>
#include <sys/kmem.h>
#include "splat-internal.h"
#define SPLAT_TASKQ_NAME "taskq"

View File

@ -24,6 +24,8 @@
* Solaris Porting LAyer Tests (SPLAT) Thread Tests.
\*****************************************************************************/
#include <sys/thread.h>
#include <sys/random.h>
#include "splat-internal.h"
#define SPLAT_THREAD_NAME "thread"

View File

@ -24,6 +24,7 @@
* Solaris Porting LAyer Tests (SPLAT) Time Tests.
\*****************************************************************************/
#include <sys/time.h>
#include "splat-internal.h"
#define SPLAT_TIME_NAME "time"

View File

@ -24,8 +24,8 @@
* Solaris Porting LAyer Tests (SPLAT) Vnode Tests.
\*****************************************************************************/
#include <sys/vnode.h>
#include "splat-internal.h"
#include <linux/rcupdate.h>
#define SPLAT_VNODE_NAME "vnode"
#define SPLAT_VNODE_DESC "Kernel Vnode Tests"

View File

@ -24,6 +24,9 @@
* Solaris Porting LAyer Tests (SPLAT) Zlib Compression Tests.
\*****************************************************************************/
#include <sys/zmod.h>
#include <sys/random.h>
#include <sys/kmem.h>
#include "splat-internal.h"
#define SPLAT_ZLIB_NAME "zlib"