Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}