vn_open_vnode(): handle error when fp == NULL
If VOP_ADD_WRITECOUNT() or adv locking failed, so VOP_CLOSE() needs to be called, we cannot use fp fo_close() when there is no fp. This occurs when e.g. kernel code directly calls vn_open() instead of the open(2) syscall. In this case, VOP_CLOSE() can be called directly, after possible lock upgrade. Reported by: nvass@gmx.com PR: 255119 Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D29830
This commit is contained in:
parent
45aec46246
commit
54f98c4dbf
@ -451,16 +451,34 @@ vn_open_vnode(struct vnode *vp, int fmode, struct ucred *cred,
|
|||||||
/*
|
/*
|
||||||
* Error from advlock or VOP_ADD_WRITECOUNT() still requires
|
* Error from advlock or VOP_ADD_WRITECOUNT() still requires
|
||||||
* calling VOP_CLOSE() to pair with earlier VOP_OPEN().
|
* calling VOP_CLOSE() to pair with earlier VOP_OPEN().
|
||||||
* Arrange for that by having fdrop() to use vn_closefile().
|
|
||||||
*/
|
*/
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
fp->f_flag |= FOPENFAILED;
|
if (fp != NULL) {
|
||||||
fp->f_vnode = vp;
|
/*
|
||||||
if (fp->f_ops == &badfileops) {
|
* Arrange the call by having fdrop() to use
|
||||||
fp->f_type = DTYPE_VNODE;
|
* vn_closefile(). This is to satisfy
|
||||||
fp->f_ops = &vnops;
|
* filesystems like devfs or tmpfs, which
|
||||||
|
* override fo_close().
|
||||||
|
*/
|
||||||
|
fp->f_flag |= FOPENFAILED;
|
||||||
|
fp->f_vnode = vp;
|
||||||
|
if (fp->f_ops == &badfileops) {
|
||||||
|
fp->f_type = DTYPE_VNODE;
|
||||||
|
fp->f_ops = &vnops;
|
||||||
|
}
|
||||||
|
vref(vp);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* If there is no fp, due to kernel-mode open,
|
||||||
|
* we can call VOP_CLOSE() now.
|
||||||
|
*/
|
||||||
|
if (vp->v_type != VFIFO && (fmode & FWRITE) != 0 &&
|
||||||
|
!MNT_EXTENDED_SHARED(vp->v_mount) &&
|
||||||
|
VOP_ISLOCKED(vp) != LK_EXCLUSIVE)
|
||||||
|
vn_lock(vp, LK_UPGRADE | LK_RETRY);
|
||||||
|
(void)VOP_CLOSE(vp, fmode & (FREAD | FWRITE | FEXEC),
|
||||||
|
cred, td);
|
||||||
}
|
}
|
||||||
vref(vp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_VOP_LOCKED(vp, "vn_open_vnode");
|
ASSERT_VOP_LOCKED(vp, "vn_open_vnode");
|
||||||
|
Loading…
Reference in New Issue
Block a user