xref: /freebsd/sys/fs/mntfs/mntfs_vnops.c (revision 4e8d558c)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2020 Netflix, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
24  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
25  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29 
30 #include <sys/param.h>
31 #include <sys/conf.h>
32 #include <sys/mount.h>
33 #include <sys/vnode.h>
34 
35 /*
36  * The "mntfs" VCHR vnodes implemented here provide a safe way for file systems
37  * to access their disk devices.  Using the normal devfs vnode has the problem
38  * that if the device disappears, the devfs vnode is vgone'd as part of
39  * removing it from the application-visible namespace, and some file systems
40  * (notably FFS with softdep) get very unhappy if their dirty buffers are
41  * invalidated out from under them.  By using a separate, private vnode,
42  * file systems are able to clean up their buffer state in a controlled fashion
43  * when the underlying device disappears.
44  */
45 
46 static int
47 mntfs_reclaim(struct vop_reclaim_args *ap)
48 {
49 	struct vnode *vp = ap->a_vp;
50 
51 	dev_rel(vp->v_rdev);
52 	return (0);
53 }
54 
55 struct vop_vector mntfs_vnodeops = {
56 	.vop_default =		&default_vnodeops,
57 
58 	.vop_fsync =		vop_stdfsync,
59 	.vop_strategy = 	VOP_PANIC,
60 	.vop_reclaim =		mntfs_reclaim,
61 };
62 VFS_VOP_VECTOR_REGISTER(mntfs_vnodeops);
63 
64 /*
65  * Allocate a private VCHR vnode for use by a mounted fs.
66  * The underlying device will be the same as for the given vnode.
67  * This mntfs vnode must be freed with mntfs_freevp() rather than just
68  * releasing the reference.
69  */
70 struct vnode *
71 mntfs_allocvp(struct mount *mp, struct vnode *ovp)
72 {
73 	struct vnode *vp;
74 	struct cdev *dev;
75 
76 	ASSERT_VOP_ELOCKED(ovp, __func__);
77 
78 	dev = ovp->v_rdev;
79 
80 	getnewvnode("mntfs", mp, &mntfs_vnodeops, &vp);
81 	vp->v_type = VCHR;
82 	vp->v_data = NULL;
83 	dev_ref(dev);
84 	vp->v_rdev = dev;
85 
86 	VOP_UNLOCK(ovp);
87 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
88 	vn_set_state(vp, VSTATE_CONSTRUCTED);
89 	return (vp);
90 }
91 
92 void
93 mntfs_freevp(struct vnode *vp)
94 {
95 	ASSERT_VOP_ELOCKED(vp, "mntfs_freevp");
96 	vgone(vp);
97 	vput(vp);
98 }
99