]> git.proxmox.com Git - mirror_spl.git/commitdiff
- Implemented vnode interfaces and 6 test cases to the test suite.
authorbehlendo <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c>
Wed, 12 Mar 2008 20:52:46 +0000 (20:52 +0000)
committerbehlendo <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c>
Wed, 12 Mar 2008 20:52:46 +0000 (20:52 +0000)
- Re-implmented kobj support based on the vnode support.
- Add TESTS option to check.sh, and removed delay after module load.

git-svn-id: https://outreach.scidac.gov/svn/spl/trunk@39 7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c

13 files changed:
FIXME
include/sys/kobj.h
include/sys/sysmacros.h
include/sys/uio.h
include/sys/vnode.h
modules/spl/spl-kobj.c
modules/spl/spl-vnode.c
modules/splat/Makefile.in
modules/splat/splat-ctl.c
modules/splat/splat-internal.h
modules/splat/splat-kobj.c
modules/splat/splat-vnode.c [new file with mode: 0644]
scripts/check.sh

diff --git a/FIXME b/FIXME
index d853e96ac76a6ed585078d80a614a331938ffabe..887616efbd612c408442c9e90c3809cd49b39683 100644 (file)
--- a/FIXME
+++ b/FIXME
@@ -11,8 +11,4 @@ sys/u8_textprep_data  - AlL borrowed from libsolcompat
 sys/acl.h              _ All borrowed from libsolcompat
 sys/acl_impl.h         _ All borrowed from libsolcompat
 
-* Fix failure in rw lock test 6
-
-* Non-atomic 64bit support for kstat.h
-
-* Write vnode interface
+* Implement solaris style atomic interfaces
index 306fcdcfc6a1a2a2fa5f3ce018d3fdf32f6080e1..82da951e147a63aa26ed5b30f92a1f35ca684d3c 100644 (file)
@@ -5,21 +5,16 @@
 extern "C" {
 #endif
 
-#include <linux/module.h>
-#include <linux/uaccess.h>
-#include <sys/types.h>
-#include <sys/kmem.h>
+#include <sys/vnode.h>
 
 typedef struct _buf {
-       struct file *fp;
+       vnode_t *vp;
 } _buf_t;
 
-extern void *rootdir;
-
 extern struct _buf *kobj_open_file(const char *name);
 extern void kobj_close_file(struct _buf *file);
 extern int kobj_read_file(struct _buf *file, char *buf,
-                         unsigned size, unsigned off);
+                         ssize_t size, offset_t off);
 extern int kobj_get_filesize(struct _buf *file, uint64_t *size);
 
 #ifdef  __cplusplus
index 218f595676a6a3a38c169ab57159d57232f2b7fa..076f2678497ad70541ba129dbeaaa686087e6e4a 100644 (file)
@@ -56,21 +56,6 @@ extern "C" {
 #define NICE_TO_PRIO(nice)             (MAX_RT_PRIO + (nice) + 20)
 #define PRIO_TO_NICE(prio)             ((prio) - MAX_RT_PRIO - 20)
 
-#define kred                            NULL
-
-#define FREAD                           1
-#define FWRITE                          2
-#define FCREAT  O_CREAT
-#define FTRUNC  O_TRUNC
-#define FOFFMAX O_LARGEFILE
-#define FSYNC   O_SYNC
-#define FDSYNC  O_DSYNC
-#define FRSYNC  O_RSYNC
-#define FEXCL   O_EXCL
-
-#define FNODSYNC  0x10000 /* fsync pseudo flag */
-#define FNOFOLLOW 0x20000 /* don't follow symlinks */
-
 /* Missing macros
  */
 #define PAGESIZE                        PAGE_SIZE
@@ -136,7 +121,6 @@ extern int highbit(unsigned long i);
 #define zone_dataset_visible(x, y)                     (1)
 #define INGLOBALZONE(z)                                        (1)
 
-/* XXX - Borrowed from zfs project libsolcompat/include/sys/sysmacros.h */
 /* common macros */
 #ifndef MIN
 #define MIN(a, b)       ((a) < (b) ? (a) : (b))
index 845256dc9d156783bfa6cf26d7e4b16040986b08..6da4d34ed3629c80e777576e3a38680eb6ea9cea 100644 (file)
@@ -1,7 +1,10 @@
 #ifndef _SPL_UIO_H
 #define _SPL_UIO_H
 
-typedef enum uio_rw { UIO_READ, UIO_WRITE } uio_rw_t;
+typedef enum uio_rw {
+       UIO_READ =      0,
+       UIO_WRITE =     1,
+} uio_rw_t;
 
 #define UIO_SYSSPACE 1
 
index 9d3484fcf3dc55576268e0c67976cecc3a26cc02..7583d04d428906980bba2209029a143a06064c95 100644 (file)
@@ -1,35 +1,94 @@
 #ifndef _SPL_VNODE_H
 #define _SPL_VNODE_H
 
+#include <linux/module.h>
 #include <linux/syscalls.h>
+#include <linux/fcntl.h>
+#include <linux/uaccess.h>
+#include <linux/buffer_head.h>
+#include <linux/dcache.h>
+#include <linux/namei.h>
+#include <linux/fs.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/uio.h>
 
 #define XVA_MAPSIZE     3
 #define XVA_MAGIC       0x78766174
 
+#define FREAD          1
+#define FWRITE         2
+#define FCREAT         O_CREAT
+#define FTRUNC         O_TRUNC
+#define FOFFMAX                O_LARGEFILE
+#define FSYNC          O_SYNC
+#define FDSYNC         O_DSYNC
+#define FRSYNC         O_RSYNC
+#define FEXCL          O_EXCL
+#define FDIRECT                O_DIRECT
+
+#define FNODSYNC       0x10000 /* fsync pseudo flag */
+#define FNOFOLLOW      0x20000 /* don't follow symlinks */
+
+#define AT_TYPE                0x00001
+#define AT_MODE                0x00002
+#undef  AT_UID         /* Conflicts with linux/auxvec.h */
+#define AT_UID          0x00004
+#undef  AT_GID         /* Conflicts with linux/auxvec.h */
+#define AT_GID          0x00008
+#define AT_FSID                0x00010
+#define AT_NODEID      0x00020
+#define AT_NLINK       0x00040
+#define AT_SIZE                0x00080
+#define AT_ATIME       0x00100
+#define AT_MTIME       0x00200
+#define AT_CTIME       0x00400
+#define AT_RDEV                0x00800
+#define AT_BLKSIZE     0x01000
+#define AT_NBLOCKS     0x02000
+#define AT_SEQ         0x08000
+#define AT_XVATTR      0x10000
+
+#define CRCREAT                0
+
 typedef enum vtype {
-        VNON    = 0,
-        VREG    = 1,
-        VDIR    = 2,
-        VBLK    = 3,
-        VCHR    = 4,
-        VLNK    = 5,
-        VFIFO   = 6,
-        VDOOR   = 7,
-        VPROC   = 8,
-        VSOCK   = 9,
-        VPORT   = 10,
-        VBAD    = 11
+       VNON            = 0,
+       VREG            = 1,
+       VDIR            = 2,
+       VBLK            = 3,
+       VCHR            = 4,
+       VLNK            = 5,
+       VFIFO           = 6,
+       VDOOR           = 7,
+       VPROC           = 8,
+       VSOCK           = 9,
+       VPORT           = 10,
+       VBAD            = 11
 } vtype_t;
 
 typedef struct vnode {
-        uint64_t        v_size;
-        int             v_fd;
-        mode_t          v_mode;
-        char            *v_path;
+       struct file     *v_fp;
        vtype_t         v_type;
 } vnode_t;
 
+typedef struct vattr {
+       enum vtype     va_type;      /* vnode type */
+       u_short        va_mode;      /* acc mode */
+       short          va_uid;       /* owner uid */
+       short          va_gid;       /* owner gid */
+       long           va_fsid;      /* fs id */
+       long           va_nodeid;    /* node # */
+       short          va_nlink;     /* # links */
+       u_long         va_size;      /* file size */
+       long           va_blocksize; /* block size */
+       struct timeval va_atime;     /* last acc */
+       struct timeval va_mtime;     /* last mod */
+       struct timeval va_ctime;     /* last chg */
+       dev_t          va_rdev;      /* dev */
+       long           va_blocks;    /* space used */
+} vattr_t;
 
+#if 0
 typedef struct xoptattr {
         timestruc_t     xoa_createtime; /* Create time of file */
         uint8_t         xoa_archive;
@@ -46,12 +105,6 @@ typedef struct xoptattr {
         uint8_t         xoa_av_modified;
 } xoptattr_t;
 
-typedef struct vattr {
-        uint_t          va_mask;        /* bit-mask of attributes */
-        u_offset_t      va_size;        /* file size in bytes */
-} vattr_t;
-
-
 typedef struct xvattr {
         vattr_t         xva_vattr;      /* Embedded vattr structure */
         uint32_t        xva_magic;      /* Magic Number */
@@ -70,46 +123,28 @@ typedef struct vsecattr {
         void            *vsa_dfaclentp; /* pointer to default ACL entries */
         size_t          vsa_aclentsz;   /* ACE size in bytes of vsa_aclentp */
 } vsecattr_t;
-
-#define AT_TYPE         0x00001
-#define AT_MODE         0x00002
-// #define AT_UID          0x00004     /* Conflicts with linux/auxvec.h */
-// #define AT_GID          0x00008     /* Conflicts with linux/auxvec.h */
-#define AT_FSID         0x00010
-#define AT_NODEID       0x00020
-#define AT_NLINK        0x00040
-#define AT_SIZE         0x00080
-#define AT_ATIME        0x00100
-#define AT_MTIME        0x00200
-#define AT_CTIME        0x00400
-#define AT_RDEV         0x00800
-#define AT_BLKSIZE      0x01000
-#define AT_NBLOCKS      0x02000
-#define AT_SEQ          0x08000
-#define AT_XVATTR       0x10000
-
-#define CRCREAT         0
-
-#define VOP_CLOSE(vp, f, c, o, cr, ct)  0
-#define VOP_PUTPAGE(vp, of, sz, fl, cr, ct)     0
-#define VOP_GETATTR(vp, vap, fl, cr, ct)  ((vap)->va_size = (vp)->v_size, 0)
-
-#define VOP_FSYNC(vp, f, cr, ct)        sys_fsync((vp)->v_fd)
-
-#define VN_RELE(vp)     vn_close(vp)
-
-extern int vn_open(char *path, int x1, int oflags, int mode, vnode_t **vpp,
-    int x2, int x3);
-extern int vn_openat(char *path, int x1, int oflags, int mode, vnode_t **vpp,
-    int x2, int x3, vnode_t *vp, int fd);
-extern int vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len,
-    offset_t offset, int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp);
-extern void vn_close(vnode_t *vp);
-
-#define vn_remove(path, x1, x2)         remove(path)
-#define vn_rename(from, to, seg)        rename((from), (to))
-#define vn_is_readonly(vp)              B_FALSE
-
-extern vnode_t *rootdir;
+#endif
+
+extern int vn_open(const char *path, int seg, int flags, int mode,
+                  vnode_t **vpp, int x1, void *x2);
+extern int vn_openat(const char *path, int seg, int flags, int mode,
+                    vnode_t **vpp, int x1, void *x2, vnode_t *vp, int fd);
+extern int vn_rdwr(uio_rw_t uio, vnode_t *vp, void *addr, ssize_t len,
+                  offset_t off, int seg, int x1, rlim64_t x2,
+                  void *x3, ssize_t *residp);
+extern int vn_close(vnode_t *vp, int flags, int x1, int x2, int x3, int x4);
+extern int vn_remove(const char *path, int x1, int x2);
+extern int vn_rename(const char *path1, const char *path2, int x1);
+extern int vn_getattr(vnode_t *vp, vattr_t *vap, int flags, int x3, void *x4);
+extern int vn_fsync(vnode_t *vp, int flags, int x3, int x4);
+
+#define VOP_CLOSE                              vn_close
+#define VN_RELE(vp)
+#define VOP_GETATTR                            vn_getattr
+#define VOP_FSYNC                              vn_fsync
+#define VOP_PUTPAGE(vp, of, sz, fl, cr, ct)
+#define vn_is_readonly(vp)                     0
+
+extern void *rootdir;
 
 #endif /* SPL_VNODE_H */
index ce0625b9f19429a928723d396eeced72c1fcf1a5..eb55ad3e182e16b8ad16128e573f92406061b23a 100644 (file)
@@ -1,21 +1,18 @@
 #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;
+       vnode_t *vp;
+       int rc;
 
-       fp = filp_open(name, O_RDONLY, 0644);
-       if (IS_ERR(fp))
+       if ((rc = vn_open(name, UIO_SYSSPACE, FREAD, 0644, &vp, 0, 0)))
                return ((_buf_t *)-1UL);
 
-       file = kmem_zalloc(sizeof(_buf_t), KM_SLEEP);
-       file->fp = fp;
+       file = kmalloc(sizeof(_buf_t), GFP_KERNEL);
+       file->vp = vp;
 
        return file;
 } /* kobj_open_file() */
@@ -24,52 +21,34 @@ EXPORT_SYMBOL(kobj_open_file);
 void
 kobj_close_file(struct _buf *file)
 {
-        filp_close(file->fp, 0);
-        kmem_free(file, sizeof(_buf_t));
+       VOP_CLOSE(file->vp, 0, 0, 0, 0, 0);
+       VN_RELE(file->vp);
+        kfree(file);
 
        return;
 } /* kobj_close_file() */
 EXPORT_SYMBOL(kobj_close_file);
 
 int
-kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
+kobj_read_file(struct _buf *file, char *buf, ssize_t size, offset_t 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;
+       return vn_rdwr(UIO_READ, file->vp, buf, size, off,
+                      UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
 } /* kobj_read_file() */
 EXPORT_SYMBOL(kobj_read_file);
 
 int
 kobj_get_filesize(struct _buf *file, uint64_t *size)
 {
-        struct kstat stat;
+        vattr_t vap;
        int rc;
 
-       if (!file || !file->fp || !size)
-               return -EINVAL;
-
-        rc = vfs_getattr(file->fp->f_vfsmnt, file->fp->f_dentry, &stat);
+       rc = VOP_GETATTR(file->vp, &vap, 0, 0, NULL);
        if (rc)
                return rc;
 
-        *size = stat.size;
+        *size = vap.va_size;
+
         return rc;
 } /* kobj_get_filesize() */
 EXPORT_SYMBOL(kobj_get_filesize);
index 5089f85672bfa2c761d3562bf60df18832c21928..9024909b8779ac41f4c017a3b023152bd570c79f 100644 (file)
 #include <sys/sysmacros.h>
+#include <sys/vnode.h>
 #include "config.h"
 
-/*
- * XXX: currently borrrowed from libsolcompat until this
- * can be adapted to the linux kernel interfaces.
- */
-#if 0
-/*
- * =========================================================================
- * vnode operations
- * =========================================================================
- */
-/*
- * Note: for the xxxat() versions of these functions, we assume that the
- * starting vp is always rootdir (which is true for spa_directory.c, the only
- * ZFS consumer of these interfaces).  We assert this is true, and then emulate
- * them by adding '/' in front of the path.
- */
-
-/*ARGSUSED*/
+void *rootdir = NULL;
+EXPORT_SYMBOL(rootdir);
+
+static vtype_t
+vn_get_sol_type(umode_t mode)
+{
+       if (S_ISREG(mode))
+               return VREG;
+
+       if (S_ISDIR(mode))
+               return VDIR;
+
+       if (S_ISCHR(mode))
+               return VCHR;
+
+       if (S_ISBLK(mode))
+               return VBLK;
+
+       if (S_ISFIFO(mode))
+               return VFIFO;
+
+       if (S_ISLNK(mode))
+               return VLNK;
+
+       if (S_ISSOCK(mode))
+               return VSOCK;
+
+       if (S_ISCHR(mode))
+               return VCHR;
+
+       return VNON;
+} /* vn_get_sol_type() */
+
 int
-vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
+vn_open(const char *path, int seg, int flags, int mode,
+       vnode_t **vpp, int x1, void *x2)
 {
-       int fd;
+        struct file *fp;
+        struct kstat stat;
+        int rc, saved_umask, flags_rw;
        vnode_t *vp;
-       int old_umask;
-       char realpath[MAXPATHLEN];
-       struct stat64 st;
-
-       /*
-        * If we're accessing a real disk from userland, we need to use
-        * the character interface to avoid caching.  This is particularly
-        * important if we're trying to look at a real in-kernel storage
-        * pool from userland, e.g. via zdb, because otherwise we won't
-        * see the changes occurring under the segmap cache.
-        * On the other hand, the stupid character device returns zero
-        * for its size.  So -- gag -- we open the block device to get
-        * its size, and remember it for subsequent VOP_GETATTR().
-        */
-#if defined(__sun__) || defined(__sun)
-       if (strncmp(path, "/dev/", 5) == 0) {
-#else
-       if (0) {
-#endif
-               char *dsk;
-               fd = open64(path, O_RDONLY);
-               if (fd == -1)
-                       return (errno);
-               if (fstat64(fd, &st) == -1) {
-                       close(fd);
-                       return (errno);
-               }
-               close(fd);
-               (void) sprintf(realpath, "%s", path);
-               dsk = strstr(path, "/dsk/");
-               if (dsk != NULL)
-                       (void) sprintf(realpath + (dsk - path) + 1, "r%s",
-                           dsk + 1);
-       } else {
-               (void) sprintf(realpath, "%s", path);
-               if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
-                       return (errno);
-       }
 
-#ifdef __linux__
-       if (!(flags & FCREAT) && S_ISBLK(st.st_mode)) {
-               flags |= O_DIRECT;
-               if (flags & FWRITE)
-                       flags |= O_EXCL;
+       BUG_ON(seg != UIO_SYSSPACE);
+       BUG_ON(!vpp);
+       *vpp = NULL;
+
+       if (!(flags & FCREAT) && (flags & FWRITE))
+               flags |= FEXCL;
+
+       flags_rw = flags & (FWRITE | FREAD);
+       flags &= ~(FWRITE | FREAD);
+       switch (flags_rw) {
+               case FWRITE:            flags |= O_WRONLY;
+               case FREAD:             flags |= O_RDONLY;
+               case (FWRITE | FREAD):  flags |= O_RDWR;
        }
-#endif
 
        if (flags & FCREAT)
-               old_umask = umask(0);
+               saved_umask = xchg(&current->fs->umask, 0);
 
-       /*
-        * The construct 'flags - FREAD' conveniently maps combinations of
-        * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
-        */
-       fd = open64(realpath, flags - FREAD, mode);
+        fp = filp_open(path, flags, mode);
 
        if (flags & FCREAT)
-               (void) umask(old_umask);
+               (void)xchg(&current->fs->umask, saved_umask);
 
-       if (fd == -1)
-               return (errno);
+        if (IS_ERR(fp))
+               return PTR_ERR(fp);
 
-       if (fstat64(fd, &st) == -1) {
-               close(fd);
-               return (errno);
+        rc = vfs_getattr(fp->f_vfsmnt, fp->f_dentry, &stat);
+       if (rc) {
+               filp_close(fp, 0);
+               return rc;
        }
 
-       (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
-
-       *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
+       vp = kmalloc(sizeof(vnode_t), GFP_ATOMIC);
+       if (!vp) {
+               filp_close(fp, 0);
+               return -ENOMEM;
+       }
 
-       vp->v_fd = fd;
-       vp->v_size = st.st_size;
-       vp->v_mode = st.st_mode;
-       vp->v_path = spa_strdup(path);
+       vp->v_type = vn_get_sol_type(stat.mode);
+       vp->v_fp = fp;
+       *vpp = vp;
 
-       return (0);
-}
+       return 0;
+} /* vn_open() */
+EXPORT_SYMBOL(vn_open);
 
-/*ARGSUSED*/
 int
-vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
-    int x3, vnode_t *startvp, int fd)
+vn_openat(const char *path, int seg, int flags, int mode,
+         vnode_t **vpp, int x1, void *x2, vnode_t *vp, int fd)
 {
-       char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
-       int ret;
+       char *realpath;
+       int rc;
 
-       ASSERT(startvp == rootdir);
-       (void) sprintf(realpath, "/%s", path);
+       BUG_ON(vp != rootdir);
 
-       /* fd ignored for now, need if want to simulate nbmand support */
-       ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
+       realpath = kmalloc(strlen(path) + 2, GFP_KERNEL);
+       if (!realpath)
+               return -ENOMEM;
 
-       umem_free(realpath, strlen(path) + 2);
+       sprintf(realpath, "/%s", path);
+       rc = vn_open(realpath, seg, flags, mode, vpp, x1, x2);
 
-       return (ret);
-}
+       kfree(realpath);
+
+       return rc;
+} /* vn_openat() */
+EXPORT_SYMBOL(vn_openat);
 
-/*ARGSUSED*/
 int
-vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
-       int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
+vn_rdwr(uio_rw_t uio, vnode_t *vp, void *addr, ssize_t len, offset_t off,
+       int seg, int x1, rlim64_t x2, void *x3, ssize_t *residp)
 {
-       ssize_t iolen, split;
+       loff_t offset;
+       mm_segment_t saved_fs;
+       struct file *fp;
+       int rc;
+
+       BUG_ON(!(uio == UIO_WRITE || uio == UIO_READ));
+       BUG_ON(!vp);
+       BUG_ON(!vp->v_fp);
+       BUG_ON(seg != UIO_SYSSPACE);
+       BUG_ON(x1 != 0);
+       BUG_ON(x2 != RLIM64_INFINITY);
+
+       offset = off;
+       fp = vp->v_fp;
+
+       /* 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());
+
+       if (uio & UIO_WRITE)
+               rc = vfs_write(fp, addr, len, &offset);
+       else
+               rc = vfs_read(fp, addr, len, &offset);
+
+       set_fs(saved_fs);
+
+       if (rc < 0)
+               return rc;
 
-       if (uio == UIO_READ) {
-               iolen = pread64(vp->v_fd, addr, len, offset);
+       if (residp) {
+               *residp = len - rc;
        } else {
-               /*
-                * To simulate partial disk writes, we split writes into two
-                * system calls so that the process can be killed in between.
-                */
-#ifdef ZFS_DEBUG
-               if (!S_ISBLK(vp->v_mode) && !S_ISCHR(vp->v_mode)) {
-                       split = (len > 0 ? rand() % len : 0);
-                       iolen = pwrite64(vp->v_fd, addr, split, offset);
-                       iolen += pwrite64(vp->v_fd, (char *)addr + split,
-                           len - split, offset + split);
-               } else
-                       iolen = pwrite64(vp->v_fd, addr, len, offset);
-#else
-               iolen = pwrite64(vp->v_fd, addr, len, offset);
-#endif
+               if (rc != len)
+                       return -EIO;
        }
 
-       if (iolen < 0)
-               return (errno);
-       if (residp)
-               *residp = len - iolen;
-       else if (iolen != len)
-               return (EIO);
-       return (0);
+       return 0;
+} /* vn_rdwr() */
+EXPORT_SYMBOL(vn_rdwr);
+
+int
+vn_close(vnode_t *vp, int flags, int x1, int x2, int x3, int x4)
+{
+       int rc;
+
+       BUG_ON(!vp);
+       BUG_ON(!vp->v_fp);
+
+        rc = filp_close(vp->v_fp, 0);
+        kfree(vp);
+
+       return rc;
+} /* vn_close() */
+EXPORT_SYMBOL(vn_close);
+
+static struct dentry *lookup_hash(struct nameidata *nd)
+{
+       return __lookup_hash(&nd->last, nd->dentry, nd);
+} /* lookup_hash() */
+
+/* Modified do_unlinkat() from linux/fs/namei.c, only uses exported symbols */
+int
+vn_remove(const char *path, int x1, int x2)
+{
+        struct dentry *dentry;
+        struct nameidata nd;
+        struct inode *inode = NULL;
+        int rc = 0;
+
+        rc = path_lookup(path, LOOKUP_PARENT, &nd);
+        if (rc)
+                goto exit;
+
+        rc = -EISDIR;
+        if (nd.last_type != LAST_NORM)
+                goto exit1;
+
+        mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
+        dentry = lookup_hash(&nd);
+        rc = PTR_ERR(dentry);
+        if (!IS_ERR(dentry)) {
+                /* Why not before? Because we want correct rc value */
+                if (nd.last.name[nd.last.len])
+                        goto slashes;
+                inode = dentry->d_inode;
+                if (inode)
+                        atomic_inc(&inode->i_count);
+                rc = vfs_unlink(nd.dentry->d_inode, dentry);
+exit2:
+                dput(dentry);
+        }
+        mutex_unlock(&nd.dentry->d_inode->i_mutex);
+        if (inode)
+                iput(inode);    /* truncate the inode here */
+exit1:
+        path_release(&nd);
+exit:
+        return rc;
+
+slashes:
+        rc = !dentry->d_inode ? -ENOENT :
+                S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR;
+        goto exit2;
+} /* vn_remove() */
+EXPORT_SYMBOL(vn_remove);
+
+/* Modified do_rename() from linux/fs/namei.c, only uses exported symbols */
+int
+vn_rename(const char *oldname, const char *newname, int x1)
+{
+        struct dentry * old_dir, * new_dir;
+        struct dentry * old_dentry, *new_dentry;
+        struct dentry * trap;
+        struct nameidata oldnd, newnd;
+        int rc = 0;
+
+        rc = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
+        if (rc)
+                goto exit;
+
+        rc = path_lookup(newname, LOOKUP_PARENT, &newnd);
+        if (rc)
+                goto exit1;
+
+        rc = -EXDEV;
+        if (oldnd.mnt != newnd.mnt)
+                goto exit2;
+
+        old_dir = oldnd.dentry;
+        rc = -EBUSY;
+        if (oldnd.last_type != LAST_NORM)
+                goto exit2;
+
+        new_dir = newnd.dentry;
+        if (newnd.last_type != LAST_NORM)
+                goto exit2;
+
+        trap = lock_rename(new_dir, old_dir);
+
+        old_dentry = lookup_hash(&oldnd);
+
+        rc = PTR_ERR(old_dentry);
+        if (IS_ERR(old_dentry))
+                goto exit3;
+
+        /* source must exist */
+        rc = -ENOENT;
+        if (!old_dentry->d_inode)
+                goto exit4;
+
+        /* unless the source is a directory trailing slashes give -ENOTDIR */
+        if (!S_ISDIR(old_dentry->d_inode->i_mode)) {
+                rc = -ENOTDIR;
+                if (oldnd.last.name[oldnd.last.len])
+                        goto exit4;
+                if (newnd.last.name[newnd.last.len])
+                        goto exit4;
+        }
+
+        /* source should not be ancestor of target */
+        rc = -EINVAL;
+        if (old_dentry == trap)
+                goto exit4;
+
+        new_dentry = lookup_hash(&newnd);
+        rc = PTR_ERR(new_dentry);
+        if (IS_ERR(new_dentry))
+                goto exit4;
+
+        /* target should not be an ancestor of source */
+        rc = -ENOTEMPTY;
+        if (new_dentry == trap)
+                goto exit5;
+
+        rc = vfs_rename(old_dir->d_inode, old_dentry,
+                        new_dir->d_inode, new_dentry);
+exit5:
+        dput(new_dentry);
+exit4:
+        dput(old_dentry);
+exit3:
+        unlock_rename(new_dir, old_dir);
+exit2:
+        path_release(&newnd);
+exit1:
+        path_release(&oldnd);
+exit:
+        return rc;
 }
+EXPORT_SYMBOL(vn_rename);
 
-void
-vn_close(vnode_t *vp)
+int
+vn_getattr(vnode_t *vp, vattr_t *vap, int flags, int x3, void *x4)
 {
-       close(vp->v_fd);
-       spa_strfree(vp->v_path);
-       umem_free(vp, sizeof (vnode_t));
+       struct file *fp;
+        struct kstat stat;
+       int rc;
+
+       BUG_ON(!vp);
+       BUG_ON(!vp->v_fp);
+       BUG_ON(!vap);
+
+       fp = vp->v_fp;
+
+        rc = vfs_getattr(fp->f_vfsmnt, fp->f_dentry, &stat);
+       if (rc)
+               return rc;
+
+       vap->va_type          = vn_get_sol_type(stat.mode);
+       vap->va_mode          = stat.mode;
+       vap->va_uid           = stat.uid;
+       vap->va_gid           = stat.gid;
+       vap->va_fsid          = 0;
+       vap->va_nodeid        = stat.ino;
+       vap->va_nlink         = stat.nlink;
+        vap->va_size          = stat.size;
+       vap->va_blocksize     = stat.blksize;
+       vap->va_atime.tv_sec  = stat.atime.tv_sec;
+       vap->va_atime.tv_usec = stat.atime.tv_nsec / NSEC_PER_USEC;
+       vap->va_mtime.tv_sec  = stat.mtime.tv_sec;
+       vap->va_mtime.tv_usec = stat.mtime.tv_nsec / NSEC_PER_USEC;
+       vap->va_ctime.tv_sec  = stat.ctime.tv_sec;
+       vap->va_ctime.tv_usec = stat.ctime.tv_nsec / NSEC_PER_USEC;
+       vap->va_rdev          = stat.rdev;
+       vap->va_blocks        = stat.blocks;
+
+        return rc;
 }
-#endif
+EXPORT_SYMBOL(vn_getattr);
+
+int vn_fsync(vnode_t *vp, int flags, int x3, int x4)
+{
+       BUG_ON(!vp);
+       BUG_ON(!vp->v_fp);
+
+       return file_fsync(vp->v_fp, vp->v_fp->f_dentry, 0);
+} /* vn_fsync() */
+EXPORT_SYMBOL(vn_fsync);
index 0c7526f1976f1902030f9402cf892654f3a7f4ba..69f38b1f577d1173d5ea1214ca5b6067f3cf0df8 100644 (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-vnode.o
 splat-objs += splat-kobj.o
 
 splatmodule := splat.ko
index 693277c5cfc294bbf95fcb66affd2ac1ce5b9fed..e9026cd8d87b6763efc1ab500543b17b02a7a386 100644 (file)
@@ -591,6 +591,7 @@ splat_init(void)
        SPLAT_SUBSYSTEM_INIT(thread);
        SPLAT_SUBSYSTEM_INIT(rwlock);
        SPLAT_SUBSYSTEM_INIT(time);
+       SPLAT_SUBSYSTEM_INIT(vnode);
        SPLAT_SUBSYSTEM_INIT(kobj);
 
        dev = MKDEV(SPLAT_MAJOR, 0);
@@ -654,6 +655,7 @@ splat_fini(void)
         unregister_chrdev_region(dev, SPLAT_MINORS);
 
        SPLAT_SUBSYSTEM_FINI(kobj);
+       SPLAT_SUBSYSTEM_FINI(vnode);
        SPLAT_SUBSYSTEM_FINI(time);
        SPLAT_SUBSYSTEM_FINI(rwlock);
        SPLAT_SUBSYSTEM_FINI(thread);
index b8e8032904a4dc7a422b6c2e5b338498504c0bb9..aca4b3d3810129b4e064f88cf86d4fe84498edc2 100644 (file)
@@ -170,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_vnode_init(void);
 splat_subsystem_t * splat_kobj_init(void);
 
 void splat_condvar_fini(splat_subsystem_t *);
@@ -180,6 +181,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_vnode_fini(splat_subsystem_t *);
 void splat_kobj_fini(splat_subsystem_t *);
 
 int splat_condvar_id(void);
@@ -190,6 +192,7 @@ int splat_rwlock_id(void);
 int splat_taskq_id(void);
 int splat_thread_id(void);
 int splat_time_id(void);
+int splat_vnode_id(void);
 int splat_kobj_id(void);
 
 #endif /* _SPLAT_INTERNAL_H */
index 91f591f462647207ba4a76430994ad4bffca84e3..c24057b0e37f9b6f5050818ed66093292671cf0d 100644 (file)
@@ -1,15 +1,15 @@
 #include "splat-internal.h"
 
-#define SPLAT_SUBSYSTEM_KOBJ           0x0900
+#define SPLAT_SUBSYSTEM_KOBJ           0x0a00
 #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_ID            0x0a01
+#define SPLAT_KOBJ_TEST1_NAME          "open"
 #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_ID            0x0a02
+#define SPLAT_KOBJ_TEST2_NAME          "size/read"
 #define SPLAT_KOBJ_TEST2_DESC          "File Size/Read Test"
 
 #define SPLAT_KOBJ_TEST_FILE           "/etc/fstab"
diff --git a/modules/splat/splat-vnode.c b/modules/splat/splat-vnode.c
new file mode 100644 (file)
index 0000000..188448d
--- /dev/null
@@ -0,0 +1,372 @@
+#include "splat-internal.h"
+
+#define SPLAT_SUBSYSTEM_VNODE          0x0900
+#define SPLAT_VNODE_NAME               "vnode"
+#define SPLAT_VNODE_DESC               "Kernel Vnode Tests"
+
+#define SPLAT_VNODE_TEST1_ID           0x0901
+#define SPLAT_VNODE_TEST1_NAME         "vn_open"
+#define SPLAT_VNODE_TEST1_DESC         "Vn_open Test"
+
+#define SPLAT_VNODE_TEST2_ID           0x0902
+#define SPLAT_VNODE_TEST2_NAME         "vn_openat"
+#define SPLAT_VNODE_TEST2_DESC         "Vn_openat Test"
+
+#define SPLAT_VNODE_TEST3_ID           0x0903
+#define SPLAT_VNODE_TEST3_NAME         "vn_rdwr"
+#define SPLAT_VNODE_TEST3_DESC         "Vn_rdwrt Test"
+
+#define SPLAT_VNODE_TEST4_ID           0x0904
+#define SPLAT_VNODE_TEST4_NAME         "vn_rename"
+#define SPLAT_VNODE_TEST4_DESC         "Vn_rename Test"
+
+#define SPLAT_VNODE_TEST5_ID           0x0905
+#define SPLAT_VNODE_TEST5_NAME         "vn_getattr"
+#define SPLAT_VNODE_TEST5_DESC         "Vn_getattr Test"
+
+#define SPLAT_VNODE_TEST6_ID           0x0906
+#define SPLAT_VNODE_TEST6_NAME         "vn_sync"
+#define SPLAT_VNODE_TEST6_DESC         "Vn_sync Test"
+
+#define SPLAT_VNODE_TEST_FILE          "/etc/fstab"
+#define SPLAT_VNODE_TEST_FILE_AT       "etc/fstab"
+#define SPLAT_VNODE_TEST_FILE_RW       "/tmp/spl.vnode.tmp"
+#define SPLAT_VNODE_TEST_FILE_RW1      "/tmp/spl.vnode.tmp.1"
+#define SPLAT_VNODE_TEST_FILE_RW2      "/tmp/spl.vnode.tmp.2"
+
+static int
+splat_vnode_test1(struct file *file, void *arg)
+{
+       vnode_t *vp;
+       int rc;
+
+       if ((rc = vn_open(SPLAT_VNODE_TEST_FILE, UIO_SYSSPACE,
+                         FREAD, 0644, &vp, 0, 0))) {
+               splat_vprint(file, SPLAT_VNODE_TEST1_NAME,
+                            "Failed to vn_open test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE, rc);
+               return rc;
+       }
+
+        rc = VOP_CLOSE(vp, 0, 0, 0, 0, 0);
+        VN_RELE(vp);
+
+       if (rc) {
+               splat_vprint(file, SPLAT_VNODE_TEST1_NAME,
+                            "Failed to vn_close test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE, rc);
+               return rc;
+       }
+
+       splat_vprint(file, SPLAT_VNODE_TEST1_NAME, "Successfully vn_open'ed "
+                    "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE);
+
+        return rc;
+} /* splat_vnode_test1() */
+
+static int
+splat_vnode_test2(struct file *file, void *arg)
+{
+       vnode_t *vp;
+       int rc;
+
+       if ((rc = vn_openat(SPLAT_VNODE_TEST_FILE_AT, UIO_SYSSPACE,
+                           FREAD, 0644, &vp, 0, 0, rootdir, 0))) {
+               splat_vprint(file, SPLAT_VNODE_TEST2_NAME,
+                            "Failed to vn_openat test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE, rc);
+               return rc;
+       }
+
+        rc = VOP_CLOSE(vp, 0, 0, 0, 0, 0);
+        VN_RELE(vp);
+
+       if (rc) {
+               splat_vprint(file, SPLAT_VNODE_TEST2_NAME,
+                            "Failed to vn_close test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE, rc);
+               return rc;
+       }
+
+       splat_vprint(file, SPLAT_VNODE_TEST2_NAME, "Successfully vn_openat'ed "
+                    "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE);
+
+        return rc;
+} /* splat_vnode_test2() */
+
+static int
+splat_vnode_test3(struct file *file, void *arg)
+{
+       vnode_t *vp;
+       char buf1[32] = "SPL VNode Interface Test File\n";
+       char buf2[32] = "";
+       int rc;
+
+       if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE,
+                         FWRITE | FREAD | FCREAT | FEXCL,
+                         0644, &vp, 0, 0))) {
+               splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
+                            "Failed to vn_open test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE_RW, rc);
+               return rc;
+       }
+
+        rc = vn_rdwr(UIO_WRITE, vp, buf1, strlen(buf1), 0,
+                     UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
+       if (rc < 0) {
+               splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
+                            "Failed vn_rdwr write of test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE_RW, rc);
+               goto out;
+       }
+
+        rc = vn_rdwr(UIO_READ, vp, buf2, strlen(buf1), 0,
+                     UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
+       if (rc < 0) {
+               splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
+                            "Failed vn_rdwr read of test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE_RW, rc);
+               goto out;
+       }
+
+       if (strncmp(buf1, buf2, strlen(buf1))) {
+               rc = EINVAL;
+               splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
+                            "Failed strncmp data written does not match "
+                            "data read\nWrote: %sRead:  %s\n", buf1, buf2);
+               goto out;
+       }
+
+       rc = 0;
+       splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Wrote: %s", buf1);
+       splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Read:  %s", buf2);
+       splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Successfully wrote and "
+                    "read expected data pattern to test file: %s\n",
+                    SPLAT_VNODE_TEST_FILE_RW);
+
+out:
+        VOP_CLOSE(vp, 0, 0, 0, 0, 0);
+        VN_RELE(vp);
+       vn_remove(SPLAT_VNODE_TEST_FILE_RW, 0, 0);
+
+        return rc;
+} /* splat_vnode_test3() */
+
+static int
+splat_vnode_test4(struct file *file, void *arg)
+{
+       vnode_t *vp;
+       char buf1[32] = "SPL VNode Interface Test File\n";
+       char buf2[32] = "";
+       int rc;
+
+       if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW1, UIO_SYSSPACE,
+                         FWRITE | FREAD | FCREAT | FEXCL, 0644, &vp, 0, 0))) {
+               splat_vprint(file, SPLAT_VNODE_TEST4_NAME,
+                            "Failed to vn_open test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE_RW1, rc);
+               goto out;
+       }
+
+        rc = vn_rdwr(UIO_WRITE, vp, buf1, strlen(buf1), 0,
+                     UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
+       if (rc < 0) {
+               splat_vprint(file, SPLAT_VNODE_TEST4_NAME,
+                            "Failed vn_rdwr write of test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE_RW1, rc);
+               goto out2;
+       }
+
+        VOP_CLOSE(vp, 0, 0, 0, 0, 0);
+        VN_RELE(vp);
+
+       rc = vn_rename(SPLAT_VNODE_TEST_FILE_RW1,SPLAT_VNODE_TEST_FILE_RW2,0);
+       if (rc) {
+               splat_vprint(file, SPLAT_VNODE_TEST4_NAME, "Failed vn_rename "
+                            "%s -> %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE_RW1,
+                            SPLAT_VNODE_TEST_FILE_RW2, rc);
+               goto out;
+       }
+
+       if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW2, UIO_SYSSPACE,
+                         FREAD | FEXCL, 0644, &vp, 0, 0))) {
+               splat_vprint(file, SPLAT_VNODE_TEST4_NAME,
+                            "Failed to vn_open test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE_RW2, rc);
+               goto out;
+       }
+
+        rc = vn_rdwr(UIO_READ, vp, buf2, strlen(buf1), 0,
+                     UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
+       if (rc < 0) {
+               splat_vprint(file, SPLAT_VNODE_TEST4_NAME,
+                            "Failed vn_rdwr read of test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE_RW2, rc);
+               goto out2;
+       }
+
+       if (strncmp(buf1, buf2, strlen(buf1))) {
+               rc = EINVAL;
+               splat_vprint(file, SPLAT_VNODE_TEST4_NAME,
+                            "Failed strncmp data written does not match "
+                            "data read\nWrote: %sRead:  %s\n", buf1, buf2);
+               goto out2;
+       }
+
+       rc = 0;
+       splat_vprint(file, SPLAT_VNODE_TEST4_NAME, "Wrote to %s:  %s",
+                    SPLAT_VNODE_TEST_FILE_RW1, buf1);
+       splat_vprint(file, SPLAT_VNODE_TEST4_NAME, "Read from %s: %s",
+                    SPLAT_VNODE_TEST_FILE_RW2, buf2);
+       splat_vprint(file, SPLAT_VNODE_TEST4_NAME, "Successfully renamed "
+                    "test file %s -> %s and verified data pattern\n",
+                    SPLAT_VNODE_TEST_FILE_RW1, SPLAT_VNODE_TEST_FILE_RW2);
+out2:
+        VOP_CLOSE(vp, 0, 0, 0, 0, 0);
+        VN_RELE(vp);
+out:
+       vn_remove(SPLAT_VNODE_TEST_FILE_RW1, 0, 0);
+       vn_remove(SPLAT_VNODE_TEST_FILE_RW2, 0, 0);
+
+        return rc;
+} /* splat_vnode_test4() */
+
+static int
+splat_vnode_test5(struct file *file, void *arg)
+{
+       vnode_t *vp;
+       vattr_t vap;
+       int rc;
+
+       if ((rc = vn_open(SPLAT_VNODE_TEST_FILE, UIO_SYSSPACE,
+                         FREAD, 0644, &vp, 0, 0))) {
+               splat_vprint(file, SPLAT_VNODE_TEST5_NAME,
+                            "Failed to vn_open test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE, rc);
+               return rc;
+       }
+
+       rc = VOP_GETATTR(vp, &vap, 0, 0, NULL);
+       if (rc) {
+               splat_vprint(file, SPLAT_VNODE_TEST5_NAME,
+                            "Failed to vn_getattr test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE, rc);
+               goto out;
+       }
+
+       if (vap.va_type != VREG) {
+               rc = -EINVAL;
+               splat_vprint(file, SPLAT_VNODE_TEST5_NAME,
+                            "Failed expected regular file type "
+                            "(%d != VREG): %s (%d)\n", vap.va_type,
+                            SPLAT_VNODE_TEST_FILE, rc);
+               goto out;
+       }
+
+       splat_vprint(file, SPLAT_VNODE_TEST1_NAME, "Successfully "
+                    "vn_getattr'ed test file: %s\n", SPLAT_VNODE_TEST_FILE);
+
+out:
+        VOP_CLOSE(vp, 0, 0, 0, 0, 0);
+        VN_RELE(vp);
+
+        return rc;
+} /* splat_vnode_test5() */
+
+static int
+splat_vnode_test6(struct file *file, void *arg)
+{
+       vnode_t *vp;
+       char buf[32] = "SPL VNode Interface Test File\n";
+       int rc;
+
+       if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE,
+                         FWRITE | FREAD | FCREAT | FEXCL, 0644, &vp, 0, 0))) {
+               splat_vprint(file, SPLAT_VNODE_TEST6_NAME,
+                            "Failed to vn_open test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE_RW, rc);
+               return rc;
+       }
+
+        rc = vn_rdwr(UIO_WRITE, vp, buf, strlen(buf), 0,
+                     UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
+       if (rc < 0) {
+               splat_vprint(file, SPLAT_VNODE_TEST6_NAME,
+                            "Failed vn_rdwr write of test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE_RW, rc);
+               goto out;
+       }
+
+       rc = vn_fsync(vp, 0, 0, 0);
+       if (rc) {
+               splat_vprint(file, SPLAT_VNODE_TEST6_NAME,
+                            "Failed vn_fsync of test file: %s (%d)\n",
+                            SPLAT_VNODE_TEST_FILE_RW, rc);
+               goto out;
+       }
+
+       rc = 0;
+       splat_vprint(file, SPLAT_VNODE_TEST6_NAME, "Successfully "
+                    "fsync'ed test file %s\n", SPLAT_VNODE_TEST_FILE_RW);
+out:
+        VOP_CLOSE(vp, 0, 0, 0, 0, 0);
+        VN_RELE(vp);
+       vn_remove(SPLAT_VNODE_TEST_FILE_RW, 0, 0);
+
+        return rc;
+} /* splat_vnode_test4() */
+
+splat_subsystem_t *
+splat_vnode_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_VNODE_NAME, SPLAT_NAME_SIZE);
+       strncpy(sub->desc.desc, SPLAT_VNODE_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_VNODE;
+
+        SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST1_NAME, SPLAT_VNODE_TEST1_DESC,
+                       SPLAT_VNODE_TEST1_ID, splat_vnode_test1);
+        SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST2_NAME, SPLAT_VNODE_TEST2_DESC,
+                       SPLAT_VNODE_TEST2_ID, splat_vnode_test2);
+        SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST3_NAME, SPLAT_VNODE_TEST3_DESC,
+                       SPLAT_VNODE_TEST3_ID, splat_vnode_test3);
+        SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST4_NAME, SPLAT_VNODE_TEST4_DESC,
+                       SPLAT_VNODE_TEST4_ID, splat_vnode_test4);
+        SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST5_NAME, SPLAT_VNODE_TEST5_DESC,
+                       SPLAT_VNODE_TEST5_ID, splat_vnode_test5);
+        SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST6_NAME, SPLAT_VNODE_TEST6_DESC,
+                       SPLAT_VNODE_TEST6_ID, splat_vnode_test6);
+
+        return sub;
+} /* splat_vnode_init() */
+
+void
+splat_vnode_fini(splat_subsystem_t *sub)
+{
+        ASSERT(sub);
+
+        SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST6_ID);
+        SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST5_ID);
+        SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST4_ID);
+        SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST3_ID);
+        SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST2_ID);
+        SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST1_ID);
+
+        kfree(sub);
+} /* splat_vnode_fini() */
+
+int
+splat_vnode_id(void)
+{
+        return SPLAT_SUBSYSTEM_VNODE;
+} /* splat_vnode_id() */
index 5d712368418297c250f15ab2611c705f8c1e3de7..3b8b758017ba28ad1344e534b01f203463cdbae9 100755 (executable)
@@ -19,6 +19,12 @@ if [ -n "$V" ]; then
        verbose="-v"
 fi
 
+if [ -n "$TESTS" ]; then
+       tests="$TESTS"
+else
+       tests="-a"
+fi
+
 if [ $(id -u) != 0 ]; then
        die "Must run as root"
 fi
@@ -37,8 +43,8 @@ echo "Loading ${spl_module}"
 echo "Loading ${splat_module}"
 /sbin/insmod ${splat_module} || die "Unable to load ${splat_module}"
 
-sleep 3
-$splat_cmd -a $verbose
+while [ ! -c /dev/splatctl ]; do sleep 0.1; done
+$splat_cmd $tests $verbose
 
 echo "Unloading ${splat_module}"
 /sbin/rmmod ${splat_module} || die "Failed to unload ${splat_module}"