1 /* ufs_vfsops.c 6.1 83/07/29 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/inode.h" 8 #include "../h/proc.h" 9 #include "../h/fs.h" 10 #include "../h/buf.h" 11 #include "../h/mount.h" 12 #include "../h/file.h" 13 #include "../h/nami.h" 14 #include "../h/conf.h" 15 16 smount() 17 { 18 register struct a { 19 char *fspec; 20 char *freg; 21 int ronly; 22 } *uap; 23 dev_t dev; 24 register struct inode *ip; 25 register struct fs *fs; 26 register char *cp; 27 28 uap = (struct a *)u.u_ap; 29 u.u_error = getmdev(&dev); 30 if (u.u_error) 31 return; 32 u.u_dirp = (caddr_t)uap->freg; 33 ip = namei(uchar, LOOKUP, 1); 34 if (ip == NULL) 35 return; 36 if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR) { 37 iput(ip); 38 u.u_error = EBUSY; 39 return; 40 } 41 fs = mountfs(dev, uap->ronly, ip); 42 if (fs == 0) 43 return; 44 u.u_dirp = uap->freg; 45 for (cp = fs->fs_fsmnt; cp < &fs->fs_fsmnt[sizeof(fs->fs_fsmnt) - 2]; ) 46 if ((*cp++ = uchar()) == 0) 47 u.u_dirp--; /* get 0 again */ 48 *cp = 0; 49 } 50 51 /* this routine has lousy error codes */ 52 /* this routine has races if running twice */ 53 struct fs * 54 mountfs(dev, ronly, ip) 55 dev_t dev; 56 int ronly; 57 struct inode *ip; 58 { 59 register struct mount *mp = 0; 60 struct buf *tp = 0; 61 register struct buf *bp = 0; 62 register struct fs *fs; 63 int blks; 64 caddr_t space; 65 int i, size; 66 67 u.u_error = 68 (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE); 69 if (u.u_error) { 70 u.u_error = EIO; 71 goto out; 72 } 73 tp = bread(dev, SBLOCK, SBSIZE); 74 if (tp->b_flags & B_ERROR) 75 goto out; 76 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 77 if (mp->m_bufp != 0 && dev == mp->m_dev) { 78 mp = 0; 79 goto out; 80 } 81 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 82 if (mp->m_bufp == 0) 83 goto found; 84 mp = 0; 85 goto out; 86 found: 87 mp->m_bufp = tp; /* just to reserve this slot */ 88 mp->m_dev = NODEV; 89 fs = tp->b_un.b_fs; 90 bp = geteblk((int)fs->fs_sbsize); 91 mp->m_bufp = bp; 92 bcopy((caddr_t)tp->b_un.b_addr, (caddr_t)bp->b_un.b_addr, 93 (u_int)fs->fs_sbsize); 94 brelse(tp); 95 tp = 0; 96 fs = bp->b_un.b_fs; 97 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE) 98 goto out; 99 fs->fs_ronly = (ronly != 0); 100 if (ronly == 0) 101 fs->fs_fmod = 1; 102 blks = howmany(fs->fs_cssize, fs->fs_fsize); 103 space = wmemall(vmemall, (int)fs->fs_cssize); 104 if (space == 0) 105 goto out; 106 for (i = 0; i < blks; i += fs->fs_frag) { 107 size = fs->fs_bsize; 108 if (i + fs->fs_frag > blks) 109 size = (blks - i) * fs->fs_fsize; 110 tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size); 111 if (tp->b_flags&B_ERROR) { 112 wmemfree(space, (int)fs->fs_cssize); 113 goto out; 114 } 115 bcopy((caddr_t)tp->b_un.b_addr, space, (u_int)size); 116 fs->fs_csp[i / fs->fs_frag] = (struct csum *)space; 117 space += size; 118 brelse(tp); 119 tp = 0; 120 } 121 mp->m_inodp = ip; 122 mp->m_dev = dev; 123 if (ip) { 124 ip->i_flag |= IMOUNT; 125 iunlock(ip); 126 } 127 return (fs); 128 out: 129 u.u_error = EBUSY; 130 if (ip) 131 iput(ip); 132 if (mp) 133 mp->m_bufp = 0; 134 if (bp) 135 brelse(bp); 136 if (tp) 137 brelse(tp); 138 return (0); 139 } 140 141 umount() 142 { 143 struct a { 144 char *fspec; 145 }; 146 147 u.u_error = unmount1(0); 148 } 149 150 unmount1(forcibly) 151 int forcibly; 152 { 153 dev_t dev; 154 register struct mount *mp; 155 int stillopen, flag, error; 156 register struct inode *ip; 157 register struct fs *fs; 158 159 error = getmdev(&dev); 160 if (error) 161 return (error); 162 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 163 if (mp->m_bufp != NULL && dev == mp->m_dev) 164 goto found; 165 return (EINVAL); 166 found: 167 xumount(dev); /* remove unused sticky files from text table */ 168 update(); 169 #ifdef QUOTA 170 if ((stillopen = iflush(dev, mp->m_qinod)) < 0 && !forcibly) 171 #else 172 if ((stillopen = iflush(dev)) < 0 && !forcibly) 173 #endif 174 return (EBUSY); 175 if (stillopen < 0) 176 return (EBUSY); /* XXX */ 177 #ifdef QUOTA 178 closedq(mp); 179 /* 180 * Here we have to iflush again to get rid of the quota inode. 181 * A drag, but it would be ugly to cheat, & this doesn't happen often 182 */ 183 (void)iflush(dev, (struct inode *)NULL); 184 #endif 185 ip = mp->m_inodp; 186 ip->i_flag &= ~IMOUNT; 187 irele(ip); 188 fs = mp->m_bufp->b_un.b_fs; 189 wmemfree((caddr_t)fs->fs_csp[0], (int)fs->fs_cssize); 190 flag = !fs->fs_ronly; 191 brelse(mp->m_bufp); 192 mp->m_bufp = 0; 193 mp->m_dev = 0; 194 mpurge(mp - &mount[0]); 195 if (!stillopen) { 196 (*bdevsw[major(dev)].d_close)(dev, flag); 197 binval(dev); 198 } 199 return (0); 200 } 201 202 sbupdate(mp) 203 struct mount *mp; 204 { 205 register struct fs *fs = mp->m_bufp->b_un.b_fs; 206 register struct buf *bp; 207 int blks; 208 caddr_t space; 209 int i, size; 210 211 bp = getblk(mp->m_dev, SBLOCK, (int)fs->fs_sbsize); 212 bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 213 bwrite(bp); 214 blks = howmany(fs->fs_cssize, fs->fs_fsize); 215 space = (caddr_t)fs->fs_csp[0]; 216 for (i = 0; i < blks; i += fs->fs_frag) { 217 size = fs->fs_bsize; 218 if (i + fs->fs_frag > blks) 219 size = (blks - i) * fs->fs_fsize; 220 bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size); 221 bcopy(space, bp->b_un.b_addr, (u_int)size); 222 space += size; 223 bwrite(bp); 224 } 225 } 226 227 /* 228 * Common code for mount and umount. 229 * Check that the user's argument is a reasonable 230 * thing on which to mount, and return the device number if so. 231 */ 232 getmdev(pdev) 233 dev_t *pdev; 234 { 235 dev_t dev; 236 register struct inode *ip; 237 238 if (!suser()) 239 return (u.u_error); 240 ip = namei(uchar, LOOKUP, 1); 241 if (ip == NULL) 242 return (u.u_error); 243 if ((ip->i_mode&IFMT) != IFBLK) 244 return (ENOTBLK); 245 dev = (dev_t)ip->i_rdev; 246 if (major(dev) >= nblkdev) 247 return (ENXIO); 248 iput(ip); 249 *pdev = dev; 250 return (0); 251 } 252