+ ILOCK(ip);
+ VREF(vp);
+ *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, NOCRED, &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;
+ ITOV(ip)->v_type = VNON;
+ 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) {
+ vp = ITOV(iq);
+ if (dp->di_rdev != vp->v_rdev)
+ continue;
+ igrab(iq);
+ if (dp->di_rdev != vp->v_rdev) {
+ iput(iq);
+ goto again;
+ }
+ /*
+ * Discard unneeded inode.
+ */
+ remque(ip);
+ ip->i_forw = ip;
+ ip->i_back = ip;
+ ip->i_number = 0;
+ ITOV(ip)->v_type = VNON;
+ 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;
+ 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;