diff options
author | behlendo <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c> | 2008-03-18 04:56:43 +0000 |
---|---|---|
committer | behlendo <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c> | 2008-03-18 04:56:43 +0000 |
commit | 5d86345d3753fd6d873ba40480e1121eb7c28e21 (patch) | |
tree | 620b75865d244e22240e1c0f7159a05b3558b6e5 /modules | |
parent | 1ec74a114cc4ec5055e7bc45cffda483505d8aba (diff) |
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
Diffstat (limited to 'modules')
-rw-r--r-- | modules/spl/Makefile.in | 1 | ||||
-rw-r--r-- | modules/spl/spl-file.c | 169 | ||||
-rw-r--r-- | modules/spl/spl-generic.c | 27 | ||||
-rw-r--r-- | modules/spl/spl-kmem.c | 24 | ||||
-rw-r--r-- | modules/spl/spl-vnode.c | 6 | ||||
-rw-r--r-- | modules/splat/Makefile.in | 1 | ||||
-rw-r--r-- | modules/splat/splat-ctl.c | 2 | ||||
-rw-r--r-- | modules/splat/splat-file.c | 57 | ||||
-rw-r--r-- | modules/splat/splat-internal.h | 3 | ||||
-rw-r--r-- | modules/splat/splat-kobj.c | 6 |
10 files changed, 273 insertions, 23 deletions
diff --git a/modules/spl/Makefile.in b/modules/spl/Makefile.in index 1005d100b..7508a3ebf 100644 --- a/modules/spl/Makefile.in +++ b/modules/spl/Makefile.in @@ -17,6 +17,7 @@ spl-objs += spl-vnode.o spl-objs += spl-err.o spl-objs += spl-time.o spl-objs += spl-kobj.o +spl-objs += spl-file.o spl-objs += spl-generic.o splmodule := spl.ko diff --git a/modules/spl/spl-file.c b/modules/spl/spl-file.c new file mode 100644 index 000000000..bce421432 --- /dev/null +++ b/modules/spl/spl-file.c @@ -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() */ diff --git a/modules/spl/spl-generic.c b/modules/spl/spl-generic.c index 9f48dd1a5..ee107d045 100644 --- a/modules/spl/spl-generic.c +++ b/modules/spl/spl-generic.c @@ -1,6 +1,7 @@ #include <sys/sysmacros.h> #include <sys/vmsystm.h> #include <sys/vnode.h> +#include <sys/file.h> #include <sys/kmem.h> #include "config.h" @@ -60,35 +61,27 @@ static int __init spl_init(void) { int rc; - rc = vn_init(); - if (rc) + if ((rc = vn_init())) + return rc; + + if ((rc = file_init())) + return rc; + + if ((rc = kmem_init())) return rc; strcpy(hw_serial, "007f0100"); /* loopback */ 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; } static void spl_fini(void) { + kmem_fini(); + file_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; } diff --git a/modules/spl/spl-kmem.c b/modules/spl/spl-kmem.c index c8808105b..50eeec132 100644 --- a/modules/spl/spl-kmem.c +++ b/modules/spl/spl-kmem.c @@ -272,3 +272,27 @@ __kmem_reap(void) { kmem_cache_generic_shrinker(KMC_REAP_CHUNK, GFP_KERNEL); } 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 +} diff --git a/modules/spl/spl-vnode.c b/modules/spl/spl-vnode.c index 5776de6dd..65cde885d 100644 --- a/modules/spl/spl-vnode.c +++ b/modules/spl/spl-vnode.c @@ -43,7 +43,6 @@ vn_alloc(int flag) vnode_t *vp; vp = kmem_cache_alloc(vn_cache, flag); - if (vp != NULL) { vp->v_fp = NULL; vp->v_type = 0; @@ -411,8 +410,9 @@ vn_cache_destructor(void *buf, void *cdrarg) int vn_init(void) { - vn_cache = kmem_cache_create("vn_cache", sizeof(struct vnode), 64, - vn_cache_constructor, vn_cache_destructor, + vn_cache = kmem_cache_create("spl_vn_cache", sizeof(struct vnode), 64, + vn_cache_constructor, + vn_cache_destructor, NULL, NULL, NULL, 0); return 0; } /* vn_init() */ diff --git a/modules/splat/Makefile.in b/modules/splat/Makefile.in index 69f38b1f5..b437331ad 100644 --- a/modules/splat/Makefile.in +++ b/modules/splat/Makefile.in @@ -23,6 +23,7 @@ splat-objs += splat-rwlock.o splat-objs += splat-time.o splat-objs += splat-vnode.o splat-objs += splat-kobj.o +splat-objs += splat-file.o splatmodule := splat.ko splatmoduledir := @kmoduledir@/kernel/lib/ diff --git a/modules/splat/splat-ctl.c b/modules/splat/splat-ctl.c index e9026cd8d..8c853fca5 100644 --- a/modules/splat/splat-ctl.c +++ b/modules/splat/splat-ctl.c @@ -593,6 +593,7 @@ splat_init(void) SPLAT_SUBSYSTEM_INIT(time); SPLAT_SUBSYSTEM_INIT(vnode); SPLAT_SUBSYSTEM_INIT(kobj); + SPLAT_SUBSYSTEM_INIT(file); dev = MKDEV(SPLAT_MAJOR, 0); if ((rc = register_chrdev_region(dev, SPLAT_MINORS, "splatctl"))) @@ -654,6 +655,7 @@ splat_fini(void) cdev_del(&splat_cdev); unregister_chrdev_region(dev, SPLAT_MINORS); + SPLAT_SUBSYSTEM_FINI(file); SPLAT_SUBSYSTEM_FINI(kobj); SPLAT_SUBSYSTEM_FINI(vnode); SPLAT_SUBSYSTEM_FINI(time); diff --git a/modules/splat/splat-file.c b/modules/splat/splat-file.c new file mode 100644 index 000000000..e05f1c5d7 --- /dev/null +++ b/modules/splat/splat-file.c @@ -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() */ diff --git a/modules/splat/splat-internal.h b/modules/splat/splat-internal.h index aca4b3d38..4286a9571 100644 --- a/modules/splat/splat-internal.h +++ b/modules/splat/splat-internal.h @@ -172,6 +172,7 @@ 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_file_init(void); void splat_condvar_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_vnode_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_kmem_id(void); @@ -194,5 +196,6 @@ int splat_thread_id(void); int splat_time_id(void); int splat_vnode_id(void); int splat_kobj_id(void); +int splat_file_id(void); #endif /* _SPLAT_INTERNAL_H */ diff --git a/modules/splat/splat-kobj.c b/modules/splat/splat-kobj.c index c24057b0e..ad6c8a06c 100644 --- a/modules/splat/splat-kobj.c +++ b/modules/splat/splat-kobj.c @@ -2,15 +2,15 @@ #define SPLAT_SUBSYSTEM_KOBJ 0x0a00 #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_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_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" |