1*15800Smckusick /* lfs_vfsops.c 6.2 84/01/03 */ 212795Ssam 312795Ssam #include "../h/param.h" 412795Ssam #include "../h/systm.h" 512795Ssam #include "../h/dir.h" 612795Ssam #include "../h/user.h" 712795Ssam #include "../h/inode.h" 812795Ssam #include "../h/proc.h" 912795Ssam #include "../h/fs.h" 1012795Ssam #include "../h/buf.h" 1112795Ssam #include "../h/mount.h" 1212795Ssam #include "../h/file.h" 1312795Ssam #include "../h/nami.h" 1412795Ssam #include "../h/conf.h" 1512795Ssam 1612795Ssam smount() 1712795Ssam { 1812795Ssam register struct a { 1912795Ssam char *fspec; 2012795Ssam char *freg; 2112795Ssam int ronly; 2212795Ssam } *uap; 2312795Ssam dev_t dev; 2412795Ssam register struct inode *ip; 2512795Ssam register struct fs *fs; 2612795Ssam register char *cp; 2712795Ssam 2812795Ssam uap = (struct a *)u.u_ap; 2912795Ssam u.u_error = getmdev(&dev); 3012795Ssam if (u.u_error) 3112795Ssam return; 3212795Ssam u.u_dirp = (caddr_t)uap->freg; 33*15800Smckusick ip = namei(uchar, LOOKUP | NOCACHE, 1); 3412795Ssam if (ip == NULL) 3512795Ssam return; 3612795Ssam if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR) { 3712795Ssam iput(ip); 3812795Ssam u.u_error = EBUSY; 3912795Ssam return; 4012795Ssam } 4112795Ssam fs = mountfs(dev, uap->ronly, ip); 4212795Ssam if (fs == 0) 4312795Ssam return; 4412795Ssam u.u_dirp = uap->freg; 4512795Ssam for (cp = fs->fs_fsmnt; cp < &fs->fs_fsmnt[sizeof(fs->fs_fsmnt) - 2]; ) 4612795Ssam if ((*cp++ = uchar()) == 0) 4712795Ssam u.u_dirp--; /* get 0 again */ 4812795Ssam *cp = 0; 4912795Ssam } 5012795Ssam 5112795Ssam /* this routine has lousy error codes */ 5212795Ssam /* this routine has races if running twice */ 5312795Ssam struct fs * 5412795Ssam mountfs(dev, ronly, ip) 5512795Ssam dev_t dev; 5612795Ssam int ronly; 5712795Ssam struct inode *ip; 5812795Ssam { 5912795Ssam register struct mount *mp = 0; 6012795Ssam struct buf *tp = 0; 6112795Ssam register struct buf *bp = 0; 6212795Ssam register struct fs *fs; 6312795Ssam int blks; 6412795Ssam caddr_t space; 6512795Ssam int i, size; 6612795Ssam 6712795Ssam u.u_error = 6812795Ssam (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE); 6912795Ssam if (u.u_error) { 7012795Ssam u.u_error = EIO; 7112795Ssam goto out; 7212795Ssam } 7312795Ssam tp = bread(dev, SBLOCK, SBSIZE); 7412795Ssam if (tp->b_flags & B_ERROR) 7512795Ssam goto out; 7612795Ssam for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 7712795Ssam if (mp->m_bufp != 0 && dev == mp->m_dev) { 7812795Ssam mp = 0; 7912795Ssam goto out; 8012795Ssam } 8112795Ssam for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 8212795Ssam if (mp->m_bufp == 0) 8312795Ssam goto found; 8412795Ssam mp = 0; 8512795Ssam goto out; 8612795Ssam found: 8712795Ssam mp->m_bufp = tp; /* just to reserve this slot */ 8812795Ssam mp->m_dev = NODEV; 8912795Ssam fs = tp->b_un.b_fs; 9012795Ssam bp = geteblk((int)fs->fs_sbsize); 9112795Ssam mp->m_bufp = bp; 9212795Ssam bcopy((caddr_t)tp->b_un.b_addr, (caddr_t)bp->b_un.b_addr, 9312795Ssam (u_int)fs->fs_sbsize); 9412795Ssam brelse(tp); 9512795Ssam tp = 0; 9612795Ssam fs = bp->b_un.b_fs; 9712795Ssam if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE) 9812795Ssam goto out; 9912795Ssam fs->fs_ronly = (ronly != 0); 10012795Ssam if (ronly == 0) 10112795Ssam fs->fs_fmod = 1; 10212795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 10312795Ssam space = wmemall(vmemall, (int)fs->fs_cssize); 10412795Ssam if (space == 0) 10512795Ssam goto out; 10612795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 10712795Ssam size = fs->fs_bsize; 10812795Ssam if (i + fs->fs_frag > blks) 10912795Ssam size = (blks - i) * fs->fs_fsize; 11012795Ssam tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size); 11112795Ssam if (tp->b_flags&B_ERROR) { 11212795Ssam wmemfree(space, (int)fs->fs_cssize); 11312795Ssam goto out; 11412795Ssam } 11512795Ssam bcopy((caddr_t)tp->b_un.b_addr, space, (u_int)size); 11612795Ssam fs->fs_csp[i / fs->fs_frag] = (struct csum *)space; 11712795Ssam space += size; 11812795Ssam brelse(tp); 11912795Ssam tp = 0; 12012795Ssam } 12112795Ssam mp->m_inodp = ip; 12212795Ssam mp->m_dev = dev; 12312795Ssam if (ip) { 12412795Ssam ip->i_flag |= IMOUNT; 12512795Ssam iunlock(ip); 12612795Ssam } 12712795Ssam return (fs); 12812795Ssam out: 12912795Ssam u.u_error = EBUSY; 13012795Ssam if (ip) 13112795Ssam iput(ip); 13212795Ssam if (mp) 13312795Ssam mp->m_bufp = 0; 13412795Ssam if (bp) 13512795Ssam brelse(bp); 13612795Ssam if (tp) 13712795Ssam brelse(tp); 13812795Ssam return (0); 13912795Ssam } 14012795Ssam 14112795Ssam umount() 14212795Ssam { 14312795Ssam struct a { 14412795Ssam char *fspec; 14512795Ssam }; 14612795Ssam 14712795Ssam u.u_error = unmount1(0); 14812795Ssam } 14912795Ssam 15012795Ssam unmount1(forcibly) 15112795Ssam int forcibly; 15212795Ssam { 15312795Ssam dev_t dev; 15412795Ssam register struct mount *mp; 15512795Ssam int stillopen, flag, error; 15612795Ssam register struct inode *ip; 15712795Ssam register struct fs *fs; 15812795Ssam 15912795Ssam error = getmdev(&dev); 16012795Ssam if (error) 16112795Ssam return (error); 16212795Ssam for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 16312795Ssam if (mp->m_bufp != NULL && dev == mp->m_dev) 16412795Ssam goto found; 16512795Ssam return (EINVAL); 16612795Ssam found: 16712795Ssam xumount(dev); /* remove unused sticky files from text table */ 168*15800Smckusick nchinval(dev); /* flush the name cache */ 16912795Ssam update(); 17012795Ssam #ifdef QUOTA 17112795Ssam if ((stillopen = iflush(dev, mp->m_qinod)) < 0 && !forcibly) 17212795Ssam #else 17312795Ssam if ((stillopen = iflush(dev)) < 0 && !forcibly) 17412795Ssam #endif 17512795Ssam return (EBUSY); 17612795Ssam if (stillopen < 0) 17712795Ssam return (EBUSY); /* XXX */ 17812795Ssam #ifdef QUOTA 17912795Ssam closedq(mp); 18012795Ssam /* 18112795Ssam * Here we have to iflush again to get rid of the quota inode. 18212795Ssam * A drag, but it would be ugly to cheat, & this doesn't happen often 18312795Ssam */ 18412795Ssam (void)iflush(dev, (struct inode *)NULL); 18512795Ssam #endif 18612795Ssam ip = mp->m_inodp; 18712795Ssam ip->i_flag &= ~IMOUNT; 18812795Ssam irele(ip); 18912795Ssam fs = mp->m_bufp->b_un.b_fs; 19012795Ssam wmemfree((caddr_t)fs->fs_csp[0], (int)fs->fs_cssize); 19112795Ssam flag = !fs->fs_ronly; 19212795Ssam brelse(mp->m_bufp); 19312795Ssam mp->m_bufp = 0; 19412795Ssam mp->m_dev = 0; 19512795Ssam mpurge(mp - &mount[0]); 19612795Ssam if (!stillopen) { 19712795Ssam (*bdevsw[major(dev)].d_close)(dev, flag); 19812795Ssam binval(dev); 19912795Ssam } 20012795Ssam return (0); 20112795Ssam } 20212795Ssam 20312795Ssam sbupdate(mp) 20412795Ssam struct mount *mp; 20512795Ssam { 20612795Ssam register struct fs *fs = mp->m_bufp->b_un.b_fs; 20712795Ssam register struct buf *bp; 20812795Ssam int blks; 20912795Ssam caddr_t space; 21012795Ssam int i, size; 21112795Ssam 21212795Ssam bp = getblk(mp->m_dev, SBLOCK, (int)fs->fs_sbsize); 21312795Ssam bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 21412795Ssam bwrite(bp); 21512795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 21612795Ssam space = (caddr_t)fs->fs_csp[0]; 21712795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 21812795Ssam size = fs->fs_bsize; 21912795Ssam if (i + fs->fs_frag > blks) 22012795Ssam size = (blks - i) * fs->fs_fsize; 22112795Ssam bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size); 22212795Ssam bcopy(space, bp->b_un.b_addr, (u_int)size); 22312795Ssam space += size; 22412795Ssam bwrite(bp); 22512795Ssam } 22612795Ssam } 22712795Ssam 22812795Ssam /* 22912795Ssam * Common code for mount and umount. 23012795Ssam * Check that the user's argument is a reasonable 23112795Ssam * thing on which to mount, and return the device number if so. 23212795Ssam */ 23312795Ssam getmdev(pdev) 23412795Ssam dev_t *pdev; 23512795Ssam { 23612795Ssam dev_t dev; 23712795Ssam register struct inode *ip; 23812795Ssam 23912795Ssam if (!suser()) 24012795Ssam return (u.u_error); 24112795Ssam ip = namei(uchar, LOOKUP, 1); 24212795Ssam if (ip == NULL) 24312795Ssam return (u.u_error); 24412795Ssam if ((ip->i_mode&IFMT) != IFBLK) 24512795Ssam return (ENOTBLK); 24612795Ssam dev = (dev_t)ip->i_rdev; 24712795Ssam if (major(dev) >= nblkdev) 24812795Ssam return (ENXIO); 24912795Ssam iput(ip); 25012795Ssam *pdev = dev; 25112795Ssam return (0); 25212795Ssam } 253