Apply fix from bug239 for rwlock deadlock.

Update check.sh script to take V=1 env var so you can run it verbosely as
follows if your chasing something: sudo make check V=1

Add new kobj api and needed regression tests to allow reading of files from
within the kernel.  Normally thats not something I support but the spa layer
needs the support for its config file.

Add some more missing stub headers



git-svn-id: https://outreach.scidac.gov/svn/spl/trunk@38 7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c
This commit is contained in:
behlendo
2008-03-11 20:54:40 +00:00
parent b123971fc2
commit 9490c14835
15 changed files with 347 additions and 5 deletions
+1
View File
@@ -16,6 +16,7 @@ spl-objs += spl-rwlock.o
spl-objs += spl-vnode.o
spl-objs += spl-err.o
spl-objs += spl-time.o
spl-objs += spl-kobj.o
spl-objs += spl-generic.o
splmodule := spl.ko
+75
View File
@@ -0,0 +1,75 @@
#include <sys/kobj.h>
#include "config.h"
void *rootdir = NULL;
EXPORT_SYMBOL(rootdir);
struct _buf *
kobj_open_file(const char *name)
{
struct _buf *file;
struct file *fp;
fp = filp_open(name, O_RDONLY, 0644);
if (IS_ERR(fp))
return ((_buf_t *)-1UL);
file = kmem_zalloc(sizeof(_buf_t), KM_SLEEP);
file->fp = fp;
return file;
} /* kobj_open_file() */
EXPORT_SYMBOL(kobj_open_file);
void
kobj_close_file(struct _buf *file)
{
filp_close(file->fp, 0);
kmem_free(file, sizeof(_buf_t));
return;
} /* kobj_close_file() */
EXPORT_SYMBOL(kobj_close_file);
int
kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
{
loff_t offset = off;
mm_segment_t saved_fs;
int rc;
if (!file || !file->fp)
return -EINVAL;
if (!file->fp->f_op || !file->fp->f_op->read)
return -ENOSYS;
/* Writable user data segment must be briefly increased for this
* process so we can use the user space read call paths to write
* in to memory allocated by the kernel. */
saved_fs = get_fs();
set_fs(get_ds());
rc = file->fp->f_op->read(file->fp, buf, size, &offset);
set_fs(saved_fs);
return rc;
} /* kobj_read_file() */
EXPORT_SYMBOL(kobj_read_file);
int
kobj_get_filesize(struct _buf *file, uint64_t *size)
{
struct kstat stat;
int rc;
if (!file || !file->fp || !size)
return -EINVAL;
rc = vfs_getattr(file->fp->f_vfsmnt, file->fp->f_dentry, &stat);
if (rc)
return rc;
*size = stat.size;
return rc;
} /* kobj_get_filesize() */
EXPORT_SYMBOL(kobj_get_filesize);
+1
View File
@@ -21,6 +21,7 @@ splat-objs += splat-condvar.o
splat-objs += splat-thread.o
splat-objs += splat-rwlock.o
splat-objs += splat-time.o
splat-objs += splat-kobj.o
splatmodule := splat.ko
splatmoduledir := @kmoduledir@/kernel/lib/
+2
View File
@@ -591,6 +591,7 @@ splat_init(void)
SPLAT_SUBSYSTEM_INIT(thread);
SPLAT_SUBSYSTEM_INIT(rwlock);
SPLAT_SUBSYSTEM_INIT(time);
SPLAT_SUBSYSTEM_INIT(kobj);
dev = MKDEV(SPLAT_MAJOR, 0);
if ((rc = register_chrdev_region(dev, SPLAT_MINORS, "splatctl")))
@@ -652,6 +653,7 @@ splat_fini(void)
cdev_del(&splat_cdev);
unregister_chrdev_region(dev, SPLAT_MINORS);
SPLAT_SUBSYSTEM_FINI(kobj);
SPLAT_SUBSYSTEM_FINI(time);
SPLAT_SUBSYSTEM_FINI(rwlock);
SPLAT_SUBSYSTEM_FINI(thread);
+4
View File
@@ -32,6 +32,7 @@
#include <sys/time.h>
#include <sys/timer.h>
#include <sys/types.h>
#include <sys/kobj.h>
#include "splat-ctl.h"
@@ -169,6 +170,7 @@ 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_kobj_init(void);
void splat_condvar_fini(splat_subsystem_t *);
void splat_kmem_fini(splat_subsystem_t *);
@@ -178,6 +180,7 @@ 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_kobj_fini(splat_subsystem_t *);
int splat_condvar_id(void);
int splat_kmem_id(void);
@@ -187,5 +190,6 @@ int splat_rwlock_id(void);
int splat_taskq_id(void);
int splat_thread_id(void);
int splat_time_id(void);
int splat_kobj_id(void);
#endif /* _SPLAT_INTERNAL_H */
+137
View File
@@ -0,0 +1,137 @@
#include "splat-internal.h"
#define SPLAT_SUBSYSTEM_KOBJ 0x0900
#define SPLAT_KOBJ_NAME "kobj"
#define SPLAT_KOBJ_DESC "Kernel File Tests"
#define SPLAT_KOBJ_TEST1_ID 0x0901
#define SPLAT_KOBJ_TEST1_NAME "kobj1"
#define SPLAT_KOBJ_TEST1_DESC "File Open/Close Test"
#define SPLAT_KOBJ_TEST2_ID 0x0902
#define SPLAT_KOBJ_TEST2_NAME "kobj2"
#define SPLAT_KOBJ_TEST2_DESC "File 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, GFP_KERNEL);
if (!buf) {
rc = -ENOMEM;
splat_vprint(file, SPLAT_KOBJ_TEST2_NAME, "Failed to alloc "
"%lld bytes for tmp buffer (%d)\n", size, rc);
goto out;
}
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", size, (uint64_t)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", 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() */