-loop:
- ih = &ihead[INOHASH(dev, ino)];
- for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
- if (ino == ip->i_number && dev == ip->i_dev) {
- /*
- * Following is essentially an inline expanded
- * copy of igrab(), expanded inline for speed,
- * and so that the test for a mounted on inode
- * can be deferred until after we are sure that
- * the inode isn't busy.
- */
- if ((ip->i_flag&ILOCKED) != 0) {
- ip->i_flag |= IWANT;
- sleep((caddr_t)ip, PINOD);
- goto loop;
- }
- vp = ITOV(ip);
- if (vp->v_count == 0) { /* ino on free list */
- if (iq = ip->i_freef)
- iq->i_freeb = ip->i_freeb;
- else
- ifreet = ip->i_freeb;
- *ip->i_freeb = iq;
- ip->i_freef = NULL;
- ip->i_freeb = NULL;
- }
- ILOCK(ip);
- vp->v_count++;
- *ipp = ip;
- return(0);
- }
- if (error = getnewino(dev, ino, &nip)) {
- *ipp = 0;
- return (error);
- }
- ip = nip;
- /*
- * Read in the disk contents for the inode.
- */
- if (error = bread(VFSTOUFS(mntp)->um_devvp, fsbtodb(fs, itod(fs, ino)),
- (int)fs->fs_bsize, &bp)) {
- /*
- * The inode doesn't contain anything useful, so it would
- * be misleading to leave it on its hash chain. Iput() will
- * take care of putting it back on the free list. We also
- * lose its inumber, just in case.
- */
- remque(ip);
- ip->i_forw = ip;
- ip->i_back = ip;
- ip->i_number = 0;
- INSFREE(ip);
- iunlock(ip);
- ip->i_flag = 0;
- brelse(bp);
- *ipp = 0;
- return(error);
- }
- /*
- * Check to see if the new inode represents a block device
- * for which we already have an inode (either because of
- * bdevvp() or because of a different inode representing
- * the same block device). If such an alias exists, put the
- * just allocated inode back on the free list, and replace
- * the contents of the existing inode with the contents of
- * the new inode.
- */
- dp = bp->b_un.b_dino;
- dp += itoo(fs, ino);
- if ((dp->di_mode & IFMT) != IFBLK) {
- ip->i_ic = dp->di_ic;
- brelse(bp);
- } else {
-again:
- for (iq = bdevlisth; iq; iq = iq->i_devlst) {
- if (dp->di_rdev != ITOV(iq)->v_rdev)
- continue;
- igrab(iq);
- if (dp->di_rdev != ITOV(iq)->v_rdev) {
- iput(iq);
- goto again;
- }
- /*
- * Discard unneeded inode.
- */
- remque(ip);
- ip->i_forw = ip;
- ip->i_back = ip;
- ip->i_number = 0;
- INSFREE(ip);
- iunlock(ip);
- ip->i_flag = 0;
- /*
- * Reinitialize aliased inode.
- * We must release the buffer that we just read
- * before doing the iupdat() to avoid a possible
- * deadlock with updating an inode in the same
- * disk block.
- */
- ip = iq;
- vp = ITOV(iq);
- tdip.di_ic = dp->di_ic;
- brelse(bp);
- error = iupdat(ip, &time, &time, 1);
- ip->i_ic = tdip.di_ic;
- remque(ip);
- insque(ip, ih);
- ip->i_dev = dev;
- ip->i_number = ino;
- if (ip->i_devvp) {
- vrele(ip->i_devvp);
- ip->i_devvp = 0;
- }
- cache_purge(vp);
- break;
- }
- if (iq == 0) {
- ip->i_ic = dp->di_ic;
- brelse(bp);
- ip->i_devlst = bdevlisth;
- bdevlisth = ip;
- }
- }
- /*
- * Finish inode initialization.
- */
- ip->i_fs = fs;
- ip->i_devvp = VFSTOUFS(mntp)->um_devvp;
- ip->i_devvp->v_count++;
- /*
- * Initialize the associated vnode
- */
- vp = ITOV(ip);
- vinit(vp, mntp, IFTOVT(ip->i_mode), &ufs_vnodeops);
- if (vp->v_type == VCHR || vp->v_type == VBLK) {
- vp->v_rdev = ip->i_rdev;
- vp->v_op = &blk_vnodeops;
- }
- if (ino == ROOTINO)
- vp->v_flag |= VROOT;
-#ifdef QUOTA
- if (ip->i_mode != 0)
- ip->i_dquot = inoquota(ip);