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*69293Smckusick * @(#)lfs_vfsops.c 8.13 (Berkeley) 05/08/95 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, 5068676Smckusick lfs_sysctl, 5137737Smckusick }; 5237737Smckusick 5351483Sbostic int 5451155Sbostic lfs_mountroot() 5512795Ssam { 5651483Sbostic panic("lfs_mountroot"); /* XXX -- implement */ 5737737Smckusick } 5837737Smckusick 5937737Smckusick /* 6037737Smckusick * VFS Operations. 6137737Smckusick * 6237737Smckusick * mount system call 6337737Smckusick */ 6451155Sbostic lfs_mount(mp, path, data, ndp, p) 6540346Smckusick register struct mount *mp; 6637737Smckusick char *path; 6737737Smckusick caddr_t data; 6837737Smckusick struct nameidata *ndp; 6948036Smckusick struct proc *p; 7037737Smckusick { 7137737Smckusick struct vnode *devvp; 7237737Smckusick struct ufs_args args; 7337737Smckusick struct ufsmount *ump; 7451501Sbostic register struct lfs *fs; /* LFS */ 7537737Smckusick u_int size; 7637737Smckusick int error; 7767533Smckusick mode_t accessmode; 7837737Smckusick 7937737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 8037737Smckusick return (error); 8151483Sbostic 8251483Sbostic /* Until LFS can do NFS right. XXX */ 8365674Shibler if (args.export.ex_flags & MNT_EXPORTED) 8451483Sbostic return (EINVAL); 8565674Shibler 8640371Smckusick /* 8750264Skarels * If updating, check whether changing from read-only to 8850264Skarels * read/write; if there is no device name, that's all we do. 8950264Skarels */ 9050264Skarels if (mp->mnt_flag & MNT_UPDATE) { 9139336Smckusick ump = VFSTOUFS(mp); 9267533Smckusick if (fs->lfs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { 9367533Smckusick /* 9467533Smckusick * If upgrade to read-write by non-root, then verify 9567533Smckusick * that user has necessary permissions on the device. 9667533Smckusick */ 9767533Smckusick if (p->p_ucred->cr_uid != 0) { 9867533Smckusick VOP_LOCK(ump->um_devvp); 9967533Smckusick if (error = VOP_ACCESS(ump->um_devvp, 10067533Smckusick VREAD | VWRITE, p->p_ucred, p)) { 10167533Smckusick VOP_UNLOCK(ump->um_devvp); 10267533Smckusick return (error); 10367533Smckusick } 10467533Smckusick VOP_UNLOCK(ump->um_devvp); 10567533Smckusick } 10651155Sbostic fs->lfs_ronly = 0; 10767533Smckusick } 10852175Smckusick if (args.fspec == 0) { 10952175Smckusick /* 11052175Smckusick * Process export requests. 11152175Smckusick */ 11265674Shibler return (vfs_export(mp, &ump->um_export, &args.export)); 11352175Smckusick } 11450264Skarels } 11550264Skarels /* 11650264Skarels * Not an update, or updating the name: look up the name 11750264Skarels * and verify that it refers to a sensible block device. 11850264Skarels */ 11952333Smckusick NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 12052333Smckusick if (error = namei(ndp)) 12150264Skarels return (error); 12250264Skarels devvp = ndp->ni_vp; 12350264Skarels if (devvp->v_type != VBLK) { 12450264Skarels vrele(devvp); 12550264Skarels return (ENOTBLK); 12650264Skarels } 12750264Skarels if (major(devvp->v_rdev) >= nblkdev) { 12850264Skarels vrele(devvp); 12950264Skarels return (ENXIO); 13050264Skarels } 13167533Smckusick /* 13267533Smckusick * If mount by non-root, then verify that user has necessary 13367533Smckusick * permissions on the device. 13467533Smckusick */ 13567533Smckusick if (p->p_ucred->cr_uid != 0) { 13667533Smckusick accessmode = VREAD; 13767533Smckusick if ((mp->mnt_flag & MNT_RDONLY) == 0) 13867533Smckusick accessmode |= VWRITE; 13967533Smckusick VOP_LOCK(devvp); 14067533Smckusick if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) { 14167533Smckusick vput(devvp); 14267533Smckusick return (error); 14367533Smckusick } 14467533Smckusick VOP_UNLOCK(devvp); 14567533Smckusick } 14650264Skarels if ((mp->mnt_flag & MNT_UPDATE) == 0) 14751155Sbostic error = lfs_mountfs(devvp, mp, p); /* LFS */ 14850264Skarels else { 14939336Smckusick if (devvp != ump->um_devvp) 15039336Smckusick error = EINVAL; /* needs translation */ 15142858Smckusick else 15242858Smckusick vrele(devvp); 15339336Smckusick } 15437737Smckusick if (error) { 15537737Smckusick vrele(devvp); 15637737Smckusick return (error); 15732721Smckusick } 15837737Smckusick ump = VFSTOUFS(mp); 15951155Sbostic fs = ump->um_lfs; /* LFS */ 16051155Sbostic #ifdef NOTLFS /* LFS */ 16137737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 16237737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 16341397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 16441397Smckusick MNAMELEN); 16551991Sbostic (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 16641397Smckusick &size); 16741397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 16848036Smckusick (void) ufs_statfs(mp, &mp->mnt_stat, p); 16951155Sbostic #else 17051155Sbostic (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size); 17151155Sbostic bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size); 17251155Sbostic bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 17351155Sbostic MNAMELEN); 17451991Sbostic (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 17551155Sbostic &size); 17651155Sbostic bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 17751155Sbostic (void) lfs_statfs(mp, &mp->mnt_stat, p); 17851155Sbostic #endif 17937737Smckusick return (0); 18012795Ssam } 18112795Ssam 18237737Smckusick /* 18337737Smckusick * Common code for mount and mountroot 18451155Sbostic * LFS specific 18537737Smckusick */ 18651991Sbostic int 18751155Sbostic lfs_mountfs(devvp, mp, p) 18840376Smckusick register struct vnode *devvp; 18937737Smckusick struct mount *mp; 19048036Smckusick struct proc *p; 19112795Ssam { 19251155Sbostic extern struct vnode *rootvp; 19351501Sbostic register struct lfs *fs; 19451155Sbostic register struct ufsmount *ump; 19551155Sbostic struct vnode *vp; 19651155Sbostic struct buf *bp; 19730749Skarels struct partinfo dpart; 19851155Sbostic dev_t dev; 19951155Sbostic int error, i, ronly, size; 20067949Smckusick struct ucred *cred; 20112795Ssam 20267949Smckusick cred = p ? p->p_ucred : NOCRED; 20340376Smckusick /* 20440376Smckusick * Disallow multiple mounts of the same device. 20545652Smckusick * Disallow mounting of a device that is currently in use 20645652Smckusick * (except for root, which might share swap device for miniroot). 20740376Smckusick * Flush out any old buffers remaining from a previous use. 20840376Smckusick */ 20965674Shibler if (error = vfs_mountedon(devvp)) 21040376Smckusick return (error); 21145652Smckusick if (vcount(devvp) > 1 && devvp != rootvp) 21240376Smckusick return (EBUSY); 21367949Smckusick if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) 21454693Sbostic return (error); 21551155Sbostic 21651155Sbostic ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 21759473Smckusick if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)) 21837737Smckusick return (error); 21951155Sbostic 22067949Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0) 22137737Smckusick size = DEV_BSIZE; 22248036Smckusick else { 22330749Skarels size = dpart.disklab->d_secsize; 22451155Sbostic #ifdef NEVER_USED 22551155Sbostic dpart.part->p_fstype = FS_LFS; 22651155Sbostic dpart.part->p_fsize = fs->lfs_fsize; /* frag size */ 22751155Sbostic dpart.part->p_frag = fs->lfs_frag; /* frags per block */ 22851155Sbostic dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */ 22951155Sbostic #endif 23037737Smckusick } 23151155Sbostic 23251155Sbostic /* Don't free random space on error. */ 23351155Sbostic bp = NULL; 23451155Sbostic ump = NULL; 23551155Sbostic 23651155Sbostic /* Read in the superblock. */ 23767949Smckusick if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, cred, &bp)) 23812795Ssam goto out; 23964523Sbostic fs = (struct lfs *)bp->b_data; 24051155Sbostic 24151155Sbostic /* Check the basics. */ 24251155Sbostic if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE || 24351501Sbostic fs->lfs_bsize < sizeof(struct lfs)) { 24441314Smckusick error = EINVAL; /* XXX needs translation */ 24516639Skarels goto out; 24616639Skarels } 24751155Sbostic 24851155Sbostic /* Allocate the mount structure, copy the superblock into it. */ 24941314Smckusick ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 25055548Sbostic fs = ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK); 25164523Sbostic bcopy(bp->b_data, fs, sizeof(struct lfs)); 25251501Sbostic if (sizeof(struct lfs) < LFS_SBPAD) /* XXX why? */ 25339675Smckusick bp->b_flags |= B_INVAL; 25434421Skarels brelse(bp); 25534421Skarels bp = NULL; 25651155Sbostic 25751183Sbostic /* Set up the I/O information */ 25851183Sbostic fs->lfs_iocount = 0; 25951183Sbostic 26055548Sbostic /* Set up the ifile and lock aflags */ 26154264Sbostic fs->lfs_doifile = 0; 26254264Sbostic fs->lfs_writer = 0; 26354264Sbostic fs->lfs_dirops = 0; 26455548Sbostic fs->lfs_seglock = 0; 26554264Sbostic 26651155Sbostic /* Set the file system readonly/modify bits. */ 26751155Sbostic fs->lfs_ronly = ronly; 26812795Ssam if (ronly == 0) 26951155Sbostic fs->lfs_fmod = 1; 27051155Sbostic 27151155Sbostic /* Initialize the mount structure. */ 27251155Sbostic dev = devvp->v_rdev; 27341397Smckusick mp->mnt_data = (qaddr_t)ump; 27441397Smckusick mp->mnt_stat.f_fsid.val[0] = (long)dev; 27568676Smckusick mp->mnt_stat.f_fsid.val[1] = lfs_mount_type; 27667395Smkm mp->mnt_maxsymlinklen = fs->lfs_maxsymlinklen; 27741397Smckusick mp->mnt_flag |= MNT_LOCAL; 278*69293Smckusick ump->um_relvp = NULL; 27937737Smckusick ump->um_mountp = mp; 28037737Smckusick ump->um_dev = dev; 28137737Smckusick ump->um_devvp = devvp; 28256475Smargo ump->um_bptrtodb = 0; 28356475Smargo ump->um_seqinc = 1 << fs->lfs_fsbtodb; 28456475Smargo ump->um_nindir = fs->lfs_nindir; 28541314Smckusick for (i = 0; i < MAXQUOTAS; i++) 28641314Smckusick ump->um_quotas[i] = NULLVP; 28752221Sbostic devvp->v_specflags |= SI_MOUNTEDON; 28851155Sbostic 28952221Sbostic /* 29052221Sbostic * We use the ifile vnode for almost every operation. Instead of 29152221Sbostic * retrieving it from the hash table each time we retrieve it here, 29252221Sbostic * artificially increment the reference count and keep a pointer 29352221Sbostic * to it in the incore copy of the superblock. 29452221Sbostic */ 29554693Sbostic if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp)) 29651155Sbostic goto out; 29751155Sbostic fs->lfs_ivnode = vp; 29852221Sbostic VREF(vp); 29952221Sbostic vput(vp); 30051155Sbostic 30137737Smckusick return (0); 30212795Ssam out: 30340872Smckusick if (bp) 30440872Smckusick brelse(bp); 30567949Smckusick (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); 30641314Smckusick if (ump) { 30751989Smckusick free(ump->um_lfs, M_UFSMNT); 30851501Sbostic free(ump, M_UFSMNT); 30941397Smckusick mp->mnt_data = (qaddr_t)0; 31032721Smckusick } 31137737Smckusick return (error); 31212795Ssam } 31312795Ssam 31439043Smckusick /* 31537737Smckusick * unmount system call 31637737Smckusick */ 31751155Sbostic lfs_unmount(mp, mntflags, p) 31837737Smckusick struct mount *mp; 31941314Smckusick int mntflags; 32048036Smckusick struct proc *p; 32112795Ssam { 32251501Sbostic extern int doforce; 32337737Smckusick register struct ufsmount *ump; 32455548Sbostic register struct lfs *fs; 32554693Sbostic int i, error, flags, ronly; 32612795Ssam 32754693Sbostic flags = 0; 32848065Smckusick if (mntflags & MNT_FORCE) { 32965240Smckusick if (!doforce || (mp->mnt_flag & MNT_ROOTFS)) 33048065Smckusick return (EINVAL); 33141314Smckusick flags |= FORCECLOSE; 33248065Smckusick } 33354264Sbostic 33454264Sbostic ump = VFSTOUFS(mp); 33554264Sbostic fs = ump->um_lfs; 33612795Ssam #ifdef QUOTA 33741397Smckusick if (mp->mnt_flag & MNT_QUOTA) { 33854264Sbostic if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags)) 33939898Smckusick return (error); 34041314Smckusick for (i = 0; i < MAXQUOTAS; i++) { 34141314Smckusick if (ump->um_quotas[i] == NULLVP) 34241314Smckusick continue; 34350114Smckusick quotaoff(p, mp, i); 34441314Smckusick } 34539898Smckusick /* 34641314Smckusick * Here we fall through to vflush again to ensure 34741314Smckusick * that we have gotten rid of all the system vnodes. 34839898Smckusick */ 34941314Smckusick } 35012795Ssam #endif 35154693Sbostic if (error = vflush(mp, fs->lfs_ivnode, flags)) 35239898Smckusick return (error); 35355548Sbostic fs->lfs_clean = 1; 35454693Sbostic if (error = VFS_SYNC(mp, 1, p->p_ucred, p)) 35554693Sbostic return (error); 35665240Smckusick if (fs->lfs_ivnode->v_dirtyblkhd.lh_first) 35754693Sbostic panic("lfs_unmount: still dirty blocks on ifile vnode\n"); 35855806Sbostic vrele(fs->lfs_ivnode); 35954693Sbostic vgone(fs->lfs_ivnode); 36054693Sbostic 36151155Sbostic ronly = !fs->lfs_ronly; 36240653Smckusick ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 36354693Sbostic error = VOP_CLOSE(ump->um_devvp, 36454693Sbostic ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 36537737Smckusick vrele(ump->um_devvp); 36651989Smckusick free(fs, M_UFSMNT); 36751501Sbostic free(ump, M_UFSMNT); 36841397Smckusick mp->mnt_data = (qaddr_t)0; 36941397Smckusick mp->mnt_flag &= ~MNT_LOCAL; 37030749Skarels return (error); 37112795Ssam } 37212795Ssam 37337737Smckusick /* 37437737Smckusick * Get file system statistics. 37537737Smckusick */ 37651155Sbostic lfs_statfs(mp, sbp, p) 37737737Smckusick struct mount *mp; 37837737Smckusick register struct statfs *sbp; 37948036Smckusick struct proc *p; 38037737Smckusick { 38151501Sbostic register struct lfs *fs; 38237737Smckusick register struct ufsmount *ump; 38337737Smckusick 38437737Smckusick ump = VFSTOUFS(mp); 38551155Sbostic fs = ump->um_lfs; 38651155Sbostic if (fs->lfs_magic != LFS_MAGIC) 38751155Sbostic panic("lfs_statfs: magic"); 38851155Sbostic sbp->f_bsize = fs->lfs_bsize; 38951943Smckusick sbp->f_iosize = fs->lfs_bsize; 39056156Smargo sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize); 39155588Sbostic sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree); 392*69293Smckusick /* 393*69293Smckusick * To compute the available space. Subtract the minimum free 394*69293Smckusick * from the total number of blocks in the file system. Set avail 395*69293Smckusick * to the smaller of this number and fs->lfs_bfree. 396*69293Smckusick */ 397*69293Smckusick sbp->f_bavail = fs->lfs_dsize * (100 - fs->lfs_minfree) / 100; 398*69293Smckusick sbp->f_bavail = 399*69293Smckusick sbp->f_bavail > fs->lfs_bfree ? fs->lfs_bfree : sbp->f_bavail; 40056156Smargo sbp->f_bavail = dbtofsb(fs, sbp->f_bavail); 40151155Sbostic sbp->f_files = fs->lfs_nfiles; 40255588Sbostic sbp->f_ffree = sbp->f_bfree * INOPB(fs); 40341397Smckusick if (sbp != &mp->mnt_stat) { 40468676Smckusick sbp->f_type = mp->mnt_vfc->vfc_typenum; 40541397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntonname, 40640346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 40741397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 40840346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 40940346Smckusick } 41037737Smckusick return (0); 41137737Smckusick } 41237737Smckusick 41337737Smckusick /* 41437737Smckusick * Go through the disk queues to initiate sandbagged IO; 41537737Smckusick * go through the inodes to write those that have been modified; 41637737Smckusick * initiate the writing of the super block if it has been modified. 41741314Smckusick * 41841314Smckusick * Note: we are always called with the filesystem marked `MPBUSY'. 41937737Smckusick */ 42054693Sbostic lfs_sync(mp, waitfor, cred, p) 42137737Smckusick struct mount *mp; 42237737Smckusick int waitfor; 42354693Sbostic struct ucred *cred; 42454693Sbostic struct proc *p; 42537737Smckusick { 42651215Sbostic int error; 42737737Smckusick 42851310Sbostic /* All syncs must be checkpoints until roll-forward is implemented. */ 42957068Smargo error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0)); 43041314Smckusick #ifdef QUOTA 43141314Smckusick qsync(mp); 43241314Smckusick #endif 43351215Sbostic return (error); 43437737Smckusick } 43551559Smckusick 43651559Smckusick /* 43754693Sbostic * Look up an LFS dinode number to find its incore vnode. If not already 43854693Sbostic * in core, read it in from the specified device. Return the inode locked. 43954693Sbostic * Detection and handling of mount points must be done by the calling routine. 44054693Sbostic */ 44154693Sbostic int 44254693Sbostic lfs_vget(mp, ino, vpp) 44354693Sbostic struct mount *mp; 44454693Sbostic ino_t ino; 44554693Sbostic struct vnode **vpp; 44654693Sbostic { 44754693Sbostic register struct lfs *fs; 44854693Sbostic register struct inode *ip; 44954693Sbostic struct buf *bp; 45054693Sbostic struct ifile *ifp; 45154693Sbostic struct vnode *vp; 45254693Sbostic struct ufsmount *ump; 45368550Smckusick ufs_daddr_t daddr; 45454693Sbostic dev_t dev; 45554693Sbostic int error; 45654693Sbostic 45754693Sbostic ump = VFSTOUFS(mp); 45854693Sbostic dev = ump->um_dev; 45954693Sbostic if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 46054693Sbostic return (0); 46154693Sbostic 46254693Sbostic /* Translate the inode number to a disk address. */ 46354693Sbostic fs = ump->um_lfs; 46454693Sbostic if (ino == LFS_IFILE_INUM) 46554693Sbostic daddr = fs->lfs_idaddr; 46654693Sbostic else { 46754693Sbostic LFS_IENTRY(ifp, fs, ino, bp); 46854693Sbostic daddr = ifp->if_daddr; 46954693Sbostic brelse(bp); 47054693Sbostic if (daddr == LFS_UNUSED_DADDR) 47154693Sbostic return (ENOENT); 47254693Sbostic } 47354693Sbostic 47454693Sbostic /* Allocate new vnode/inode. */ 47554693Sbostic if (error = lfs_vcreate(mp, ino, &vp)) { 47654693Sbostic *vpp = NULL; 47754693Sbostic return (error); 47854693Sbostic } 47954693Sbostic 48054693Sbostic /* 48154693Sbostic * Put it onto its hash chain and lock it so that other requests for 48254693Sbostic * this inode will block if they arrive while we are sleeping waiting 48354693Sbostic * for old data structures to be purged or for the contents of the 48454693Sbostic * disk portion of this inode to be read. 48554693Sbostic */ 48654693Sbostic ip = VTOI(vp); 48754693Sbostic ufs_ihashins(ip); 48854693Sbostic 48954693Sbostic /* 49054693Sbostic * XXX 49154693Sbostic * This may not need to be here, logically it should go down with 49254693Sbostic * the i_devvp initialization. 49354693Sbostic * Ask Kirk. 49454693Sbostic */ 49554693Sbostic ip->i_lfs = ump->um_lfs; 49654693Sbostic 49754693Sbostic /* Read in the disk contents for the inode, copy into the inode. */ 49854693Sbostic if (error = 49954693Sbostic bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) { 50054693Sbostic /* 50159820Smckusick * The inode does not contain anything useful, so it would 50259820Smckusick * be misleading to leave it on its hash chain. With mode 50359820Smckusick * still zero, it will be unlinked and returned to the free 50459820Smckusick * list by vput(). 50554693Sbostic */ 50656799Smckusick vput(vp); 50754693Sbostic brelse(bp); 50854693Sbostic *vpp = NULL; 50954693Sbostic return (error); 51054693Sbostic } 51164523Sbostic ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data); 51254693Sbostic brelse(bp); 51354693Sbostic 51454693Sbostic /* 51554693Sbostic * Initialize the vnode from the inode, check for aliases. In all 51654693Sbostic * cases re-init ip, the underlying vnode/inode may have changed. 51754693Sbostic */ 51854693Sbostic if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) { 51956799Smckusick vput(vp); 52054693Sbostic *vpp = NULL; 52154693Sbostic return (error); 52254693Sbostic } 52354693Sbostic /* 52454693Sbostic * Finish inode initialization now that aliasing has been resolved. 52554693Sbostic */ 52654693Sbostic ip->i_devvp = ump->um_devvp; 52754693Sbostic VREF(ip->i_devvp); 52854693Sbostic *vpp = vp; 52954693Sbostic return (0); 53054693Sbostic } 53154693Sbostic 53254693Sbostic /* 53351559Smckusick * File handle to vnode 53451559Smckusick * 53551559Smckusick * Have to be really careful about stale file handles: 53651559Smckusick * - check that the inode number is valid 53751559Smckusick * - call lfs_vget() to get the locked inode 53851559Smckusick * - check for an unallocated inode (i_mode == 0) 53955891Smckusick * - check that the given client host has export rights and return 54055891Smckusick * those rights via. exflagsp and credanonp 54151559Smckusick * 54251559Smckusick * XXX 54351559Smckusick * use ifile to see if inode is allocated instead of reading off disk 54451559Smckusick * what is the relationship between my generational number and the NFS 54551559Smckusick * generational number. 54651559Smckusick */ 54751559Smckusick int 54854734Smckusick lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 54951559Smckusick register struct mount *mp; 55051559Smckusick struct fid *fhp; 55154734Smckusick struct mbuf *nam; 55251559Smckusick struct vnode **vpp; 55354734Smckusick int *exflagsp; 55454734Smckusick struct ucred **credanonp; 55551559Smckusick { 55651559Smckusick register struct ufid *ufhp; 55751559Smckusick 55851559Smckusick ufhp = (struct ufid *)fhp; 55951559Smckusick if (ufhp->ufid_ino < ROOTINO) 56054734Smckusick return (ESTALE); 56156246Smckusick return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); 56251559Smckusick } 56351559Smckusick 56451559Smckusick /* 56551559Smckusick * Vnode pointer to File handle 56651559Smckusick */ 56751559Smckusick /* ARGSUSED */ 56851559Smckusick lfs_vptofh(vp, fhp) 56951559Smckusick struct vnode *vp; 57051559Smckusick struct fid *fhp; 57151559Smckusick { 57251559Smckusick register struct inode *ip; 57351559Smckusick register struct ufid *ufhp; 57451559Smckusick 57551559Smckusick ip = VTOI(vp); 57651559Smckusick ufhp = (struct ufid *)fhp; 57751559Smckusick ufhp->ufid_len = sizeof(struct ufid); 57851559Smckusick ufhp->ufid_ino = ip->i_number; 57951559Smckusick ufhp->ufid_gen = ip->i_gen; 58051559Smckusick return (0); 58151559Smckusick } 58268676Smckusick 58368676Smckusick /* 58468676Smckusick * Initialize the filesystem, most work done by ufs_init. 58568676Smckusick */ 58668676Smckusick int lfs_mount_type; 58768676Smckusick 58868676Smckusick int 58968676Smckusick lfs_init(vfsp) 59068676Smckusick struct vfsconf *vfsp; 59168676Smckusick { 59268676Smckusick 59368676Smckusick lfs_mount_type = vfsp->vfc_typenum; 59468676Smckusick return (ufs_init(vfsp)); 59568676Smckusick } 596