- dev_t dev = xp->i_dev;
- struct mount *mntp = ITOV(xp)->v_mount;
- register struct fs *fs = VFSTOUFS(mntp)->um_fs;
- extern struct vnodeops ufs_vnodeops, spec_inodeops;
- register struct inode *ip, *iq;
- register struct vnode *vp;
- struct vnode *nvp;
- struct buf *bp;
- struct dinode *dp;
- union ihead *ih;
- int error;
-
- ih = &ihead[INOHASH(dev, ino)];
-loop:
- for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) {
- if (ino != ip->i_number || dev != ip->i_dev)
- continue;
- if ((ip->i_flag&ILOCKED) != 0) {
- ip->i_flag |= IWANT;
- sleep((caddr_t)ip, PINOD);
- goto loop;
- }
- if (vget(ITOV(ip)))
- goto loop;
- *ipp = ip;
- return(0);
- }
- /*
- * Allocate a new inode.
- */
- if (error = getnewvnode(VT_UFS, mntp, &ufs_vnodeops, &nvp)) {
- *ipp = 0;
- return (error);
- }
- ip = VTOI(nvp);
- ip->i_vnode = nvp;
- ip->i_flag = 0;
- ip->i_devvp = 0;
- ip->i_lastr = 0;
- ip->i_mode = 0;
- ip->i_flags = 0;
-#ifdef QUOTA
- ip->i_dquot = 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.
- */
- ip->i_dev = dev;
- ip->i_number = ino;
- insque(ip, ih);
- ILOCK(ip);
- /*
- * Read in the disk contents for the inode.
- */
- if (error = bread(VFSTOUFS(mntp)->um_devvp, fsbtodb(fs, itod(fs, ino)),
- (int)fs->fs_bsize, NOCRED, &bp)) {
- /*
- * Unlock and discard unneeded inode.
- */
- iput(ip);
- brelse(bp);
- *ipp = 0;
- return (error);
- }
- dp = bp->b_un.b_dino;
- dp += itoo(fs, ino);
- ip->i_din = *dp;
- brelse(bp);
- /*
- * Initialize the associated vnode
- */
- vp = ITOV(ip);
- vp->v_type = IFTOVT(ip->i_mode);
- if (vp->v_type == VCHR || vp->v_type == VBLK) {
- vp->v_rdev = ip->i_rdev;
- vp->v_op = &spec_inodeops;
- if (nvp = checkalias(vp, mntp)) {
- /*
- * Reinitialize aliased inode.
- */
- vp = nvp;
- iq = VTOI(vp);
- iq->i_vnode = vp;
- iq->i_lastr = 0;
- iq->i_flags = 0;
- ILOCK(iq);
- iq->i_din = ip->i_din;
- iq->i_dev = dev;
- iq->i_number = ino;
- insque(iq, ih);
- /*
- * Discard unneeded vnode
- */
- ip->i_mode = 0;
- iput(ip);
- ip = iq;
- }
- }
- if (ino == ROOTINO)
- vp->v_flag |= VROOT;
- /*
- * Finish inode initialization.
- */
- ip->i_fs = fs;
- ip->i_devvp = VFSTOUFS(mntp)->um_devvp;
- VREF(ip->i_devvp);
-#ifdef QUOTA
- if (ip->i_mode != 0)
- ip->i_dquot = inoquota(ip);
-#endif
- /*
- * 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->m_flag & M_RDONLY) == 0)
- ip->i_flag |= IMOD;
- }
- *ipp = ip;
- return (0);
-}