aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-04-03 18:55:11 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-04-15 09:48:27 +0000
commita5970a529c2d952714f20e4bc6e529c74fd2b3b5 (patch)
tree3e02def33d5dab3f36911337f39f3930316015e1 /sys
parent8d9ed174f3afba5f114742447e622fc1173d4774 (diff)
downloadsrc-a5970a529c2d952714f20e4bc6e529c74fd2b3b5.tar.gz
src-a5970a529c2d952714f20e4bc6e529c74fd2b3b5.zip
Make files opened with O_PATH to not block non-forced unmount
by only keeping hold count on the vnode, instead of the use count. Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D29323
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_descrip.c6
-rw-r--r--sys/kern/vfs_lookup.c2
-rw-r--r--sys/kern/vfs_syscalls.c11
3 files changed, 12 insertions, 7 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 81af58fbddd1..a28e94634326 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -3430,7 +3430,7 @@ _fgetvp(struct thread *td, int fd, int flags, cap_rights_t *needrightsp,
error = EINVAL;
} else {
*vpp = fp->f_vnode;
- vrefact(*vpp);
+ vref(*vpp);
}
fdrop(fp, td);
@@ -3466,7 +3466,7 @@ fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp,
*havecaps = caps;
*vpp = fp->f_vnode;
- vrefact(*vpp);
+ vref(*vpp);
fdrop(fp, td);
return (0);
@@ -4978,7 +4978,7 @@ path_close(struct file *fp, struct thread *td)
{
MPASS(fp->f_type == DTYPE_VNODE);
fp->f_ops = &badfileops;
- vrele(fp->f_vnode);
+ vdrop(fp->f_vnode);
return (0);
}
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index f979676f4c7d..3050275c1b6f 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -380,7 +380,7 @@ namei_setup(struct nameidata *ndp, struct vnode **dpp, struct pwd **pwdp)
error = ENOTDIR;
} else {
*dpp = dfp->f_vnode;
- vrefact(*dpp);
+ vref(*dpp);
if ((dfp->f_flag & FSEARCH) != 0)
cnp->cn_flags |= NOEXECCHECK;
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 5a1efcdec467..9130843f6761 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -896,7 +896,7 @@ sys_fchdir(struct thread *td, struct fchdir_args *uap)
if (error != 0)
return (error);
vp = fp->f_vnode;
- vrefact(vp);
+ vref(vp);
fdrop(fp, td);
vn_lock(vp, LK_SHARED | LK_RETRY);
AUDIT_ARG_VNODE1(vp);
@@ -1191,8 +1191,13 @@ kern_openat(struct thread *td, int fd, const char *path, enum uio_seg pathseg,
if (fp->f_ops == &badfileops) {
KASSERT(vp->v_type != VFIFO || (flags & O_PATH) != 0,
("Unexpected fifo fp %p vp %p", fp, vp));
- finit_vnode(fp, flags, NULL, (flags & O_PATH) != 0 ?
- &path_fileops : &vnops);
+ if ((flags & O_PATH) != 0) {
+ finit_vnode(fp, flags, NULL, &path_fileops);
+ vhold(vp);
+ vunref(vp);
+ } else {
+ finit_vnode(fp, flags, NULL, &vnops);
+ }
}
VOP_UNLOCK(vp);