123400Smckusick /* 250264Skarels * Copyright (c) 1989, 1991 The Regents of the University of California. 337737Smckusick * All rights reserved. 423400Smckusick * 544539Sbostic * %sccs.include.redist.c% 637737Smckusick * 7*54693Sbostic * @(#)lfs_vfsops.c 7.76 (Berkeley) 07/05/92 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/specdev.h> 1751483Sbostic #include <sys/mount.h> 1851483Sbostic #include <sys/buf.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> 2412795Ssam 2551501Sbostic #include <ufs/ufs/quota.h> 2651501Sbostic #include <ufs/ufs/inode.h> 2751501Sbostic #include <ufs/ufs/ufsmount.h> 2851501Sbostic #include <ufs/ufs/ufs_extern.h> 2947571Skarels 3051501Sbostic #include <ufs/lfs/lfs.h> 3151501Sbostic #include <ufs/lfs/lfs_extern.h> 3251155Sbostic 3351991Sbostic int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); 3451215Sbostic 3551155Sbostic struct vfsops lfs_vfsops = { 3651155Sbostic lfs_mount, 3739043Smckusick ufs_start, 3851155Sbostic lfs_unmount, 3951559Smckusick lfs_root, 4041314Smckusick ufs_quotactl, 4151155Sbostic lfs_statfs, 4251155Sbostic lfs_sync, 43*54693Sbostic lfs_vget, 4451559Smckusick lfs_fhtovp, 4551559Smckusick lfs_vptofh, 4651483Sbostic lfs_init, 4737737Smckusick }; 4837737Smckusick 4951483Sbostic int 5051155Sbostic lfs_mountroot() 5112795Ssam { 5251483Sbostic panic("lfs_mountroot"); /* XXX -- implement */ 5337737Smckusick } 5437737Smckusick 5537737Smckusick /* 5637737Smckusick * VFS Operations. 5737737Smckusick * 5837737Smckusick * mount system call 5937737Smckusick */ 6051155Sbostic lfs_mount(mp, path, data, ndp, p) 6140346Smckusick register struct mount *mp; 6237737Smckusick char *path; 6337737Smckusick caddr_t data; 6437737Smckusick struct nameidata *ndp; 6548036Smckusick struct proc *p; 6637737Smckusick { 6737737Smckusick struct vnode *devvp; 6837737Smckusick struct ufs_args args; 6937737Smckusick struct ufsmount *ump; 7051501Sbostic register struct lfs *fs; /* LFS */ 7137737Smckusick u_int size; 7237737Smckusick int error; 7337737Smckusick 7437737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 7537737Smckusick return (error); 7651483Sbostic 7751483Sbostic /* Until LFS can do NFS right. XXX */ 7851483Sbostic if (args.exflags & MNT_EXPORTED) 7951483Sbostic return (EINVAL); 8040371Smckusick /* 8150264Skarels * If updating, check whether changing from read-only to 8250264Skarels * read/write; if there is no device name, that's all we do. 8350264Skarels */ 8450264Skarels if (mp->mnt_flag & MNT_UPDATE) { 8539336Smckusick ump = VFSTOUFS(mp); 8651155Sbostic #ifdef NOTLFS /* LFS */ 8739336Smckusick fs = ump->um_fs; 8841397Smckusick if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 8939336Smckusick fs->fs_ronly = 0; 9051155Sbostic #else 9151155Sbostic fs = ump->um_lfs; 9251155Sbostic if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 9351155Sbostic fs->lfs_ronly = 0; 9451155Sbostic #endif 9552175Smckusick if (args.fspec == 0) { 9652175Smckusick /* 9752175Smckusick * Process export requests. 9852175Smckusick */ 9952175Smckusick if (args.exflags & MNT_EXPORTED) { 100*54693Sbostic if (error = ufs_hang_addrlist(mp, &args)) 10152175Smckusick return (error); 10252175Smckusick mp->mnt_flag |= MNT_EXPORTED; 10352175Smckusick } 10452175Smckusick if (args.exflags & MNT_DELEXPORT) { 105*54693Sbostic ufs_free_addrlist(ump); 10652175Smckusick mp->mnt_flag &= 10752175Smckusick ~(MNT_EXPORTED | MNT_DEFEXPORTED); 10852175Smckusick } 10940371Smckusick return (0); 11052175Smckusick } 11150264Skarels } 11250264Skarels /* 11350264Skarels * Not an update, or updating the name: look up the name 11450264Skarels * and verify that it refers to a sensible block device. 11550264Skarels */ 11652333Smckusick NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 11752333Smckusick if (error = namei(ndp)) 11850264Skarels return (error); 11950264Skarels devvp = ndp->ni_vp; 12050264Skarels if (devvp->v_type != VBLK) { 12150264Skarels vrele(devvp); 12250264Skarels return (ENOTBLK); 12350264Skarels } 12450264Skarels if (major(devvp->v_rdev) >= nblkdev) { 12550264Skarels vrele(devvp); 12650264Skarels return (ENXIO); 12750264Skarels } 12850264Skarels if ((mp->mnt_flag & MNT_UPDATE) == 0) 12951155Sbostic error = lfs_mountfs(devvp, mp, p); /* LFS */ 13050264Skarels else { 13139336Smckusick if (devvp != ump->um_devvp) 13239336Smckusick error = EINVAL; /* needs translation */ 13342858Smckusick else 13442858Smckusick vrele(devvp); 13539336Smckusick } 13637737Smckusick if (error) { 13737737Smckusick vrele(devvp); 13837737Smckusick return (error); 13932721Smckusick } 14037737Smckusick ump = VFSTOUFS(mp); 14151155Sbostic fs = ump->um_lfs; /* LFS */ 14251155Sbostic #ifdef NOTLFS /* LFS */ 14337737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 14437737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 14541397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 14641397Smckusick MNAMELEN); 14751991Sbostic (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 14841397Smckusick &size); 14941397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 15048036Smckusick (void) ufs_statfs(mp, &mp->mnt_stat, p); 15151155Sbostic #else 15251155Sbostic (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size); 15351155Sbostic bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size); 15451155Sbostic bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 15551155Sbostic MNAMELEN); 15651991Sbostic (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 15751155Sbostic &size); 15851155Sbostic bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 15951155Sbostic (void) lfs_statfs(mp, &mp->mnt_stat, p); 16051155Sbostic #endif 16137737Smckusick return (0); 16212795Ssam } 16312795Ssam 16437737Smckusick /* 16537737Smckusick * Common code for mount and mountroot 16651155Sbostic * LFS specific 16737737Smckusick */ 16851991Sbostic int 16951155Sbostic lfs_mountfs(devvp, mp, p) 17040376Smckusick register struct vnode *devvp; 17137737Smckusick struct mount *mp; 17248036Smckusick struct proc *p; 17312795Ssam { 17451155Sbostic extern struct vnode *rootvp; 17551501Sbostic register struct lfs *fs; 17651155Sbostic register struct ufsmount *ump; 17751155Sbostic struct vnode *vp; 17851155Sbostic struct buf *bp; 17930749Skarels struct partinfo dpart; 18051155Sbostic dev_t dev; 18151155Sbostic int error, i, ronly, size; 18212795Ssam 18340376Smckusick /* 18440376Smckusick * Disallow multiple mounts of the same device. 18545652Smckusick * Disallow mounting of a device that is currently in use 18645652Smckusick * (except for root, which might share swap device for miniroot). 18740376Smckusick * Flush out any old buffers remaining from a previous use. 18840376Smckusick */ 18951483Sbostic if (error = ufs_mountedon(devvp)) 19040376Smckusick return (error); 19145652Smckusick if (vcount(devvp) > 1 && devvp != rootvp) 19240376Smckusick return (EBUSY); 193*54693Sbostic if (error = vinvalbuf(devvp, 1, p->p_ucred, p)) 194*54693Sbostic return (error); 19551155Sbostic 19651155Sbostic ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 19748036Smckusick if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p)) 19837737Smckusick return (error); 19951155Sbostic 20048036Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 20137737Smckusick size = DEV_BSIZE; 20248036Smckusick else { 20330749Skarels size = dpart.disklab->d_secsize; 20451155Sbostic #ifdef NEVER_USED 20551155Sbostic dpart.part->p_fstype = FS_LFS; 20651155Sbostic dpart.part->p_fsize = fs->lfs_fsize; /* frag size */ 20751155Sbostic dpart.part->p_frag = fs->lfs_frag; /* frags per block */ 20851155Sbostic dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */ 20951155Sbostic #endif 21037737Smckusick } 21151155Sbostic 21251155Sbostic /* Don't free random space on error. */ 21351155Sbostic bp = NULL; 21451155Sbostic ump = NULL; 21551155Sbostic 21651155Sbostic /* Read in the superblock. */ 21751155Sbostic if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp)) 21812795Ssam goto out; 21951155Sbostic fs = bp->b_un.b_lfs; 22051155Sbostic 22151155Sbostic /* Check the basics. */ 22251155Sbostic if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE || 22351501Sbostic fs->lfs_bsize < sizeof(struct lfs)) { 22441314Smckusick error = EINVAL; /* XXX needs translation */ 22516639Skarels goto out; 22616639Skarels } 22751155Sbostic #ifdef DEBUG 22851483Sbostic lfs_dump_super(fs); 22951155Sbostic #endif 23051155Sbostic 23151155Sbostic /* Allocate the mount structure, copy the superblock into it. */ 23241314Smckusick ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 23351989Smckusick ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK); 23451501Sbostic bcopy(bp->b_un.b_addr, ump->um_lfs, sizeof(struct lfs)); 23551501Sbostic if (sizeof(struct lfs) < LFS_SBPAD) /* XXX why? */ 23639675Smckusick bp->b_flags |= B_INVAL; 23734421Skarels brelse(bp); 23834421Skarels bp = NULL; 23951155Sbostic 24051183Sbostic /* Set up the I/O information */ 24151183Sbostic fs->lfs_iocount = 0; 24251183Sbostic 24354264Sbostic /* Set up the ifile flags */ 24454264Sbostic fs->lfs_doifile = 0; 24554264Sbostic fs->lfs_writer = 0; 24654264Sbostic fs->lfs_dirops = 0; 24754264Sbostic 24851155Sbostic /* Set the file system readonly/modify bits. */ 24951155Sbostic fs = ump->um_lfs; 25051155Sbostic fs->lfs_ronly = ronly; 25112795Ssam if (ronly == 0) 25251155Sbostic fs->lfs_fmod = 1; 25351155Sbostic 25451155Sbostic /* Initialize the mount structure. */ 25551155Sbostic dev = devvp->v_rdev; 25641397Smckusick mp->mnt_data = (qaddr_t)ump; 25741397Smckusick mp->mnt_stat.f_fsid.val[0] = (long)dev; 25851991Sbostic mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS; 25941397Smckusick mp->mnt_flag |= MNT_LOCAL; 26037737Smckusick ump->um_mountp = mp; 26137737Smckusick ump->um_dev = dev; 26237737Smckusick ump->um_devvp = devvp; 26341314Smckusick for (i = 0; i < MAXQUOTAS; i++) 26441314Smckusick ump->um_quotas[i] = NULLVP; 26552221Sbostic devvp->v_specflags |= SI_MOUNTEDON; 26651155Sbostic 26752221Sbostic /* 26852221Sbostic * We use the ifile vnode for almost every operation. Instead of 26952221Sbostic * retrieving it from the hash table each time we retrieve it here, 27052221Sbostic * artificially increment the reference count and keep a pointer 27152221Sbostic * to it in the incore copy of the superblock. 27252221Sbostic */ 273*54693Sbostic if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp)) 27451155Sbostic goto out; 27551155Sbostic fs->lfs_ivnode = vp; 27652221Sbostic VREF(vp); 27752221Sbostic vput(vp); 27851155Sbostic 27937737Smckusick return (0); 28012795Ssam out: 28140872Smckusick if (bp) 28240872Smckusick brelse(bp); 28351155Sbostic (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 28441314Smckusick if (ump) { 28551989Smckusick free(ump->um_lfs, M_UFSMNT); 28651501Sbostic free(ump, M_UFSMNT); 28741397Smckusick mp->mnt_data = (qaddr_t)0; 28832721Smckusick } 28937737Smckusick return (error); 29012795Ssam } 29112795Ssam 29239043Smckusick /* 29337737Smckusick * unmount system call 29437737Smckusick */ 29551155Sbostic lfs_unmount(mp, mntflags, p) 29637737Smckusick struct mount *mp; 29741314Smckusick int mntflags; 29848036Smckusick struct proc *p; 29912795Ssam { 30051501Sbostic extern int doforce; 30137737Smckusick register struct ufsmount *ump; 30251501Sbostic register struct lfs *fs; /* LFS */ 303*54693Sbostic int i, error, flags, ronly; 30412795Ssam 30551853Sbostic #ifdef VERBOSE 30651853Sbostic printf("lfs_unmount\n"); 30751853Sbostic #endif 308*54693Sbostic flags = 0; 30948065Smckusick if (mntflags & MNT_FORCE) { 31048359Smckusick if (!doforce || mp == rootfs) 31148065Smckusick return (EINVAL); 31241314Smckusick flags |= FORCECLOSE; 31348065Smckusick } 31454264Sbostic 31554264Sbostic ump = VFSTOUFS(mp); 31654264Sbostic fs = ump->um_lfs; 31712795Ssam #ifdef QUOTA 31841397Smckusick if (mp->mnt_flag & MNT_QUOTA) { 31954264Sbostic if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags)) 32039898Smckusick return (error); 32141314Smckusick for (i = 0; i < MAXQUOTAS; i++) { 32241314Smckusick if (ump->um_quotas[i] == NULLVP) 32341314Smckusick continue; 32450114Smckusick quotaoff(p, mp, i); 32541314Smckusick } 32639898Smckusick /* 32741314Smckusick * Here we fall through to vflush again to ensure 32841314Smckusick * that we have gotten rid of all the system vnodes. 32939898Smckusick */ 33041314Smckusick } 33112795Ssam #endif 33254264Sbostic vrele(fs->lfs_ivnode); 333*54693Sbostic if (error = vflush(mp, fs->lfs_ivnode, flags)) 33439898Smckusick return (error); 335*54693Sbostic if (error = VFS_SYNC(mp, 1, p->p_ucred, p)) 336*54693Sbostic return (error); 337*54693Sbostic if (fs->lfs_ivnode->v_dirtyblkhd) 338*54693Sbostic panic("lfs_unmount: still dirty blocks on ifile vnode\n"); 339*54693Sbostic vgone(fs->lfs_ivnode); 340*54693Sbostic 34151155Sbostic ronly = !fs->lfs_ronly; 34240653Smckusick ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 343*54693Sbostic error = VOP_CLOSE(ump->um_devvp, 344*54693Sbostic ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 34537737Smckusick vrele(ump->um_devvp); 34651989Smckusick free(fs, M_UFSMNT); 34751501Sbostic free(ump, M_UFSMNT); 34841397Smckusick mp->mnt_data = (qaddr_t)0; 34941397Smckusick mp->mnt_flag &= ~MNT_LOCAL; 35030749Skarels return (error); 35112795Ssam } 35212795Ssam 35337737Smckusick /* 35451559Smckusick * Return root of a filesystem 35551559Smckusick */ 35651559Smckusick int 35751559Smckusick lfs_root(mp, vpp) 35851559Smckusick struct mount *mp; 35951559Smckusick struct vnode **vpp; 36051559Smckusick { 36151559Smckusick struct vnode *nvp; 36251559Smckusick int error; 36351559Smckusick 36451853Sbostic #ifdef VERBOSE 36551853Sbostic printf("lfs_root\n"); 36651853Sbostic #endif 367*54693Sbostic if (error = VFS_VGET(mp, (ino_t)ROOTINO, &nvp)) 36851559Smckusick return (error); 36951559Smckusick *vpp = nvp; 37051559Smckusick return (0); 37151559Smckusick } 37251559Smckusick 37351559Smckusick /* 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_type = MOUNT_LFS; 38951155Sbostic sbp->f_bsize = fs->lfs_bsize; 39051943Smckusick sbp->f_iosize = fs->lfs_bsize; 39151155Sbostic sbp->f_blocks = fs->lfs_dsize; 39251155Sbostic sbp->f_bfree = fs->lfs_bfree; 39351155Sbostic sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) - 39451155Sbostic (fs->lfs_dsize - sbp->f_bfree); 39551155Sbostic sbp->f_files = fs->lfs_nfiles; 39651155Sbostic sbp->f_ffree = fs->lfs_bfree * INOPB(fs); 39741397Smckusick if (sbp != &mp->mnt_stat) { 39841397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntonname, 39940346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 40041397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 40140346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 40240346Smckusick } 40337737Smckusick return (0); 40437737Smckusick } 40537737Smckusick 40637737Smckusick /* 40737737Smckusick * Go through the disk queues to initiate sandbagged IO; 40837737Smckusick * go through the inodes to write those that have been modified; 40937737Smckusick * initiate the writing of the super block if it has been modified. 41041314Smckusick * 41141314Smckusick * Note: we are always called with the filesystem marked `MPBUSY'. 41237737Smckusick */ 413*54693Sbostic lfs_sync(mp, waitfor, cred, p) 41437737Smckusick struct mount *mp; 41537737Smckusick int waitfor; 416*54693Sbostic struct ucred *cred; 417*54693Sbostic struct proc *p; 41837737Smckusick { 41951914Sbostic extern int crashandburn, syncprt; 42051215Sbostic int error; 42137737Smckusick 42251853Sbostic #ifdef VERBOSE 42351853Sbostic printf("lfs_sync\n"); 42451853Sbostic #endif 42551215Sbostic 42651914Sbostic #ifdef DIAGNOSTIC 42751914Sbostic if (crashandburn) 42851914Sbostic return (0); 42951914Sbostic #endif 43051310Sbostic 43151310Sbostic /* All syncs must be checkpoints until roll-forward is implemented. */ 43251991Sbostic error = lfs_segwrite(mp, 1); 43341314Smckusick #ifdef QUOTA 43441314Smckusick qsync(mp); 43541314Smckusick #endif 43651215Sbostic return (error); 43737737Smckusick } 43851559Smckusick 43951559Smckusick /* 440*54693Sbostic * Look up an LFS dinode number to find its incore vnode. If not already 441*54693Sbostic * in core, read it in from the specified device. Return the inode locked. 442*54693Sbostic * Detection and handling of mount points must be done by the calling routine. 443*54693Sbostic */ 444*54693Sbostic int 445*54693Sbostic lfs_vget(mp, ino, vpp) 446*54693Sbostic struct mount *mp; 447*54693Sbostic ino_t ino; 448*54693Sbostic struct vnode **vpp; 449*54693Sbostic { 450*54693Sbostic register struct lfs *fs; 451*54693Sbostic register struct inode *ip; 452*54693Sbostic struct buf *bp; 453*54693Sbostic struct ifile *ifp; 454*54693Sbostic struct vnode *vp; 455*54693Sbostic struct ufsmount *ump; 456*54693Sbostic daddr_t daddr; 457*54693Sbostic dev_t dev; 458*54693Sbostic int error; 459*54693Sbostic 460*54693Sbostic #ifdef VERBOSE 461*54693Sbostic printf("lfs_vget\n"); 462*54693Sbostic #endif 463*54693Sbostic ump = VFSTOUFS(mp); 464*54693Sbostic dev = ump->um_dev; 465*54693Sbostic if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 466*54693Sbostic return (0); 467*54693Sbostic 468*54693Sbostic /* Translate the inode number to a disk address. */ 469*54693Sbostic fs = ump->um_lfs; 470*54693Sbostic if (ino == LFS_IFILE_INUM) 471*54693Sbostic daddr = fs->lfs_idaddr; 472*54693Sbostic else { 473*54693Sbostic LFS_IENTRY(ifp, fs, ino, bp); 474*54693Sbostic daddr = ifp->if_daddr; 475*54693Sbostic brelse(bp); 476*54693Sbostic if (daddr == LFS_UNUSED_DADDR) 477*54693Sbostic return (ENOENT); 478*54693Sbostic } 479*54693Sbostic 480*54693Sbostic /* Allocate new vnode/inode. */ 481*54693Sbostic if (error = lfs_vcreate(mp, ino, &vp)) { 482*54693Sbostic *vpp = NULL; 483*54693Sbostic return (error); 484*54693Sbostic } 485*54693Sbostic 486*54693Sbostic /* 487*54693Sbostic * Put it onto its hash chain and lock it so that other requests for 488*54693Sbostic * this inode will block if they arrive while we are sleeping waiting 489*54693Sbostic * for old data structures to be purged or for the contents of the 490*54693Sbostic * disk portion of this inode to be read. 491*54693Sbostic */ 492*54693Sbostic ip = VTOI(vp); 493*54693Sbostic ufs_ihashins(ip); 494*54693Sbostic 495*54693Sbostic /* 496*54693Sbostic * XXX 497*54693Sbostic * This may not need to be here, logically it should go down with 498*54693Sbostic * the i_devvp initialization. 499*54693Sbostic * Ask Kirk. 500*54693Sbostic */ 501*54693Sbostic ip->i_lfs = ump->um_lfs; 502*54693Sbostic 503*54693Sbostic /* Read in the disk contents for the inode, copy into the inode. */ 504*54693Sbostic if (error = 505*54693Sbostic bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) { 506*54693Sbostic /* 507*54693Sbostic * The inode does not contain anything useful, so it 508*54693Sbostic * would be misleading to leave it on its hash chain. 509*54693Sbostic * Iput() will return it to the free list. 510*54693Sbostic */ 511*54693Sbostic remque(ip); 512*54693Sbostic ip->i_forw = ip; 513*54693Sbostic ip->i_back = ip; 514*54693Sbostic 515*54693Sbostic /* Unlock and discard unneeded inode. */ 516*54693Sbostic ufs_iput(ip); 517*54693Sbostic brelse(bp); 518*54693Sbostic *vpp = NULL; 519*54693Sbostic return (error); 520*54693Sbostic } 521*54693Sbostic ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino); 522*54693Sbostic brelse(bp); 523*54693Sbostic 524*54693Sbostic /* 525*54693Sbostic * Initialize the vnode from the inode, check for aliases. In all 526*54693Sbostic * cases re-init ip, the underlying vnode/inode may have changed. 527*54693Sbostic */ 528*54693Sbostic if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) { 529*54693Sbostic ufs_iput(ip); 530*54693Sbostic *vpp = NULL; 531*54693Sbostic return (error); 532*54693Sbostic } 533*54693Sbostic /* 534*54693Sbostic * Finish inode initialization now that aliasing has been resolved. 535*54693Sbostic */ 536*54693Sbostic ip->i_devvp = ump->um_devvp; 537*54693Sbostic VREF(ip->i_devvp); 538*54693Sbostic *vpp = vp; 539*54693Sbostic return (0); 540*54693Sbostic } 541*54693Sbostic 542*54693Sbostic /* 54351559Smckusick * File handle to vnode 54451559Smckusick * 54551559Smckusick * Have to be really careful about stale file handles: 54651559Smckusick * - check that the inode number is valid 54751559Smckusick * - call lfs_vget() to get the locked inode 54851559Smckusick * - check for an unallocated inode (i_mode == 0) 54951559Smckusick * - check that the generation number matches 55051559Smckusick * 55151559Smckusick * XXX 55251559Smckusick * use ifile to see if inode is allocated instead of reading off disk 55351559Smckusick * what is the relationship between my generational number and the NFS 55451559Smckusick * generational number. 55551559Smckusick */ 55651559Smckusick int 557*54693Sbostic lfs_fhtovp(mp, fhp, vpp) 55851559Smckusick register struct mount *mp; 55951559Smckusick struct fid *fhp; 56051559Smckusick struct vnode **vpp; 56151559Smckusick { 56251559Smckusick register struct inode *ip; 56351559Smckusick register struct ufid *ufhp; 56451559Smckusick struct vnode *nvp; 56551559Smckusick int error; 56651559Smckusick 56751559Smckusick ufhp = (struct ufid *)fhp; 56851559Smckusick if (ufhp->ufid_ino < ROOTINO) 56951559Smckusick return (EINVAL); 570*54693Sbostic if (error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) { 57151559Smckusick *vpp = NULLVP; 57251559Smckusick return (error); 57351559Smckusick } 57451559Smckusick ip = VTOI(nvp); 575*54693Sbostic if (ip->i_mode == 0 || ip->i_gen != ufhp->ufid_gen) { 57651559Smckusick ufs_iput(ip); 57751559Smckusick *vpp = NULLVP; 57851559Smckusick return (EINVAL); 57951559Smckusick } 58051559Smckusick *vpp = nvp; 58151559Smckusick return (0); 58251559Smckusick } 58351559Smckusick 58451559Smckusick /* 58551559Smckusick * Vnode pointer to File handle 58651559Smckusick */ 58751559Smckusick /* ARGSUSED */ 58851559Smckusick lfs_vptofh(vp, fhp) 58951559Smckusick struct vnode *vp; 59051559Smckusick struct fid *fhp; 59151559Smckusick { 59251559Smckusick register struct inode *ip; 59351559Smckusick register struct ufid *ufhp; 59451559Smckusick 59551559Smckusick ip = VTOI(vp); 59651559Smckusick ufhp = (struct ufid *)fhp; 59751559Smckusick ufhp->ufid_len = sizeof(struct ufid); 59851559Smckusick ufhp->ufid_ino = ip->i_number; 59951559Smckusick ufhp->ufid_gen = ip->i_gen; 60051559Smckusick return (0); 60151559Smckusick } 602