123400Smckusick /* 2*66805Sbostic * 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*66805Sbostic * @(#)lfs_vfsops.c 8.7 (Berkeley) 04/16/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, 42*66805Sbostic 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; 25041397Smckusick mp->mnt_flag |= MNT_LOCAL; 25137737Smckusick ump->um_mountp = mp; 25237737Smckusick ump->um_dev = dev; 25337737Smckusick ump->um_devvp = devvp; 25456475Smargo ump->um_bptrtodb = 0; 25556475Smargo ump->um_seqinc = 1 << fs->lfs_fsbtodb; 25656475Smargo ump->um_nindir = fs->lfs_nindir; 25741314Smckusick for (i = 0; i < MAXQUOTAS; i++) 25841314Smckusick ump->um_quotas[i] = NULLVP; 25952221Sbostic devvp->v_specflags |= SI_MOUNTEDON; 26051155Sbostic 26152221Sbostic /* 26252221Sbostic * We use the ifile vnode for almost every operation. Instead of 26352221Sbostic * retrieving it from the hash table each time we retrieve it here, 26452221Sbostic * artificially increment the reference count and keep a pointer 26552221Sbostic * to it in the incore copy of the superblock. 26652221Sbostic */ 26754693Sbostic if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp)) 26851155Sbostic goto out; 26951155Sbostic fs->lfs_ivnode = vp; 27052221Sbostic VREF(vp); 27152221Sbostic vput(vp); 27251155Sbostic 27337737Smckusick return (0); 27412795Ssam out: 27540872Smckusick if (bp) 27640872Smckusick brelse(bp); 27751155Sbostic (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 27841314Smckusick if (ump) { 27951989Smckusick free(ump->um_lfs, M_UFSMNT); 28051501Sbostic free(ump, M_UFSMNT); 28141397Smckusick mp->mnt_data = (qaddr_t)0; 28232721Smckusick } 28337737Smckusick return (error); 28412795Ssam } 28512795Ssam 28639043Smckusick /* 28737737Smckusick * unmount system call 28837737Smckusick */ 28951155Sbostic lfs_unmount(mp, mntflags, p) 29037737Smckusick struct mount *mp; 29141314Smckusick int mntflags; 29248036Smckusick struct proc *p; 29312795Ssam { 29451501Sbostic extern int doforce; 29537737Smckusick register struct ufsmount *ump; 29655548Sbostic register struct lfs *fs; 29754693Sbostic int i, error, flags, ronly; 29812795Ssam 29954693Sbostic flags = 0; 30048065Smckusick if (mntflags & MNT_FORCE) { 30165240Smckusick if (!doforce || (mp->mnt_flag & MNT_ROOTFS)) 30248065Smckusick return (EINVAL); 30341314Smckusick flags |= FORCECLOSE; 30448065Smckusick } 30554264Sbostic 30654264Sbostic ump = VFSTOUFS(mp); 30754264Sbostic fs = ump->um_lfs; 30812795Ssam #ifdef QUOTA 30941397Smckusick if (mp->mnt_flag & MNT_QUOTA) { 31054264Sbostic if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags)) 31139898Smckusick return (error); 31241314Smckusick for (i = 0; i < MAXQUOTAS; i++) { 31341314Smckusick if (ump->um_quotas[i] == NULLVP) 31441314Smckusick continue; 31550114Smckusick quotaoff(p, mp, i); 31641314Smckusick } 31739898Smckusick /* 31841314Smckusick * Here we fall through to vflush again to ensure 31941314Smckusick * that we have gotten rid of all the system vnodes. 32039898Smckusick */ 32141314Smckusick } 32212795Ssam #endif 32354693Sbostic if (error = vflush(mp, fs->lfs_ivnode, flags)) 32439898Smckusick return (error); 32555548Sbostic fs->lfs_clean = 1; 32654693Sbostic if (error = VFS_SYNC(mp, 1, p->p_ucred, p)) 32754693Sbostic return (error); 32865240Smckusick if (fs->lfs_ivnode->v_dirtyblkhd.lh_first) 32954693Sbostic panic("lfs_unmount: still dirty blocks on ifile vnode\n"); 33055806Sbostic vrele(fs->lfs_ivnode); 33154693Sbostic vgone(fs->lfs_ivnode); 33254693Sbostic 33351155Sbostic ronly = !fs->lfs_ronly; 33440653Smckusick ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 33554693Sbostic error = VOP_CLOSE(ump->um_devvp, 33654693Sbostic ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 33737737Smckusick vrele(ump->um_devvp); 33851989Smckusick free(fs, M_UFSMNT); 33951501Sbostic free(ump, M_UFSMNT); 34041397Smckusick mp->mnt_data = (qaddr_t)0; 34141397Smckusick mp->mnt_flag &= ~MNT_LOCAL; 34230749Skarels return (error); 34312795Ssam } 34412795Ssam 34537737Smckusick /* 34637737Smckusick * Get file system statistics. 34737737Smckusick */ 34851155Sbostic lfs_statfs(mp, sbp, p) 34937737Smckusick struct mount *mp; 35037737Smckusick register struct statfs *sbp; 35148036Smckusick struct proc *p; 35237737Smckusick { 35351501Sbostic register struct lfs *fs; 35437737Smckusick register struct ufsmount *ump; 35537737Smckusick 35637737Smckusick ump = VFSTOUFS(mp); 35751155Sbostic fs = ump->um_lfs; 35851155Sbostic if (fs->lfs_magic != LFS_MAGIC) 35951155Sbostic panic("lfs_statfs: magic"); 36051155Sbostic sbp->f_type = MOUNT_LFS; 36151155Sbostic sbp->f_bsize = fs->lfs_bsize; 36251943Smckusick sbp->f_iosize = fs->lfs_bsize; 36356156Smargo sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize); 36455588Sbostic sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree); 36551155Sbostic sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) - 36656368Smargo (fs->lfs_dsize - fs->lfs_bfree); 36756156Smargo sbp->f_bavail = dbtofsb(fs, sbp->f_bavail); 36851155Sbostic sbp->f_files = fs->lfs_nfiles; 36955588Sbostic sbp->f_ffree = sbp->f_bfree * INOPB(fs); 37041397Smckusick if (sbp != &mp->mnt_stat) { 37141397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntonname, 37240346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 37341397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 37440346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 37540346Smckusick } 37637737Smckusick return (0); 37737737Smckusick } 37837737Smckusick 37937737Smckusick /* 38037737Smckusick * Go through the disk queues to initiate sandbagged IO; 38137737Smckusick * go through the inodes to write those that have been modified; 38237737Smckusick * initiate the writing of the super block if it has been modified. 38341314Smckusick * 38441314Smckusick * Note: we are always called with the filesystem marked `MPBUSY'. 38537737Smckusick */ 38654693Sbostic lfs_sync(mp, waitfor, cred, p) 38737737Smckusick struct mount *mp; 38837737Smckusick int waitfor; 38954693Sbostic struct ucred *cred; 39054693Sbostic struct proc *p; 39137737Smckusick { 39251215Sbostic int error; 39337737Smckusick 39451310Sbostic /* All syncs must be checkpoints until roll-forward is implemented. */ 39557068Smargo error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0)); 39641314Smckusick #ifdef QUOTA 39741314Smckusick qsync(mp); 39841314Smckusick #endif 39951215Sbostic return (error); 40037737Smckusick } 40151559Smckusick 40251559Smckusick /* 40354693Sbostic * Look up an LFS dinode number to find its incore vnode. If not already 40454693Sbostic * in core, read it in from the specified device. Return the inode locked. 40554693Sbostic * Detection and handling of mount points must be done by the calling routine. 40654693Sbostic */ 40754693Sbostic int 40854693Sbostic lfs_vget(mp, ino, vpp) 40954693Sbostic struct mount *mp; 41054693Sbostic ino_t ino; 41154693Sbostic struct vnode **vpp; 41254693Sbostic { 41354693Sbostic register struct lfs *fs; 41454693Sbostic register struct inode *ip; 41554693Sbostic struct buf *bp; 41654693Sbostic struct ifile *ifp; 41754693Sbostic struct vnode *vp; 41854693Sbostic struct ufsmount *ump; 41954693Sbostic daddr_t daddr; 42054693Sbostic dev_t dev; 42154693Sbostic int error; 42254693Sbostic 42354693Sbostic ump = VFSTOUFS(mp); 42454693Sbostic dev = ump->um_dev; 42554693Sbostic if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 42654693Sbostic return (0); 42754693Sbostic 42854693Sbostic /* Translate the inode number to a disk address. */ 42954693Sbostic fs = ump->um_lfs; 43054693Sbostic if (ino == LFS_IFILE_INUM) 43154693Sbostic daddr = fs->lfs_idaddr; 43254693Sbostic else { 43354693Sbostic LFS_IENTRY(ifp, fs, ino, bp); 43454693Sbostic daddr = ifp->if_daddr; 43554693Sbostic brelse(bp); 43654693Sbostic if (daddr == LFS_UNUSED_DADDR) 43754693Sbostic return (ENOENT); 43854693Sbostic } 43954693Sbostic 44054693Sbostic /* Allocate new vnode/inode. */ 44154693Sbostic if (error = lfs_vcreate(mp, ino, &vp)) { 44254693Sbostic *vpp = NULL; 44354693Sbostic return (error); 44454693Sbostic } 44554693Sbostic 44654693Sbostic /* 44754693Sbostic * Put it onto its hash chain and lock it so that other requests for 44854693Sbostic * this inode will block if they arrive while we are sleeping waiting 44954693Sbostic * for old data structures to be purged or for the contents of the 45054693Sbostic * disk portion of this inode to be read. 45154693Sbostic */ 45254693Sbostic ip = VTOI(vp); 45354693Sbostic ufs_ihashins(ip); 45454693Sbostic 45554693Sbostic /* 45654693Sbostic * XXX 45754693Sbostic * This may not need to be here, logically it should go down with 45854693Sbostic * the i_devvp initialization. 45954693Sbostic * Ask Kirk. 46054693Sbostic */ 46154693Sbostic ip->i_lfs = ump->um_lfs; 46254693Sbostic 46354693Sbostic /* Read in the disk contents for the inode, copy into the inode. */ 46454693Sbostic if (error = 46554693Sbostic bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) { 46654693Sbostic /* 46759820Smckusick * The inode does not contain anything useful, so it would 46859820Smckusick * be misleading to leave it on its hash chain. With mode 46959820Smckusick * still zero, it will be unlinked and returned to the free 47059820Smckusick * list by vput(). 47154693Sbostic */ 47256799Smckusick vput(vp); 47354693Sbostic brelse(bp); 47454693Sbostic *vpp = NULL; 47554693Sbostic return (error); 47654693Sbostic } 47764523Sbostic ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data); 47854693Sbostic brelse(bp); 47954693Sbostic 48054693Sbostic /* 48154693Sbostic * Initialize the vnode from the inode, check for aliases. In all 48254693Sbostic * cases re-init ip, the underlying vnode/inode may have changed. 48354693Sbostic */ 48454693Sbostic if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) { 48556799Smckusick vput(vp); 48654693Sbostic *vpp = NULL; 48754693Sbostic return (error); 48854693Sbostic } 48954693Sbostic /* 49054693Sbostic * Finish inode initialization now that aliasing has been resolved. 49154693Sbostic */ 49254693Sbostic ip->i_devvp = ump->um_devvp; 49354693Sbostic VREF(ip->i_devvp); 49454693Sbostic *vpp = vp; 49554693Sbostic return (0); 49654693Sbostic } 49754693Sbostic 49854693Sbostic /* 49951559Smckusick * File handle to vnode 50051559Smckusick * 50151559Smckusick * Have to be really careful about stale file handles: 50251559Smckusick * - check that the inode number is valid 50351559Smckusick * - call lfs_vget() to get the locked inode 50451559Smckusick * - check for an unallocated inode (i_mode == 0) 50555891Smckusick * - check that the given client host has export rights and return 50655891Smckusick * those rights via. exflagsp and credanonp 50751559Smckusick * 50851559Smckusick * XXX 50951559Smckusick * use ifile to see if inode is allocated instead of reading off disk 51051559Smckusick * what is the relationship between my generational number and the NFS 51151559Smckusick * generational number. 51251559Smckusick */ 51351559Smckusick int 51454734Smckusick lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 51551559Smckusick register struct mount *mp; 51651559Smckusick struct fid *fhp; 51754734Smckusick struct mbuf *nam; 51851559Smckusick struct vnode **vpp; 51954734Smckusick int *exflagsp; 52054734Smckusick struct ucred **credanonp; 52151559Smckusick { 52251559Smckusick register struct ufid *ufhp; 52351559Smckusick 52451559Smckusick ufhp = (struct ufid *)fhp; 52551559Smckusick if (ufhp->ufid_ino < ROOTINO) 52654734Smckusick return (ESTALE); 52756246Smckusick return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); 52851559Smckusick } 52951559Smckusick 53051559Smckusick /* 53151559Smckusick * Vnode pointer to File handle 53251559Smckusick */ 53351559Smckusick /* ARGSUSED */ 53451559Smckusick lfs_vptofh(vp, fhp) 53551559Smckusick struct vnode *vp; 53651559Smckusick struct fid *fhp; 53751559Smckusick { 53851559Smckusick register struct inode *ip; 53951559Smckusick register struct ufid *ufhp; 54051559Smckusick 54151559Smckusick ip = VTOI(vp); 54251559Smckusick ufhp = (struct ufid *)fhp; 54351559Smckusick ufhp->ufid_len = sizeof(struct ufid); 54451559Smckusick ufhp->ufid_ino = ip->i_number; 54551559Smckusick ufhp->ufid_gen = ip->i_gen; 54651559Smckusick return (0); 54751559Smckusick } 548