]> granicus.if.org Git - zfs/commitdiff
Initial pass at a file API getf/releasef hooks
authorbehlendo <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c>
Tue, 18 Mar 2008 04:56:43 +0000 (04:56 +0000)
committerbehlendo <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c>
Tue, 18 Mar 2008 04:56:43 +0000 (04:56 +0000)
git-svn-id: https://outreach.scidac.gov/svn/spl/trunk@50 7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c

14 files changed:
include/sys/file.h
include/sys/kmem.h
include/sys/types.h
include/sys/vnode.h
modules/spl/Makefile.in
modules/spl/spl-file.c [new file with mode: 0644]
modules/spl/spl-generic.c
modules/spl/spl-kmem.c
modules/spl/spl-vnode.c
modules/splat/Makefile.in
modules/splat/splat-ctl.c
modules/splat/splat-file.c [new file with mode: 0644]
modules/splat/splat-internal.h
modules/splat/splat-kobj.c

index 63d662237dcb98c43e6470228ec6841bd16e59a4..8b135c4b11d7e685d6283e4c42fea829c9d92f98 100644 (file)
@@ -1,4 +1,34 @@
 #ifndef _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 */
index cce2a05e74df3ec007265e1b1ad0c09810671e2f..39c547185053423ec73af76e37b642d5920d89c3 100644 (file)
@@ -204,6 +204,9 @@ extern __kmem_cache_destroy(kmem_cache_t *cache);
 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) \
         __kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags)
 #define kmem_cache_destroy(cache)       __kmem_cache_destroy(cache)
index dc660a761de1b16e08dfb49912952d5a7d69f80f..0d6a71ca0bba57aa324dc8686d24d756956ded26 100644 (file)
@@ -31,5 +31,7 @@ typedef longlong_t                    diskaddr_t;
 typedef ushort_t                       o_mode_t;
 typedef uint_t                         major_t;
 typedef uint_t                         minor_t;
+typedef uint_t                         ldi_ident_t;
+typedef dev_t                          dev_info_t;
 
 #endif /* _SPL_TYPES_H */
index 3ec11abe26c970f290e7f192289633e82c9b2b91..74a09b9b6550b5942cf7176d889a70d9c99bb850 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef _SPL_VNODE_H
 #define _SPL_VNODE_H
 
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
 #include <linux/module.h>
 #include <linux/syscalls.h>
 #include <linux/fcntl.h>
@@ -30,6 +34,7 @@
 #define FRSYNC         O_RSYNC
 #define FEXCL          O_EXCL
 #define FDIRECT                O_DIRECT
+#define FAPPEND                O_APPEND
 
 #define FNODSYNC       0x10000 /* fsync pseudo flag */
 #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;
 
+#ifdef  __cplusplus
+}
+#endif
+
 #endif /* SPL_VNODE_H */
index 1005d100b8f8341ed28922fbc72f8950c921bbed..7508a3ebfa9299bf8a30e8538df698ba720928a3 100644 (file)
@@ -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 (file)
index 0000000..bce4214
--- /dev/null
@@ -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() */
index 9f48dd1a5ab0f10ee98bd8a9e022c70119787dcb..ee107d04541f744b4913e9c38e5c2c53c9ada048 100644 (file)
@@ -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;
 }
 
index c8808105b2638417abaa4ab440aea30c305a865d..50eeec13218dbf1154bf5b3439cec71147803d62 100644 (file)
@@ -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
+}
index 5776de6ddacbdd1031ce6a5f99f80b28c8348709..65cde885d65c8a72f23a729ddf73b29854f9f377 100644 (file)
@@ -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() */
index 69f38b1f577d1173d5ea1214ca5b6067f3cf0df8..b437331ad4a2d063c64ae3e8424ae5461cb1bafa 100644 (file)
@@ -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/
index e9026cd8d87b6763efc1ab500543b17b02a7a386..8c853fca5bce927f17eb318e6071b62b83080ab3 100644 (file)
@@ -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 (file)
index 0000000..e05f1c5
--- /dev/null
@@ -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() */
index aca4b3d3810129b4e064f88cf86d4fe84498edc2..4286a95715755f90be6b1ab2b5dd6b0abc0fd2c2 100644 (file)
@@ -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 */
index c24057b0e37f9b6f5050818ed66093292671cf0d..ad6c8a06c345f4285a1cde76e22cee74ae6dbe07 100644 (file)
@@ -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"