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