union dinode * getino(ino_t inum) { static daddr_t inoblkno; daddr_t blkno; static struct ufs1_dinode inoblock[MAXBSIZE / sizeof (struct ufs1_dinode)]; static struct ufs1_dinode ifile_dinode; /* XXX fill this in */ static struct ufs1_dinode empty_dinode; /* Always stays zeroed */ struct ufs1_dinode *dp; if(inum == sblock->lfs_ifile) { /* Load the ifile inode if not already */ if(ifile_dinode.di_u.inumber == 0) { blkno = sblock->lfs_idaddr; bread(fsbtodb(sblock, blkno), (char *)inoblock, (int)sblock->lfs_bsize); dp = lfs_ifind(sblock, inum, inoblock); ifile_dinode = *dp; /* Structure copy */ } return (union dinode *)&ifile_dinode; } curino = inum; blkno = lfs_ientry(inum)->if_daddr; if(blkno == LFS_UNUSED_DADDR) return (union dinode *)&empty_dinode; if(blkno != inoblkno) { bread(fsbtodb(sblock, blkno), (char *)inoblock, (int)sblock->lfs_bsize); #ifdef notyet if (needswap) for (i = 0; i < MAXINOPB; i++) ffs_dinode_swap(&inoblock[i], &inoblock[i]); #endif } return (union dinode *)lfs_ifind(sblock, inum, inoblock); }
int lfs_fastvget(struct mount *mp, ino_t ino, daddr_t daddr, struct vnode **vpp, struct ulfs1_dinode *dinp) { struct inode *ip; struct ulfs1_dinode *dip; struct vnode *vp; struct ulfsmount *ump; dev_t dev; int error, retries; struct buf *bp; struct lfs *fs; ump = VFSTOULFS(mp); dev = ump->um_dev; fs = ump->um_lfs; /* * Wait until the filesystem is fully mounted before allowing vget * to complete. This prevents possible problems with roll-forward. */ mutex_enter(&lfs_lock); while (fs->lfs_flags & LFS_NOTYET) { mtsleep(&fs->lfs_flags, PRIBIO+1, "lfs_fnotyet", 0, &lfs_lock); } mutex_exit(&lfs_lock); /* * This is playing fast and loose. Someone may have the inode * locked, in which case they are going to be distinctly unhappy * if we trash something. */ error = lfs_fasthashget(dev, ino, vpp); if (error != 0 || *vpp != NULL) return (error); /* * getnewvnode(9) will call vfs_busy, which will block if the * filesystem is being unmounted; but umount(9) is waiting for * us because we're already holding the fs busy. * XXXMP */ if (mp->mnt_iflag & IMNT_UNMOUNT) { *vpp = NULL; return EDEADLK; } error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, NULL, &vp); if (error) { *vpp = NULL; return (error); } mutex_enter(&ulfs_hashlock); error = lfs_fasthashget(dev, ino, vpp); if (error != 0 || *vpp != NULL) { mutex_exit(&ulfs_hashlock); ungetnewvnode(vp); return (error); } /* Allocate new vnode/inode. */ lfs_vcreate(mp, ino, vp); /* * 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 = VTOI(vp); ulfs_ihashins(ip); mutex_exit(&ulfs_hashlock); #ifdef notyet /* Not found in the cache => this vnode was loaded only for cleaning. */ ip->i_lfs_iflags |= LFSI_BMAP; #endif /* * XXX * This may not need to be here, logically it should go down with * the i_devvp initialization. * Ask Kirk. */ ip->i_lfs = fs; /* Read in the disk contents for the inode, copy into the inode. */ if (dinp) { error = copyin(dinp, ip->i_din.ffs1_din, sizeof (struct ulfs1_dinode)); if (error) { DLOG((DLOG_CLEAN, "lfs_fastvget: dinode copyin failed" " for ino %d\n", ino)); ulfs_ihashrem(ip); /* Unlock and discard unneeded inode. */ VOP_UNLOCK(vp); lfs_vunref(vp); *vpp = NULL; return (error); } if (ip->i_number != ino) panic("lfs_fastvget: I was fed the wrong inode!"); } else { retries = 0; again: error = bread(ump->um_devvp, LFS_FSBTODB(fs, daddr), fs->lfs_ibsize, NOCRED, 0, &bp); if (error) { DLOG((DLOG_CLEAN, "lfs_fastvget: bread failed (%d)\n", error)); /* * The inode does not contain anything useful, so it * would be misleading to leave it on its hash chain. * Iput() will return it to the free list. */ ulfs_ihashrem(ip); /* Unlock and discard unneeded inode. */ VOP_UNLOCK(vp); lfs_vunref(vp); *vpp = NULL; return (error); } dip = lfs_ifind(ump->um_lfs, ino, bp); if (dip == NULL) { /* Assume write has not completed yet; try again */ brelse(bp, BC_INVAL); ++retries; if (retries > LFS_IFIND_RETRIES) panic("lfs_fastvget: dinode not found"); DLOG((DLOG_CLEAN, "lfs_fastvget: dinode not found," " retrying...\n")); goto again; } *ip->i_din.ffs1_din = *dip; brelse(bp, 0); } lfs_vinit(mp, &vp); *vpp = vp; KASSERT(VOP_ISLOCKED(vp)); VOP_UNLOCK(vp); return (0); }