add VFS_START call for memory filesystem;
[unix-history] / usr / src / sys / kern / vfs_subr.c
CommitLineData
3c4390e8
KM
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 *
8fe1c702 17 * @(#)vfs_subr.c 7.5 (Berkeley) %G%
3c4390e8
KM
18 */
19
20/*
21 * External virtual filesystem routines
22 */
23
24#include "param.h"
25#include "mount.h"
26#include "time.h"
27#include "vnode.h"
c60798ca
KM
28#include "namei.h"
29#include "ucred.h"
3c4390e8
KM
30#include "errno.h"
31
32/*
33 * Add a new mount point to the list of mounted filesystems.
34 * Lock the filesystem so that namei will not cross into the
35 * the tree below the covered vnode.
36 */
37vfs_add(mountedvp, mp, flags)
38 register struct vnode *mountedvp;
39 register struct mount *mp;
40 int flags;
41{
42 register int error;
43
44 error = vfs_lock(mp);
45 if (error)
46 return (error);
47 if (mountedvp == (struct vnode *)0) {
48 /*
49 * We are mounting the root filesystem.
50 */
51 rootfs = mp;
52 mp->m_next = mp;
53 mp->m_prev = mp;
54 } else {
55 if (mountedvp->v_mountedhere != (struct mount *)0) {
56 vfs_unlock(mp);
57 return(EBUSY);
58 }
59 /*
60 * Put the new filesystem on the mount list after root.
61 */
62 mp->m_next = rootfs->m_next;
63 mp->m_prev = rootfs;
64 rootfs->m_next = mp;
65 mp->m_next->m_prev = mp;
66 mountedvp->v_mountedhere = mp;
67 }
68 mp->m_vnodecovered = mountedvp;
69 if (flags & M_RDONLY) {
70 mp->m_flag |= M_RDONLY;
71 } else {
72 mp->m_flag &= ~M_RDONLY;
73 }
74 if (flags & M_NOSUID) {
75 mp->m_flag |= M_NOSUID;
76 } else {
77 mp->m_flag &= ~M_NOSUID;
78 }
79 return (0);
80}
81
82/*
83 * Remove a mount point from the list of mounted filesystems.
84 * Unmount of the root is illegal.
85 */
86void
87vfs_remove(mp)
88 register struct mount *mp;
89{
90
91 if (mp == rootfs)
92 panic("vfs_remove: unmounting root");
93 mp->m_prev->m_next = mp->m_next;
94 mp->m_next->m_prev = mp->m_prev;
95 mp->m_vnodecovered->v_mountedhere = (struct mount *)0;
96 vfs_unlock(mp);
97}
98
99/*
100 * Lock a filesystem.
101 * Used to prevent access to it while mounting and unmounting.
102 */
103vfs_lock(mp)
104 register struct mount *mp;
105{
106
107 if (mp->m_flag & M_MLOCK)
108 return (EBUSY);
109 mp->m_flag |= M_MLOCK;
110 return (0);
111}
112
113/*
114 * Unlock a locked filesystem.
115 * Panic if filesystem is not locked.
116 */
117void
118vfs_unlock(mp)
119 register struct mount *mp;
120{
121
122 if ((mp->m_flag & M_MLOCK) == 0)
123 panic("vfs_unlock: locked fs");
124 mp->m_flag &= ~M_MLOCK;
125 if (mp->m_flag & M_MWAIT) {
126 mp->m_flag &= ~M_MWAIT;
127 wakeup((caddr_t)mp);
128 }
129}
130
131/*
132 * Lookup a mount point by filesystem identifier.
133 */
134struct mount *
135getvfs(fsid)
136 fsid_t *fsid;
137{
138 register struct mount *mp;
139
d713f801
KM
140 mp = rootfs;
141 do {
3c4390e8
KM
142 if (mp->m_fsid.val[0] == fsid->val[0] &&
143 mp->m_fsid.val[1] == fsid->val[1]) {
d713f801 144 return (mp);
3c4390e8 145 }
d713f801
KM
146 mp = mp->m_next;
147 } while (mp != rootfs);
148 return ((struct mount *)0);
3c4390e8
KM
149}
150
151/*
152 * Set vnode attributes to VNOVAL
153 */
154void vattr_null(vap)
155 register struct vattr *vap;
156{
157
158 vap->va_type = VNON;
159 vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
160 vap->va_fsid = vap->va_fileid = vap->va_size =
161 vap->va_size1 = vap->va_blocksize = vap->va_rdev =
162 vap->va_bytes = vap->va_bytes1 =
163 vap->va_atime.tv_sec = vap->va_atime.tv_usec =
164 vap->va_mtime.tv_sec = vap->va_mtime.tv_usec =
8cf4d4fb
KM
165 vap->va_ctime.tv_sec = vap->va_ctime.tv_usec =
166 vap->va_flags = vap->va_gen = VNOVAL;
3c4390e8 167}
c60798ca
KM
168
169/*
170 * Initialize a nameidata structure
171 */
172ndinit(ndp)
173 register struct nameidata *ndp;
174{
175
176 bzero((caddr_t)ndp, sizeof(struct nameidata));
177 ndp->ni_iov = &ndp->ni_nd.nd_iovec;
178 ndp->ni_iovcnt = 1;
179 ndp->ni_base = (caddr_t)&ndp->ni_dent;
180 ndp->ni_rw = UIO_WRITE;
181 ndp->ni_segflg = UIO_SYSSPACE;
182}
183
184/*
185 * Duplicate a nameidata structure
186 */
187nddup(ndp, newndp)
188 register struct nameidata *ndp, *newndp;
189{
190
191 ndinit(newndp);
192 newndp->ni_cdir = ndp->ni_cdir;
8fe1c702 193 VREF(newndp->ni_cdir);
c60798ca
KM
194 newndp->ni_rdir = ndp->ni_rdir;
195 if (newndp->ni_rdir)
8fe1c702 196 VREF(newndp->ni_rdir);
c60798ca
KM
197 newndp->ni_cred = ndp->ni_cred;
198 crhold(newndp->ni_cred);
199}
200
201/*
202 * Release a nameidata structure
203 */
204ndrele(ndp)
205 register struct nameidata *ndp;
206{
207
208 vrele(ndp->ni_cdir);
209 if (ndp->ni_rdir)
210 vrele(ndp->ni_rdir);
211 crfree(ndp->ni_cred);
212}