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