1*16639Skarels /* lfs_vfsops.c 6.4 84/06/26 */ 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; 3315800Smckusick 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 races if running twice */ 5212795Ssam struct fs * 5312795Ssam mountfs(dev, ronly, ip) 5412795Ssam dev_t dev; 5512795Ssam int ronly; 5612795Ssam struct inode *ip; 5712795Ssam { 5812795Ssam register struct mount *mp = 0; 5912795Ssam struct buf *tp = 0; 6012795Ssam register struct buf *bp = 0; 6112795Ssam register struct fs *fs; 6212795Ssam int blks; 6312795Ssam caddr_t space; 6412795Ssam int i, size; 65*16639Skarels register error; 6612795Ssam 67*16639Skarels error = 6812795Ssam (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE); 69*16639Skarels if (error) 7012795Ssam goto out; 7112795Ssam tp = bread(dev, SBLOCK, SBSIZE); 7212795Ssam if (tp->b_flags & B_ERROR) 7312795Ssam goto out; 7412795Ssam for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 7512795Ssam if (mp->m_bufp != 0 && dev == mp->m_dev) { 7612795Ssam mp = 0; 77*16639Skarels error = EBUSY; 7812795Ssam goto out; 7912795Ssam } 8012795Ssam for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 8112795Ssam if (mp->m_bufp == 0) 8212795Ssam goto found; 8312795Ssam mp = 0; 84*16639Skarels error = EMFILE; /* needs translation */ 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; 90*16639Skarels if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE 91*16639Skarels || fs->fs_bsize < sizeof(struct fs)) { 92*16639Skarels error = EINVAL; /* also needs translation */ 93*16639Skarels goto out; 94*16639Skarels } 9512795Ssam bp = geteblk((int)fs->fs_sbsize); 9612795Ssam mp->m_bufp = bp; 9712795Ssam bcopy((caddr_t)tp->b_un.b_addr, (caddr_t)bp->b_un.b_addr, 9812795Ssam (u_int)fs->fs_sbsize); 9912795Ssam brelse(tp); 10012795Ssam tp = 0; 10112795Ssam fs = bp->b_un.b_fs; 10212795Ssam fs->fs_ronly = (ronly != 0); 10312795Ssam if (ronly == 0) 10412795Ssam fs->fs_fmod = 1; 10512795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 10612795Ssam space = wmemall(vmemall, (int)fs->fs_cssize); 107*16639Skarels if (space == 0) { 108*16639Skarels error = ENOMEM; 10912795Ssam goto out; 110*16639Skarels } 11112795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 11212795Ssam size = fs->fs_bsize; 11312795Ssam if (i + fs->fs_frag > blks) 11412795Ssam size = (blks - i) * fs->fs_fsize; 11512795Ssam tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size); 11612795Ssam if (tp->b_flags&B_ERROR) { 11712795Ssam wmemfree(space, (int)fs->fs_cssize); 11812795Ssam goto out; 11912795Ssam } 12012795Ssam bcopy((caddr_t)tp->b_un.b_addr, space, (u_int)size); 12112795Ssam fs->fs_csp[i / fs->fs_frag] = (struct csum *)space; 12212795Ssam space += size; 12312795Ssam brelse(tp); 12412795Ssam tp = 0; 12512795Ssam } 12612795Ssam mp->m_inodp = ip; 12712795Ssam mp->m_dev = dev; 12812795Ssam if (ip) { 12912795Ssam ip->i_flag |= IMOUNT; 13012795Ssam iunlock(ip); 13112795Ssam } 13212795Ssam return (fs); 13312795Ssam out: 134*16639Skarels if (error == 0) 135*16639Skarels error = EIO; 13612795Ssam if (ip) 13712795Ssam iput(ip); 13812795Ssam if (mp) 13912795Ssam mp->m_bufp = 0; 14012795Ssam if (bp) 14112795Ssam brelse(bp); 14212795Ssam if (tp) 14312795Ssam brelse(tp); 144*16639Skarels u.u_error = error; 14512795Ssam return (0); 14612795Ssam } 14712795Ssam 14812795Ssam umount() 14912795Ssam { 15012795Ssam struct a { 15112795Ssam char *fspec; 15212795Ssam }; 15312795Ssam 15412795Ssam u.u_error = unmount1(0); 15512795Ssam } 15612795Ssam 15712795Ssam unmount1(forcibly) 15812795Ssam int forcibly; 15912795Ssam { 16012795Ssam dev_t dev; 16112795Ssam register struct mount *mp; 16212795Ssam int stillopen, flag, error; 16312795Ssam register struct inode *ip; 16412795Ssam register struct fs *fs; 16512795Ssam 16612795Ssam error = getmdev(&dev); 16712795Ssam if (error) 16812795Ssam return (error); 16912795Ssam for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 17012795Ssam if (mp->m_bufp != NULL && dev == mp->m_dev) 17112795Ssam goto found; 17212795Ssam return (EINVAL); 17312795Ssam found: 17412795Ssam xumount(dev); /* remove unused sticky files from text table */ 17515800Smckusick nchinval(dev); /* flush the name cache */ 17612795Ssam update(); 17712795Ssam #ifdef QUOTA 17812795Ssam if ((stillopen = iflush(dev, mp->m_qinod)) < 0 && !forcibly) 17912795Ssam #else 18012795Ssam if ((stillopen = iflush(dev)) < 0 && !forcibly) 18112795Ssam #endif 18212795Ssam return (EBUSY); 18312795Ssam if (stillopen < 0) 18412795Ssam return (EBUSY); /* XXX */ 18512795Ssam #ifdef QUOTA 18612795Ssam closedq(mp); 18712795Ssam /* 18812795Ssam * Here we have to iflush again to get rid of the quota inode. 18912795Ssam * A drag, but it would be ugly to cheat, & this doesn't happen often 19012795Ssam */ 19112795Ssam (void)iflush(dev, (struct inode *)NULL); 19212795Ssam #endif 19312795Ssam ip = mp->m_inodp; 19412795Ssam ip->i_flag &= ~IMOUNT; 19512795Ssam irele(ip); 19612795Ssam fs = mp->m_bufp->b_un.b_fs; 19712795Ssam wmemfree((caddr_t)fs->fs_csp[0], (int)fs->fs_cssize); 19812795Ssam flag = !fs->fs_ronly; 19912795Ssam brelse(mp->m_bufp); 20012795Ssam mp->m_bufp = 0; 20112795Ssam mp->m_dev = 0; 20212795Ssam mpurge(mp - &mount[0]); 20312795Ssam if (!stillopen) { 20412795Ssam (*bdevsw[major(dev)].d_close)(dev, flag); 20512795Ssam binval(dev); 20612795Ssam } 20712795Ssam return (0); 20812795Ssam } 20912795Ssam 21012795Ssam sbupdate(mp) 21112795Ssam struct mount *mp; 21212795Ssam { 21312795Ssam register struct fs *fs = mp->m_bufp->b_un.b_fs; 21412795Ssam register struct buf *bp; 21512795Ssam int blks; 21612795Ssam caddr_t space; 21712795Ssam int i, size; 21812795Ssam 21912795Ssam bp = getblk(mp->m_dev, SBLOCK, (int)fs->fs_sbsize); 22012795Ssam bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 22112795Ssam bwrite(bp); 22212795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 22312795Ssam space = (caddr_t)fs->fs_csp[0]; 22412795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 22512795Ssam size = fs->fs_bsize; 22612795Ssam if (i + fs->fs_frag > blks) 22712795Ssam size = (blks - i) * fs->fs_fsize; 22812795Ssam bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size); 22912795Ssam bcopy(space, bp->b_un.b_addr, (u_int)size); 23012795Ssam space += size; 23112795Ssam bwrite(bp); 23212795Ssam } 23312795Ssam } 23412795Ssam 23512795Ssam /* 23612795Ssam * Common code for mount and umount. 23712795Ssam * Check that the user's argument is a reasonable 23812795Ssam * thing on which to mount, and return the device number if so. 23912795Ssam */ 24012795Ssam getmdev(pdev) 24112795Ssam dev_t *pdev; 24212795Ssam { 24312795Ssam dev_t dev; 24412795Ssam register struct inode *ip; 24512795Ssam 24612795Ssam if (!suser()) 24712795Ssam return (u.u_error); 24812795Ssam ip = namei(uchar, LOOKUP, 1); 24912795Ssam if (ip == NULL) 25012795Ssam return (u.u_error); 25115956Skarels if ((ip->i_mode&IFMT) != IFBLK) { 25215956Skarels iput(ip); 25312795Ssam return (ENOTBLK); 25415956Skarels } 25512795Ssam dev = (dev_t)ip->i_rdev; 25615956Skarels iput(ip); 25712795Ssam if (major(dev) >= nblkdev) 25812795Ssam return (ENXIO); 25912795Ssam *pdev = dev; 26012795Ssam return (0); 26112795Ssam } 262