示例#1
0
/*
 * Interface of geteblk() is kept intact to maintain driver compatibility.
 * Use ngeteblk() to allocate block size other than 1 KB.
 */
struct buf *
geteblk(void)
{
	return (ngeteblk((long)1024));
}
示例#2
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);
}