]> git.proxmox.com Git - mirror_spl.git/commitdiff
Implement areleasef()
authorRichard Yao <richard.yao@clusterhq.com>
Tue, 17 Feb 2015 15:12:56 +0000 (10:12 -0500)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 24 Apr 2015 20:02:37 +0000 (13:02 -0700)
Signed-off-by: Richard Yao <ryao@gentoo.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #449

include/sys/Makefile.am
include/sys/user.h [new file with mode: 0644]
include/sys/vnode.h
module/spl/spl-vnode.c

index f9e883fd41ab31e9a57e981ce078a32a0ef12775..73c4a84217829d204bb0b42d4fb9a21d21a28f1d 100644 (file)
@@ -91,6 +91,7 @@ KERNEL_H = \
        $(top_srcdir)/include/sys/u8_textprep.h \
        $(top_srcdir)/include/sys/uio.h \
        $(top_srcdir)/include/sys/unistd.h \
+       $(top_srcdir)/include/sys/user.h \
        $(top_srcdir)/include/sys/va_list.h \
        $(top_srcdir)/include/sys/varargs.h \
        $(top_srcdir)/include/sys/vfs.h \
diff --git a/include/sys/user.h b/include/sys/user.h
new file mode 100644 (file)
index 0000000..ebbe8f6
--- /dev/null
@@ -0,0 +1,42 @@
+/*****************************************************************************\
+ *  Copyright (C) 2015 Cluster Inc.
+ *  Produced at ClusterHQ Inc (cf, DISCLAIMER).
+ *  Written by Richard Yao <richard.yao@clusterhq.com>.
+ *
+ *  This file is part of the SPL, Solaris Porting Layer.
+ *  For details, see <http://zfsonlinux.org/>.
+ *
+ *  The SPL is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  The SPL is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with the SPL.  If not, see <http://www.gnu.org/licenses/>.
+\*****************************************************************************/
+
+#ifndef _SPL_USER_H
+#define _SPL_USER_H
+
+/*
+ * We have uf_info_t for areleasef(). We implement areleasef() using a global
+ * linked list of all open file descriptors with the task structs referenced,
+ * so accessing the correct descriptor from areleasef() only requires knowing
+ * about the Linux task_struct. Since this is internal to our compatibility
+ * layer, we make it an opaque type.
+ *
+ * XXX: If the descriptor changes under us, we would get an incorrect
+ * reference.
+ */
+
+struct uf_info;
+typedef struct uf_info uf_info_t;
+
+#define P_FINFO(x) ((uf_info_t *)x)
+
+#endif /* SPL_USER_H */
index 07a34493837b4356f5f847b7606c2753a0e06e8e..0b857d384ba572a540263e59b830c4d8d96fa754 100644 (file)
@@ -40,6 +40,7 @@
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/uio.h>
+#include <sys/user.h>
 #include <sys/sunldi.h>
 
 /*
@@ -184,6 +185,7 @@ extern int vn_space(vnode_t *vp, int cmd, struct flock *bfp, int flag,
     offset_t offset, void *x6, void *x7);
 extern file_t *vn_getf(int fd);
 extern void vn_releasef(int fd);
+extern void vn_areleasef(int fd, uf_info_t *fip);
 extern int vn_set_pwd(const char *filename);
 
 int spl_vn_init(void);
@@ -198,6 +200,7 @@ void spl_vn_fini(void);
 #define vn_is_readonly(vp)                     0
 #define getf                                   vn_getf
 #define releasef                               vn_releasef
+#define areleasef                              vn_areleasef
 
 extern vnode_t *rootdir;
 
index 4c62097dcc574b008d36abd1f9c079f793fd1b3b..ab9830d1867a04ea6577d534110d6f41a229b85c 100644 (file)
@@ -623,14 +623,14 @@ EXPORT_SYMBOL(vn_space);
 
 /* Function must be called while holding the vn_file_lock */
 static file_t *
-file_find(int fd)
+file_find(int fd, struct task_struct *task)
 {
         file_t *fp;
 
        ASSERT(spin_is_locked(&vn_file_lock));
 
         list_for_each_entry(fp, &vn_file_list,  f_list) {
-               if (fd == fp->f_fd && fp->f_task == current) {
+               if (fd == fp->f_fd && fp->f_task == task) {
                        ASSERT(atomic_read(&fp->f_ref) != 0);
                         return fp;
                }
@@ -654,7 +654,7 @@ vn_getf(int fd)
        /* Already open just take an extra reference */
        spin_lock(&vn_file_lock);
 
-       fp = file_find(fd);
+       fp = file_find(fd, current);
        if (fp) {
                atomic_inc(&fp->f_ref);
                spin_unlock(&vn_file_lock);
@@ -733,14 +733,22 @@ static void releasef_locked(file_t *fp)
 
 void
 vn_releasef(int fd)
+{
+       areleasef(fd, P_FINFO(current));
+}
+EXPORT_SYMBOL(releasef);
+
+void
+vn_areleasef(int fd, uf_info_t *fip)
 {
        file_t *fp;
+       struct task_struct *task = (struct task_struct *)fip;
 
        if (fd < 0)
                return;
 
        spin_lock(&vn_file_lock);
-       fp = file_find(fd);
+       fp = file_find(fd, task);
        if (fp) {
                atomic_dec(&fp->f_ref);
                if (atomic_read(&fp->f_ref) > 0) {
@@ -755,7 +763,8 @@ vn_releasef(int fd)
 
        return;
 } /* releasef() */
-EXPORT_SYMBOL(releasef);
+EXPORT_SYMBOL(areleasef);
+
 
 static void
 #ifdef HAVE_SET_FS_PWD_WITH_CONST