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
This commit is contained in:
Konstantin Belousov 2021-04-03 21:55:11 +03:00
parent 8d9ed174f3
commit a5970a529c
4 changed files with 15 additions and 7 deletions

View File

@ -349,6 +349,9 @@ But operations like
and any other that operate on file and not on file descriptor (except
.Xr fstat 2 ),
are not allowed.
File opened with the
.Dv O_PATH
flag does not prevent non-forced unmount of the volume it belongs to.
See also the description of
.Dv AT_EMPTY_PATH
flag for

View File

@ -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);
}

View File

@ -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;

View File

@ -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);