예제 #1
0
파일: setup.c 프로젝트: andreiw/polaris
/*
 * Roll the embedded log, if any, and set up the global variables
 * islog and islogok.
 */
static int
logsetup(caddr_t devstr)
{
	void		*buf;
	extent_block_t	*ebp;
	ml_unit_t	*ul;
	ml_odunit_t	*ud;
	void		*ud_buf;
	int		badlog;

	islog = islogok = 0;
	if (bflag != 0)
		return (1); /* can't roll log while alternate sb specified */

	/*
	 * Roll the log, if any.  A bad sb implies we'll be using
	 * an alternate sb as far as logging goes, so just fail back
	 * to the caller if we can't read the default sb.  Suppress
	 * complaints, because the caller will be reading the same
	 * superblock again and running full verification on it, so
	 * whatever is bad will be reported then.
	 */
	sblock.fs_logbno = 0;
	badlog = 0;
	if (!read_super_block(0))
		return (1);

	/*
	 * Roll the log in 3 cases:
	 * 1. If it's unmounted (mount_point == NULL) and it's not marked
	 *    as fully rolled (sblock.fs_rolled != FS_ALL_ROLLED)
	 * 2. If it's mounted and anything other than a sanity
	 *    check fsck (mflag) is being done, as we have the current
	 *    super block. Note, only a sanity check is done for
	 *    root/usr at boot. If a roll were done then the expensive
	 *    ufs_flush() gets called, leading to a slower boot.
	 * 3. If anything other then a sanity check (mflag) is being done
	 *    to a mounted filesystem while it is in read-only state
	 *    (e.g. root during early boot stages) we have to detect this
	 *    and have to roll the log as well. NB. the read-only mount
	 *    will flip fs_clean from FSLOG to FSSTABLE and marks the
	 *    log as FS_NEED_ROLL.
	 */
	if (sblock.fs_logbno &&
	    (((mount_point == NULL) && (sblock.fs_rolled != FS_ALL_ROLLED)) ||
	    ((mount_point != NULL) && !mflag))) {
		int roll_log_err = 0;

		if (sblock.fs_ronly && (sblock.fs_clean == FSSTABLE) &&
			(sblock.fs_state + sblock.fs_time == FSOKAY)) {
			/*
			 * roll the log without a mount
			 */
			flush_fs();
		}
		if (sblock.fs_clean == FSLOG &&
			(sblock.fs_state + sblock.fs_time == FSOKAY)) {
			if (rl_roll_log(devstr) != RL_SUCCESS)
				roll_log_err = 1;
		}
		if (roll_log_err) {
			(void) printf("Can't roll the log for %s.\n", devstr);
			/*
			 * There are two cases where we want to set
			 * an error code and return:
			 *  - We're preening
			 *  - We're not on a live root and the user
			 *    chose *not* to ignore the log
			 * Otherwise, we want to mark the log as bad
			 * and continue to check the filesystem.  This
			 * has the side effect of destroying the log.
			 */
			if (preen || (!hotroot &&
			    reply(
			"DISCARDING THE LOG MAY DISCARD PENDING TRANSACTIONS.\n"
					"DISCARD THE LOG AND CONTINUE") == 0)) {
				exitstat = EXERRFATAL;
				return (0);
			}
			++badlog;
		}
	}

	/* Logging UFS may be enabled */
	if (sblock.fs_logbno) {
		++islog;

		/* log is not okay; check the fs */
		if (FSOKAY != (sblock.fs_state + sblock.fs_time))
			return (1);

		/*
		 * If logging or (stable and mounted) then continue
		 */
		if (!((sblock.fs_clean == FSLOG) ||
		    (sblock.fs_clean == FSSTABLE) && (mount_point != NULL)))
			return (1);

		/* get the log allocation block */
		buf = malloc(dev_bsize);
		if (buf == NULL) {
			return (1);
		}
		ud_buf = malloc(dev_bsize);
		if (ud_buf == NULL) {
			free(buf);
			return (1);
		}
		(void) fsck_bread(fsreadfd, buf,
		    logbtodb(&sblock, sblock.fs_logbno),
		    dev_bsize);
		ebp = (extent_block_t *)buf;

		/* log allocation block is not okay; check the fs */
		if (ebp->type != LUFS_EXTENTS) {
			free(buf);
			free(ud_buf);
			return (1);
		}

		/* get the log state block(s) */
		if (fsck_bread(fsreadfd, ud_buf,
		    (logbtodb(&sblock, ebp->extents[0].pbno)),
		    dev_bsize)) {
			(void) fsck_bread(fsreadfd, ud_buf,
			    (logbtodb(&sblock, ebp->extents[0].pbno)) + 1,
			    dev_bsize);
		}
		ud = (ml_odunit_t *)ud_buf;
		ul = (ml_unit_t *)malloc(sizeof (*ul));
		if (ul == NULL) {
			free(buf);
			free(ud_buf);
			return (1);
		}
		ul->un_ondisk = *ud;

		/* log state is okay; don't need to check the fs */
		if ((ul->un_chksum == ul->un_head_ident + ul->un_tail_ident) &&
		    (ul->un_version == LUFS_VERSION_LATEST) &&
		    (ul->un_badlog == 0) && (!badlog)) {
			++islogok;
		}
		free(ud_buf);
		free(buf);
		free(ul);
	}

	return (1);
}
예제 #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);
}
예제 #3
0
int
lqfs_snarf(qfsvfs_t *qfsvfsp, fs_lqfs_common_t *fs, int ronly)
{
	buf_t		*bp, *tbp;
	ml_unit_t	*ul;
	extent_block_t	*ebp;
	ic_extent_block_t  *nebp;
	size_t		nb;
	daddr_t		bno;	/* in disk blocks */
	int		ord;
	int		i;

	/* LINTED: warning: logical expression always true: op "||" */
	ASSERT(sizeof (ml_odunit_t) < DEV_BSIZE);

	/*
	 * Get the allocation table
	 *	During a remount the superblock pointed to by the qfsvfsp
	 *	is out of date.  Hence the need for the ``new'' superblock
	 *	pointer, fs, passed in as a parameter.
	 */
	sam_bread_db(qfsvfsp, qfsvfsp->mi.m_fs[LQFS_GET_LOGORD(fs)].dev,
	    logbtodb(fs, LQFS_GET_LOGBNO(fs)), FS_BSIZE(fs), &bp);
	if (bp->b_flags & B_ERROR) {
		brelse(bp);
		return (EIO);
	}
	ebp = (void *)bp->b_un.b_addr;
	if (!checksum(&ebp->chksum, (int32_t *)(void *)bp->b_un.b_addr,
	    FS_BSIZE(fs))) {
		brelse(bp);
		return (ENODEV);
	}

	/*
	 * It is possible to get log blocks with all zeros.
	 * We should also check for nextents to be zero in such case.
	 */
	if (ebp->type != LQFS_EXTENTS || ebp->nextents == 0) {
		brelse(bp);
		return (EDOM);
	}
	/*
	 * Put allocation into memory.  This requires conversion between
	 * on the ondisk format of the extent (type extent_t) and the
	 * in-core format of the extent (type ic_extent_t).  The
	 * difference is the in-core form of the extent block stores
	 * the physical offset of the extent in disk blocks, which
	 * can require more than a 32-bit field.
	 */
	nb = (size_t)(sizeof (ic_extent_block_t) +
	    ((ebp->nextents - 1) * sizeof (ic_extent_t)));
	nebp = kmem_alloc(nb, KM_SLEEP);
	nebp->ic_nextents = ebp->nextents;
	nebp->ic_nbytes = ebp->nbytes;
	nebp->ic_nextbno = ebp->nextbno;
	nebp->ic_nextord = ebp->nextord;
	for (i = 0; i < ebp->nextents; i++) {
		nebp->ic_extents[i].ic_lbno = ebp->extents[i].lbno;
		nebp->ic_extents[i].ic_nbno = ebp->extents[i].nbno;
		nebp->ic_extents[i].ic_pbno =
		    logbtodb(fs, ebp->extents[i].pbno);
		nebp->ic_extents[i].ic_ord = ebp->extents[i].ord;
	}
	brelse(bp);

	/*
	 * Get the log state
	 */
	bno = nebp->ic_extents[0].ic_pbno;
	ord = nebp->ic_extents[0].ic_ord;
	sam_bread_db(qfsvfsp, qfsvfsp->mi.m_fs[ord].dev, bno, DEV_BSIZE, &bp);
	if (bp->b_flags & B_ERROR) {
		brelse(bp);
		sam_bread_db(qfsvfsp, qfsvfsp->mi.m_fs[ord].dev, bno + 1,
		    DEV_BSIZE, &bp);
		if (bp->b_flags & B_ERROR) {
			brelse(bp);
			kmem_free(nebp, nb);
			return (EIO);
		}
	}

	/*
	 * Put ondisk struct into an anonymous buffer
	 *	This buffer will contain the memory for the ml_odunit struct
	 */
	tbp = ngeteblk(dbtob(LS_SECTORS));
	tbp->b_edev = bp->b_edev;
	tbp->b_dev = bp->b_dev;
	tbp->b_blkno = bno;
	bcopy(bp->b_un.b_addr, tbp->b_un.b_addr, DEV_BSIZE);
	bcopy(bp->b_un.b_addr, tbp->b_un.b_addr + DEV_BSIZE, DEV_BSIZE);
	bp->b_flags |= (B_STALE | B_AGE);
	brelse(bp);
	bp = tbp;

	/*
	 * Verify the log state
	 *
	 * read/only mounts w/bad logs are allowed.  umount will
	 * eventually roll the bad log until the first IO error.
	 * fsck will then repair the file system.
	 *
	 * read/write mounts with bad logs are not allowed.
	 *
	 */
	ul = (ml_unit_t *)kmem_zalloc(sizeof (*ul), KM_SLEEP);
	bcopy(bp->b_un.b_addr, &ul->un_ondisk, sizeof (ml_odunit_t));
	if ((ul->un_chksum != ul->un_head_ident + ul->un_tail_ident) ||
	    (ul->un_version != LQFS_VERSION_LATEST) ||
	    (!ronly && ul->un_badlog)) {
		kmem_free(ul, sizeof (*ul));
		brelse(bp);
		kmem_free(nebp, nb);
		return (EIO);
	}
	/*
	 * Initialize the incore-only fields
	 */
	if (ronly) {
		ul->un_flags |= LDL_NOROLL;
	}
	ul->un_bp = bp;
	ul->un_qfsvfs = qfsvfsp;
	ul->un_dev = qfsvfsp->mi.m_fs[ord].dev;
	ul->un_ebp = nebp;
	ul->un_nbeb = nb;
	ul->un_maxresv = btodb(ul->un_logsize) * LDL_USABLE_BSIZE;
	ul->un_deltamap = map_get(ul, deltamaptype, DELTAMAP_NHASH);
	ul->un_logmap = map_get(ul, logmaptype, LOGMAP_NHASH);
	if (ul->un_debug & MT_MATAMAP) {
		ul->un_matamap = map_get(ul, matamaptype, DELTAMAP_NHASH);
	}
	sam_mutex_init(&ul->un_log_mutex, NULL, MUTEX_DEFAULT, NULL);
	sam_mutex_init(&ul->un_state_mutex, NULL, MUTEX_DEFAULT, NULL);

	/*
	 * Aquire the qfs_scan_lock before linking the mtm data
	 * structure so that we keep qfs_sync() and qfs_update() away
	 * when they execute the qfs_scan_inodes() run while we're in
	 * progress of enabling/disabling logging.
	 */

	mutex_enter(&qfs_scan_lock);
	LQFS_SET_LOGP(qfsvfsp, ul);
	ml_unit_validate(ul);

	/* remember the state of the log before the log scan */
	logmap_logscan(ul);
	mutex_exit(&qfs_scan_lock);

	/*
	 * Error during scan
	 *
	 * If this is a read/only mount; ignore the error.
	 * At a later time umount/fsck will repair the fs.
	 *
	 */
	if (ul->un_flags & LDL_ERROR) {
		if (!ronly) {
			/*
			 * Aquire the qfs_scan_lock before de-linking
			 * the mtm data structure so that we keep qfs_sync()
			 * and qfs_update() away when they execute the
			 * qfs_scan_inodes() run while we're in progress of
			 * enabling/disabling logging.
			 */
			mutex_enter(&qfs_scan_lock);
			lqfs_unsnarf(qfsvfsp);
			mutex_exit(&qfs_scan_lock);
			return (EIO);
		}
		ul->un_flags &= ~LDL_ERROR;
	}
	if (!ronly) {
		logmap_start_roll(ul);
	}

	return (0);
}
예제 #4
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);
}
예제 #5
0
/* ARGSUSED */
static int
lqfs_log_validate(qfsvfs_t *qfsvfsp, struct fiolog *flp, cred_t *cr)
{
	int		error = 0;
	buf_t		*bp = NULL;
	extent_t	*ep;
	extent_block_t	*ebp;
	fs_lqfs_common_t	*fs = VFS_FS_PTR(qfsvfsp);
	daddr_t		fno;	/* in frags */
#ifdef LUFS
	extent_t	*nep;
	daddr_t		bno;	/* in disk blocks */
#endif /* LUFS */
	int32_t		logbno;
	int		logord;
	int		i;
	int		j;
	long		nfno;

	logbno = LQFS_GET_LOGBNO(fs);
	logord = LQFS_GET_LOGORD(fs);

	if (logbno == 0) {
		error = EINVAL;
		goto errout;
	}

	LQFS_MSG(CE_WARN,
	    "lqfs_log_validate: Extent alloc block offset 0x%x ord %d.\n",
	    (dbtob(logbtodb(fs, logbno))), logord);
	sam_bread_db(qfsvfsp, qfsvfsp->mi.m_fs[logord].dev,
	    logbtodb(fs, logbno), FS_BSIZE(fs), &bp);
	if (bp->b_flags & B_ERROR) {
		LQFS_MSG(CE_WARN,
		    "lqfs_log_validate: Can't read extent alloc block\n");
		error = EIO;
		goto errout;
	}
	ebp = (void *)bp->b_un.b_addr;
	LQFS_MSG(CE_WARN,
	    "lqfs_log_validate: Ext alloc block type 0x%x chksum 0x%x\n",
	    ebp->type, ebp->chksum);
	LQFS_MSG(CE_WARN,
	    "lqfs_log_validate: Ext alloc block nextents 0x%x nb 0x%x.\n",
	    ebp->nextents, ebp->nbytes);
	LQFS_MSG(CE_WARN,
	    "lqfs_log_validate: Ext alloc block nxtbno 0x%x nxtord 0x%x.\n",
	    ebp->nextbno, ebp->nextord);
	for (i = 0, ep = &ebp->extents[0]; i < ebp->nextents; ++i, ++ep) {
		fno = logbtofrag(fs, ep->pbno);
		nfno = dbtofsb(fs, ep->nbno);
		LQFS_MSG(CE_WARN,
		    "   Extent # %d - 0x%x 1K blocks:\n", i, nfno);
		for (j = 0; j < nfno; j += FS_FRAG(fs), fno += FS_FRAG(fs)) {
			int lastord;

			if (j == 0) {
				LQFS_MSG(CE_WARN,
				    "      First 4K block at offset 0x%x "
				    "ord %d (incl. last 1K frag 0x%x, last "
				    "sector 0x%x)\n",
				    logbtofsblk(fs, fno), ep->ord,
				    fno+FS_FRAG(fs)-1,
				    logbtodb(fs, fno+1)-1);
				lastord = ep->ord;
			} else if (j >= (nfno - (FS_FRAG(fs)))) {
				LQFS_MSG(CE_WARN,
				    "      Last 4K block at offset 0x%x "
				    "ord %d (incl. last 1K frag 0x%x, last "
				    "sector 0x%x)\n",
				    logbtofsblk(fs, fno), ep->ord,
				    fno+FS_FRAG(fs)-1,
				    logbtodb(fs, fno+1)-1);
			} else if (ep->ord != lastord) {
				LQFS_MSG(CE_WARN,
				    "      Includes 4K block at offset "
				    "0x%x ord %d (incl. last 1K frag 0x%x, "
				    "last sector 0x%x)\n",
				    logbtofsblk(fs, fno), ep->ord,
				    fno+FS_FRAG(fs)-1,
				    logbtodb(fs, fno+1)-1);
				lastord = ep->ord;
			}
		}
	}
errout:
	if (bp) {
		brelse(bp);
	}

	if (!error) {
		LQFS_MSG(CE_WARN, "lqfs_log_validate(): Returning OK.\n");
	} else {
		LQFS_MSG(CE_WARN,
		    "lqfs_log_validate(): Returning error code %d\n", error);
	}
	return (error);
}