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*54734Smckusick * @(#)lfs_vfsops.c 7.77 (Berkeley) 07/06/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> 19*54734Smckusick #include <sys/mbuf.h> 2051483Sbostic #include <sys/file.h> 2151483Sbostic #include <sys/disklabel.h> 2251483Sbostic #include <sys/ioctl.h> 2351483Sbostic #include <sys/errno.h> 2451483Sbostic #include <sys/malloc.h> 25*54734Smckusick #include <sys/socket.h> 2612795Ssam 2751501Sbostic #include <ufs/ufs/quota.h> 2851501Sbostic #include <ufs/ufs/inode.h> 2951501Sbostic #include <ufs/ufs/ufsmount.h> 3051501Sbostic #include <ufs/ufs/ufs_extern.h> 3147571Skarels 3251501Sbostic #include <ufs/lfs/lfs.h> 3351501Sbostic #include <ufs/lfs/lfs_extern.h> 3451155Sbostic 3551991Sbostic int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); 3651215Sbostic 3751155Sbostic struct vfsops lfs_vfsops = { 3851155Sbostic lfs_mount, 3939043Smckusick ufs_start, 4051155Sbostic lfs_unmount, 4151559Smckusick lfs_root, 4241314Smckusick ufs_quotactl, 4351155Sbostic lfs_statfs, 4451155Sbostic lfs_sync, 4554693Sbostic lfs_vget, 4651559Smckusick lfs_fhtovp, 4751559Smckusick lfs_vptofh, 4851483Sbostic lfs_init, 4937737Smckusick }; 5037737Smckusick 5151483Sbostic int 5251155Sbostic lfs_mountroot() 5312795Ssam { 5451483Sbostic panic("lfs_mountroot"); /* XXX -- implement */ 5537737Smckusick } 5637737Smckusick 5737737Smckusick /* 5837737Smckusick * VFS Operations. 5937737Smckusick * 6037737Smckusick * mount system call 6137737Smckusick */ 6251155Sbostic lfs_mount(mp, path, data, ndp, p) 6340346Smckusick register struct mount *mp; 6437737Smckusick char *path; 6537737Smckusick caddr_t data; 6637737Smckusick struct nameidata *ndp; 6748036Smckusick struct proc *p; 6837737Smckusick { 6937737Smckusick struct vnode *devvp; 7037737Smckusick struct ufs_args args; 7137737Smckusick struct ufsmount *ump; 7251501Sbostic register struct lfs *fs; /* LFS */ 7337737Smckusick u_int size; 7437737Smckusick int error; 7537737Smckusick 7637737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 7737737Smckusick return (error); 7851483Sbostic 7951483Sbostic /* Until LFS can do NFS right. XXX */ 8051483Sbostic if (args.exflags & MNT_EXPORTED) 8151483Sbostic return (EINVAL); 8240371Smckusick /* 8350264Skarels * If updating, check whether changing from read-only to 8450264Skarels * read/write; if there is no device name, that's all we do. 8550264Skarels */ 8650264Skarels if (mp->mnt_flag & MNT_UPDATE) { 8739336Smckusick ump = VFSTOUFS(mp); 8851155Sbostic #ifdef NOTLFS /* LFS */ 8939336Smckusick fs = ump->um_fs; 9041397Smckusick if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 9139336Smckusick fs->fs_ronly = 0; 9251155Sbostic #else 9351155Sbostic fs = ump->um_lfs; 9451155Sbostic if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 9551155Sbostic fs->lfs_ronly = 0; 9651155Sbostic #endif 9752175Smckusick if (args.fspec == 0) { 9852175Smckusick /* 9952175Smckusick * Process export requests. 10052175Smckusick */ 10152175Smckusick if (args.exflags & MNT_EXPORTED) { 10254693Sbostic if (error = ufs_hang_addrlist(mp, &args)) 10352175Smckusick return (error); 10452175Smckusick mp->mnt_flag |= MNT_EXPORTED; 10552175Smckusick } 10652175Smckusick if (args.exflags & MNT_DELEXPORT) { 10754693Sbostic ufs_free_addrlist(ump); 10852175Smckusick mp->mnt_flag &= 10952175Smckusick ~(MNT_EXPORTED | MNT_DEFEXPORTED); 11052175Smckusick } 11140371Smckusick return (0); 11252175Smckusick } 11350264Skarels } 11450264Skarels /* 11550264Skarels * Not an update, or updating the name: look up the name 11650264Skarels * and verify that it refers to a sensible block device. 11750264Skarels */ 11852333Smckusick NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 11952333Smckusick if (error = namei(ndp)) 12050264Skarels return (error); 12150264Skarels devvp = ndp->ni_vp; 12250264Skarels if (devvp->v_type != VBLK) { 12350264Skarels vrele(devvp); 12450264Skarels return (ENOTBLK); 12550264Skarels } 12650264Skarels if (major(devvp->v_rdev) >= nblkdev) { 12750264Skarels vrele(devvp); 12850264Skarels return (ENXIO); 12950264Skarels } 13050264Skarels if ((mp->mnt_flag & MNT_UPDATE) == 0) 13151155Sbostic error = lfs_mountfs(devvp, mp, p); /* LFS */ 13250264Skarels else { 13339336Smckusick if (devvp != ump->um_devvp) 13439336Smckusick error = EINVAL; /* needs translation */ 13542858Smckusick else 13642858Smckusick vrele(devvp); 13739336Smckusick } 13837737Smckusick if (error) { 13937737Smckusick vrele(devvp); 14037737Smckusick return (error); 14132721Smckusick } 14237737Smckusick ump = VFSTOUFS(mp); 14351155Sbostic fs = ump->um_lfs; /* LFS */ 14451155Sbostic #ifdef NOTLFS /* LFS */ 14537737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 14637737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 14741397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 14841397Smckusick MNAMELEN); 14951991Sbostic (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 15041397Smckusick &size); 15141397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 15248036Smckusick (void) ufs_statfs(mp, &mp->mnt_stat, p); 15351155Sbostic #else 15451155Sbostic (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size); 15551155Sbostic bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size); 15651155Sbostic bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 15751155Sbostic MNAMELEN); 15851991Sbostic (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 15951155Sbostic &size); 16051155Sbostic bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 16151155Sbostic (void) lfs_statfs(mp, &mp->mnt_stat, p); 16251155Sbostic #endif 16337737Smckusick return (0); 16412795Ssam } 16512795Ssam 16637737Smckusick /* 16737737Smckusick * Common code for mount and mountroot 16851155Sbostic * LFS specific 16937737Smckusick */ 17051991Sbostic int 17151155Sbostic lfs_mountfs(devvp, mp, p) 17240376Smckusick register struct vnode *devvp; 17337737Smckusick struct mount *mp; 17448036Smckusick struct proc *p; 17512795Ssam { 17651155Sbostic extern struct vnode *rootvp; 17751501Sbostic register struct lfs *fs; 17851155Sbostic register struct ufsmount *ump; 17951155Sbostic struct vnode *vp; 18051155Sbostic struct buf *bp; 18130749Skarels struct partinfo dpart; 18251155Sbostic dev_t dev; 18351155Sbostic int error, i, ronly, size; 18412795Ssam 18540376Smckusick /* 18640376Smckusick * Disallow multiple mounts of the same device. 18745652Smckusick * Disallow mounting of a device that is currently in use 18845652Smckusick * (except for root, which might share swap device for miniroot). 18940376Smckusick * Flush out any old buffers remaining from a previous use. 19040376Smckusick */ 19151483Sbostic if (error = ufs_mountedon(devvp)) 19240376Smckusick return (error); 19345652Smckusick if (vcount(devvp) > 1 && devvp != rootvp) 19440376Smckusick return (EBUSY); 19554693Sbostic if (error = vinvalbuf(devvp, 1, p->p_ucred, p)) 19654693Sbostic return (error); 19751155Sbostic 19851155Sbostic ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 19948036Smckusick if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p)) 20037737Smckusick return (error); 20151155Sbostic 20248036Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 20337737Smckusick size = DEV_BSIZE; 20448036Smckusick else { 20530749Skarels size = dpart.disklab->d_secsize; 20651155Sbostic #ifdef NEVER_USED 20751155Sbostic dpart.part->p_fstype = FS_LFS; 20851155Sbostic dpart.part->p_fsize = fs->lfs_fsize; /* frag size */ 20951155Sbostic dpart.part->p_frag = fs->lfs_frag; /* frags per block */ 21051155Sbostic dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */ 21151155Sbostic #endif 21237737Smckusick } 21351155Sbostic 21451155Sbostic /* Don't free random space on error. */ 21551155Sbostic bp = NULL; 21651155Sbostic ump = NULL; 21751155Sbostic 21851155Sbostic /* Read in the superblock. */ 21951155Sbostic if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp)) 22012795Ssam goto out; 22151155Sbostic fs = bp->b_un.b_lfs; 22251155Sbostic 22351155Sbostic /* Check the basics. */ 22451155Sbostic if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE || 22551501Sbostic fs->lfs_bsize < sizeof(struct lfs)) { 22641314Smckusick error = EINVAL; /* XXX needs translation */ 22716639Skarels goto out; 22816639Skarels } 22951155Sbostic #ifdef DEBUG 23051483Sbostic lfs_dump_super(fs); 23151155Sbostic #endif 23251155Sbostic 23351155Sbostic /* Allocate the mount structure, copy the superblock into it. */ 23441314Smckusick ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 23551989Smckusick ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK); 23651501Sbostic bcopy(bp->b_un.b_addr, ump->um_lfs, sizeof(struct lfs)); 23751501Sbostic if (sizeof(struct lfs) < LFS_SBPAD) /* XXX why? */ 23839675Smckusick bp->b_flags |= B_INVAL; 23934421Skarels brelse(bp); 24034421Skarels bp = NULL; 24151155Sbostic 24251183Sbostic /* Set up the I/O information */ 24351183Sbostic fs->lfs_iocount = 0; 24451183Sbostic 24554264Sbostic /* Set up the ifile flags */ 24654264Sbostic fs->lfs_doifile = 0; 24754264Sbostic fs->lfs_writer = 0; 24854264Sbostic fs->lfs_dirops = 0; 24954264Sbostic 25051155Sbostic /* Set the file system readonly/modify bits. */ 25151155Sbostic fs = ump->um_lfs; 25251155Sbostic fs->lfs_ronly = ronly; 25312795Ssam if (ronly == 0) 25451155Sbostic fs->lfs_fmod = 1; 25551155Sbostic 25651155Sbostic /* Initialize the mount structure. */ 25751155Sbostic dev = devvp->v_rdev; 25841397Smckusick mp->mnt_data = (qaddr_t)ump; 25941397Smckusick mp->mnt_stat.f_fsid.val[0] = (long)dev; 26051991Sbostic mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS; 26141397Smckusick mp->mnt_flag |= MNT_LOCAL; 26237737Smckusick ump->um_mountp = mp; 26337737Smckusick ump->um_dev = dev; 26437737Smckusick ump->um_devvp = devvp; 26541314Smckusick for (i = 0; i < MAXQUOTAS; i++) 26641314Smckusick ump->um_quotas[i] = NULLVP; 26752221Sbostic devvp->v_specflags |= SI_MOUNTEDON; 26851155Sbostic 26952221Sbostic /* 27052221Sbostic * We use the ifile vnode for almost every operation. Instead of 27152221Sbostic * retrieving it from the hash table each time we retrieve it here, 27252221Sbostic * artificially increment the reference count and keep a pointer 27352221Sbostic * to it in the incore copy of the superblock. 27452221Sbostic */ 27554693Sbostic if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp)) 27651155Sbostic goto out; 27751155Sbostic fs->lfs_ivnode = vp; 27852221Sbostic VREF(vp); 27952221Sbostic vput(vp); 28051155Sbostic 28137737Smckusick return (0); 28212795Ssam out: 28340872Smckusick if (bp) 28440872Smckusick brelse(bp); 28551155Sbostic (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 28641314Smckusick if (ump) { 28751989Smckusick free(ump->um_lfs, M_UFSMNT); 28851501Sbostic free(ump, M_UFSMNT); 28941397Smckusick mp->mnt_data = (qaddr_t)0; 29032721Smckusick } 29137737Smckusick return (error); 29212795Ssam } 29312795Ssam 29439043Smckusick /* 29537737Smckusick * unmount system call 29637737Smckusick */ 29751155Sbostic lfs_unmount(mp, mntflags, p) 29837737Smckusick struct mount *mp; 29941314Smckusick int mntflags; 30048036Smckusick struct proc *p; 30112795Ssam { 30251501Sbostic extern int doforce; 30337737Smckusick register struct ufsmount *ump; 30451501Sbostic register struct lfs *fs; /* LFS */ 30554693Sbostic int i, error, flags, ronly; 30612795Ssam 30751853Sbostic #ifdef VERBOSE 30851853Sbostic printf("lfs_unmount\n"); 30951853Sbostic #endif 31054693Sbostic flags = 0; 31148065Smckusick if (mntflags & MNT_FORCE) { 31248359Smckusick if (!doforce || mp == rootfs) 31348065Smckusick return (EINVAL); 31441314Smckusick flags |= FORCECLOSE; 31548065Smckusick } 31654264Sbostic 31754264Sbostic ump = VFSTOUFS(mp); 31854264Sbostic fs = ump->um_lfs; 31912795Ssam #ifdef QUOTA 32041397Smckusick if (mp->mnt_flag & MNT_QUOTA) { 32154264Sbostic if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags)) 32239898Smckusick return (error); 32341314Smckusick for (i = 0; i < MAXQUOTAS; i++) { 32441314Smckusick if (ump->um_quotas[i] == NULLVP) 32541314Smckusick continue; 32650114Smckusick quotaoff(p, mp, i); 32741314Smckusick } 32839898Smckusick /* 32941314Smckusick * Here we fall through to vflush again to ensure 33041314Smckusick * that we have gotten rid of all the system vnodes. 33139898Smckusick */ 33241314Smckusick } 33312795Ssam #endif 33454264Sbostic vrele(fs->lfs_ivnode); 33554693Sbostic if (error = vflush(mp, fs->lfs_ivnode, flags)) 33639898Smckusick return (error); 33754693Sbostic if (error = VFS_SYNC(mp, 1, p->p_ucred, p)) 33854693Sbostic return (error); 33954693Sbostic if (fs->lfs_ivnode->v_dirtyblkhd) 34054693Sbostic panic("lfs_unmount: still dirty blocks on ifile vnode\n"); 34154693Sbostic vgone(fs->lfs_ivnode); 34254693Sbostic 34351155Sbostic ronly = !fs->lfs_ronly; 34440653Smckusick ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 34554693Sbostic error = VOP_CLOSE(ump->um_devvp, 34654693Sbostic ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 34737737Smckusick vrele(ump->um_devvp); 34851989Smckusick free(fs, M_UFSMNT); 34951501Sbostic free(ump, M_UFSMNT); 35041397Smckusick mp->mnt_data = (qaddr_t)0; 35141397Smckusick mp->mnt_flag &= ~MNT_LOCAL; 35230749Skarels return (error); 35312795Ssam } 35412795Ssam 35537737Smckusick /* 35651559Smckusick * Return root of a filesystem 35751559Smckusick */ 35851559Smckusick int 35951559Smckusick lfs_root(mp, vpp) 36051559Smckusick struct mount *mp; 36151559Smckusick struct vnode **vpp; 36251559Smckusick { 36351559Smckusick struct vnode *nvp; 36451559Smckusick int error; 36551559Smckusick 36651853Sbostic #ifdef VERBOSE 36751853Sbostic printf("lfs_root\n"); 36851853Sbostic #endif 36954693Sbostic if (error = VFS_VGET(mp, (ino_t)ROOTINO, &nvp)) 37051559Smckusick return (error); 37151559Smckusick *vpp = nvp; 37251559Smckusick return (0); 37351559Smckusick } 37451559Smckusick 37551559Smckusick /* 37637737Smckusick * Get file system statistics. 37737737Smckusick */ 37851155Sbostic lfs_statfs(mp, sbp, p) 37937737Smckusick struct mount *mp; 38037737Smckusick register struct statfs *sbp; 38148036Smckusick struct proc *p; 38237737Smckusick { 38351501Sbostic register struct lfs *fs; 38437737Smckusick register struct ufsmount *ump; 38537737Smckusick 38637737Smckusick ump = VFSTOUFS(mp); 38751155Sbostic fs = ump->um_lfs; 38851155Sbostic if (fs->lfs_magic != LFS_MAGIC) 38951155Sbostic panic("lfs_statfs: magic"); 39051155Sbostic sbp->f_type = MOUNT_LFS; 39151155Sbostic sbp->f_bsize = fs->lfs_bsize; 39251943Smckusick sbp->f_iosize = fs->lfs_bsize; 39351155Sbostic sbp->f_blocks = fs->lfs_dsize; 39451155Sbostic sbp->f_bfree = fs->lfs_bfree; 39551155Sbostic sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) - 39651155Sbostic (fs->lfs_dsize - sbp->f_bfree); 39751155Sbostic sbp->f_files = fs->lfs_nfiles; 39851155Sbostic sbp->f_ffree = fs->lfs_bfree * INOPB(fs); 39941397Smckusick if (sbp != &mp->mnt_stat) { 40041397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntonname, 40140346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 40241397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 40340346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 40440346Smckusick } 40537737Smckusick return (0); 40637737Smckusick } 40737737Smckusick 40837737Smckusick /* 40937737Smckusick * Go through the disk queues to initiate sandbagged IO; 41037737Smckusick * go through the inodes to write those that have been modified; 41137737Smckusick * initiate the writing of the super block if it has been modified. 41241314Smckusick * 41341314Smckusick * Note: we are always called with the filesystem marked `MPBUSY'. 41437737Smckusick */ 41554693Sbostic lfs_sync(mp, waitfor, cred, p) 41637737Smckusick struct mount *mp; 41737737Smckusick int waitfor; 41854693Sbostic struct ucred *cred; 41954693Sbostic struct proc *p; 42037737Smckusick { 42151914Sbostic extern int crashandburn, syncprt; 42251215Sbostic int error; 42337737Smckusick 42451853Sbostic #ifdef VERBOSE 42551853Sbostic printf("lfs_sync\n"); 42651853Sbostic #endif 42751215Sbostic 42851914Sbostic #ifdef DIAGNOSTIC 42951914Sbostic if (crashandburn) 43051914Sbostic return (0); 43151914Sbostic #endif 43251310Sbostic 43351310Sbostic /* All syncs must be checkpoints until roll-forward is implemented. */ 43451991Sbostic error = lfs_segwrite(mp, 1); 43541314Smckusick #ifdef QUOTA 43641314Smckusick qsync(mp); 43741314Smckusick #endif 43851215Sbostic return (error); 43937737Smckusick } 44051559Smckusick 44151559Smckusick /* 44254693Sbostic * Look up an LFS dinode number to find its incore vnode. If not already 44354693Sbostic * in core, read it in from the specified device. Return the inode locked. 44454693Sbostic * Detection and handling of mount points must be done by the calling routine. 44554693Sbostic */ 44654693Sbostic int 44754693Sbostic lfs_vget(mp, ino, vpp) 44854693Sbostic struct mount *mp; 44954693Sbostic ino_t ino; 45054693Sbostic struct vnode **vpp; 45154693Sbostic { 45254693Sbostic register struct lfs *fs; 45354693Sbostic register struct inode *ip; 45454693Sbostic struct buf *bp; 45554693Sbostic struct ifile *ifp; 45654693Sbostic struct vnode *vp; 45754693Sbostic struct ufsmount *ump; 45854693Sbostic daddr_t daddr; 45954693Sbostic dev_t dev; 46054693Sbostic int error; 46154693Sbostic 46254693Sbostic #ifdef VERBOSE 46354693Sbostic printf("lfs_vget\n"); 46454693Sbostic #endif 46554693Sbostic ump = VFSTOUFS(mp); 46654693Sbostic dev = ump->um_dev; 46754693Sbostic if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 46854693Sbostic return (0); 46954693Sbostic 47054693Sbostic /* Translate the inode number to a disk address. */ 47154693Sbostic fs = ump->um_lfs; 47254693Sbostic if (ino == LFS_IFILE_INUM) 47354693Sbostic daddr = fs->lfs_idaddr; 47454693Sbostic else { 47554693Sbostic LFS_IENTRY(ifp, fs, ino, bp); 47654693Sbostic daddr = ifp->if_daddr; 47754693Sbostic brelse(bp); 47854693Sbostic if (daddr == LFS_UNUSED_DADDR) 47954693Sbostic return (ENOENT); 48054693Sbostic } 48154693Sbostic 48254693Sbostic /* Allocate new vnode/inode. */ 48354693Sbostic if (error = lfs_vcreate(mp, ino, &vp)) { 48454693Sbostic *vpp = NULL; 48554693Sbostic return (error); 48654693Sbostic } 48754693Sbostic 48854693Sbostic /* 48954693Sbostic * Put it onto its hash chain and lock it so that other requests for 49054693Sbostic * this inode will block if they arrive while we are sleeping waiting 49154693Sbostic * for old data structures to be purged or for the contents of the 49254693Sbostic * disk portion of this inode to be read. 49354693Sbostic */ 49454693Sbostic ip = VTOI(vp); 49554693Sbostic ufs_ihashins(ip); 49654693Sbostic 49754693Sbostic /* 49854693Sbostic * XXX 49954693Sbostic * This may not need to be here, logically it should go down with 50054693Sbostic * the i_devvp initialization. 50154693Sbostic * Ask Kirk. 50254693Sbostic */ 50354693Sbostic ip->i_lfs = ump->um_lfs; 50454693Sbostic 50554693Sbostic /* Read in the disk contents for the inode, copy into the inode. */ 50654693Sbostic if (error = 50754693Sbostic bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) { 50854693Sbostic /* 50954693Sbostic * The inode does not contain anything useful, so it 51054693Sbostic * would be misleading to leave it on its hash chain. 51154693Sbostic * Iput() will return it to the free list. 51254693Sbostic */ 51354693Sbostic remque(ip); 51454693Sbostic ip->i_forw = ip; 51554693Sbostic ip->i_back = ip; 51654693Sbostic 51754693Sbostic /* Unlock and discard unneeded inode. */ 51854693Sbostic ufs_iput(ip); 51954693Sbostic brelse(bp); 52054693Sbostic *vpp = NULL; 52154693Sbostic return (error); 52254693Sbostic } 52354693Sbostic ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino); 52454693Sbostic brelse(bp); 52554693Sbostic 52654693Sbostic /* 52754693Sbostic * Initialize the vnode from the inode, check for aliases. In all 52854693Sbostic * cases re-init ip, the underlying vnode/inode may have changed. 52954693Sbostic */ 53054693Sbostic if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) { 53154693Sbostic ufs_iput(ip); 53254693Sbostic *vpp = NULL; 53354693Sbostic return (error); 53454693Sbostic } 53554693Sbostic /* 53654693Sbostic * Finish inode initialization now that aliasing has been resolved. 53754693Sbostic */ 53854693Sbostic ip->i_devvp = ump->um_devvp; 53954693Sbostic VREF(ip->i_devvp); 54054693Sbostic *vpp = vp; 54154693Sbostic return (0); 54254693Sbostic } 54354693Sbostic 54454693Sbostic /* 54551559Smckusick * File handle to vnode 54651559Smckusick * 54751559Smckusick * Have to be really careful about stale file handles: 54851559Smckusick * - check that the inode number is valid 54951559Smckusick * - call lfs_vget() to get the locked inode 55051559Smckusick * - check for an unallocated inode (i_mode == 0) 55151559Smckusick * - check that the generation number matches 55251559Smckusick * 55351559Smckusick * XXX 55451559Smckusick * use ifile to see if inode is allocated instead of reading off disk 55551559Smckusick * what is the relationship between my generational number and the NFS 55651559Smckusick * generational number. 55751559Smckusick */ 55851559Smckusick int 559*54734Smckusick lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 56051559Smckusick register struct mount *mp; 56151559Smckusick struct fid *fhp; 562*54734Smckusick struct mbuf *nam; 56351559Smckusick struct vnode **vpp; 564*54734Smckusick int *exflagsp; 565*54734Smckusick struct ucred **credanonp; 56651559Smckusick { 56751559Smckusick register struct inode *ip; 56851559Smckusick register struct ufid *ufhp; 569*54734Smckusick register struct netaddrhash *np; 570*54734Smckusick register struct ufsmount *ump = VFSTOUFS(mp); 57151559Smckusick struct vnode *nvp; 572*54734Smckusick struct sockaddr *saddr; 57351559Smckusick int error; 57451559Smckusick 57551559Smckusick ufhp = (struct ufid *)fhp; 57651559Smckusick if (ufhp->ufid_ino < ROOTINO) 577*54734Smckusick return (ESTALE); 578*54734Smckusick /* 579*54734Smckusick * Get the export permission structure for this <mp, client> tuple. 580*54734Smckusick */ 581*54734Smckusick if ((mp->mnt_flag & MNT_EXPORTED) == 0) 582*54734Smckusick return (EACCES); 583*54734Smckusick if (nam == NULL) { 584*54734Smckusick np = (struct netaddrhash *)0; 585*54734Smckusick } else { 586*54734Smckusick /* 587*54734Smckusick * First search for a network match. 588*54734Smckusick */ 589*54734Smckusick np = ump->um_netaddr[NETMASK_HASH]; 590*54734Smckusick while (np) { 591*54734Smckusick if (netaddr_match(np->neth_family, &np->neth_haddr, 592*54734Smckusick &np->neth_hmask, nam)) 593*54734Smckusick break; 594*54734Smckusick np = np->neth_next; 595*54734Smckusick } 596*54734Smckusick 597*54734Smckusick /* 598*54734Smckusick * If not found, try for an address match. 599*54734Smckusick */ 600*54734Smckusick if (np == (struct netaddrhash *)0) { 601*54734Smckusick saddr = mtod(nam, struct sockaddr *); 602*54734Smckusick np = ump->um_netaddr[NETADDRHASH(saddr)]; 603*54734Smckusick while (np) { 604*54734Smckusick if (netaddr_match(np->neth_family, 605*54734Smckusick &np->neth_haddr, (struct netaddrhash *)0, 606*54734Smckusick nam)) 607*54734Smckusick break; 608*54734Smckusick np = np->neth_next; 609*54734Smckusick } 610*54734Smckusick } 611*54734Smckusick } 612*54734Smckusick if (np == (struct netaddrhash *)0) { 613*54734Smckusick /* 614*54734Smckusick * If no address match, use the default if it exists. 615*54734Smckusick */ 616*54734Smckusick if ((mp->mnt_flag & MNT_DEFEXPORTED) == 0) 617*54734Smckusick return (EACCES); 618*54734Smckusick np = &ump->um_defexported; 619*54734Smckusick } 62054693Sbostic if (error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) { 62151559Smckusick *vpp = NULLVP; 62251559Smckusick return (error); 62351559Smckusick } 62451559Smckusick ip = VTOI(nvp); 62554693Sbostic if (ip->i_mode == 0 || ip->i_gen != ufhp->ufid_gen) { 62651559Smckusick ufs_iput(ip); 62751559Smckusick *vpp = NULLVP; 628*54734Smckusick return (ESTALE); 62951559Smckusick } 63051559Smckusick *vpp = nvp; 631*54734Smckusick *exflagsp = np->neth_exflags; 632*54734Smckusick *credanonp = &np->neth_anon; 63351559Smckusick return (0); 63451559Smckusick } 63551559Smckusick 63651559Smckusick /* 63751559Smckusick * Vnode pointer to File handle 63851559Smckusick */ 63951559Smckusick /* ARGSUSED */ 64051559Smckusick lfs_vptofh(vp, fhp) 64151559Smckusick struct vnode *vp; 64251559Smckusick struct fid *fhp; 64351559Smckusick { 64451559Smckusick register struct inode *ip; 64551559Smckusick register struct ufid *ufhp; 64651559Smckusick 64751559Smckusick ip = VTOI(vp); 64851559Smckusick ufhp = (struct ufid *)fhp; 64951559Smckusick ufhp->ufid_len = sizeof(struct ufid); 65051559Smckusick ufhp->ufid_ino = ip->i_number; 65151559Smckusick ufhp->ufid_gen = ip->i_gen; 65251559Smckusick return (0); 65351559Smckusick } 654