123400Smckusick /* 263375Sbostic * Copyright (c) 1989, 1991, 1993 363375Sbostic * The Regents of the University of California. All rights reserved. 423400Smckusick * 544539Sbostic * %sccs.include.redist.c% 637737Smckusick * 7*65674Shibler * @(#)lfs_vfsops.c 8.5 (Berkeley) 01/12/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, 4251559Smckusick lfs_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 */ 81*65674Shibler if (args.export.ex_flags & MNT_EXPORTED) 8251483Sbostic return (EINVAL); 83*65674Shibler 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 */ 103*65674Shibler 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 */ 183*65674Shibler if (error = vfs_mountedon(devvp)) 18440376Smckusick return (error); 18545652Smckusick if (vcount(devvp) > 1 && devvp != rootvp) 18640376Smckusick return (EBUSY); 18757805Smckusick if (error = vinvalbuf(devvp, 1, 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 /* 34651559Smckusick * Return root of a filesystem 34751559Smckusick */ 34851559Smckusick int 34951559Smckusick lfs_root(mp, vpp) 35051559Smckusick struct mount *mp; 35151559Smckusick struct vnode **vpp; 35251559Smckusick { 35351559Smckusick struct vnode *nvp; 35451559Smckusick int error; 35551559Smckusick 35654693Sbostic if (error = VFS_VGET(mp, (ino_t)ROOTINO, &nvp)) 35751559Smckusick return (error); 35851559Smckusick *vpp = nvp; 35951559Smckusick return (0); 36051559Smckusick } 36151559Smckusick 36251559Smckusick /* 36337737Smckusick * Get file system statistics. 36437737Smckusick */ 36551155Sbostic lfs_statfs(mp, sbp, p) 36637737Smckusick struct mount *mp; 36737737Smckusick register struct statfs *sbp; 36848036Smckusick struct proc *p; 36937737Smckusick { 37051501Sbostic register struct lfs *fs; 37137737Smckusick register struct ufsmount *ump; 37237737Smckusick 37337737Smckusick ump = VFSTOUFS(mp); 37451155Sbostic fs = ump->um_lfs; 37551155Sbostic if (fs->lfs_magic != LFS_MAGIC) 37651155Sbostic panic("lfs_statfs: magic"); 37751155Sbostic sbp->f_type = MOUNT_LFS; 37851155Sbostic sbp->f_bsize = fs->lfs_bsize; 37951943Smckusick sbp->f_iosize = fs->lfs_bsize; 38056156Smargo sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize); 38155588Sbostic sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree); 38251155Sbostic sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) - 38356368Smargo (fs->lfs_dsize - fs->lfs_bfree); 38456156Smargo sbp->f_bavail = dbtofsb(fs, sbp->f_bavail); 38551155Sbostic sbp->f_files = fs->lfs_nfiles; 38655588Sbostic sbp->f_ffree = sbp->f_bfree * INOPB(fs); 38741397Smckusick if (sbp != &mp->mnt_stat) { 38841397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntonname, 38940346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 39041397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 39140346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 39240346Smckusick } 39337737Smckusick return (0); 39437737Smckusick } 39537737Smckusick 39637737Smckusick /* 39737737Smckusick * Go through the disk queues to initiate sandbagged IO; 39837737Smckusick * go through the inodes to write those that have been modified; 39937737Smckusick * initiate the writing of the super block if it has been modified. 40041314Smckusick * 40141314Smckusick * Note: we are always called with the filesystem marked `MPBUSY'. 40237737Smckusick */ 40354693Sbostic lfs_sync(mp, waitfor, cred, p) 40437737Smckusick struct mount *mp; 40537737Smckusick int waitfor; 40654693Sbostic struct ucred *cred; 40754693Sbostic struct proc *p; 40837737Smckusick { 40951215Sbostic int error; 41037737Smckusick 41151310Sbostic /* All syncs must be checkpoints until roll-forward is implemented. */ 41257068Smargo error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0)); 41341314Smckusick #ifdef QUOTA 41441314Smckusick qsync(mp); 41541314Smckusick #endif 41651215Sbostic return (error); 41737737Smckusick } 41851559Smckusick 41951559Smckusick /* 42054693Sbostic * Look up an LFS dinode number to find its incore vnode. If not already 42154693Sbostic * in core, read it in from the specified device. Return the inode locked. 42254693Sbostic * Detection and handling of mount points must be done by the calling routine. 42354693Sbostic */ 42454693Sbostic int 42554693Sbostic lfs_vget(mp, ino, vpp) 42654693Sbostic struct mount *mp; 42754693Sbostic ino_t ino; 42854693Sbostic struct vnode **vpp; 42954693Sbostic { 43054693Sbostic register struct lfs *fs; 43154693Sbostic register struct inode *ip; 43254693Sbostic struct buf *bp; 43354693Sbostic struct ifile *ifp; 43454693Sbostic struct vnode *vp; 43554693Sbostic struct ufsmount *ump; 43654693Sbostic daddr_t daddr; 43754693Sbostic dev_t dev; 43854693Sbostic int error; 43954693Sbostic 44054693Sbostic ump = VFSTOUFS(mp); 44154693Sbostic dev = ump->um_dev; 44254693Sbostic if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 44354693Sbostic return (0); 44454693Sbostic 44554693Sbostic /* Translate the inode number to a disk address. */ 44654693Sbostic fs = ump->um_lfs; 44754693Sbostic if (ino == LFS_IFILE_INUM) 44854693Sbostic daddr = fs->lfs_idaddr; 44954693Sbostic else { 45054693Sbostic LFS_IENTRY(ifp, fs, ino, bp); 45154693Sbostic daddr = ifp->if_daddr; 45254693Sbostic brelse(bp); 45354693Sbostic if (daddr == LFS_UNUSED_DADDR) 45454693Sbostic return (ENOENT); 45554693Sbostic } 45654693Sbostic 45754693Sbostic /* Allocate new vnode/inode. */ 45854693Sbostic if (error = lfs_vcreate(mp, ino, &vp)) { 45954693Sbostic *vpp = NULL; 46054693Sbostic return (error); 46154693Sbostic } 46254693Sbostic 46354693Sbostic /* 46454693Sbostic * Put it onto its hash chain and lock it so that other requests for 46554693Sbostic * this inode will block if they arrive while we are sleeping waiting 46654693Sbostic * for old data structures to be purged or for the contents of the 46754693Sbostic * disk portion of this inode to be read. 46854693Sbostic */ 46954693Sbostic ip = VTOI(vp); 47054693Sbostic ufs_ihashins(ip); 47154693Sbostic 47254693Sbostic /* 47354693Sbostic * XXX 47454693Sbostic * This may not need to be here, logically it should go down with 47554693Sbostic * the i_devvp initialization. 47654693Sbostic * Ask Kirk. 47754693Sbostic */ 47854693Sbostic ip->i_lfs = ump->um_lfs; 47954693Sbostic 48054693Sbostic /* Read in the disk contents for the inode, copy into the inode. */ 48154693Sbostic if (error = 48254693Sbostic bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) { 48354693Sbostic /* 48459820Smckusick * The inode does not contain anything useful, so it would 48559820Smckusick * be misleading to leave it on its hash chain. With mode 48659820Smckusick * still zero, it will be unlinked and returned to the free 48759820Smckusick * list by vput(). 48854693Sbostic */ 48956799Smckusick vput(vp); 49054693Sbostic brelse(bp); 49154693Sbostic *vpp = NULL; 49254693Sbostic return (error); 49354693Sbostic } 49464523Sbostic ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data); 49554693Sbostic brelse(bp); 49654693Sbostic 49754693Sbostic /* 49854693Sbostic * Initialize the vnode from the inode, check for aliases. In all 49954693Sbostic * cases re-init ip, the underlying vnode/inode may have changed. 50054693Sbostic */ 50154693Sbostic if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) { 50256799Smckusick vput(vp); 50354693Sbostic *vpp = NULL; 50454693Sbostic return (error); 50554693Sbostic } 50654693Sbostic /* 50754693Sbostic * Finish inode initialization now that aliasing has been resolved. 50854693Sbostic */ 50954693Sbostic ip->i_devvp = ump->um_devvp; 51054693Sbostic VREF(ip->i_devvp); 51154693Sbostic *vpp = vp; 51254693Sbostic return (0); 51354693Sbostic } 51454693Sbostic 51554693Sbostic /* 51651559Smckusick * File handle to vnode 51751559Smckusick * 51851559Smckusick * Have to be really careful about stale file handles: 51951559Smckusick * - check that the inode number is valid 52051559Smckusick * - call lfs_vget() to get the locked inode 52151559Smckusick * - check for an unallocated inode (i_mode == 0) 52255891Smckusick * - check that the given client host has export rights and return 52355891Smckusick * those rights via. exflagsp and credanonp 52451559Smckusick * 52551559Smckusick * XXX 52651559Smckusick * use ifile to see if inode is allocated instead of reading off disk 52751559Smckusick * what is the relationship between my generational number and the NFS 52851559Smckusick * generational number. 52951559Smckusick */ 53051559Smckusick int 53154734Smckusick lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 53251559Smckusick register struct mount *mp; 53351559Smckusick struct fid *fhp; 53454734Smckusick struct mbuf *nam; 53551559Smckusick struct vnode **vpp; 53654734Smckusick int *exflagsp; 53754734Smckusick struct ucred **credanonp; 53851559Smckusick { 53951559Smckusick register struct ufid *ufhp; 54051559Smckusick 54151559Smckusick ufhp = (struct ufid *)fhp; 54251559Smckusick if (ufhp->ufid_ino < ROOTINO) 54354734Smckusick return (ESTALE); 54456246Smckusick return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); 54551559Smckusick } 54651559Smckusick 54751559Smckusick /* 54851559Smckusick * Vnode pointer to File handle 54951559Smckusick */ 55051559Smckusick /* ARGSUSED */ 55151559Smckusick lfs_vptofh(vp, fhp) 55251559Smckusick struct vnode *vp; 55351559Smckusick struct fid *fhp; 55451559Smckusick { 55551559Smckusick register struct inode *ip; 55651559Smckusick register struct ufid *ufhp; 55751559Smckusick 55851559Smckusick ip = VTOI(vp); 55951559Smckusick ufhp = (struct ufid *)fhp; 56051559Smckusick ufhp->ufid_len = sizeof(struct ufid); 56151559Smckusick ufhp->ufid_ino = ip->i_number; 56251559Smckusick ufhp->ufid_gen = ip->i_gen; 56351559Smckusick return (0); 56451559Smckusick } 565