Implement areleasef()

Signed-off-by: Richard Yao <ryao@gentoo.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #449
This commit is contained in:
Richard Yao 2015-02-17 10:12:56 -05:00 committed by Brian Behlendorf
parent 313b1ea622
commit d3c677bcd3
4 changed files with 60 additions and 5 deletions

View File

@ -91,6 +91,7 @@ KERNEL_H = \
$(top_srcdir)/include/sys/u8_textprep.h \ $(top_srcdir)/include/sys/u8_textprep.h \
$(top_srcdir)/include/sys/uio.h \ $(top_srcdir)/include/sys/uio.h \
$(top_srcdir)/include/sys/unistd.h \ $(top_srcdir)/include/sys/unistd.h \
$(top_srcdir)/include/sys/user.h \
$(top_srcdir)/include/sys/va_list.h \ $(top_srcdir)/include/sys/va_list.h \
$(top_srcdir)/include/sys/varargs.h \ $(top_srcdir)/include/sys/varargs.h \
$(top_srcdir)/include/sys/vfs.h \ $(top_srcdir)/include/sys/vfs.h \

42
include/sys/user.h Normal file
View File

@ -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 */

View File

@ -40,6 +40,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <sys/user.h>
#include <sys/sunldi.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); offset_t offset, void *x6, void *x7);
extern file_t *vn_getf(int fd); extern file_t *vn_getf(int fd);
extern void vn_releasef(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); extern int vn_set_pwd(const char *filename);
int spl_vn_init(void); int spl_vn_init(void);
@ -198,6 +200,7 @@ void spl_vn_fini(void);
#define vn_is_readonly(vp) 0 #define vn_is_readonly(vp) 0
#define getf vn_getf #define getf vn_getf
#define releasef vn_releasef #define releasef vn_releasef
#define areleasef vn_areleasef
extern vnode_t *rootdir; extern vnode_t *rootdir;

View File

@ -623,14 +623,14 @@ EXPORT_SYMBOL(vn_space);
/* Function must be called while holding the vn_file_lock */ /* Function must be called while holding the vn_file_lock */
static file_t * static file_t *
file_find(int fd) file_find(int fd, struct task_struct *task)
{ {
file_t *fp; file_t *fp;
ASSERT(spin_is_locked(&vn_file_lock)); ASSERT(spin_is_locked(&vn_file_lock));
list_for_each_entry(fp, &vn_file_list, f_list) { 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); ASSERT(atomic_read(&fp->f_ref) != 0);
return fp; return fp;
} }
@ -654,7 +654,7 @@ vn_getf(int fd)
/* Already open just take an extra reference */ /* Already open just take an extra reference */
spin_lock(&vn_file_lock); spin_lock(&vn_file_lock);
fp = file_find(fd); fp = file_find(fd, current);
if (fp) { if (fp) {
atomic_inc(&fp->f_ref); atomic_inc(&fp->f_ref);
spin_unlock(&vn_file_lock); spin_unlock(&vn_file_lock);
@ -733,14 +733,22 @@ static void releasef_locked(file_t *fp)
void void
vn_releasef(int fd) vn_releasef(int fd)
{
areleasef(fd, P_FINFO(current));
}
EXPORT_SYMBOL(releasef);
void
vn_areleasef(int fd, uf_info_t *fip)
{ {
file_t *fp; file_t *fp;
struct task_struct *task = (struct task_struct *)fip;
if (fd < 0) if (fd < 0)
return; return;
spin_lock(&vn_file_lock); spin_lock(&vn_file_lock);
fp = file_find(fd); fp = file_find(fd, task);
if (fp) { if (fp) {
atomic_dec(&fp->f_ref); atomic_dec(&fp->f_ref);
if (atomic_read(&fp->f_ref) > 0) { if (atomic_read(&fp->f_ref) > 0) {
@ -755,7 +763,8 @@ vn_releasef(int fd)
return; return;
} /* releasef() */ } /* releasef() */
EXPORT_SYMBOL(releasef); EXPORT_SYMBOL(areleasef);
static void static void
#ifdef HAVE_SET_FS_PWD_WITH_CONST #ifdef HAVE_SET_FS_PWD_WITH_CONST