123400Smckusick /* 237737Smckusick * Copyright (c) 1989 The Regents of the University of California. 337737Smckusick * All rights reserved. 423400Smckusick * 537737Smckusick * Redistribution and use in source and binary forms are permitted 637737Smckusick * provided that the above copyright notice and this paragraph are 737737Smckusick * duplicated in all such forms and that any documentation, 837737Smckusick * advertising materials, and other materials related to such 937737Smckusick * distribution and use acknowledge that the software was developed 1037737Smckusick * by the University of California, Berkeley. The name of the 1137737Smckusick * University may not be used to endorse or promote products derived 1237737Smckusick * from this software without specific prior written permission. 1337737Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437737Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537737Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637737Smckusick * 17*38776Smckusick * @(#)lfs_vfsops.c 7.19 (Berkeley) 08/26/89 1823400Smckusick */ 1912795Ssam 2017100Sbloom #include "param.h" 2117100Sbloom #include "systm.h" 2237737Smckusick #include "time.h" 2337737Smckusick #include "kernel.h" 2437737Smckusick #include "namei.h" 2537737Smckusick #include "vnode.h" 2637737Smckusick #include "mount.h" 2717100Sbloom #include "buf.h" 28*38776Smckusick #include "ucred.h" 2917100Sbloom #include "file.h" 3037737Smckusick #include "disklabel.h" 3130749Skarels #include "ioctl.h" 3237737Smckusick #include "errno.h" 3331660Smckusick #include "malloc.h" 3437737Smckusick #include "../ufs/fs.h" 3537737Smckusick #include "../ufs/ufsmount.h" 3637737Smckusick #include "../ufs/inode.h" 3712795Ssam 3837737Smckusick /* 3937737Smckusick * ufs vfs operations. 4037737Smckusick */ 4137737Smckusick int ufs_mount(); 4237737Smckusick int ufs_unmount(); 4337737Smckusick int ufs_root(); 4437737Smckusick int ufs_statfs(); 4537737Smckusick int ufs_sync(); 4637737Smckusick int ufs_fhtovp(); 4737737Smckusick int ufs_vptofh(); 4837737Smckusick 4937737Smckusick struct vfsops ufs_vfsops = { 5037737Smckusick ufs_mount, 5137737Smckusick ufs_unmount, 5237737Smckusick ufs_root, 5337737Smckusick ufs_statfs, 5437737Smckusick ufs_sync, 5537737Smckusick ufs_fhtovp, 5637737Smckusick ufs_vptofh 5737737Smckusick }; 5837737Smckusick 5937737Smckusick /* 6037737Smckusick * ufs mount table. 6137737Smckusick */ 6237737Smckusick struct ufsmount mounttab[NMOUNT]; 6337737Smckusick 6437737Smckusick /* 6537737Smckusick * Called by vfs_mountroot when ufs is going to be mounted as root 6637737Smckusick * 6737737Smckusick * XXX - Need to have a way of figuring the name of the root device 6837737Smckusick */ 6937737Smckusick #define ROOTNAME "root device" 7037737Smckusick 7137737Smckusick ufs_mountroot() 7212795Ssam { 7337737Smckusick register struct mount *mp; 7437737Smckusick extern struct vnode *rootvp; 7537737Smckusick struct ufsmount *ump; 7612795Ssam register struct fs *fs; 7737737Smckusick u_int size; 7837737Smckusick int error; 7912795Ssam 8037737Smckusick mp = (struct mount *)malloc((u_long)sizeof(struct mount), 8137737Smckusick M_MOUNT, M_WAITOK); 8237737Smckusick mp->m_op = &ufs_vfsops; 8337737Smckusick mp->m_flag = 0; 8437737Smckusick mp->m_exroot = 0; 8537737Smckusick error = mountfs(rootvp, mp); 8637737Smckusick if (error) { 8737737Smckusick free((caddr_t)mp, M_MOUNT); 8837737Smckusick return (error); 8912795Ssam } 9037737Smckusick error = vfs_add((struct vnode *)0, mp, 0); 9137737Smckusick if (error) { 9237737Smckusick (void)ufs_unmount(mp, 0); 9337737Smckusick free((caddr_t)mp, M_MOUNT); 9437737Smckusick return (error); 9521013Smckusick } 9637737Smckusick ump = VFSTOUFS(mp); 9737737Smckusick fs = ump->um_fs; 9837737Smckusick fs->fs_fsmnt[0] = '/'; 9937737Smckusick bzero(fs->fs_fsmnt + 1, sizeof(fs->fs_fsmnt) - 1); 10037737Smckusick (void) copystr(ROOTNAME, ump->um_mntname, MNAMELEN - 1, &size); 10137737Smckusick bzero(ump->um_mntname + size, MNAMELEN - size); 10237737Smckusick vfs_unlock(mp); 10337737Smckusick inittodr(fs->fs_time); 10437737Smckusick return (0); 10537737Smckusick } 10637737Smckusick 10737737Smckusick /* 10837737Smckusick * VFS Operations. 10937737Smckusick * 11037737Smckusick * mount system call 11137737Smckusick */ 11237737Smckusick ufs_mount(mp, path, data, ndp) 11337737Smckusick struct mount *mp; 11437737Smckusick char *path; 11537737Smckusick caddr_t data; 11637737Smckusick struct nameidata *ndp; 11737737Smckusick { 11837737Smckusick struct vnode *devvp; 11937737Smckusick struct ufs_args args; 12037737Smckusick struct ufsmount *ump; 12137737Smckusick register struct fs *fs; 12237737Smckusick u_int size; 12337737Smckusick int error; 12437737Smckusick 12537737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 12637737Smckusick return (error); 12737737Smckusick if ((error = getmdev(&devvp, args.fspec, ndp)) != 0) 12837737Smckusick return (error); 12937737Smckusick error = mountfs(devvp, mp); 13037737Smckusick if (error) { 13137737Smckusick vrele(devvp); 13237737Smckusick return (error); 13332721Smckusick } 13437737Smckusick ump = VFSTOUFS(mp); 13537737Smckusick fs = ump->um_fs; 13637737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 13737737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 13837737Smckusick (void) copyinstr(args.fspec, ump->um_mntname, MNAMELEN - 1, &size); 13937737Smckusick bzero(ump->um_mntname + size, MNAMELEN - size); 14037737Smckusick return (0); 14112795Ssam } 14212795Ssam 14337737Smckusick /* 14437737Smckusick * Common code for mount and mountroot 14537737Smckusick */ 14637737Smckusick mountfs(devvp, mp) 14737737Smckusick struct vnode *devvp; 14837737Smckusick struct mount *mp; 14912795Ssam { 15037737Smckusick register struct ufsmount *ump; 15137737Smckusick struct ufsmount *fmp = NULL; 15237737Smckusick struct buf *bp = NULL; 15312795Ssam register struct fs *fs; 15437737Smckusick dev_t dev = devvp->v_rdev; 15530749Skarels struct partinfo dpart; 15637737Smckusick caddr_t base, space; 15730749Skarels int havepart = 0, blks; 15837737Smckusick int error, i, size; 15921013Smckusick int needclose = 0; 16037737Smckusick int ronly = (mp->m_flag & M_RDONLY) != 0; 16112795Ssam 16237737Smckusick for (ump = &mounttab[0]; ump < &mounttab[NMOUNT]; ump++) { 16337737Smckusick if (ump->um_fs == NULL) { 16432721Smckusick if (fmp == NULL) 16537737Smckusick fmp = ump; 16637737Smckusick } else if (dev == ump->um_dev) { 16737737Smckusick return (EBUSY); /* needs translation */ 16832721Smckusick } 16932721Smckusick } 17037737Smckusick if ((ump = fmp) == NULL) 17137737Smckusick return (EMFILE); /* needs translation */ 17237737Smckusick ump->um_fs = (struct fs *)1; /* just to reserve this slot */ 173*38776Smckusick error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 17432721Smckusick if (error) { 17537737Smckusick ump->um_fs = NULL; 17637737Smckusick return (error); 17732721Smckusick } 17821013Smckusick needclose = 1; 179*38776Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0) 18037737Smckusick size = DEV_BSIZE; 18137737Smckusick else { 18230749Skarels havepart = 1; 18330749Skarels size = dpart.disklab->d_secsize; 18437737Smckusick } 185*38776Smckusick if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) { 18637737Smckusick ump->um_fs = NULL; 18712795Ssam goto out; 18832721Smckusick } 18934421Skarels fs = bp->b_un.b_fs; 19030749Skarels if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 19130749Skarels fs->fs_bsize < sizeof(struct fs)) { 19237737Smckusick ump->um_fs = NULL; 19337737Smckusick error = EINVAL; /* XXX also needs translation */ 19416639Skarels goto out; 19516639Skarels } 19637737Smckusick ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK, 19734473Smckusick M_WAITOK); 19837737Smckusick bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, 19912795Ssam (u_int)fs->fs_sbsize); 20034421Skarels brelse(bp); 20134421Skarels bp = NULL; 20237737Smckusick fs = ump->um_fs; 20337737Smckusick fs->fs_ronly = ronly; 20412795Ssam if (ronly == 0) 20512795Ssam fs->fs_fmod = 1; 20630749Skarels if (havepart) { 20730749Skarels dpart.part->p_fstype = FS_BSDFFS; 20830749Skarels dpart.part->p_fsize = fs->fs_fsize; 20930749Skarels dpart.part->p_frag = fs->fs_frag; 21031385Skarels dpart.part->p_cpg = fs->fs_cpg; 21130749Skarels } 21212795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 21334473Smckusick base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK, 21434473Smckusick M_WAITOK); 21512795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 21612795Ssam size = fs->fs_bsize; 21712795Ssam if (i + fs->fs_frag > blks) 21812795Ssam size = (blks - i) * fs->fs_fsize; 219*38776Smckusick error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 220*38776Smckusick NOCRED, &bp); 22137737Smckusick if (error) { 22234473Smckusick free((caddr_t)base, M_SUPERBLK); 22312795Ssam goto out; 22412795Ssam } 22534421Skarels bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size); 22617225Smckusick fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 22712795Ssam space += size; 22834421Skarels brelse(bp); 22934421Skarels bp = NULL; 23012795Ssam } 23137737Smckusick mp->m_data = (qaddr_t)ump; 23237737Smckusick mp->m_bsize = fs->fs_bsize; 23337737Smckusick mp->m_fsize = fs->fs_fsize; 23437737Smckusick mp->m_fsid.val[0] = (long)dev; 23537737Smckusick mp->m_fsid.val[1] = MOUNT_UFS; 23637737Smckusick ump->um_mountp = mp; 23737737Smckusick ump->um_dev = dev; 23837737Smckusick ump->um_devvp = devvp; 23937737Smckusick ump->um_qinod = NULL; 240*38776Smckusick devvp->v_mount = mp; 24137737Smckusick 24230383Smckusick /* Sanity checks for old file systems. XXX */ 24330383Smckusick fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ 24430383Smckusick fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ 24534145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 24634145Smckusick fs->fs_nrpos = 8; /* XXX */ 24737737Smckusick return (0); 24812795Ssam out: 24932721Smckusick if (needclose) 250*38776Smckusick (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 25137737Smckusick if (ump->um_fs) { 25237737Smckusick free((caddr_t)ump->um_fs, M_SUPERBLK); 25337737Smckusick ump->um_fs = NULL; 25432721Smckusick } 25534421Skarels if (bp) 25634421Skarels brelse(bp); 25737737Smckusick return (error); 25812795Ssam } 25912795Ssam 26012795Ssam 26137737Smckusick /* 26237737Smckusick * unmount system call 26337737Smckusick */ 26437737Smckusick ufs_unmount(mp, flags) 26537737Smckusick struct mount *mp; 26637737Smckusick int flags; 26712795Ssam { 26837737Smckusick register struct ufsmount *ump; 26937737Smckusick register struct fs *fs; 27012795Ssam dev_t dev; 27137737Smckusick int error, ronly; 27212795Ssam 27337737Smckusick if (flags & MNT_FORCE) 27437737Smckusick return (EINVAL); 27537737Smckusick ump = VFSTOUFS(mp); 27637737Smckusick dev = ump->um_dev; 27712795Ssam #ifdef QUOTA 27837737Smckusick if (error = iflush(dev, ump->um_qinod)) 27912795Ssam #else 28037737Smckusick if (error = iflush(dev)) 28112795Ssam #endif 28230749Skarels return (error); 28312795Ssam #ifdef QUOTA 28437737Smckusick (void)closedq(ump); 28512795Ssam /* 28612795Ssam * Here we have to iflush again to get rid of the quota inode. 28737737Smckusick * A drag, but it would be ugly to cheat, & this doesn't happen often 28812795Ssam */ 28912795Ssam (void)iflush(dev, (struct inode *)NULL); 29012795Ssam #endif 29137737Smckusick fs = ump->um_fs; 29237737Smckusick ronly = !fs->fs_ronly; 29331660Smckusick free((caddr_t)fs->fs_csp[0], M_SUPERBLK); 29437737Smckusick free((caddr_t)fs, M_SUPERBLK); 29537737Smckusick ump->um_fs = NULL; 29637737Smckusick ump->um_dev = NODEV; 297*38776Smckusick error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 298*38776Smckusick ump->um_devvp->v_mount = (struct mount *)0; 29937737Smckusick vrele(ump->um_devvp); 30037737Smckusick ump->um_devvp = (struct vnode *)0; 30130749Skarels return (error); 30212795Ssam } 30312795Ssam 30437737Smckusick /* 30537737Smckusick * Return root of a filesystem 30637737Smckusick */ 30737737Smckusick ufs_root(mp, vpp) 30812795Ssam struct mount *mp; 30937737Smckusick struct vnode **vpp; 31012795Ssam { 31137737Smckusick struct inode tip, *ip; 31237737Smckusick int error; 31337737Smckusick 31437737Smckusick tip.i_dev = VFSTOUFS(mp)->um_dev; 31537737Smckusick tip.i_vnode.v_mount = mp; 31637737Smckusick error = iget(&tip, (ino_t)ROOTINO, &ip); 31737737Smckusick if (error) 31837737Smckusick return (error); 31937737Smckusick *vpp = ITOV(ip); 32037737Smckusick return (0); 32137737Smckusick } 32237737Smckusick 32337737Smckusick /* 32437737Smckusick * Get file system statistics. 32537737Smckusick */ 32637737Smckusick ufs_statfs(mp, sbp) 32737737Smckusick struct mount *mp; 32837737Smckusick register struct statfs *sbp; 32937737Smckusick { 33037737Smckusick register struct ufsmount *ump; 33137737Smckusick register struct fs *fs; 33237737Smckusick 33337737Smckusick ump = VFSTOUFS(mp); 33437737Smckusick fs = ump->um_fs; 33537737Smckusick if (fs->fs_magic != FS_MAGIC) 33637737Smckusick panic("ufs_statfs"); 33737737Smckusick sbp->f_type = MOUNT_UFS; 33837737Smckusick sbp->f_flags = mp->m_flag &~ (M_MLOCK|M_MWAIT); 33937737Smckusick sbp->f_fsize = fs->fs_fsize; 34037737Smckusick sbp->f_bsize = fs->fs_bsize; 34137737Smckusick sbp->f_blocks = fs->fs_dsize; 34237737Smckusick sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 34337737Smckusick fs->fs_cstotal.cs_nffree; 34437737Smckusick sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 34537737Smckusick (fs->fs_dsize - sbp->f_bfree); 34637737Smckusick if (sbp->f_bavail < 0) 34737737Smckusick sbp->f_bavail = 0; 34837737Smckusick sbp->f_files = fs->fs_ncg * fs->fs_ipg; 34937737Smckusick sbp->f_ffree = fs->fs_cstotal.cs_nifree; 35037737Smckusick sbp->f_fsid = mp->m_fsid; 35137737Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 35237737Smckusick bcopy((caddr_t)ump->um_mntname, (caddr_t)&sbp->f_mntfromname[0], 35337737Smckusick MNAMELEN); 35437737Smckusick return (0); 35537737Smckusick } 35637737Smckusick 35737737Smckusick int syncprt = 0; 35837737Smckusick 35937737Smckusick /* 36037737Smckusick * Go through the disk queues to initiate sandbagged IO; 36137737Smckusick * go through the inodes to write those that have been modified; 36237737Smckusick * initiate the writing of the super block if it has been modified. 36337737Smckusick */ 36437737Smckusick ufs_sync(mp, waitfor) 36537737Smckusick struct mount *mp; 36637737Smckusick int waitfor; 36737737Smckusick { 36837737Smckusick register struct inode *ip; 36937737Smckusick register struct ufsmount *ump = VFSTOUFS(mp); 37037737Smckusick register struct fs *fs; 37137737Smckusick int error = 0; 37237737Smckusick static int updlock = 0; 37337737Smckusick 37437737Smckusick if (syncprt) 37537737Smckusick bufstats(); 37637737Smckusick if (updlock) 37737737Smckusick return (EBUSY); 37837737Smckusick fs = ump->um_fs; 37937737Smckusick if (fs == (struct fs *)1) 38037737Smckusick return (0); 38137737Smckusick updlock++; 38237737Smckusick /* 38337737Smckusick * Write back modified superblock. 38437737Smckusick * Consistency check that the superblock 38537737Smckusick * is still in the buffer cache. 38637737Smckusick */ 38737737Smckusick if (fs->fs_fmod != 0) { 38837737Smckusick if (fs->fs_ronly != 0) { /* XXX */ 38937737Smckusick printf("fs = %s\n", fs->fs_fsmnt); 39037737Smckusick panic("update: rofs mod"); 39137737Smckusick } 39237737Smckusick fs->fs_fmod = 0; 39337737Smckusick fs->fs_time = time.tv_sec; 39437737Smckusick error = sbupdate(ump, waitfor); 39537737Smckusick } 39637737Smckusick /* 39737737Smckusick * Write back each (modified) inode. 39837737Smckusick */ 39937737Smckusick for (ip = inode; ip < inodeNINODE; ip++) { 40037737Smckusick if (ip->i_devvp != ump->um_devvp || 40137737Smckusick (ip->i_flag & ILOCKED) != 0 || ITOV(ip)->v_count == 0 || 40237737Smckusick (ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0) 40337737Smckusick continue; 40438227Smckusick ILOCK(ip); 40538346Smckusick VREF(ITOV(ip)); 40637737Smckusick error = iupdat(ip, &time, &time, waitfor == MNT_WAIT); 40737737Smckusick iput(ip); 40837737Smckusick } 40937737Smckusick updlock = 0; 41037737Smckusick /* 41137737Smckusick * Force stale buffer cache information to be flushed. 41237737Smckusick */ 413*38776Smckusick bflush(ump->um_devvp->v_mount); 41437737Smckusick return (error); 41537737Smckusick } 41637737Smckusick 41737737Smckusick /* 41837737Smckusick * Write a superblock and associated information back to disk. 41937737Smckusick */ 42037737Smckusick sbupdate(mp, waitfor) 42137737Smckusick struct ufsmount *mp; 42237737Smckusick int waitfor; 42337737Smckusick { 42437737Smckusick register struct fs *fs = mp->um_fs; 42512795Ssam register struct buf *bp; 42612795Ssam int blks; 42712795Ssam caddr_t space; 42837737Smckusick int i, size, error = 0; 42912795Ssam 43037737Smckusick bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); 43112795Ssam bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 43234145Smckusick /* Restore compatibility to old file systems. XXX */ 43334145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 43434145Smckusick bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ 43537737Smckusick if (waitfor == MNT_WAIT) 43637737Smckusick error = bwrite(bp); 43737737Smckusick else 43837737Smckusick bawrite(bp); 43912795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 44012795Ssam space = (caddr_t)fs->fs_csp[0]; 44112795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 44212795Ssam size = fs->fs_bsize; 44312795Ssam if (i + fs->fs_frag > blks) 44412795Ssam size = (blks - i) * fs->fs_fsize; 44537737Smckusick bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); 44612795Ssam bcopy(space, bp->b_un.b_addr, (u_int)size); 44712795Ssam space += size; 44837737Smckusick if (waitfor == MNT_WAIT) 44937737Smckusick error = bwrite(bp); 45037737Smckusick else 45137737Smckusick bawrite(bp); 45212795Ssam } 45337737Smckusick return (error); 45412795Ssam } 45512795Ssam 45612795Ssam /* 45737737Smckusick * Print out statistics on the current allocation of the buffer pool. 45837737Smckusick * Can be enabled to print out on every ``sync'' by setting "syncprt" 45937737Smckusick * above. 46037737Smckusick */ 46137737Smckusick bufstats() 46237737Smckusick { 46337737Smckusick int s, i, j, count; 46437737Smckusick register struct buf *bp, *dp; 46537737Smckusick int counts[MAXBSIZE/CLBYTES+1]; 46637737Smckusick static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 46737737Smckusick 46837737Smckusick for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { 46937737Smckusick count = 0; 47037737Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 47137737Smckusick counts[j] = 0; 47237737Smckusick s = splbio(); 47337737Smckusick for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { 47437737Smckusick counts[dp->b_bufsize/CLBYTES]++; 47537737Smckusick count++; 47637737Smckusick } 47737737Smckusick splx(s); 47837737Smckusick printf("%s: total-%d", bname[i], count); 47937737Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 48037737Smckusick if (counts[j] != 0) 48137737Smckusick printf(", %d-%d", j * CLBYTES, counts[j]); 48237737Smckusick printf("\n"); 48337737Smckusick } 48437737Smckusick } 48537737Smckusick 48637737Smckusick /* 48737737Smckusick * File handle to vnode 48838453Smckusick * 48938453Smckusick * Have to be really careful about stale file handles: 49038453Smckusick * - check that the inode number is in range 49138453Smckusick * - call iget() to get the locked inode 49238453Smckusick * - check for an unallocated inode (i_mode == 0) 49338453Smckusick * - check that the generation number matches 49437737Smckusick */ 49537737Smckusick ufs_fhtovp(mp, fhp, vpp) 49638453Smckusick register struct mount *mp; 49737737Smckusick struct fid *fhp; 49837737Smckusick struct vnode **vpp; 49937737Smckusick { 50037737Smckusick register struct ufid *ufhp; 50138453Smckusick register struct fs *fs; 50237737Smckusick struct inode tip, *ip; 50337737Smckusick int error; 50437737Smckusick 50537737Smckusick ufhp = (struct ufid *)fhp; 50638453Smckusick fs = VFSTOUFS(mp)->um_fs; 50738453Smckusick if (ufhp->ufid_ino < ROOTINO || 50838453Smckusick ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) { 50938453Smckusick *vpp = (struct vnode *)0; 51038453Smckusick return (EINVAL); 51138453Smckusick } 51237737Smckusick tip.i_dev = VFSTOUFS(mp)->um_dev; 51337737Smckusick tip.i_vnode.v_mount = mp; 51437737Smckusick if (error = iget(&tip, ufhp->ufid_ino, &ip)) { 51538453Smckusick *vpp = (struct vnode *)0; 51637737Smckusick return (error); 51737737Smckusick } 51838453Smckusick if (ip->i_mode == 0) { 51938453Smckusick iput(ip); 52038453Smckusick *vpp = (struct vnode *)0; 52138453Smckusick return (EINVAL); 52238453Smckusick } 52337737Smckusick if (ip->i_gen != ufhp->ufid_gen) { 52437737Smckusick iput(ip); 52538453Smckusick *vpp = (struct vnode *)0; 52637737Smckusick return (EINVAL); 52737737Smckusick } 52837737Smckusick *vpp = ITOV(ip); 52937737Smckusick return (0); 53037737Smckusick } 53137737Smckusick 53237737Smckusick /* 53338355Smckusick * Vnode pointer to File handle 53437737Smckusick */ 53537737Smckusick /* ARGSUSED */ 53638143Smckusick ufs_vptofh(vp, fhp) 53738143Smckusick struct vnode *vp; 53837737Smckusick struct fid *fhp; 53937737Smckusick { 54038143Smckusick register struct inode *ip = VTOI(vp); 54138143Smckusick register struct ufid *ufhp; 54237737Smckusick 54338143Smckusick ufhp = (struct ufid *)fhp; 54438143Smckusick ufhp->ufid_len = sizeof(struct ufid); 54538143Smckusick ufhp->ufid_ino = ip->i_number; 54638143Smckusick ufhp->ufid_gen = ip->i_gen; 54738143Smckusick return (0); 54837737Smckusick } 54937737Smckusick 55037737Smckusick /* 55137737Smckusick * Common code for mount and quota. 55212795Ssam * Check that the user's argument is a reasonable 55312795Ssam * thing on which to mount, and return the device number if so. 55412795Ssam */ 55537737Smckusick getmdev(devvpp, fname, ndp) 55637737Smckusick struct vnode **devvpp; 55716697Smckusick caddr_t fname; 55837737Smckusick register struct nameidata *ndp; 55912795Ssam { 56037737Smckusick register struct vnode *vp; 56137737Smckusick int error; 56212795Ssam 56337737Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 56416697Smckusick ndp->ni_segflg = UIO_USERSPACE; 56516697Smckusick ndp->ni_dirp = fname; 56637737Smckusick if (error = namei(ndp)) { 56737737Smckusick if (error == ENOENT) 56837737Smckusick return (ENODEV); /* needs translation */ 56937737Smckusick return (error); 57021013Smckusick } 57137737Smckusick vp = ndp->ni_vp; 57237737Smckusick if (vp->v_type != VBLK) { 57337737Smckusick vput(vp); 57412795Ssam return (ENOTBLK); 57515956Skarels } 57637737Smckusick if (major(vp->v_rdev) >= nblkdev) 57712795Ssam return (ENXIO); 57837737Smckusick iunlock(VTOI(vp)); 57937737Smckusick *devvpp = vp; 58012795Ssam return (0); 58112795Ssam } 582