Initial pass at a file API getf/releasef hooks

git-svn-id: https://outreach.scidac.gov/svn/spl/trunk@50 7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c
This commit is contained in:
behlendo 2008-03-18 04:56:43 +00:00
parent 1ec74a114c
commit 5d86345d37
14 changed files with 317 additions and 23 deletions

View File

@ -1,4 +1,34 @@
#ifndef _SPL_FILE_H #ifndef _SPL_FILE_H
#define _SPL_FILE_H #define _SPL_FILE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <linux/module.h>
#include <linux/file.h>
#include <sys/kmem.h>
#include <sys/mutex.h>
#include <sys/vnode.h>
typedef struct spl_file {
int f_fd; /* linux fd for lookup */
struct file *f_file; /* linux file struct */
atomic_t f_ref; /* ref count */
kmutex_t f_lock; /* struct lock */
loff_t f_offset; /* offset */
vnode_t *f_vnode; /* vnode */
struct list_head f_list; /* list of referenced file_t's */
} file_t;
extern file_t *getf(int fd);
extern void releasef(int fd);
int file_init(void);
void file_fini(void);
#ifdef __cplusplus
}
#endif
#endif /* SPL_FILE_H */ #endif /* SPL_FILE_H */

View File

@ -204,6 +204,9 @@ extern __kmem_cache_destroy(kmem_cache_t *cache);
void void
extern __kmem_reap(void); extern __kmem_reap(void);
int kmem_init(void);
void kmem_fini(void);
#define kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags) \ #define kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags) \
__kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags) __kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags)
#define kmem_cache_destroy(cache) __kmem_cache_destroy(cache) #define kmem_cache_destroy(cache) __kmem_cache_destroy(cache)

View File

@ -31,5 +31,7 @@ typedef longlong_t diskaddr_t;
typedef ushort_t o_mode_t; typedef ushort_t o_mode_t;
typedef uint_t major_t; typedef uint_t major_t;
typedef uint_t minor_t; typedef uint_t minor_t;
typedef uint_t ldi_ident_t;
typedef dev_t dev_info_t;
#endif /* _SPL_TYPES_H */ #endif /* _SPL_TYPES_H */

View File

@ -1,6 +1,10 @@
#ifndef _SPL_VNODE_H #ifndef _SPL_VNODE_H
#define _SPL_VNODE_H #define _SPL_VNODE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <linux/module.h> #include <linux/module.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
@ -30,6 +34,7 @@
#define FRSYNC O_RSYNC #define FRSYNC O_RSYNC
#define FEXCL O_EXCL #define FEXCL O_EXCL
#define FDIRECT O_DIRECT #define FDIRECT O_DIRECT
#define FAPPEND O_APPEND
#define FNODSYNC 0x10000 /* fsync pseudo flag */ #define FNODSYNC 0x10000 /* fsync pseudo flag */
#define FNOFOLLOW 0x20000 /* don't follow symlinks */ #define FNOFOLLOW 0x20000 /* don't follow symlinks */
@ -178,4 +183,8 @@ vn_putpage(vnode_t *vp, offset_t off, ssize_t size,
extern void *rootdir; extern void *rootdir;
#ifdef __cplusplus
}
#endif
#endif /* SPL_VNODE_H */ #endif /* SPL_VNODE_H */

View File

@ -17,6 +17,7 @@ spl-objs += spl-vnode.o
spl-objs += spl-err.o spl-objs += spl-err.o
spl-objs += spl-time.o spl-objs += spl-time.o
spl-objs += spl-kobj.o spl-objs += spl-kobj.o
spl-objs += spl-file.o
spl-objs += spl-generic.o spl-objs += spl-generic.o
splmodule := spl.ko splmodule := spl.ko

169
modules/spl/spl-file.c Normal file
View File

@ -0,0 +1,169 @@
#include <sys/sysmacros.h>
#include <sys/file.h>
#include "config.h"
/* File interface */
static spinlock_t file_lock = SPIN_LOCK_UNLOCKED;
static LIST_HEAD(file_list);
static kmem_cache_t *file_cache;
/* Function must be called while holding the file_lock */
static file_t *
file_find(int fd)
{
file_t *fp;
BUG_ON(!spin_is_locked(&file_lock));
list_for_each_entry(fp, &file_list, f_list) {
if (fd == fp->f_fd) {
BUG_ON(atomic_read(&fp->f_ref) == 0);
return fp;
}
}
return NULL;
} /* file_find() */
file_t *
getf(int fd)
{
file_t *fp;
/* Already open just take an extra reference */
spin_lock(&file_lock);
fp = file_find(fd);
if (fp) {
atomic_inc(&fp->f_ref);
spin_unlock(&file_lock);
return fp;
}
spin_unlock(&file_lock);
/* File was not yet opened via the SPL layer create needed bits */
fp = kmem_cache_alloc(file_cache, 0);
if (fp == NULL)
goto out;
mutex_enter(&fp->f_lock);
fp->f_vnode = vn_alloc(KM_SLEEP);
if (fp->f_vnode == NULL)
goto out_mutex;
/* XXX: Setup needed vnode stop, open file etc */
fp->f_file = fget(fd);
if (fp->f_file == NULL)
goto out_vnode;
fp->f_fd = fd;
atomic_inc(&fp->f_ref);
spin_lock(&file_lock);
list_add(&fp->f_list, &file_list);
spin_unlock(&file_lock);
mutex_exit(&fp->f_lock);
return fp;
out_vnode:
vn_free(fp->f_vnode);
out_mutex:
mutex_exit(&fp->f_lock);
kmem_cache_free(file_cache, fp);
out:
return NULL;
} /* getf() */
EXPORT_SYMBOL(getf);
static void releasef_locked(file_t *fp)
{
BUG_ON(fp->f_file == NULL);
BUG_ON(fp->f_vnode == NULL);
/* Unlinked from list, no refs, safe to free outside mutex */
fput(fp->f_file);
vn_free(fp->f_vnode);
kmem_cache_free(file_cache, fp);
}
void
releasef(int fd)
{
file_t *fp;
spin_lock(&file_lock);
fp = file_find(fd);
if (fp) {
atomic_dec(&fp->f_ref);
if (atomic_read(&fp->f_ref) > 0) {
spin_unlock(&file_lock);
return;
}
list_del(&fp->f_list);
spin_unlock(&file_lock);
releasef_locked(fp);
}
return;
} /* releasef() */
EXPORT_SYMBOL(releasef);
static int
file_cache_constructor(void *buf, void *cdrarg, int kmflags)
{
file_t *fp = buf;
atomic_set(&fp->f_ref, 0);
mutex_init(&fp->f_lock, NULL, MUTEX_DEFAULT, NULL);
return (0);
} /* file_cache_constructor() */
static void
file_cache_destructor(void *buf, void *cdrarg)
{
file_t *fp = buf;
mutex_destroy(&fp->f_lock);
} /* file_cache_destructor() */
int
file_init(void)
{
file_cache = kmem_cache_create("spl_file_cache", sizeof(file_t), 64,
file_cache_constructor,
file_cache_destructor,
NULL, NULL, NULL, 0);
return 0;
} /* file_init() */
void file_fini(void)
{
file_t *fp, *next_fp;
int leaked = 0;
spin_lock(&file_lock);
list_for_each_entry_safe(fp, next_fp, &file_list, f_list) {
list_del(&fp->f_list);
releasef_locked(fp);
leaked++;
}
kmem_cache_destroy(file_cache);
file_cache = NULL;
spin_unlock(&file_lock);
if (leaked > 0)
printk("Warning: %d files leaked\n", leaked);
} /* file_fini() */

View File

@ -1,6 +1,7 @@
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#include <sys/vmsystm.h> #include <sys/vmsystm.h>
#include <sys/vnode.h> #include <sys/vnode.h>
#include <sys/file.h>
#include <sys/kmem.h> #include <sys/kmem.h>
#include "config.h" #include "config.h"
@ -60,35 +61,27 @@ static int __init spl_init(void)
{ {
int rc; int rc;
rc = vn_init(); if ((rc = vn_init()))
if (rc) return rc;
if ((rc = file_init()))
return rc;
if ((rc = kmem_init()))
return rc; return rc;
strcpy(hw_serial, "007f0100"); /* loopback */ strcpy(hw_serial, "007f0100"); /* loopback */
printk(KERN_INFO "spl: Loaded Solaris Porting Layer v%s\n", VERSION); printk(KERN_INFO "spl: Loaded Solaris Porting Layer v%s\n", VERSION);
#ifdef DEBUG_KMEM
atomic64_set(&kmem_alloc_used, 0);
atomic64_set(&vmem_alloc_used, 0);
#endif
return 0; return 0;
} }
static void spl_fini(void) static void spl_fini(void)
{ {
kmem_fini();
file_fini();
vn_fini(); vn_fini();
#ifdef DEBUG_KMEM
if (atomic64_read(&kmem_alloc_used) != 0)
printk("Warning: kmem leaked %ld/%ld bytes\n",
atomic_read(&kmem_alloc_used), kmem_alloc_max);
if (atomic64_read(&vmem_alloc_used) != 0)
printk("Warning: vmem leaked %ld/%ld bytes\n",
atomic_read(&vmem_alloc_used), vmem_alloc_max);
#endif
return; return;
} }

View File

@ -272,3 +272,27 @@ __kmem_reap(void) {
kmem_cache_generic_shrinker(KMC_REAP_CHUNK, GFP_KERNEL); kmem_cache_generic_shrinker(KMC_REAP_CHUNK, GFP_KERNEL);
} }
EXPORT_SYMBOL(__kmem_reap); EXPORT_SYMBOL(__kmem_reap);
int
kmem_init(void)
{
#ifdef DEBUG_KMEM
atomic64_set(&kmem_alloc_used, 0);
atomic64_set(&vmem_alloc_used, 0);
#endif
return 0;
}
void
kmem_fini(void)
{
#ifdef DEBUG_KMEM
if (atomic64_read(&kmem_alloc_used) != 0)
printk("Warning: kmem leaked %ld/%ld bytes\n",
atomic_read(&kmem_alloc_used), kmem_alloc_max);
if (atomic64_read(&vmem_alloc_used) != 0)
printk("Warning: vmem leaked %ld/%ld bytes\n",
atomic_read(&vmem_alloc_used), vmem_alloc_max);
#endif
}

View File

@ -43,7 +43,6 @@ vn_alloc(int flag)
vnode_t *vp; vnode_t *vp;
vp = kmem_cache_alloc(vn_cache, flag); vp = kmem_cache_alloc(vn_cache, flag);
if (vp != NULL) { if (vp != NULL) {
vp->v_fp = NULL; vp->v_fp = NULL;
vp->v_type = 0; vp->v_type = 0;
@ -411,8 +410,9 @@ vn_cache_destructor(void *buf, void *cdrarg)
int int
vn_init(void) vn_init(void)
{ {
vn_cache = kmem_cache_create("vn_cache", sizeof(struct vnode), 64, vn_cache = kmem_cache_create("spl_vn_cache", sizeof(struct vnode), 64,
vn_cache_constructor, vn_cache_destructor, vn_cache_constructor,
vn_cache_destructor,
NULL, NULL, NULL, 0); NULL, NULL, NULL, 0);
return 0; return 0;
} /* vn_init() */ } /* vn_init() */

View File

@ -23,6 +23,7 @@ splat-objs += splat-rwlock.o
splat-objs += splat-time.o splat-objs += splat-time.o
splat-objs += splat-vnode.o splat-objs += splat-vnode.o
splat-objs += splat-kobj.o splat-objs += splat-kobj.o
splat-objs += splat-file.o
splatmodule := splat.ko splatmodule := splat.ko
splatmoduledir := @kmoduledir@/kernel/lib/ splatmoduledir := @kmoduledir@/kernel/lib/

View File

@ -593,6 +593,7 @@ splat_init(void)
SPLAT_SUBSYSTEM_INIT(time); SPLAT_SUBSYSTEM_INIT(time);
SPLAT_SUBSYSTEM_INIT(vnode); SPLAT_SUBSYSTEM_INIT(vnode);
SPLAT_SUBSYSTEM_INIT(kobj); SPLAT_SUBSYSTEM_INIT(kobj);
SPLAT_SUBSYSTEM_INIT(file);
dev = MKDEV(SPLAT_MAJOR, 0); dev = MKDEV(SPLAT_MAJOR, 0);
if ((rc = register_chrdev_region(dev, SPLAT_MINORS, "splatctl"))) if ((rc = register_chrdev_region(dev, SPLAT_MINORS, "splatctl")))
@ -654,6 +655,7 @@ splat_fini(void)
cdev_del(&splat_cdev); cdev_del(&splat_cdev);
unregister_chrdev_region(dev, SPLAT_MINORS); unregister_chrdev_region(dev, SPLAT_MINORS);
SPLAT_SUBSYSTEM_FINI(file);
SPLAT_SUBSYSTEM_FINI(kobj); SPLAT_SUBSYSTEM_FINI(kobj);
SPLAT_SUBSYSTEM_FINI(vnode); SPLAT_SUBSYSTEM_FINI(vnode);
SPLAT_SUBSYSTEM_FINI(time); SPLAT_SUBSYSTEM_FINI(time);

View File

@ -0,0 +1,57 @@
#include "splat-internal.h"
#define SPLAT_SUBSYSTEM_FILE 0x0b00
#define SPLAT_FILE_NAME "file"
#define SPLAT_FILE_DESC "Kernel File Tests"
#define SPLAT_FILE_TEST1_ID 0x0b01
#define SPLAT_FILE_TEST1_NAME "getf"
#define SPLAT_FILE_TEST1_DESC "File getf/releasef Test"
static int
splat_file_test1(struct file *file, void *arg)
{
splat_vprint(file, SPLAT_FILE_TEST1_NAME, "WRITE A TEST, %d\n", 0);
return 0;
} /* splat_file_test1() */
splat_subsystem_t *
splat_file_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_FILE_NAME, SPLAT_NAME_SIZE);
strncpy(sub->desc.desc, SPLAT_FILE_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_FILE;
SPLAT_TEST_INIT(sub, SPLAT_FILE_TEST1_NAME, SPLAT_FILE_TEST1_DESC,
SPLAT_FILE_TEST1_ID, splat_file_test1);
return sub;
} /* splat_file_init() */
void
splat_file_fini(splat_subsystem_t *sub)
{
ASSERT(sub);
SPLAT_TEST_FINI(sub, SPLAT_FILE_TEST1_ID);
kfree(sub);
} /* splat_file_fini() */
int
splat_file_id(void)
{
return SPLAT_SUBSYSTEM_FILE;
} /* splat_file_id() */

View File

@ -172,6 +172,7 @@ splat_subsystem_t * splat_thread_init(void);
splat_subsystem_t * splat_time_init(void); splat_subsystem_t * splat_time_init(void);
splat_subsystem_t * splat_vnode_init(void); splat_subsystem_t * splat_vnode_init(void);
splat_subsystem_t * splat_kobj_init(void); splat_subsystem_t * splat_kobj_init(void);
splat_subsystem_t * splat_file_init(void);
void splat_condvar_fini(splat_subsystem_t *); void splat_condvar_fini(splat_subsystem_t *);
void splat_kmem_fini(splat_subsystem_t *); void splat_kmem_fini(splat_subsystem_t *);
@ -183,6 +184,7 @@ void splat_thread_fini(splat_subsystem_t *);
void splat_time_fini(splat_subsystem_t *); void splat_time_fini(splat_subsystem_t *);
void splat_vnode_fini(splat_subsystem_t *); void splat_vnode_fini(splat_subsystem_t *);
void splat_kobj_fini(splat_subsystem_t *); void splat_kobj_fini(splat_subsystem_t *);
void splat_file_fini(splat_subsystem_t *);
int splat_condvar_id(void); int splat_condvar_id(void);
int splat_kmem_id(void); int splat_kmem_id(void);
@ -194,5 +196,6 @@ int splat_thread_id(void);
int splat_time_id(void); int splat_time_id(void);
int splat_vnode_id(void); int splat_vnode_id(void);
int splat_kobj_id(void); int splat_kobj_id(void);
int splat_file_id(void);
#endif /* _SPLAT_INTERNAL_H */ #endif /* _SPLAT_INTERNAL_H */

View File

@ -2,15 +2,15 @@
#define SPLAT_SUBSYSTEM_KOBJ 0x0a00 #define SPLAT_SUBSYSTEM_KOBJ 0x0a00
#define SPLAT_KOBJ_NAME "kobj" #define SPLAT_KOBJ_NAME "kobj"
#define SPLAT_KOBJ_DESC "Kernel File Tests" #define SPLAT_KOBJ_DESC "Kernel Kobj Tests"
#define SPLAT_KOBJ_TEST1_ID 0x0a01 #define SPLAT_KOBJ_TEST1_ID 0x0a01
#define SPLAT_KOBJ_TEST1_NAME "open" #define SPLAT_KOBJ_TEST1_NAME "open"
#define SPLAT_KOBJ_TEST1_DESC "File Open/Close Test" #define SPLAT_KOBJ_TEST1_DESC "Kobj Open/Close Test"
#define SPLAT_KOBJ_TEST2_ID 0x0a02 #define SPLAT_KOBJ_TEST2_ID 0x0a02
#define SPLAT_KOBJ_TEST2_NAME "size/read" #define SPLAT_KOBJ_TEST2_NAME "size/read"
#define SPLAT_KOBJ_TEST2_DESC "File Size/Read Test" #define SPLAT_KOBJ_TEST2_DESC "Kobj Size/Read Test"
#define SPLAT_KOBJ_TEST_FILE "/etc/fstab" #define SPLAT_KOBJ_TEST_FILE "/etc/fstab"