diff options
Diffstat (limited to 'sys/compat')
-rw-r--r-- | sys/compat/linux/linux_file.c | 21 | ||||
-rw-r--r-- | sys/compat/svr4/svr4_filio.c | 8 |
2 files changed, 21 insertions, 8 deletions
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index ae99416..042a5b2 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -193,7 +193,7 @@ static int linux_at(struct thread *td, int dirfd, char *filename, char **newpath, char **freebuf) { struct file *fp; - int error = 0; + int error = 0, vfslocked; struct vnode *dvp; struct filedesc *fdp = td->td_proc->p_fd; char *fullpath = "unknown"; @@ -207,9 +207,10 @@ linux_at(struct thread *td, int dirfd, char *filename, char **newpath, char **fr /* check for AT_FDWCD */ if (dirfd == LINUX_AT_FDCWD) { - FILEDESC_LOCK(fdp); + FILEDESC_SLOCK(fdp); dvp = fdp->fd_cdir; - FILEDESC_UNLOCK(fdp); + vref(dvp); + FILEDESC_SUNLOCK(fdp); } else { error = fget(td, dirfd, &fp); if (error) @@ -220,16 +221,28 @@ linux_at(struct thread *td, int dirfd, char *filename, char **newpath, char **fr fdrop(fp, td); return (ENOTDIR); } + vref(dvp); fdrop(fp, td); } + /* + * XXXRW: This is bogus, as vn_fullpath() returns only an advisory + * file path, and may fail in several common situations, including + * for file systmes that don't use the name cache, and if the entry + * for the file falls out of the name cache. We should implement + * openat() in the FreeBSD native system call layer properly (using a + * requested starting directory), and have Linux and other ABIs wrap + * the native implementation. + */ error = vn_fullpath(td, dvp, &fullpath, &freepath); if (!error) { *newpath = malloc(strlen(fullpath) + strlen(filename) + 2, M_TEMP, M_WAITOK | M_ZERO); *freebuf = freepath; sprintf(*newpath, "%s/%s", fullpath, filename); } - + vfslocked = VFS_LOCK_GIANT(dvp->v_mount); + vrele(dvp); + VFS_UNLOCK_GIANT(vfslocked); return (error); } diff --git a/sys/compat/svr4/svr4_filio.c b/sys/compat/svr4/svr4_filio.c index d782443..701bf15 100644 --- a/sys/compat/svr4/svr4_filio.c +++ b/sys/compat/svr4/svr4_filio.c @@ -211,15 +211,15 @@ svr4_fil_ioctl(fp, td, retval, fd, cmd, data) switch (cmd) { case SVR4_FIOCLEX: - FILEDESC_LOCK_FAST(fdp); + FILEDESC_XLOCK(fdp); fdp->fd_ofileflags[fd] |= UF_EXCLOSE; - FILEDESC_UNLOCK_FAST(fdp); + FILEDESC_XUNLOCK(fdp); return 0; case SVR4_FIONCLEX: - FILEDESC_LOCK_FAST(fdp); + FILEDESC_XLOCK(fdp); fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE; - FILEDESC_UNLOCK_FAST(fdp); + FILEDESC_XUNLOCK(fdp); return 0; case SVR4_FIOGETOWN: |