123400Smckusick /* 266805Sbostic * Copyright (c) 1989, 1991, 1993, 1994 363375Sbostic * The Regents of the University of California. All rights reserved. 423400Smckusick * 544539Sbostic * %sccs.include.redist.c% 637737Smckusick * 7*67395Smkm * @(#)lfs_vfsops.c 8.8 (Berkeley) 06/15/94 823400Smckusick */ 912795Ssam 1051483Sbostic #include <sys/param.h> 1151483Sbostic #include <sys/systm.h> 1251483Sbostic #include <sys/namei.h> 1351483Sbostic #include <sys/proc.h> 1451483Sbostic #include <sys/kernel.h> 1551483Sbostic #include <sys/vnode.h> 1651483Sbostic #include <sys/mount.h> 1751483Sbostic #include <sys/buf.h> 1854734Smckusick #include <sys/mbuf.h> 1951483Sbostic #include <sys/file.h> 2051483Sbostic #include <sys/disklabel.h> 2151483Sbostic #include <sys/ioctl.h> 2251483Sbostic #include <sys/errno.h> 2351483Sbostic #include <sys/malloc.h> 2454734Smckusick #include <sys/socket.h> 2512795Ssam 2655047Smckusick #include <miscfs/specfs/specdev.h> 2755047Smckusick 2851501Sbostic #include <ufs/ufs/quota.h> 2951501Sbostic #include <ufs/ufs/inode.h> 3051501Sbostic #include <ufs/ufs/ufsmount.h> 3151501Sbostic #include <ufs/ufs/ufs_extern.h> 3247571Skarels 3351501Sbostic #include <ufs/lfs/lfs.h> 3451501Sbostic #include <ufs/lfs/lfs_extern.h> 3551155Sbostic 3651991Sbostic int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); 3751215Sbostic 3851155Sbostic struct vfsops lfs_vfsops = { 3951155Sbostic lfs_mount, 4039043Smckusick ufs_start, 4151155Sbostic lfs_unmount, 4266805Sbostic ufs_root, 4341314Smckusick ufs_quotactl, 4451155Sbostic lfs_statfs, 4551155Sbostic lfs_sync, 4654693Sbostic lfs_vget, 4751559Smckusick lfs_fhtovp, 4851559Smckusick lfs_vptofh, 4951483Sbostic lfs_init, 5037737Smckusick }; 5137737Smckusick 5251483Sbostic int 5351155Sbostic lfs_mountroot() 5412795Ssam { 5551483Sbostic panic("lfs_mountroot"); /* XXX -- implement */ 5637737Smckusick } 5737737Smckusick 5837737Smckusick /* 5937737Smckusick * VFS Operations. 6037737Smckusick * 6137737Smckusick * mount system call 6237737Smckusick */ 6351155Sbostic lfs_mount(mp, path, data, ndp, p) 6440346Smckusick register struct mount *mp; 6537737Smckusick char *path; 6637737Smckusick caddr_t data; 6737737Smckusick struct nameidata *ndp; 6848036Smckusick struct proc *p; 6937737Smckusick { 7037737Smckusick struct vnode *devvp; 7137737Smckusick struct ufs_args args; 7237737Smckusick struct ufsmount *ump; 7351501Sbostic register struct lfs *fs; /* LFS */ 7437737Smckusick u_int size; 7537737Smckusick int error; 7637737Smckusick 7737737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 7837737Smckusick return (error); 7951483Sbostic 8051483Sbostic /* Until LFS can do NFS right. XXX */ 8165674Shibler if (args.export.ex_flags & MNT_EXPORTED) 8251483Sbostic return (EINVAL); 8365674Shibler 8440371Smckusick /* 8550264Skarels * If updating, check whether changing from read-only to 8650264Skarels * read/write; if there is no device name, that's all we do. 8750264Skarels */ 8850264Skarels if (mp->mnt_flag & MNT_UPDATE) { 8939336Smckusick ump = VFSTOUFS(mp); 9051155Sbostic #ifdef NOTLFS /* LFS */ 9139336Smckusick fs = ump->um_fs; 9241397Smckusick if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 9339336Smckusick fs->fs_ronly = 0; 9451155Sbostic #else 9551155Sbostic fs = ump->um_lfs; 9651155Sbostic if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 9751155Sbostic fs->lfs_ronly = 0; 9851155Sbostic #endif 9952175Smckusick if (args.fspec == 0) { 10052175Smckusick /* 10152175Smckusick * Process export requests. 10252175Smckusick */ 10365674Shibler return (vfs_export(mp, &ump->um_export, &args.export)); 10452175Smckusick } 10550264Skarels } 10650264Skarels /* 10750264Skarels * Not an update, or updating the name: look up the name 10850264Skarels * and verify that it refers to a sensible block device. 10950264Skarels */ 11052333Smckusick NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 11152333Smckusick if (error = namei(ndp)) 11250264Skarels return (error); 11350264Skarels devvp = ndp->ni_vp; 11450264Skarels if (devvp->v_type != VBLK) { 11550264Skarels vrele(devvp); 11650264Skarels return (ENOTBLK); 11750264Skarels } 11850264Skarels if (major(devvp->v_rdev) >= nblkdev) { 11950264Skarels vrele(devvp); 12050264Skarels return (ENXIO); 12150264Skarels } 12250264Skarels if ((mp->mnt_flag & MNT_UPDATE) == 0) 12351155Sbostic error = lfs_mountfs(devvp, mp, p); /* LFS */ 12450264Skarels else { 12539336Smckusick if (devvp != ump->um_devvp) 12639336Smckusick error = EINVAL; /* needs translation */ 12742858Smckusick else 12842858Smckusick vrele(devvp); 12939336Smckusick } 13037737Smckusick if (error) { 13137737Smckusick vrele(devvp); 13237737Smckusick return (error); 13332721Smckusick } 13437737Smckusick ump = VFSTOUFS(mp); 13551155Sbostic fs = ump->um_lfs; /* LFS */ 13651155Sbostic #ifdef NOTLFS /* LFS */ 13737737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 13837737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 13941397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 14041397Smckusick MNAMELEN); 14151991Sbostic (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 14241397Smckusick &size); 14341397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 14448036Smckusick (void) ufs_statfs(mp, &mp->mnt_stat, p); 14551155Sbostic #else 14651155Sbostic (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size); 14751155Sbostic bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size); 14851155Sbostic bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 14951155Sbostic MNAMELEN); 15051991Sbostic (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 15151155Sbostic &size); 15251155Sbostic bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 15351155Sbostic (void) lfs_statfs(mp, &mp->mnt_stat, p); 15451155Sbostic #endif 15537737Smckusick return (0); 15612795Ssam } 15712795Ssam 15837737Smckusick /* 15937737Smckusick * Common code for mount and mountroot 16051155Sbostic * LFS specific 16137737Smckusick */ 16251991Sbostic int 16351155Sbostic lfs_mountfs(devvp, mp, p) 16440376Smckusick register struct vnode *devvp; 16537737Smckusick struct mount *mp; 16648036Smckusick struct proc *p; 16712795Ssam { 16851155Sbostic extern struct vnode *rootvp; 16951501Sbostic register struct lfs *fs; 17051155Sbostic register struct ufsmount *ump; 17151155Sbostic struct vnode *vp; 17251155Sbostic struct buf *bp; 17330749Skarels struct partinfo dpart; 17451155Sbostic dev_t dev; 17551155Sbostic int error, i, ronly, size; 17612795Ssam 17740376Smckusick /* 17840376Smckusick * Disallow multiple mounts of the same device. 17945652Smckusick * Disallow mounting of a device that is currently in use 18045652Smckusick * (except for root, which might share swap device for miniroot). 18140376Smckusick * Flush out any old buffers remaining from a previous use. 18240376Smckusick */ 18365674Shibler if (error = vfs_mountedon(devvp)) 18440376Smckusick return (error); 18545652Smckusick if (vcount(devvp) > 1 && devvp != rootvp) 18640376Smckusick return (EBUSY); 18766738Spendry if (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) 18854693Sbostic return (error); 18951155Sbostic 19051155Sbostic ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 19159473Smckusick if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)) 19237737Smckusick return (error); 19351155Sbostic 19448036Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 19537737Smckusick size = DEV_BSIZE; 19648036Smckusick else { 19730749Skarels size = dpart.disklab->d_secsize; 19851155Sbostic #ifdef NEVER_USED 19951155Sbostic dpart.part->p_fstype = FS_LFS; 20051155Sbostic dpart.part->p_fsize = fs->lfs_fsize; /* frag size */ 20151155Sbostic dpart.part->p_frag = fs->lfs_frag; /* frags per block */ 20251155Sbostic dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */ 20351155Sbostic #endif 20437737Smckusick } 20551155Sbostic 20651155Sbostic /* Don't free random space on error. */ 20751155Sbostic bp = NULL; 20851155Sbostic ump = NULL; 20951155Sbostic 21051155Sbostic /* Read in the superblock. */ 21151155Sbostic if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp)) 21212795Ssam goto out; 21364523Sbostic fs = (struct lfs *)bp->b_data; 21451155Sbostic 21551155Sbostic /* Check the basics. */ 21651155Sbostic if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE || 21751501Sbostic fs->lfs_bsize < sizeof(struct lfs)) { 21841314Smckusick error = EINVAL; /* XXX needs translation */ 21916639Skarels goto out; 22016639Skarels } 22151155Sbostic 22251155Sbostic /* Allocate the mount structure, copy the superblock into it. */ 22341314Smckusick ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 22455548Sbostic fs = ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK); 22564523Sbostic bcopy(bp->b_data, fs, sizeof(struct lfs)); 22651501Sbostic if (sizeof(struct lfs) < LFS_SBPAD) /* XXX why? */ 22739675Smckusick bp->b_flags |= B_INVAL; 22834421Skarels brelse(bp); 22934421Skarels bp = NULL; 23051155Sbostic 23151183Sbostic /* Set up the I/O information */ 23251183Sbostic fs->lfs_iocount = 0; 23351183Sbostic 23455548Sbostic /* Set up the ifile and lock aflags */ 23554264Sbostic fs->lfs_doifile = 0; 23654264Sbostic fs->lfs_writer = 0; 23754264Sbostic fs->lfs_dirops = 0; 23855548Sbostic fs->lfs_seglock = 0; 23954264Sbostic 24051155Sbostic /* Set the file system readonly/modify bits. */ 24151155Sbostic fs->lfs_ronly = ronly; 24212795Ssam if (ronly == 0) 24351155Sbostic fs->lfs_fmod = 1; 24451155Sbostic 24551155Sbostic /* Initialize the mount structure. */ 24651155Sbostic dev = devvp->v_rdev; 24741397Smckusick mp->mnt_data = (qaddr_t)ump; 24841397Smckusick mp->mnt_stat.f_fsid.val[0] = (long)dev; 24951991Sbostic mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS; 250*67395Smkm mp->mnt_maxsymlinklen = fs->lfs_maxsymlinklen; 25141397Smckusick mp->mnt_flag |= MNT_LOCAL; 25237737Smckusick ump->um_mountp = mp; 25337737Smckusick ump->um_dev = dev; 25437737Smckusick ump->um_devvp = devvp; 25556475Smargo ump->um_bptrtodb = 0; 25656475Smargo ump->um_seqinc = 1 << fs->lfs_fsbtodb; 25756475Smargo ump->um_nindir = fs->lfs_nindir; 25841314Smckusick for (i = 0; i < MAXQUOTAS; i++) 25941314Smckusick ump->um_quotas[i] = NULLVP; 26052221Sbostic devvp->v_specflags |= SI_MOUNTEDON; 26151155Sbostic 26252221Sbostic /* 26352221Sbostic * We use the ifile vnode for almost every operation. Instead of 26452221Sbostic * retrieving it from the hash table each time we retrieve it here, 26552221Sbostic * artificially increment the reference count and keep a pointer 26652221Sbostic * to it in the incore copy of the superblock. 26752221Sbostic */ 26854693Sbostic if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp)) 26951155Sbostic goto out; 27051155Sbostic fs->lfs_ivnode = vp; 27152221Sbostic VREF(vp); 27252221Sbostic vput(vp); 27351155Sbostic 27437737Smckusick return (0); 27512795Ssam out: 27640872Smckusick if (bp) 27740872Smckusick brelse(bp); 27851155Sbostic (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 27941314Smckusick if (ump) { 28051989Smckusick free(ump->um_lfs, M_UFSMNT); 28151501Sbostic free(ump, M_UFSMNT); 28241397Smckusick mp->mnt_data = (qaddr_t)0; 28332721Smckusick } 28437737Smckusick return (error); 28512795Ssam } 28612795Ssam 28739043Smckusick /* 28837737Smckusick * unmount system call 28937737Smckusick */ 29051155Sbostic lfs_unmount(mp, mntflags, p) 29137737Smckusick struct mount *mp; 29241314Smckusick int mntflags; 29348036Smckusick struct proc *p; 29412795Ssam { 29551501Sbostic extern int doforce; 29637737Smckusick register struct ufsmount *ump; 29755548Sbostic register struct lfs *fs; 29854693Sbostic int i, error, flags, ronly; 29912795Ssam 30054693Sbostic flags = 0; 30148065Smckusick if (mntflags & MNT_FORCE) { 30265240Smckusick if (!doforce || (mp->mnt_flag & MNT_ROOTFS)) 30348065Smckusick return (EINVAL); 30441314Smckusick flags |= FORCECLOSE; 30548065Smckusick } 30654264Sbostic 30754264Sbostic ump = VFSTOUFS(mp); 30854264Sbostic fs = ump->um_lfs; 30912795Ssam #ifdef QUOTA 31041397Smckusick if (mp->mnt_flag & MNT_QUOTA) { 31154264Sbostic if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags)) 31239898Smckusick return (error); 31341314Smckusick for (i = 0; i < MAXQUOTAS; i++) { 31441314Smckusick if (ump->um_quotas[i] == NULLVP) 31541314Smckusick continue; 31650114Smckusick quotaoff(p, mp, i); 31741314Smckusick } 31839898Smckusick /* 31941314Smckusick * Here we fall through to vflush again to ensure 32041314Smckusick * that we have gotten rid of all the system vnodes. 32139898Smckusick */ 32241314Smckusick } 32312795Ssam #endif 32454693Sbostic if (error = vflush(mp, fs->lfs_ivnode, flags)) 32539898Smckusick return (error); 32655548Sbostic fs->lfs_clean = 1; 32754693Sbostic if (error = VFS_SYNC(mp, 1, p->p_ucred, p)) 32854693Sbostic return (error); 32965240Smckusick if (fs->lfs_ivnode->v_dirtyblkhd.lh_first) 33054693Sbostic panic("lfs_unmount: still dirty blocks on ifile vnode\n"); 33155806Sbostic vrele(fs->lfs_ivnode); 33254693Sbostic vgone(fs->lfs_ivnode); 33354693Sbostic 33451155Sbostic ronly = !fs->lfs_ronly; 33540653Smckusick ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 33654693Sbostic error = VOP_CLOSE(ump->um_devvp, 33754693Sbostic ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 33837737Smckusick vrele(ump->um_devvp); 33951989Smckusick free(fs, M_UFSMNT); 34051501Sbostic free(ump, M_UFSMNT); 34141397Smckusick mp->mnt_data = (qaddr_t)0; 34241397Smckusick mp->mnt_flag &= ~MNT_LOCAL; 34330749Skarels return (error); 34412795Ssam } 34512795Ssam 34637737Smckusick /* 34737737Smckusick * Get file system statistics. 34837737Smckusick */ 34951155Sbostic lfs_statfs(mp, sbp, p) 35037737Smckusick struct mount *mp; 35137737Smckusick register struct statfs *sbp; 35248036Smckusick struct proc *p; 35337737Smckusick { 35451501Sbostic register struct lfs *fs; 35537737Smckusick register struct ufsmount *ump; 35637737Smckusick 35737737Smckusick ump = VFSTOUFS(mp); 35851155Sbostic fs = ump->um_lfs; 35951155Sbostic if (fs->lfs_magic != LFS_MAGIC) 36051155Sbostic panic("lfs_statfs: magic"); 36151155Sbostic sbp->f_type = MOUNT_LFS; 36251155Sbostic sbp->f_bsize = fs->lfs_bsize; 36351943Smckusick sbp->f_iosize = fs->lfs_bsize; 36456156Smargo sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize); 36555588Sbostic sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree); 36651155Sbostic sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) - 36756368Smargo (fs->lfs_dsize - fs->lfs_bfree); 36856156Smargo sbp->f_bavail = dbtofsb(fs, sbp->f_bavail); 36951155Sbostic sbp->f_files = fs->lfs_nfiles; 37055588Sbostic sbp->f_ffree = sbp->f_bfree * INOPB(fs); 37141397Smckusick if (sbp != &mp->mnt_stat) { 37241397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntonname, 37340346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 37441397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 37540346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 37640346Smckusick } 37737737Smckusick return (0); 37837737Smckusick } 37937737Smckusick 38037737Smckusick /* 38137737Smckusick * Go through the disk queues to initiate sandbagged IO; 38237737Smckusick * go through the inodes to write those that have been modified; 38337737Smckusick * initiate the writing of the super block if it has been modified. 38441314Smckusick * 38541314Smckusick * Note: we are always called with the filesystem marked `MPBUSY'. 38637737Smckusick */ 38754693Sbostic lfs_sync(mp, waitfor, cred, p) 38837737Smckusick struct mount *mp; 38937737Smckusick int waitfor; 39054693Sbostic struct ucred *cred; 39154693Sbostic struct proc *p; 39237737Smckusick { 39351215Sbostic int error; 39437737Smckusick 39551310Sbostic /* All syncs must be checkpoints until roll-forward is implemented. */ 39657068Smargo error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0)); 39741314Smckusick #ifdef QUOTA 39841314Smckusick qsync(mp); 39941314Smckusick #endif 40051215Sbostic return (error); 40137737Smckusick } 40251559Smckusick 40351559Smckusick /* 40454693Sbostic * Look up an LFS dinode number to find its incore vnode. If not already 40554693Sbostic * in core, read it in from the specified device. Return the inode locked. 40654693Sbostic * Detection and handling of mount points must be done by the calling routine. 40754693Sbostic */ 40854693Sbostic int 40954693Sbostic lfs_vget(mp, ino, vpp) 41054693Sbostic struct mount *mp; 41154693Sbostic ino_t ino; 41254693Sbostic struct vnode **vpp; 41354693Sbostic { 41454693Sbostic register struct lfs *fs; 41554693Sbostic register struct inode *ip; 41654693Sbostic struct buf *bp; 41754693Sbostic struct ifile *ifp; 41854693Sbostic struct vnode *vp; 41954693Sbostic struct ufsmount *ump; 42054693Sbostic daddr_t daddr; 42154693Sbostic dev_t dev; 42254693Sbostic int error; 42354693Sbostic 42454693Sbostic ump = VFSTOUFS(mp); 42554693Sbostic dev = ump->um_dev; 42654693Sbostic if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 42754693Sbostic return (0); 42854693Sbostic 42954693Sbostic /* Translate the inode number to a disk address. */ 43054693Sbostic fs = ump->um_lfs; 43154693Sbostic if (ino == LFS_IFILE_INUM) 43254693Sbostic daddr = fs->lfs_idaddr; 43354693Sbostic else { 43454693Sbostic LFS_IENTRY(ifp, fs, ino, bp); 43554693Sbostic daddr = ifp->if_daddr; 43654693Sbostic brelse(bp); 43754693Sbostic if (daddr == LFS_UNUSED_DADDR) 43854693Sbostic return (ENOENT); 43954693Sbostic } 44054693Sbostic 44154693Sbostic /* Allocate new vnode/inode. */ 44254693Sbostic if (error = lfs_vcreate(mp, ino, &vp)) { 44354693Sbostic *vpp = NULL; 44454693Sbostic return (error); 44554693Sbostic } 44654693Sbostic 44754693Sbostic /* 44854693Sbostic * Put it onto its hash chain and lock it so that other requests for 44954693Sbostic * this inode will block if they arrive while we are sleeping waiting 45054693Sbostic * for old data structures to be purged or for the contents of the 45154693Sbostic * disk portion of this inode to be read. 45254693Sbostic */ 45354693Sbostic ip = VTOI(vp); 45454693Sbostic ufs_ihashins(ip); 45554693Sbostic 45654693Sbostic /* 45754693Sbostic * XXX 45854693Sbostic * This may not need to be here, logically it should go down with 45954693Sbostic * the i_devvp initialization. 46054693Sbostic * Ask Kirk. 46154693Sbostic */ 46254693Sbostic ip->i_lfs = ump->um_lfs; 46354693Sbostic 46454693Sbostic /* Read in the disk contents for the inode, copy into the inode. */ 46554693Sbostic if (error = 46654693Sbostic bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) { 46754693Sbostic /* 46859820Smckusick * The inode does not contain anything useful, so it would 46959820Smckusick * be misleading to leave it on its hash chain. With mode 47059820Smckusick * still zero, it will be unlinked and returned to the free 47159820Smckusick * list by vput(). 47254693Sbostic */ 47356799Smckusick vput(vp); 47454693Sbostic brelse(bp); 47554693Sbostic *vpp = NULL; 47654693Sbostic return (error); 47754693Sbostic } 47864523Sbostic ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data); 47954693Sbostic brelse(bp); 48054693Sbostic 48154693Sbostic /* 48254693Sbostic * Initialize the vnode from the inode, check for aliases. In all 48354693Sbostic * cases re-init ip, the underlying vnode/inode may have changed. 48454693Sbostic */ 48554693Sbostic if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) { 48656799Smckusick vput(vp); 48754693Sbostic *vpp = NULL; 48854693Sbostic return (error); 48954693Sbostic } 49054693Sbostic /* 49154693Sbostic * Finish inode initialization now that aliasing has been resolved. 49254693Sbostic */ 49354693Sbostic ip->i_devvp = ump->um_devvp; 49454693Sbostic VREF(ip->i_devvp); 49554693Sbostic *vpp = vp; 49654693Sbostic return (0); 49754693Sbostic } 49854693Sbostic 49954693Sbostic /* 50051559Smckusick * File handle to vnode 50151559Smckusick * 50251559Smckusick * Have to be really careful about stale file handles: 50351559Smckusick * - check that the inode number is valid 50451559Smckusick * - call lfs_vget() to get the locked inode 50551559Smckusick * - check for an unallocated inode (i_mode == 0) 50655891Smckusick * - check that the given client host has export rights and return 50755891Smckusick * those rights via. exflagsp and credanonp 50851559Smckusick * 50951559Smckusick * XXX 51051559Smckusick * use ifile to see if inode is allocated instead of reading off disk 51151559Smckusick * what is the relationship between my generational number and the NFS 51251559Smckusick * generational number. 51351559Smckusick */ 51451559Smckusick int 51554734Smckusick lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 51651559Smckusick register struct mount *mp; 51751559Smckusick struct fid *fhp; 51854734Smckusick struct mbuf *nam; 51951559Smckusick struct vnode **vpp; 52054734Smckusick int *exflagsp; 52154734Smckusick struct ucred **credanonp; 52251559Smckusick { 52351559Smckusick register struct ufid *ufhp; 52451559Smckusick 52551559Smckusick ufhp = (struct ufid *)fhp; 52651559Smckusick if (ufhp->ufid_ino < ROOTINO) 52754734Smckusick return (ESTALE); 52856246Smckusick return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); 52951559Smckusick } 53051559Smckusick 53151559Smckusick /* 53251559Smckusick * Vnode pointer to File handle 53351559Smckusick */ 53451559Smckusick /* ARGSUSED */ 53551559Smckusick lfs_vptofh(vp, fhp) 53651559Smckusick struct vnode *vp; 53751559Smckusick struct fid *fhp; 53851559Smckusick { 53951559Smckusick register struct inode *ip; 54051559Smckusick register struct ufid *ufhp; 54151559Smckusick 54251559Smckusick ip = VTOI(vp); 54351559Smckusick ufhp = (struct ufid *)fhp; 54451559Smckusick ufhp->ufid_len = sizeof(struct ufid); 54551559Smckusick ufhp->ufid_ino = ip->i_number; 54651559Smckusick ufhp->ufid_gen = ip->i_gen; 54751559Smckusick return (0); 54851559Smckusick } 549