-/*
- * Look up a UFS dinode number to find its incore vnode.
- * If it is not in core, read it in from the specified device.
- * If it is in core, wait for the lock bit to clear, then
- * return the inode locked. Detection and handling of mount
- * points must be done by the calling routine.
- */
-ffs_vget (ap)
- struct vop_vget_args *ap;
-{
- register struct fs *fs;
- register struct inode *ip;
- struct ufsmount *ump;
- struct buf *bp;
- struct dinode *dp;
- struct vnode *vp;
- union ihead *ih;
- dev_t dev;
- int i, type, error;
-
- ump = VFSTOUFS(ap->a_mp);
- dev = ump->um_dev;
- if ((*ap->a_vpp = ufs_ihashget(dev, ap->a_ino)) != NULL)
- return (0);
-
- /* Allocate a new vnode/inode. */
- if (error = getnewvnode(VT_UFS, ap->a_mp, ffs_vnodeop_p, &vp)) {
- *ap->a_vpp = NULL;
- return (error);
- }
- type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */
- MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
- vp->v_data = ip;
- ip->i_vnode = vp;
- ip->i_flag = 0;
- ip->i_devvp = 0;
- ip->i_mode = 0;
- ip->i_diroff = 0;
- ip->i_lockf = 0;
- ip->i_fs = fs = ump->um_fs;
- ip->i_dev = dev;
- ip->i_number = ap->a_ino;
-#ifdef QUOTA
- for (i = 0; i < MAXQUOTAS; i++)
- ip->i_dquot[i] = NODQUOT;
-#endif
- /*
- * Put it onto its hash chain and lock it so that other requests for
- * this inode will block if they arrive while we are sleeping waiting
- * for old data structures to be purged or for the contents of the
- * disk portion of this inode to be read.
- */
- ufs_ihashins(ip);
-
- /* Read in the disk contents for the inode, copy into the inode. */
- if (error = bread(ump->um_devvp, fsbtodb(fs, itod(fs, ap->a_ino)),
- (int)fs->fs_bsize, NOCRED, &bp)) {
- /*
- * The inode does not contain anything useful, so it would
- * be misleading to leave it on its hash chain. It will be
- * returned to the free list by ufs_iput().
- */
- remque(ip);
- ip->i_forw = ip;
- ip->i_back = ip;
-
- /* Unlock and discard unneeded inode. */
- ufs_iput(ip);
- brelse(bp);
- *ap->a_vpp = NULL;
- return (error);
- }
- dp = bp->b_un.b_dino;
- dp += itoo(fs, ap->a_ino);
- ip->i_din = *dp;
- brelse(bp);
-
- /*
- * Initialize the vnode from the inode, check for aliases.
- * Note that the underlying vnode may have changed.
- */
- if (error = ufs_vinit(ap->a_mp, ffs_specop_p, FFS_FIFOOPS, &vp)) {
- ufs_iput(ip);
- *ap->a_vpp = NULL;
- return (error);
- }
- /*
- * Finish inode initialization now that aliasing has been resolved.
- */
- ip->i_devvp = ump->um_devvp;
- VREF(ip->i_devvp);
- /*
- * Set up a generation number for this inode if it does not
- * already have one. This should only happen on old filesystems.
- */
- if (ip->i_gen == 0) {
- if (++nextgennumber < (u_long)time.tv_sec)
- nextgennumber = time.tv_sec;
- ip->i_gen = nextgennumber;
- if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
- ip->i_flag |= IMOD;
- }
- /*
- * Ensure that uid and gid are correct. This is a temporary
- * fix until fsck has been changed to do the update.
- */
- if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
- ip->i_uid = ip->i_din.di_ouid; /* XXX */
- ip->i_gid = ip->i_din.di_ogid; /* XXX */
- } /* XXX */
-
- *ap->a_vpp = vp;
- return (0);
-}
-