have to set the base before each uio
[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 *
c60798ca 17 * @(#)vfs_subr.c 7.3 (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
140 for (mp = rootfs; mp; mp = mp->m_next) {
141 if (mp->m_fsid.val[0] == fsid->val[0] &&
142 mp->m_fsid.val[1] == fsid->val[1]) {
143 break;
144 }
145 }
146 return (mp);
147}
148
149/*
150 * Set vnode attributes to VNOVAL
151 */
152void vattr_null(vap)
153 register struct vattr *vap;
154{
155
156 vap->va_type = VNON;
157 vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
158 vap->va_fsid = vap->va_fileid = vap->va_size =
159 vap->va_size1 = vap->va_blocksize = vap->va_rdev =
160 vap->va_bytes = vap->va_bytes1 =
161 vap->va_atime.tv_sec = vap->va_atime.tv_usec =
162 vap->va_mtime.tv_sec = vap->va_mtime.tv_usec =
8cf4d4fb
KM
163 vap->va_ctime.tv_sec = vap->va_ctime.tv_usec =
164 vap->va_flags = vap->va_gen = VNOVAL;
3c4390e8 165}
c60798ca
KM
166
167/*
168 * Initialize a nameidata structure
169 */
170ndinit(ndp)
171 register struct nameidata *ndp;
172{
173
174 bzero((caddr_t)ndp, sizeof(struct nameidata));
175 ndp->ni_iov = &ndp->ni_nd.nd_iovec;
176 ndp->ni_iovcnt = 1;
177 ndp->ni_base = (caddr_t)&ndp->ni_dent;
178 ndp->ni_rw = UIO_WRITE;
179 ndp->ni_segflg = UIO_SYSSPACE;
180}
181
182/*
183 * Duplicate a nameidata structure
184 */
185nddup(ndp, newndp)
186 register struct nameidata *ndp, *newndp;
187{
188
189 ndinit(newndp);
190 newndp->ni_cdir = ndp->ni_cdir;
191 newndp->ni_cdir->v_count++;
192 newndp->ni_rdir = ndp->ni_rdir;
193 if (newndp->ni_rdir)
194 newndp->ni_rdir->v_count++;
195 newndp->ni_cred = ndp->ni_cred;
196 crhold(newndp->ni_cred);
197}
198
199/*
200 * Release a nameidata structure
201 */
202ndrele(ndp)
203 register struct nameidata *ndp;
204{
205
206 vrele(ndp->ni_cdir);
207 if (ndp->ni_rdir)
208 vrele(ndp->ni_rdir);
209 crfree(ndp->ni_cred);
210}