Ejemplo n.º 1
0
void
sbdiskhash(Shabuf *sb, vlong eoffset)
{
	static uchar dbuf[4*M];
	int n;
	
	while(sb->offset < eoffset){
		n = sizeof dbuf;
		if(sb->offset+n > eoffset)
			n = eoffset - sb->offset;
		readdisk(dbuf, sb->offset, n);
		sbupdate(sb, dbuf, sb->offset, n);
	}
}
Ejemplo n.º 2
0
/* ARGSUSED2 */
static int
lqfs_alloc(qfsvfs_t *qfsvfsp, struct fiolog *flp, cred_t *cr)
{
	int		error = 0;
	buf_t		*bp = NULL;
	extent_t	*ep, *nep;
	extent_block_t	*ebp;
	fs_lqfs_common_t	*fs = VFS_FS_PTR(qfsvfsp);
	daddr_t		fno;	/* in frags */
#ifdef LUFS
	daddr_t		bno;	/* in disk blocks */
#endif /* LUFS */
	int32_t		logbno = INT32_C(0);	/* will be fs_logbno */
	ushort_t	logord = 0;		/* will be fs_logord */
	inode_t		*ip = NULL;
#ifndef LUFS
	sam_bn_t	bno;
#endif /* LUFS */
	size_t		nb = flp->nbytes_actual;
	size_t		tb = 0;
	int		ord = 0;
	uchar_t		save_unit;

	/*
	 * Mark the file system as FSACTIVE
	 */
	UL_SBOWNER_SET(qfsvfsp, curthread);
	VFS_LOCK_MUTEX_ENTER(qfsvfsp);
	LQFS_SET_FS_CLEAN(fs, FSACTIVE);
#ifdef LUFS
	qfs_sbwrite(qfsvfsp);
#else
	sam_update_sblk(qfsvfsp, 0, 0, TRUE);
	sam_update_sblk(qfsvfsp, 0, 1, TRUE);
#endif /* LUFS */
	VFS_LOCK_MUTEX_EXIT(qfsvfsp);
	UL_SBOWNER_SET(qfsvfsp, -1);

	/*
	 * Allocate the allocation block (need dummy shadow inode;
	 * we use a shadow inode so the quota sub-system ignores
	 * the block allocations.)
	 *	superblock -> one block of extents -> log data
	 */
#ifdef LUFS
	ip = qfs_alloc_inode(qfsvfsp, QFSROOTINO);
	ip->i_mode = IFSHAD;		/* make the dummy a shadow inode */
#else
	/*
	 * Although QFS has "extension" inodes, it doesn't really implement
	 * the concept of "shadow" inodes.  We can't bypass having the quota
	 * system track the allocation of log blocks.  For now, use the
	 * .inodes inode (SAM_INO_INO) to which we we will allocate space
	 * for a UFS-like log of the requested size.  Allocate space at mount
	 * time BEFORE the quota system is initialized.
	 */
	ip = qfsvfsp->mi.m_inodir;
#endif /* LUFS */

	rw_enter(&ip->i_contents, RW_WRITER);

#ifdef LUFS
	/* Allocate first log block (extent info). */
	fno = contigpref(qfsvfsp, nb + FS_BSIZE(fs));
	error = alloc(ip, fno, FS_BSIZE(fs), &fno, cr);
#else
	save_unit = ip->di.unit;
	ip->di.unit = 0;
	if ((error = sam_alloc_block(ip, SM, &bno, &ord)) == 0) {
		/* Convert 4K block offset to 1K frag offset. */
		fno = fsblktologb(fs, bno);
	}
#endif /* LUFS */
	if (error) {
		goto errout;
	}
	/* Convert 1K frag offset to 512B disk block offset. */
	bno = fsbtodb(fs, fno);
	sam_bread_db(qfsvfsp, qfsvfsp->mi.m_fs[ord].dev, bno,
	    FS_BSIZE(fs), &bp);
	if (bp->b_flags & B_ERROR) {
		error = EIO;
		goto errout;
	}

	ebp = (void *)bp->b_un.b_addr;
	ebp->type = LQFS_EXTENTS;
	ebp->nextbno = UINT32_C(0);
	ebp->nextord = 0;
	ebp->nextents = UINT32_C(0);
	ebp->chksum = INT32_C(0);
#ifdef LUFS
	if (fs->fs_magic == SAM_MAGIC) {
		logbno = bno;
	} else {
#endif /* LUFS */
		logbno = dbtofsb(fs, bno);
#ifdef LUFS
	}
#endif /* LUFS */
	logord = (ushort_t)ord;

	/*
	 * Initialize the first extent
	 */
	ep = &ebp->extents[0];
#ifdef LUFS
	error = alloc(ip, fno + FS_FRAG(fs), FS_BSIZE(fs), &fno, cr);
#else
	ip->di.unit = 0;
	if ((error = sam_alloc_block(ip, SM, &bno, &ord)) == 0) {
		/* Convert 4K block offset to 1K block (frag) offset. */
		fno = fsblktologb(fs, bno);
	}
#endif /* LUFS */
	if (error) {
		goto errout;
	}

	/* Convert frag offset to physical disk block (512B block) offset. */
	bno = fsbtodb(fs, fno);

	ep->lbno = UINT32_C(0);
#ifdef LUFS
	if (fs->fs_magic == SAM_MAGIC) {
		ep->pbno = (uint32_t)bno;
	} else {
#endif /* LUFS */
		ep->pbno = (uint32_t)fno;
#ifdef LUFS
	}
#endif /* LUFS */

	ep->nbno = (uint32_t)fsbtodb(fs, FS_FRAG(fs));	/* Has 8 disk blocks */
	ep->ord = ord;
	ebp->nextents = UINT32_C(1);
	tb = FS_BSIZE(fs);
	nb -= FS_BSIZE(fs);

	while (nb) {
#ifdef LUFS
		error = alloc(ip, fno + FS_FRAG(fs), FS_BSIZE(fs), &fno, cr);
#else
		ip->di.unit = 0;
		error = sam_alloc_block(ip, SM, &bno, &ord);
		if (!error) {
			fno = fsblktologb(fs, bno);
		}
#endif /* LUFS */
		if (error) {
			if (tb < ldl_minlogsize) {
				goto errout;
			}
			error = 0;
			break;
		}
		bno = fsbtodb(fs, fno);
		if ((ep->ord == ord) &&
		    ((daddr_t)((logbtodb(fs, ep->pbno) + ep->nbno) == bno))) {
			ep->nbno += (uint32_t)(fsbtodb(fs, FS_FRAG(fs)));
		} else {
			nep = ep + 1;
			if ((caddr_t)(nep + 1) >
			    (bp->b_un.b_addr + FS_BSIZE(fs))) {
#ifdef LUFS
				free(ip, fno, FS_BSIZE(fs), 0);
#else
				sam_free_block(qfsvfsp, SM,
				    logbtofsblk(fs, fno), ord);
#endif /* LUFS */
				break;
			}
			nep->lbno = ep->lbno + ep->nbno;
#ifdef LUFS
			if (fs->fs_magic == SAM_MAGIC) {
				nep->pbno = (uint32_t)bno;
			} else {
#endif /* LUFS */
				nep->pbno = (uint32_t)fno;
#ifdef LUFS
			}
#endif /* LUFS */
			nep->nbno = (uint32_t)(fsbtodb(fs, FS_FRAG(fs)));
			nep->ord = ord;
			ebp->nextents++;
			ep = nep;
		}
		tb += FS_BSIZE(fs);
		nb -= FS_BSIZE(fs);
	}
	ebp->nbytes = (uint32_t)tb;
	setsum(&ebp->chksum, (int32_t *)(void *)bp->b_un.b_addr, FS_BSIZE(fs));
	if ((error = SAM_BWRITE2(qfsvfsp, bp)) != 0) {
		goto errout;
	}

	/*
	 * Initialize the first two sectors of the log
	 */
	error = lqfs_initialize(qfsvfsp, logbtodb(fs, ebp->extents[0].pbno),
	    ebp->extents[0].ord, tb, flp);
	if (error) {
		goto errout;
	}

	/*
	 * We are done initializing the allocation block and the log
	 */
	brelse(bp);
	bp = NULL;

	/*
	 * Update the superblock and push the dirty metadata
	 */
	UL_SBOWNER_SET(qfsvfsp, curthread);
#ifdef LUFS
	sbupdate(qfsvfsp->vfs_vfs);
#else
	sam_update_sblk(qfsvfsp, 0, 0, TRUE);
#endif /* LUFS */
	UL_SBOWNER_SET(qfsvfsp, -1);

	bflush(qfsvfsp->mi.m_fs[logord].dev);

	error = bfinval(qfsvfsp->mi.m_fs[logord].dev, 1);
	if (error) {
		goto errout;
	}
#ifdef LUFS
	if (qfsvfsp->vfs_bufp->b_flags & B_ERROR) {
		error = EIO;
		goto errout;
	}
#endif /* LUFS */

	/*
	 * Everything is safely on disk; update log space pointer in sb
	 */
	UL_SBOWNER_SET(qfsvfsp, curthread);
	VFS_LOCK_MUTEX_ENTER(qfsvfsp);
	LQFS_SET_LOGBNO(fs, (uint32_t)logbno);
	LQFS_SET_LOGORD(fs, logord);
#ifdef LUFS
	qfs_sbwrite(qfsvfsp);
#else
	sam_update_sblk(qfsvfsp, 0, 0, TRUE);
	sam_update_sblk(qfsvfsp, 0, 1, TRUE);
#endif /* LUFS */
	VFS_LOCK_MUTEX_EXIT(qfsvfsp);
	UL_SBOWNER_SET(qfsvfsp, -1);
	ip->di.unit = save_unit;

	/*
	 * Free the dummy inode
	 */
	rw_exit(&ip->i_contents);
#ifdef LUFS
	qfs_free_inode(ip);
#endif /* LUFS */

	/* inform user of real log size */
	flp->nbytes_actual = tb;
	return (0);

errout:
	/*
	 * Free all resources
	 */
	if (bp) {
		brelse(bp);
	}
	if (logbno) {
		LQFS_SET_LOGBNO(fs, logbno);
		LQFS_SET_LOGORD(fs, logord);
		(void) lqfs_free(qfsvfsp);
	}
	if (ip) {
		ip->di.unit = save_unit;
		rw_exit(&ip->i_contents);
#ifdef LUFS
		qfs_free_inode(ip);
#endif /* LUFS */
	}
	return (error);
}
Ejemplo n.º 3
0
/*
 * Free log space
 *	Assumes the file system is write locked and is not logging
 */
int
lqfs_free(qfsvfs_t *qfsvfsp)
{
	int		error = 0, i, j;
	buf_t		*bp = NULL;
	extent_t	*ep;
	extent_block_t	*ebp;
	fs_lqfs_common_t	*fs = VFS_FS_PTR(qfsvfsp);
	daddr_t		fno;
	int32_t		logbno;
	ushort_t	logord;
	long		nfno;
	inode_t		*ip = NULL;
	char		clean;

	/*
	 * Nothing to free
	 */
	if (LQFS_GET_LOGBNO(fs) == 0) {
		return (0);
	}

	/*
	 * Mark the file system as FSACTIVE and no log but honor the
	 * current value of fs_reclaim.  The reclaim thread could have
	 * been active when lqfs_disable() was called and if fs_reclaim
	 * is reset to zero here it could lead to lost inodes.
	 */
	UL_SBOWNER_SET(qfsvfsp, curthread);
	VFS_LOCK_MUTEX_ENTER(qfsvfsp);
	clean = LQFS_GET_FS_CLEAN(fs);
	logbno = LQFS_GET_LOGBNO(fs);
	logord = LQFS_GET_LOGORD(fs);
	LQFS_SET_FS_CLEAN(fs, FSACTIVE);
	LQFS_SET_LOGBNO(fs, INT32_C(0));
	LQFS_SET_LOGORD(fs, 0);
#ifdef LUFS
	qfs_sbwrite(qfsvfsp);
	error = (qfsvfsp->vfs_bufp->b_flags & B_ERROR);
#else
	error = sam_update_sblk(qfsvfsp, 0, 0, TRUE);
	error = sam_update_sblk(qfsvfsp, 0, 1, TRUE);
#endif /* LUFS */
	VFS_LOCK_MUTEX_EXIT(qfsvfsp);
	UL_SBOWNER_SET(qfsvfsp, -1);
	if (error) {
		error = EIO;
		LQFS_SET_FS_CLEAN(fs, clean);
		LQFS_SET_LOGBNO(fs, logbno);
		LQFS_SET_LOGORD(fs, logord);
		goto errout;
	}

	/*
	 * fetch the allocation block
	 *	superblock -> one block of extents -> log data
	 */
	sam_bread_db(qfsvfsp, qfsvfsp->mi.m_fs[logord].dev,
	    logbtodb(fs, logbno), FS_BSIZE(fs), &bp);
	if (bp->b_flags & B_ERROR) {
		error = EIO;
		goto errout;
	}

#ifdef LUFS
	/*
	 * Free up the allocated space (dummy inode needed for free())
	 */
	ip = qfs_alloc_inode(qfsvfsp, QFSROOTINO);
#else
	/*
	 * QFS doesn't need an inode to free blocks.
	 */
#endif /* LUFS */
	ebp = (void *)bp->b_un.b_addr;
	for (i = 0, ep = &ebp->extents[0]; i < ebp->nextents; ++i, ++ep) {
		fno = logbtofrag(fs, ep->pbno);
		nfno = dbtofsb(fs, ep->nbno);
		for (j = 0; j < nfno; j += FS_FRAG(fs), fno += FS_FRAG(fs)) {
#ifdef LUFS
			free(ip, fno, FS_BSIZE(fs), 0);
#else
			sam_free_block(qfsvfsp, SM, logbtofsblk(fs, fno),
			    ep->ord);
#endif /* LUFS */
		}
	}
#ifdef LUFS
	free(ip, logbtofrag(fs, logbno), FS_BSIZE(fs), 0);
#else
	sam_free_block(qfsvfsp, SM, logbtofsblk(fs, logbno), logord);
#endif /* LUFS */
	brelse(bp);
	bp = NULL;

	/*
	 * Push the metadata dirtied during the allocations
	 */
	UL_SBOWNER_SET(qfsvfsp, curthread);
#ifdef LUFS
	sbupdate(qfsvfsp->vfs_vfs);
#else
	sam_update_sblk(qfsvfsp, 0, 0, TRUE);
#endif /* LUFS */
	UL_SBOWNER_SET(qfsvfsp, -1);
	bflush(qfsvfsp->mi.m_fs[logord].dev);
	error = bfinval(qfsvfsp->mi.m_fs[logord].dev, 0);
	if (error) {
		goto errout;
	}

	/*
	 * Free the dummy inode
	 */
#ifdef LUFS
	qfs_free_inode(ip);
#else
	/* QFS uses a reserved inode */
	VN_RELE(SAM_ITOV(ip));
#endif /* LUFS */

	return (0);

errout:
	/*
	 * Free up all resources
	 */
	if (bp) {
		brelse(bp);
	}
	if (ip) {
#ifdef LUFS
		qfs_free_inode(ip);
#else
		/* QFS uses a reserved inode */
		VN_RELE(SAM_ITOV(ip));
#endif /* LUFS */
	}
	return (error);
}