xref: /original-bsd/sys/kern/vfs_subr.c (revision fbc8b8c6)
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  *
17  *	@(#)vfs_subr.c	7.1 (Berkeley) 04/24/89
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"
28 #include "errno.h"
29 
30 /*
31  * Add a new mount point to the list of mounted filesystems.
32  * Lock the filesystem so that namei will not cross into the
33  * the tree below the covered vnode.
34  */
35 vfs_add(mountedvp, mp, flags)
36 	register struct vnode *mountedvp;
37 	register struct mount *mp;
38 	int flags;
39 {
40 	register int error;
41 
42 	error = vfs_lock(mp);
43 	if (error)
44 		return (error);
45 	if (mountedvp == (struct vnode *)0) {
46 		/*
47 		 * We are mounting the root filesystem.
48 		 */
49 		rootfs = mp;
50 		mp->m_next = mp;
51 		mp->m_prev = mp;
52 	} else {
53 		if (mountedvp->v_mountedhere != (struct mount *)0) {
54 			vfs_unlock(mp);
55 			return(EBUSY);
56 		}
57 		/*
58 		 * Put the new filesystem on the mount list after root.
59 		 */
60 		mp->m_next = rootfs->m_next;
61 		mp->m_prev = rootfs;
62 		rootfs->m_next = mp;
63 		mp->m_next->m_prev = mp;
64 		mountedvp->v_mountedhere = mp;
65 	}
66 	mp->m_vnodecovered = mountedvp;
67 	if (flags & M_RDONLY) {
68 		mp->m_flag |= M_RDONLY;
69 	} else {
70 		mp->m_flag &= ~M_RDONLY;
71 	}
72 	if (flags & M_NOSUID) {
73 		mp->m_flag |= M_NOSUID;
74 	} else {
75 		mp->m_flag &= ~M_NOSUID;
76 	}
77 	return (0);
78 }
79 
80 /*
81  * Remove a mount point from the list of mounted filesystems.
82  * Unmount of the root is illegal.
83  */
84 void
85 vfs_remove(mp)
86 	register struct mount *mp;
87 {
88 
89 	if (mp == rootfs)
90 		panic("vfs_remove: unmounting root");
91 	mp->m_prev->m_next = mp->m_next;
92 	mp->m_next->m_prev = mp->m_prev;
93 	mp->m_vnodecovered->v_mountedhere = (struct mount *)0;
94 	vfs_unlock(mp);
95 }
96 
97 /*
98  * Lock a filesystem.
99  * Used to prevent access to it while mounting and unmounting.
100  */
101 vfs_lock(mp)
102 	register struct mount *mp;
103 {
104 
105 	if (mp->m_flag & M_MLOCK)
106 		return (EBUSY);
107 	mp->m_flag |= M_MLOCK;
108 	return (0);
109 }
110 
111 /*
112  * Unlock a locked filesystem.
113  * Panic if filesystem is not locked.
114  */
115 void
116 vfs_unlock(mp)
117 	register struct mount *mp;
118 {
119 
120 	if ((mp->m_flag & M_MLOCK) == 0)
121 		panic("vfs_unlock: locked fs");
122 	mp->m_flag &= ~M_MLOCK;
123 	if (mp->m_flag & M_MWAIT) {
124 		mp->m_flag &= ~M_MWAIT;
125 		wakeup((caddr_t)mp);
126 	}
127 }
128 
129 /*
130  * Lookup a mount point by filesystem identifier.
131  */
132 struct mount *
133 getvfs(fsid)
134 	fsid_t *fsid;
135 {
136 	register struct mount *mp;
137 
138 	for (mp = rootfs; mp; mp = mp->m_next) {
139 		if (mp->m_fsid.val[0] == fsid->val[0] &&
140 		    mp->m_fsid.val[1] == fsid->val[1]) {
141 			break;
142 		}
143 	}
144 	return (mp);
145 }
146 
147 /*
148  * Set vnode attributes to VNOVAL
149  */
150 void vattr_null(vap)
151 	register struct vattr *vap;
152 {
153 
154 	vap->va_type = VNON;
155 	vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
156 		vap->va_fsid = vap->va_fileid = vap->va_size =
157 		vap->va_size1 = vap->va_blocksize = vap->va_rdev =
158 		vap->va_bytes = vap->va_bytes1 =
159 		vap->va_atime.tv_sec = vap->va_atime.tv_usec =
160 		vap->va_mtime.tv_sec = vap->va_mtime.tv_usec =
161 		vap->va_ctime.tv_sec = vap->va_ctime.tv_usec = VNOVAL;
162 }
163