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