1*f38668ffShannken /* $NetBSD: mfs_vnops.c,v 1.64 2022/03/19 13:48:42 hannken Exp $ */
2fccfa11aScgd
3264b874cSmycroft /*
4264b874cSmycroft * Copyright (c) 1989, 1993
5264b874cSmycroft * The Regents of the University of California. All rights reserved.
6264b874cSmycroft *
7264b874cSmycroft * Redistribution and use in source and binary forms, with or without
8264b874cSmycroft * modification, are permitted provided that the following conditions
9264b874cSmycroft * are met:
10264b874cSmycroft * 1. Redistributions of source code must retain the above copyright
11264b874cSmycroft * notice, this list of conditions and the following disclaimer.
12264b874cSmycroft * 2. Redistributions in binary form must reproduce the above copyright
13264b874cSmycroft * notice, this list of conditions and the following disclaimer in the
14264b874cSmycroft * documentation and/or other materials provided with the distribution.
15aad01611Sagc * 3. Neither the name of the University nor the names of its contributors
16264b874cSmycroft * may be used to endorse or promote products derived from this software
17264b874cSmycroft * without specific prior written permission.
18264b874cSmycroft *
19264b874cSmycroft * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20264b874cSmycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21264b874cSmycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22264b874cSmycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23264b874cSmycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24264b874cSmycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25264b874cSmycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26264b874cSmycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27264b874cSmycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28264b874cSmycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29264b874cSmycroft * SUCH DAMAGE.
30264b874cSmycroft *
31e5bc90f4Sfvdl * @(#)mfs_vnops.c 8.11 (Berkeley) 5/22/95
32264b874cSmycroft */
33264b874cSmycroft
34ec624546Slukem #include <sys/cdefs.h>
35*f38668ffShannken __KERNEL_RCSID(0, "$NetBSD: mfs_vnops.c,v 1.64 2022/03/19 13:48:42 hannken Exp $");
36ec624546Slukem
37264b874cSmycroft #include <sys/param.h>
38264b874cSmycroft #include <sys/systm.h>
39264b874cSmycroft #include <sys/time.h>
40264b874cSmycroft #include <sys/kernel.h>
41264b874cSmycroft #include <sys/proc.h>
42264b874cSmycroft #include <sys/buf.h>
4305f25dccSyamt #include <sys/bufq.h>
44264b874cSmycroft #include <sys/vnode.h>
45021b86ddSad #include <sys/kmem.h>
46264b874cSmycroft
47c52352c8Smycroft #include <miscfs/genfs/genfs.h>
48264b874cSmycroft #include <miscfs/specfs/specdev.h>
49264b874cSmycroft
505026e056Sthorpej #include <machine/vmparam.h>
515026e056Sthorpej
52264b874cSmycroft #include <ufs/mfs/mfsnode.h>
53264b874cSmycroft #include <ufs/mfs/mfs_extern.h>
54264b874cSmycroft
55264b874cSmycroft /*
56264b874cSmycroft * mfs vnode operations.
57264b874cSmycroft */
5823ebf62dSxtraeme int (**mfs_vnodeop_p)(void *);
59d9466585Sjdolecek const struct vnodeopv_entry_desc mfs_vnodeop_entries[] = {
60264b874cSmycroft { &vop_default_desc, vn_default_error },
61c6c16cd0Sdholland { &vop_parsepath_desc, genfs_parsepath }, /* parsepath */
6241715070Sdholland { &vop_lookup_desc, genfs_badop }, /* lookup */
6341715070Sdholland { &vop_create_desc, genfs_badop }, /* create */
6441715070Sdholland { &vop_mknod_desc, genfs_badop }, /* mknod */
65264b874cSmycroft { &vop_open_desc, mfs_open }, /* open */
66264b874cSmycroft { &vop_close_desc, mfs_close }, /* close */
6741715070Sdholland { &vop_access_desc, genfs_badop }, /* access */
6841715070Sdholland { &vop_accessx_desc, genfs_badop }, /* accessx */
6941715070Sdholland { &vop_getattr_desc, genfs_badop }, /* getattr */
7041715070Sdholland { &vop_setattr_desc, genfs_badop }, /* setattr */
7141715070Sdholland { &vop_read_desc, genfs_badop }, /* read */
7241715070Sdholland { &vop_write_desc, genfs_badop }, /* write */
7305d075b3Sdholland { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */
7405d075b3Sdholland { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */
7541715070Sdholland { &vop_ioctl_desc, genfs_enoioctl }, /* ioctl */
7641715070Sdholland { &vop_poll_desc, genfs_badop }, /* poll */
7741715070Sdholland { &vop_revoke_desc, genfs_revoke }, /* revoke */
7841715070Sdholland { &vop_mmap_desc, genfs_badop }, /* mmap */
79ee16aae1Schristos { &vop_fsync_desc, spec_fsync }, /* fsync */
8041715070Sdholland { &vop_seek_desc, genfs_badop }, /* seek */
8141715070Sdholland { &vop_remove_desc, genfs_badop }, /* remove */
8241715070Sdholland { &vop_link_desc, genfs_badop }, /* link */
8341715070Sdholland { &vop_rename_desc, genfs_badop }, /* rename */
8441715070Sdholland { &vop_mkdir_desc, genfs_badop }, /* mkdir */
8541715070Sdholland { &vop_rmdir_desc, genfs_badop }, /* rmdir */
8641715070Sdholland { &vop_symlink_desc, genfs_badop }, /* symlink */
8741715070Sdholland { &vop_readdir_desc, genfs_badop }, /* readdir */
8841715070Sdholland { &vop_readlink_desc, genfs_badop }, /* readlink */
8941715070Sdholland { &vop_abortop_desc, genfs_badop }, /* abortop */
90264b874cSmycroft { &vop_inactive_desc, mfs_inactive }, /* inactive */
91264b874cSmycroft { &vop_reclaim_desc, mfs_reclaim }, /* reclaim */
92*f38668ffShannken { &vop_lock_desc, genfs_lock }, /* lock */
93*f38668ffShannken { &vop_unlock_desc, genfs_unlock }, /* unlock */
94264b874cSmycroft { &vop_bmap_desc, mfs_bmap }, /* bmap */
95264b874cSmycroft { &vop_strategy_desc, mfs_strategy }, /* strategy */
96264b874cSmycroft { &vop_print_desc, mfs_print }, /* print */
97*f38668ffShannken { &vop_islocked_desc, genfs_islocked }, /* islocked */
9841715070Sdholland { &vop_pathconf_desc, genfs_badop }, /* pathconf */
9941715070Sdholland { &vop_advlock_desc, genfs_badop }, /* advlock */
10041715070Sdholland { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
10141715070Sdholland { &vop_putpages_desc, genfs_null_putpages }, /* putpages */
1025a690c92Schs { NULL, NULL }
103264b874cSmycroft };
104d9466585Sjdolecek const struct vnodeopv_desc mfs_vnodeop_opv_desc =
105264b874cSmycroft { &mfs_vnodeop_p, mfs_vnodeop_entries };
106264b874cSmycroft
107264b874cSmycroft /*
108264b874cSmycroft * Vnode Operations.
109264b874cSmycroft *
110264b874cSmycroft * Open called to allow memory filesystem to initialize and
111264b874cSmycroft * validate before actual IO. Record our process identifier
112264b874cSmycroft * so we can tell when we are doing I/O to ourself.
113264b874cSmycroft */
114264b874cSmycroft /* ARGSUSED */
115264b874cSmycroft int
mfs_open(void * v)11623ebf62dSxtraeme mfs_open(void *v)
117573481f5Schristos {
118264b874cSmycroft struct vop_open_args /* {
119264b874cSmycroft struct vnode *a_vp;
120264b874cSmycroft int a_mode;
121fc9422c9Selad kauth_cred_t a_cred;
122573481f5Schristos } */ *ap = v;
123264b874cSmycroft
124264b874cSmycroft if (ap->a_vp->v_type != VBLK) {
12541715070Sdholland panic("mfs_open not VBLK");
126264b874cSmycroft /* NOTREACHED */
127264b874cSmycroft }
128264b874cSmycroft return (0);
129264b874cSmycroft }
130264b874cSmycroft
131264b874cSmycroft /*
132264b874cSmycroft * Pass I/O requests to the memory filesystem process.
133264b874cSmycroft */
134264b874cSmycroft int
mfs_strategy(void * v)13523ebf62dSxtraeme mfs_strategy(void *v)
136573481f5Schristos {
137264b874cSmycroft struct vop_strategy_args /* {
13884b45bc3Shannken struct vnode *a_vp;
139264b874cSmycroft struct buf *a_bp;
140573481f5Schristos } */ *ap = v;
14184b45bc3Shannken struct vnode *vp = ap->a_vp;
142169ac5b3Saugustss struct buf *bp = ap->a_bp;
143169ac5b3Saugustss struct mfsnode *mfsp;
144264b874cSmycroft
14523bf8800Sad if (vp->v_type != VBLK || vrefcnt(vp) == 0)
146264b874cSmycroft panic("mfs_strategy: bad dev");
147264b874cSmycroft mfsp = VTOMFS(vp);
1485026e056Sthorpej /* check for mini-root access */
1495026e056Sthorpej if (mfsp->mfs_proc == NULL) {
15053524e44Schristos void *base;
151264b874cSmycroft
15253524e44Schristos base = (char *)mfsp->mfs_baseoff + (bp->b_blkno << DEV_BSHIFT);
153264b874cSmycroft if (bp->b_flags & B_READ)
15427ca6798Sperry memcpy(bp->b_data, base, bp->b_bcount);
155264b874cSmycroft else
15627ca6798Sperry memcpy(base, bp->b_data, bp->b_bcount);
157053e3ba1Sthorpej bp->b_resid = 0;
1585026e056Sthorpej biodone(bp);
159110d5cc2Sad } else if (mfsp->mfs_proc == curproc) {
1605026e056Sthorpej mfs_doio(bp, mfsp->mfs_baseoff);
161c4ae18d0Ssommerfeld } else if (doing_shutdown) {
162c4ae18d0Ssommerfeld /*
163c4ae18d0Ssommerfeld * bitbucket I/O during shutdown.
164c4ae18d0Ssommerfeld * Note that reads should *not* happen here, but..
165c4ae18d0Ssommerfeld */
166c4ae18d0Ssommerfeld if (bp->b_flags & B_READ)
167c4ae18d0Ssommerfeld printf("warning: mfs read during shutdown\n");
168053e3ba1Sthorpej bp->b_resid = 0;
169c4ae18d0Ssommerfeld biodone(bp);
1705026e056Sthorpej } else {
171021b86ddSad mutex_enter(&mfs_lock);
17270de9736Syamt bufq_put(mfsp->mfs_buflist, bp);
173110d5cc2Sad cv_broadcast(&mfsp->mfs_cv);
174021b86ddSad mutex_exit(&mfs_lock);
1755026e056Sthorpej }
1765026e056Sthorpej return (0);
1775026e056Sthorpej }
1785026e056Sthorpej
179264b874cSmycroft /*
1805026e056Sthorpej * Memory file system I/O.
181264b874cSmycroft */
1825026e056Sthorpej void
mfs_doio(struct buf * bp,void * base)18353524e44Schristos mfs_doio(struct buf *bp, void *base)
1845026e056Sthorpej {
185110d5cc2Sad
18653524e44Schristos base = (char *)base + (bp->b_blkno << DEV_BSHIFT);
187264b874cSmycroft if (bp->b_flags & B_READ)
188264b874cSmycroft bp->b_error = copyin(base, bp->b_data, bp->b_bcount);
189264b874cSmycroft else
190264b874cSmycroft bp->b_error = copyout(bp->b_data, base, bp->b_bcount);
191a0d1fd8dSad if (bp->b_error == 0)
192462ac411Schs bp->b_resid = 0;
193264b874cSmycroft biodone(bp);
194264b874cSmycroft }
195264b874cSmycroft
196264b874cSmycroft /*
197264b874cSmycroft * This is a noop, simply returning what one has been given.
198264b874cSmycroft */
199264b874cSmycroft int
mfs_bmap(void * v)20023ebf62dSxtraeme mfs_bmap(void *v)
201573481f5Schristos {
202264b874cSmycroft struct vop_bmap_args /* {
203264b874cSmycroft struct vnode *a_vp;
204264b874cSmycroft daddr_t a_bn;
205264b874cSmycroft struct vnode **a_vpp;
206264b874cSmycroft daddr_t *a_bnp;
207264b874cSmycroft int *a_runp;
208573481f5Schristos } */ *ap = v;
209264b874cSmycroft
210264b874cSmycroft if (ap->a_vpp != NULL)
211264b874cSmycroft *ap->a_vpp = ap->a_vp;
212264b874cSmycroft if (ap->a_bnp != NULL)
213264b874cSmycroft *ap->a_bnp = ap->a_bn;
214e5bc90f4Sfvdl if (ap->a_runp != NULL)
215e5bc90f4Sfvdl *ap->a_runp = 0;
216264b874cSmycroft return (0);
217264b874cSmycroft }
218264b874cSmycroft
219264b874cSmycroft /*
220264b874cSmycroft * Memory filesystem close routine
221264b874cSmycroft */
222264b874cSmycroft /* ARGSUSED */
223264b874cSmycroft int
mfs_close(void * v)22423ebf62dSxtraeme mfs_close(void *v)
225573481f5Schristos {
226264b874cSmycroft struct vop_close_args /* {
227264b874cSmycroft struct vnode *a_vp;
228264b874cSmycroft int a_fflag;
229fc9422c9Selad kauth_cred_t a_cred;
230573481f5Schristos } */ *ap = v;
231169ac5b3Saugustss struct vnode *vp = ap->a_vp;
232169ac5b3Saugustss struct mfsnode *mfsp = VTOMFS(vp);
2335026e056Sthorpej struct buf *bp;
234264b874cSmycroft int error;
235264b874cSmycroft
236264b874cSmycroft /*
2375026e056Sthorpej * Finish any pending I/O requests.
2385026e056Sthorpej */
239021b86ddSad mutex_enter(&mfs_lock);
24070de9736Syamt while ((bp = bufq_get(mfsp->mfs_buflist)) != NULL) {
241021b86ddSad mutex_exit(&mfs_lock);
2425026e056Sthorpej mfs_doio(bp, mfsp->mfs_baseoff);
243021b86ddSad mutex_enter(&mfs_lock);
2445026e056Sthorpej }
245021b86ddSad mutex_exit(&mfs_lock);
2465026e056Sthorpej /*
247264b874cSmycroft * On last close of a memory filesystem
248264b874cSmycroft * we must invalidate any in core blocks, so that
249264b874cSmycroft * we can, free up its vnode.
250264b874cSmycroft */
25161e8303eSpooka if ((error = vinvalbuf(vp, V_SAVE, ap->a_cred, curlwp, 0, 0)) != 0)
252264b874cSmycroft return (error);
253264b874cSmycroft /*
254264b874cSmycroft * There should be no way to have any more uses of this
255264b874cSmycroft * vnode, so if we find any other uses, it is a panic.
256264b874cSmycroft */
25770de9736Syamt if (bufq_peek(mfsp->mfs_buflist) != NULL)
258264b874cSmycroft panic("mfs_close");
259264b874cSmycroft /*
260264b874cSmycroft * Send a request to the filesystem server to exit.
261264b874cSmycroft */
262021b86ddSad mutex_enter(&mfs_lock);
263d4c062b4Shannken mfsp->mfs_shutdown = 1;
264110d5cc2Sad cv_broadcast(&mfsp->mfs_cv);
265021b86ddSad mutex_exit(&mfs_lock);
266264b874cSmycroft return (0);
267264b874cSmycroft }
268264b874cSmycroft
269264b874cSmycroft /*
270264b874cSmycroft * Memory filesystem inactive routine
271264b874cSmycroft */
272264b874cSmycroft /* ARGSUSED */
273264b874cSmycroft int
mfs_inactive(void * v)27423ebf62dSxtraeme mfs_inactive(void *v)
275573481f5Schristos {
27687fb3229Sriastradh struct vop_inactive_v2_args /* {
277264b874cSmycroft struct vnode *a_vp;
278573481f5Schristos } */ *ap = v;
279e5bc90f4Sfvdl struct vnode *vp = ap->a_vp;
280e5bc90f4Sfvdl struct mfsnode *mfsp = VTOMFS(vp);
281264b874cSmycroft
28270de9736Syamt if (bufq_peek(mfsp->mfs_buflist) != NULL)
28348fda0b4Schristos panic("mfs_inactive: not inactive (mfs_buflist %p)",
28470de9736Syamt bufq_peek(mfsp->mfs_buflist));
2852547f842Shannken
2862547f842Shannken return VOCALL(spec_vnodeop_p, VOFFSET(vop_inactive), ap);
287264b874cSmycroft }
288264b874cSmycroft
289264b874cSmycroft /*
290264b874cSmycroft * Reclaim a memory filesystem devvp so that it can be reused.
291264b874cSmycroft */
292264b874cSmycroft int
mfs_reclaim(void * v)29323ebf62dSxtraeme mfs_reclaim(void *v)
294573481f5Schristos {
2957f7aad09Sriastradh struct vop_reclaim_v2_args /* {
296264b874cSmycroft struct vnode *a_vp;
297573481f5Schristos } */ *ap = v;
298169ac5b3Saugustss struct vnode *vp = ap->a_vp;
299110d5cc2Sad struct mfsnode *mfsp = VTOMFS(vp);
300021b86ddSad int refcnt;
301110d5cc2Sad
302021b86ddSad mutex_enter(&mfs_lock);
303264b874cSmycroft vp->v_data = NULL;
304021b86ddSad refcnt = --mfsp->mfs_refcnt;
305021b86ddSad mutex_exit(&mfs_lock);
306021b86ddSad
307021b86ddSad if (refcnt == 0) {
308021b86ddSad bufq_free(mfsp->mfs_buflist);
309021b86ddSad cv_destroy(&mfsp->mfs_cv);
310021b86ddSad kmem_free(mfsp, sizeof(*mfsp));
311021b86ddSad }
312021b86ddSad
3132547f842Shannken return VOCALL(spec_vnodeop_p, VOFFSET(vop_reclaim), ap);
314264b874cSmycroft }
315264b874cSmycroft
316264b874cSmycroft /*
317264b874cSmycroft * Print out the contents of an mfsnode.
318264b874cSmycroft */
319264b874cSmycroft int
mfs_print(void * v)32023ebf62dSxtraeme mfs_print(void *v)
321573481f5Schristos {
322264b874cSmycroft struct vop_print_args /* {
323264b874cSmycroft struct vnode *a_vp;
324573481f5Schristos } */ *ap = v;
325169ac5b3Saugustss struct mfsnode *mfsp = VTOMFS(ap->a_vp);
326264b874cSmycroft
3276d7f14dcSthorpej printf("tag VT_MFS, pid %d, base %p, size %ld\n",
3286d7f14dcSthorpej (mfsp->mfs_proc != NULL) ? mfsp->mfs_proc->p_pid : 0,
3299c956342Scgd mfsp->mfs_baseoff, mfsp->mfs_size);
330264b874cSmycroft return (0);
331264b874cSmycroft }
332