Create a dedicated function for ensuring that cdir and rdir are populated.

Previously several places were doing it on its own, partially
incorrectly (e.g. without the filedesc locked) or even actively harmful
by populating jdir or assigning rootvnode without vrefing it.

Reviewed by:	kib
This commit is contained in:
mjg 2015-07-11 16:22:48 +00:00
parent c71e9ab863
commit a85ed5531d
8 changed files with 26 additions and 64 deletions

View File

@ -2123,18 +2123,7 @@ ctl_be_block_open(struct ctl_be_block_softc *softc,
return (1);
}
if (!curthread->td_proc->p_fd->fd_cdir) {
curthread->td_proc->p_fd->fd_cdir = rootvnode;
VREF(rootvnode);
}
if (!curthread->td_proc->p_fd->fd_rdir) {
curthread->td_proc->p_fd->fd_rdir = rootvnode;
VREF(rootvnode);
}
if (!curthread->td_proc->p_fd->fd_jdir) {
curthread->td_proc->p_fd->fd_jdir = rootvnode;
VREF(rootvnode);
}
pwd_ensure_dirs();
again:
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, be_lun->dev_path, curthread);

View File

@ -67,21 +67,10 @@ static void *
kobj_open_file_vnode(const char *file)
{
struct thread *td = curthread;
struct filedesc *fd;
struct nameidata nd;
int error, flags;
fd = td->td_proc->p_fd;
FILEDESC_XLOCK(fd);
if (fd->fd_rdir == NULL) {
fd->fd_rdir = rootvnode;
vref(fd->fd_rdir);
}
if (fd->fd_cdir == NULL) {
fd->fd_cdir = rootvnode;
vref(fd->fd_cdir);
}
FILEDESC_XUNLOCK(fd);
pwd_ensure_dirs();
flags = FREAD | O_NOFOLLOW;
NDINIT(&nd, LOOKUP, 0, UIO_SYSSPACE, file, td);

View File

@ -162,7 +162,6 @@ vn_openat(char *pnamep, enum uio_seg seg, int filemode, int createmode,
int fd)
{
struct thread *td = curthread;
struct filedesc *fdc;
struct nameidata nd;
int error, operation;
@ -179,17 +178,7 @@ vn_openat(char *pnamep, enum uio_seg seg, int filemode, int createmode,
}
ASSERT(umask == 0);
fdc = td->td_proc->p_fd;
FILEDESC_XLOCK(fdc);
if (fdc->fd_rdir == NULL) {
fdc->fd_rdir = rootvnode;
vref(fdc->fd_rdir);
}
if (fdc->fd_cdir == NULL) {
fdc->fd_cdir = rootvnode;
vref(fdc->fd_rdir);
}
FILEDESC_XUNLOCK(fdc);
pwd_ensure_dirs();
if (startvp != NULL)
vref(startvp);

View File

@ -2817,10 +2817,7 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr)
/* Some threads don't have a current working directory. */
if (td->td_proc->p_fd->fd_rdir == NULL)
td->td_proc->p_fd->fd_rdir = rootvnode;
if (td->td_proc->p_fd->fd_cdir == NULL)
td->td_proc->p_fd->fd_cdir = rootvnode;
pwd_ensure_dirs();
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);

View File

@ -2692,18 +2692,7 @@ xbb_open_backend(struct xbb_softc *xbb)
if ((xbb->flags & XBBF_READ_ONLY) == 0)
flags |= FWRITE;
if (!curthread->td_proc->p_fd->fd_cdir) {
curthread->td_proc->p_fd->fd_cdir = rootvnode;
VREF(rootvnode);
}
if (!curthread->td_proc->p_fd->fd_rdir) {
curthread->td_proc->p_fd->fd_rdir = rootvnode;
VREF(rootvnode);
}
if (!curthread->td_proc->p_fd->fd_jdir) {
curthread->td_proc->p_fd->fd_jdir = rootvnode;
VREF(rootvnode);
}
pwd_ensure_dirs();
again:
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, xbb->dev_name, curthread);

View File

@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sbuf.h>
#include <sys/signalvar.h>
#include <sys/socketvar.h>
#include <sys/kdb.h>
#include <sys/stat.h>
#include <sys/sx.h>
#include <sys/syscallsubr.h>
@ -308,6 +309,24 @@ fdfree(struct filedesc *fdp, int fd)
#endif
}
void
pwd_ensure_dirs(void)
{
struct filedesc *fdp;
fdp = curproc->p_fd;
FILEDESC_XLOCK(fdp);
if (fdp->fd_cdir == NULL) {
fdp->fd_cdir = rootvnode;
VREF(rootvnode);
}
if (fdp->fd_rdir == NULL) {
fdp->fd_rdir = rootvnode;
VREF(rootvnode);
}
FILEDESC_XUNLOCK(fdp);
}
/*
* System calls on descriptors.
*/

View File

@ -383,19 +383,8 @@ firmware_put(const struct firmware *p, int flags)
static void
set_rootvnode(void *arg, int npending)
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
FILEDESC_XLOCK(p->p_fd);
if (p->p_fd->fd_cdir == NULL) {
p->p_fd->fd_cdir = rootvnode;
VREF(rootvnode);
}
if (p->p_fd->fd_rdir == NULL) {
p->p_fd->fd_rdir = rootvnode;
VREF(rootvnode);
}
FILEDESC_XUNLOCK(p->p_fd);
pwd_ensure_dirs();
free(arg, M_TEMP);
}

View File

@ -208,6 +208,7 @@ fd_modified(struct filedesc *fdp, int fd, seq_t seq)
/* cdir/rdir/jdir manipulation functions. */
void pwd_chdir(struct thread *td, struct vnode *vp);
int pwd_chroot(struct thread *td, struct vnode *vp);
void pwd_ensure_dirs(void);
#endif /* _KERNEL */