+++ /dev/null
-#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 */
kmem_reclaim_t reclaim,
void *priv, void *vmp, int flags);
-void
+int
extern __kmem_cache_destroy(kmem_cache_t *cache);
void
#include <linux/buffer_head.h>
#include <linux/dcache.h>
#include <linux/namei.h>
+#include <linux/file.h>
#include <linux/fs.h>
#include <sys/kmem.h>
#include <sys/mutex.h>
} vsecattr_t;
typedef struct vnode {
- struct file *v_fp;
+ struct file *v_file;
kmutex_t v_lock; /* protects vnode fields */
uint_t v_flag; /* vnode flags (see below) */
uint_t v_count; /* reference count */
dev_t v_rdev; /* device (VCHR, VBLK) */
} vnode_t;
+typedef struct vn_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 vnode_t *vn_alloc(int flag);
void vn_free(vnode_t *vp);
extern int vn_open(const char *path, uio_seg_t seg, int flags, int mode,
extern int vn_rename(const char *path1, const char *path2, int x1);
extern int vn_getattr(vnode_t *vp, vattr_t *vap, int flags, void *x3, void *x4);
extern int vn_fsync(vnode_t *vp, int flags, void *x3, void *x4);
+extern file_t *vn_getf(int fd);
+extern void vn_releasef(int fd);
int vn_init(void);
void vn_fini(void);
#define VOP_FSYNC vn_fsync
#define VOP_PUTPAGE vn_putpage
#define vn_is_readonly(vp) 0
+#define getf vn_getf
+#define releasef vn_releasef
extern void *rootdir;
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
+++ /dev/null
-#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() */
#include <sys/sysmacros.h>
#include <sys/vmsystm.h>
#include <sys/vnode.h>
-#include <sys/file.h>
#include <sys/kmem.h>
#include "config.h"
{
int rc;
- if ((rc = vn_init()))
- return rc;
-
- if ((rc = file_init()))
+ if ((rc = kmem_init()))
return rc;
- if ((rc = kmem_init()))
+ if ((rc = vn_init()))
return rc;
strcpy(hw_serial, "007f0100"); /* loopback */
static void spl_fini(void)
{
- kmem_fini();
- file_fini();
vn_fini();
+ kmem_fini();
return;
}
}
EXPORT_SYMBOL(__kmem_cache_create);
-/* Return codes discarded because Solaris implementation has void return */
-void
+/* Return code provided despite Solaris's void return. There should be no
+ * harm here since the Solaris versions will ignore it anyway. */
+int
__kmem_cache_destroy(kmem_cache_t *cache)
{
kmem_cache_cb_t *kcc;
char *name;
+ int rc;
spin_lock(&kmem_cache_cb_lock);
kcc = kmem_cache_find_cache_cb(cache);
spin_unlock(&kmem_cache_cb_lock);
if (kcc == NULL)
- return;
+ return -EINVAL;
name = (char *)kmem_cache_name(cache);
- kmem_cache_destroy(cache);
+ rc = kmem_cache_destroy(cache);
kmem_cache_remove_cache_cb(kcc);
kfree(name);
remove_shrinker(kmem_cache_shrinker);
spin_unlock(&kmem_cache_cb_lock);
+ return rc;
}
EXPORT_SYMBOL(__kmem_cache_destroy);
void *rootdir = NULL;
EXPORT_SYMBOL(rootdir);
-kmem_cache_t *vn_cache;
+static kmem_cache_t *vn_cache;
+static kmem_cache_t *vn_file_cache;
+
+static spinlock_t vn_file_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(vn_file_list);
static vtype_t
vn_get_sol_type(umode_t mode)
vp = kmem_cache_alloc(vn_cache, flag);
if (vp != NULL) {
- vp->v_fp = NULL;
+ vp->v_file = NULL;
vp->v_type = 0;
}
return -ENOMEM;
}
+ mutex_enter(&vp->v_lock);
vp->v_type = vn_get_sol_type(stat.mode);
- vp->v_fp = fp;
+ vp->v_file = fp;
*vpp = vp;
+ mutex_exit(&vp->v_lock);
return 0;
} /* vn_open() */
BUG_ON(!(uio == UIO_WRITE || uio == UIO_READ));
BUG_ON(!vp);
- BUG_ON(!vp->v_fp);
+ BUG_ON(!vp->v_file);
BUG_ON(seg != UIO_SYSSPACE);
BUG_ON(x1 != 0);
BUG_ON(x2 != RLIM64_INFINITY);
offset = off;
- fp = vp->v_fp;
+ fp = vp->v_file;
/* Writable user data segment must be briefly increased for this
* process so we can use the user space read call paths to write
int rc;
BUG_ON(!vp);
- BUG_ON(!vp->v_fp);
+ BUG_ON(!vp->v_file);
- rc = filp_close(vp->v_fp, 0);
+ rc = filp_close(vp->v_file, 0);
vn_free(vp);
return rc;
int rc;
BUG_ON(!vp);
- BUG_ON(!vp->v_fp);
+ BUG_ON(!vp->v_file);
BUG_ON(!vap);
- fp = vp->v_fp;
+ fp = vp->v_file;
rc = vfs_getattr(fp->f_vfsmnt, fp->f_dentry, &stat);
if (rc)
int datasync = 0;
BUG_ON(!vp);
- BUG_ON(!vp->v_fp);
+ BUG_ON(!vp->v_file);
if (flags & FDSYNC)
datasync = 1;
- return file_fsync(vp->v_fp, vp->v_fp->f_dentry, datasync);
+ return file_fsync(vp->v_file, vp->v_file->f_dentry, datasync);
} /* vn_fsync() */
EXPORT_SYMBOL(vn_fsync);
+/* Function must be called while holding the vn_file_lock */
+static file_t *
+file_find(int fd)
+{
+ file_t *fp;
+
+ BUG_ON(!spin_is_locked(&vn_file_lock));
+
+ list_for_each_entry(fp, &vn_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 *
+vn_getf(int fd)
+{
+ struct kstat stat;
+ struct file *lfp;
+ file_t *fp;
+ vnode_t *vp;
+
+ /* Already open just take an extra reference */
+ spin_lock(&vn_file_lock);
+
+ fp = file_find(fd);
+ if (fp) {
+ atomic_inc(&fp->f_ref);
+ spin_unlock(&vn_file_lock);
+ printk("found file\n");
+ return fp;
+ }
+
+ spin_unlock(&vn_file_lock);
+
+ /* File was not yet opened create the object and setup */
+ fp = kmem_cache_alloc(vn_file_cache, 0);
+ if (fp == NULL)
+ goto out;
+
+ mutex_enter(&fp->f_lock);
+
+ fp->f_fd = fd;
+ fp->f_offset = 0;
+ atomic_inc(&fp->f_ref);
+
+ lfp = fget(fd);
+ if (lfp == NULL)
+ goto out_mutex;
+
+ vp = vn_alloc(KM_SLEEP);
+ if (vp == NULL)
+ goto out_fget;
+
+ if (vfs_getattr(lfp->f_vfsmnt, lfp->f_dentry, &stat))
+ goto out_vnode;
+
+ mutex_enter(&vp->v_lock);
+ vp->v_type = vn_get_sol_type(stat.mode);
+ vp->v_file = lfp;
+ mutex_exit(&vp->v_lock);
+
+ fp->f_vnode = vp;
+ fp->f_file = lfp;
+
+ /* Put it on the tracking list */
+ spin_lock(&vn_file_lock);
+ list_add(&fp->f_list, &vn_file_list);
+ spin_unlock(&vn_file_lock);
+
+ mutex_exit(&fp->f_lock);
+ return fp;
+
+out_vnode:
+ printk("out_vnode\n");
+ vn_free(vp);
+out_fget:
+ printk("out_fget\n");
+ fput(lfp);
+out_mutex:
+ printk("out_mutex\n");
+ mutex_exit(&fp->f_lock);
+ kmem_cache_free(vn_file_cache, fp);
+out:
+ printk("out\n");
+ 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(vn_file_cache, fp);
+}
+
+void
+vn_releasef(int fd)
+{
+ file_t *fp;
+
+ spin_lock(&vn_file_lock);
+ fp = file_find(fd);
+ if (fp) {
+ atomic_dec(&fp->f_ref);
+ if (atomic_read(&fp->f_ref) > 0) {
+ spin_unlock(&vn_file_lock);
+ return;
+ }
+
+ list_del(&fp->f_list);
+ releasef_locked(fp);
+ }
+ spin_unlock(&vn_file_lock);
+
+ return;
+} /* releasef() */
+EXPORT_SYMBOL(releasef);
+
static int
vn_cache_constructor(void *buf, void *cdrarg, int kmflags)
{
mutex_destroy(&vp->v_lock);
} /* vn_cache_destructor() */
+static int
+vn_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
+vn_file_cache_destructor(void *buf, void *cdrarg)
+{
+ file_t *fp = buf;
+
+ mutex_destroy(&fp->f_lock);
+} /* vn_file_cache_destructor() */
+
int
vn_init(void)
{
vn_cache_constructor,
vn_cache_destructor,
NULL, NULL, NULL, 0);
+
+ vn_file_cache = kmem_cache_create("spl_vn_file_cache",
+ sizeof(file_t), 64,
+ vn_file_cache_constructor,
+ vn_file_cache_destructor,
+ NULL, NULL, NULL, 0);
return 0;
} /* vn_init() */
void
vn_fini(void)
{
- kmem_cache_destroy(vn_cache);
+ file_t *fp, *next_fp;
+ int rc, leaked = 0;
+
+ spin_lock(&vn_file_lock);
+
+ list_for_each_entry_safe(fp, next_fp, &vn_file_list, f_list) {
+ list_del(&fp->f_list);
+ releasef_locked(fp);
+ leaked++;
+ }
+
+ rc = kmem_cache_destroy(vn_file_cache);
+ if (rc)
+ printk("Warning leaked vn_file_cache objects\n");
+
+ vn_file_cache = NULL;
+ spin_unlock(&vn_file_lock);
+
+ if (leaked > 0)
+ printk("Warning: %d files leaked\n", leaked);
+
+ rc = kmem_cache_destroy(vn_cache);
+ if (rc)
+ printk("Warning leaked vn_cache objects\n");
+
+ return;
} /* vn_fini() */
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/
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")))
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);
+++ /dev/null
-#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() */
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 *);
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);
int splat_time_id(void);
int splat_vnode_id(void);
int splat_kobj_id(void);
-int splat_file_id(void);
#endif /* _SPLAT_INTERNAL_H */
goto out;
}
- buf = kmalloc(size, GFP_KERNEL);
+ buf = kmalloc(size + 1, GFP_KERNEL);
if (!buf) {
rc = -ENOMEM;
splat_vprint(file, SPLAT_KOBJ_TEST2_NAME, "Failed to alloc "
goto out;
}
+ memset(buf, 0, size + 1);
rc = kobj_read_file(f, buf, size, 0);
if (rc < 0) {
splat_vprint(file, SPLAT_KOBJ_TEST2_NAME, "Failed read of "
* 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;
+ 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));
#include "splat-internal.h"
+#include <linux/rcupdate.h>
#define SPLAT_SUBSYSTEM_VNODE 0x0900
#define SPLAT_VNODE_NAME "vnode"
#define SPLAT_VNODE_TEST6_NAME "vn_sync"
#define SPLAT_VNODE_TEST6_DESC "Vn_sync Test"
+#define SPLAT_VNODE_TEST7_ID 0x0907
+#define SPLAT_VNODE_TEST7_NAME "getf"
+#define SPLAT_VNODE_TEST7_DESC "getf/releasef 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"
}
if (strncmp(buf1, buf2, strlen(buf1))) {
- rc = EINVAL;
+ rc = -EINVAL;
splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
"Failed strncmp data written does not match "
"data read\nWrote: %sRead: %s\n", buf1, buf2);
vn_remove(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE, RMFILE);
return rc;
-} /* splat_vnode_test4() */
+} /* splat_vnode_test6() */
+
+/* Basically a slightly modified version of sys_close() */
+static int
+fd_uninstall(int fd)
+{
+ struct file *fp;
+ struct files_struct *files = current->files;
+ struct fdtable *fdt;
+
+ spin_lock(&files->file_lock);
+ fdt = files_fdtable(files);
+
+ if (fd >= fdt->max_fds)
+ goto out_unlock;
+
+ fp = fdt->fd[fd];
+ if (!fp)
+ goto out_unlock;
+
+ rcu_assign_pointer(fdt->fd[fd], NULL);
+ FD_CLR(fd, fdt->close_on_exec);
+
+ /* Dropping the lock here exposes a minor race but it allows me
+ * to use the existing kernel interfaces for this, and for a test
+ * case I think that's reasonable. */
+ spin_unlock(&files->file_lock);
+ put_unused_fd(fd);
+
+out_unlock:
+ spin_unlock(&files->file_lock);
+ return -EBADF;
+} /* fd_uninstall() */
+
+static int
+splat_vnode_test7(struct file *file, void *arg)
+{
+ char buf1[32] = "SPL VNode Interface Test File\n";
+ char buf2[32] = "";
+ struct file *lfp;
+ file_t *fp;
+ int rc, fd;
+
+ /* Prep work needed to test getf/releasef */
+ fd = get_unused_fd();
+ if (fd < 0) {
+ splat_vprint(file, SPLAT_VNODE_TEST7_NAME,
+ "Failed to get unused fd (%d)\n", fd);
+ return fd;
+ }
+
+ lfp = filp_open(SPLAT_VNODE_TEST_FILE_RW, O_RDWR|O_CREAT|O_EXCL, 0644);
+ if (IS_ERR(lfp)) {
+ put_unused_fd(fd);
+ rc = PTR_ERR(lfp);
+ splat_vprint(file, SPLAT_VNODE_TEST7_NAME,
+ "Failed to filp_open: %s (%d)\n",
+ SPLAT_VNODE_TEST_FILE_RW, rc);
+ return rc;
+ }
+
+ /* Pair up the new fd and lfp in the current context, this allows
+ * getf to lookup the file struct simply by the known open fd */
+ fd_install(fd, lfp);
+
+ /* Actual getf()/releasef() test */
+ fp = vn_getf(fd);
+ if (fp == NULL) {
+ rc = -EINVAL;
+ splat_vprint(file, SPLAT_VNODE_TEST7_NAME,
+ "Failed to getf fd %d: (%d)\n", fd, rc);
+ goto out;
+ }
+
+ rc = vn_rdwr(UIO_WRITE, fp->f_vnode, buf1, strlen(buf1), 0,
+ UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
+ if (rc < 0) {
+ splat_vprint(file, SPLAT_VNODE_TEST7_NAME,
+ "Failed vn_rdwr write of test file: %s (%d)\n",
+ SPLAT_VNODE_TEST_FILE_RW, rc);
+ goto out;
+ }
+
+ rc = vn_rdwr(UIO_READ, fp->f_vnode, buf2, strlen(buf1), 0,
+ UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
+ if (rc < 0) {
+ splat_vprint(file, SPLAT_VNODE_TEST7_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_TEST7_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:
+ vn_releasef(fd);
+ fd_uninstall(fd);
+ filp_close(lfp, 0);
+ vn_remove(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE, RMFILE);
+
+ return rc;
+} /* splat_vnode_test7() */
splat_subsystem_t *
splat_vnode_init(void)
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);
+ SPLAT_TEST_INIT(sub, SPLAT_VNODE_TEST7_NAME, SPLAT_VNODE_TEST7_DESC,
+ SPLAT_VNODE_TEST7_ID, splat_vnode_test7);
return sub;
} /* splat_vnode_init() */
{
ASSERT(sub);
+ SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST7_ID);
SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST6_ID);
SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST5_ID);
SPLAT_TEST_FINI(sub, SPLAT_VNODE_TEST4_ID);