aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2020-08-16 21:05:56 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2020-08-16 21:05:56 +0000
commit685cb01a18595e8e7cb15f3ea225ac1dd13bd319 (patch)
tree1427047a9afda35df9b344cee9c39de0c7ec9a35
parentfbca789fc328487a1be438f5235e4c0ad0eb849b (diff)
Notes
-rw-r--r--sys/fs/nullfs/null_subr.c21
-rw-r--r--sys/fs/nullfs/null_vnops.c11
2 files changed, 31 insertions, 1 deletions
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index 125b623cb638..80f6943ac7c3 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -259,12 +259,33 @@ null_nodeget(mp, lowervp, vpp)
vp->v_vflag |= VV_ROOT;
/*
+ * We might miss the case where lower vnode sets VIRF_PGREAD
+ * some time after construction, which is typical case.
+ * null_open rechecks.
+ */
+ if ((lowervp->v_irflag & VIRF_PGREAD) != 0) {
+ MPASS(lowervp->v_object != NULL);
+ if ((vp->v_irflag & VIRF_PGREAD) == 0) {
+ if (vp->v_object == NULL)
+ vp->v_object = lowervp->v_object;
+ else
+ MPASS(vp->v_object == lowervp->v_object);
+ VI_LOCK(vp);
+ vp->v_irflag |= VIRF_PGREAD;
+ VI_UNLOCK(vp);
+ } else {
+ MPASS(vp->v_object != NULL);
+ }
+ }
+
+ /*
* Atomically insert our new node into the hash or vget existing
* if someone else has beaten us to it.
*/
*vpp = null_hashins(mp, xp);
if (*vpp != NULL) {
vrele(lowervp);
+ vp->v_object = NULL; /* in case VIRF_PGREAD set it */
null_destroy_proto(vp, xp);
return (0);
}
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index 60fd2a2c3660..b9f4b7849982 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -439,8 +439,17 @@ null_open(struct vop_open_args *ap)
vp = ap->a_vp;
ldvp = NULLVPTOLOWERVP(vp);
retval = null_bypass(&ap->a_gen);
- if (retval == 0)
+ if (retval == 0) {
vp->v_object = ldvp->v_object;
+ if ((ldvp->v_irflag & VIRF_PGREAD) != 0) {
+ MPASS(vp->v_object != NULL);
+ if ((vp->v_irflag & VIRF_PGREAD) == 0) {
+ VI_LOCK(vp);
+ vp->v_irflag |= VIRF_PGREAD;
+ VI_UNLOCK(vp);
+ }
+ }
+ }
return (retval);
}