summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorKirk McKusick <mckusick@FreeBSD.org>2000-07-24 05:28:33 +0000
committerKirk McKusick <mckusick@FreeBSD.org>2000-07-24 05:28:33 +0000
commit9b97113391a63a82eeac6ccbbdf607f67bce1d08 (patch)
tree62690c6f979cb730f89f23fa1d8a48b3b0fc7626 /sys/kern
parent3adc8b3d1d5a8ce84f17b396ef9ccc3edf14f94e (diff)
Notes
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/vfs_export.c36
-rw-r--r--sys/kern/vfs_subr.c36
-rw-r--r--sys/kern/vfs_vnops.c14
3 files changed, 74 insertions, 12 deletions
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 0e5ec3f30304..db16d9fe6080 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -1296,15 +1296,45 @@ bdevvp(dev, vpp)
* how many users there are is inadequate; the v_usecount for
* the vnodes need to be accumulated. vcount() does that.
*/
-void
+struct vnode *
addaliasu(nvp, nvp_rdev)
struct vnode *nvp;
udev_t nvp_rdev;
{
+ struct vnode *ovp;
+ vop_t **ops;
+ dev_t dev;
if (nvp->v_type != VBLK && nvp->v_type != VCHR)
panic("addaliasu on non-special vnode");
- addalias(nvp, udev2dev(nvp_rdev, nvp->v_type == VBLK ? 1 : 0));
+ dev = udev2dev(nvp_rdev, nvp->v_type == VBLK ? 1 : 0);
+ /*
+ * Check to see if we have a bdevvp vnode with no associated
+ * filesystem. If so, we want to associate the filesystem of
+ * the new newly instigated vnode with the bdevvp vnode and
+ * discard the newly created vnode rather than leaving the
+ * bdevvp vnode lying around with no associated filesystem.
+ */
+ if (vfinddev(dev, nvp->v_type, &ovp) == 0 || ovp->v_data != NULL) {
+ addalias(nvp, dev);
+ return (nvp);
+ }
+ /*
+ * Discard unneeded vnode, but save its node specific data.
+ * Note that if there is a lock, it is carried over in the
+ * node specific data to the replacement vnode.
+ */
+ vref(ovp);
+ ovp->v_data = nvp->v_data;
+ ovp->v_tag = nvp->v_tag;
+ nvp->v_data = NULL;
+ ops = nvp->v_op;
+ nvp->v_op = ovp->v_op;
+ ovp->v_op = ops;
+ insmntque(ovp, nvp->v_mount);
+ vrele(nvp);
+ vgone(nvp);
+ return (ovp);
}
void
@@ -1648,7 +1678,7 @@ vclean(vp, flags, p)
*/
if (flags & DOCLOSE) {
if (TAILQ_FIRST(&vp->v_dirtyblkhd) != NULL)
- (void) vn_write_suspend_wait(vp, V_WAIT);
+ (void) vn_write_suspend_wait(vp, NULL, V_WAIT);
if (vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0) != 0)
vinvalbuf(vp, 0, NOCRED, p, 0, 0);
}
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 0e5ec3f30304..db16d9fe6080 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1296,15 +1296,45 @@ bdevvp(dev, vpp)
* how many users there are is inadequate; the v_usecount for
* the vnodes need to be accumulated. vcount() does that.
*/
-void
+struct vnode *
addaliasu(nvp, nvp_rdev)
struct vnode *nvp;
udev_t nvp_rdev;
{
+ struct vnode *ovp;
+ vop_t **ops;
+ dev_t dev;
if (nvp->v_type != VBLK && nvp->v_type != VCHR)
panic("addaliasu on non-special vnode");
- addalias(nvp, udev2dev(nvp_rdev, nvp->v_type == VBLK ? 1 : 0));
+ dev = udev2dev(nvp_rdev, nvp->v_type == VBLK ? 1 : 0);
+ /*
+ * Check to see if we have a bdevvp vnode with no associated
+ * filesystem. If so, we want to associate the filesystem of
+ * the new newly instigated vnode with the bdevvp vnode and
+ * discard the newly created vnode rather than leaving the
+ * bdevvp vnode lying around with no associated filesystem.
+ */
+ if (vfinddev(dev, nvp->v_type, &ovp) == 0 || ovp->v_data != NULL) {
+ addalias(nvp, dev);
+ return (nvp);
+ }
+ /*
+ * Discard unneeded vnode, but save its node specific data.
+ * Note that if there is a lock, it is carried over in the
+ * node specific data to the replacement vnode.
+ */
+ vref(ovp);
+ ovp->v_data = nvp->v_data;
+ ovp->v_tag = nvp->v_tag;
+ nvp->v_data = NULL;
+ ops = nvp->v_op;
+ nvp->v_op = ovp->v_op;
+ ovp->v_op = ops;
+ insmntque(ovp, nvp->v_mount);
+ vrele(nvp);
+ vgone(nvp);
+ return (ovp);
}
void
@@ -1648,7 +1678,7 @@ vclean(vp, flags, p)
*/
if (flags & DOCLOSE) {
if (TAILQ_FIRST(&vp->v_dirtyblkhd) != NULL)
- (void) vn_write_suspend_wait(vp, V_WAIT);
+ (void) vn_write_suspend_wait(vp, NULL, V_WAIT);
if (vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0) != 0)
vinvalbuf(vp, 0, NOCRED, p, 0, 0);
}
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 0708f7c044ed..0c4707b95d6d 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -729,17 +729,19 @@ vn_start_write(vp, mpp, flags)
* time, these operations are halted until the suspension is over.
*/
int
-vn_write_suspend_wait(vp, flags)
+vn_write_suspend_wait(vp, mp, flags)
struct vnode *vp;
+ struct mount *mp;
int flags;
{
- struct mount *mp;
int error;
- if ((error = VOP_GETWRITEMOUNT(vp, &mp)) != 0) {
- if (error != EOPNOTSUPP)
- return (error);
- return (0);
+ if (vp != NULL) {
+ if ((error = VOP_GETWRITEMOUNT(vp, &mp)) != 0) {
+ if (error != EOPNOTSUPP)
+ return (error);
+ return (0);
+ }
}
/*
* If we are not suspended or have not yet reached suspended