/*
 * Write disk label back to device after modification.
 * this means write out the Rigid disk blocks to represent the 
 * label.  Hope the user was carefull.
 */
int
writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
    struct cpu_disklabel *clp)
{
	struct buf *bp;
	struct disklabel *dlp;
	int error = 0;

	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;
	bp->b_blkno = LABELSECTOR;
	bp->b_cylinder = 0;
	bp->b_bcount = lp->d_secsize;
	bp->b_flags |= B_READ;           /* get current label */
	(*strat)(bp);
	if ((error = biowait(bp)) != 0)
		goto done;

	dlp = (struct disklabel *)((char *)bp->b_data + LABELOFFSET);
	*dlp = *lp;     /* struct assignment */

	bp->b_oflags &= ~(BO_DONE);
	bp->b_flags &= ~(B_READ);
	bp->b_flags |= B_WRITE;
	(*strat)(bp);
	error = biowait(bp);

done:
	brelse(bp, 0);
	return (error);
}
Exemple #2
0
/*
 * Write disk label back to device after modification.
 */
int
writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
{
	struct buf *bp = NULL;
	int error;

	/* get a buffer and initialize it */
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;

	/* Read it in, slap the new label in, and write it back out */
	bp->b_blkno = LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if ((error = biowait(bp)) != 0)
		goto done;

	bsdtocpulabel(lp, (struct mvmedisklabel *)bp->b_data);

	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW);
	(*strat)(bp);
	error = biowait(bp);

done:
	if (bp) {
		bp->b_flags |= B_INVAL;
		brelse(bp);
	}
	disk_change = 1;
	return (error);
}
/*
 * Write disk label back to device after modification.
 */
int
writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
	       struct cpu_disklabel *osdep)
{
	struct buf *bp;
	struct disklabel *dlp;
	int error;

#ifdef maybe
	/* disklabel in appropriate location? */
	if (lp->d_partitions[2].p_offset != 0
		&& lp->d_partitions[2].p_offset != dospartoff) {
		error = EXDEV;		
		goto done;
	}
#endif

	/* get a buffer and initialize it */
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;
	bp->b_blkno = LABELSECTOR;
	bp->b_cylinder = 0;
	bp->b_bcount = lp->d_secsize;
	bp->b_flags |= B_READ;
	(*strat)(bp);

	/* if successful, locate disk label within block and validate */
	if ((error = biowait(bp)) != 0)
		goto done;
	for (dlp = (struct disklabel *)bp->b_data;
	    dlp <= (struct disklabel *)((char *)bp->b_data + lp->d_secsize -
		sizeof(*dlp));
	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
		if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
		    dkcksum(dlp) == 0) {
			*dlp = *lp;
			bp->b_cflags = BC_BUSY;
			bp->b_flags = B_WRITE;
			CLR(bp->b_oflags, BO_DONE);
			(*strat)(bp);
			error = biowait(bp);
			goto done;
		}
	}
	error = ESRCH;

done:
	brelse(bp, 0);
	return (error);
}
Exemple #4
0
/*
 * Synchronous write.
 * Release buffer on completion.
 */
int
bwrite(register struct buf *bp)
{
	int rv;

	if(bp->b_flags & B_INVAL) {
		brelse(bp);
		return (0);
	} else {
		int wasdelayed;

		if(!(bp->b_flags & B_BUSY))
			panic("bwrite: not busy");

		wasdelayed = bp->b_flags & B_DELWRI;
		bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_ASYNC|B_DELWRI);
		if(wasdelayed)
			reassignbuf(bp, bp->b_vp);

		bp->b_flags |= B_DIRTY;
		bp->b_vp->v_numoutput++;
		VOP_STRATEGY(bp);
		rv = biowait(bp);
		brelse(bp);
		return (rv);
	}
}
Exemple #5
0
/*
 * Common code for reading a buffer with various options
 *
 * Read in (if necessary) the block and return a buffer pointer.
 */
struct buf *
bread_common(void *arg, dev_t dev, daddr_t blkno, long bsize)
{
	struct ufsvfs *ufsvfsp = (struct ufsvfs *)arg;
	struct buf *bp;
	klwp_t *lwp = ttolwp(curthread);

	CPU_STATS_ADD_K(sys, lread, 1);
	bp = getblk_common(ufsvfsp, dev, blkno, bsize, /* errflg */ 1);
	if (bp->b_flags & B_DONE)
		return (bp);
	bp->b_flags |= B_READ;
	ASSERT(bp->b_bcount == bsize);
	if (ufsvfsp == NULL) {					/* !ufs */
		(void) bdev_strategy(bp);
	} else if (ufsvfsp->vfs_log && bio_lufs_strategy != NULL) {
							/* ufs && logging */
		(*bio_lufs_strategy)(ufsvfsp->vfs_log, bp);
	} else if (ufsvfsp->vfs_snapshot && bio_snapshot_strategy != NULL) {
							/* ufs && snapshots */
		(*bio_snapshot_strategy)(&ufsvfsp->vfs_snapshot, bp);
	} else {
		ufsvfsp->vfs_iotstamp = ddi_get_lbolt();
		ub.ub_breads.value.ul++;		/* ufs && !logging */
		(void) bdev_strategy(bp);
	}
	if (lwp != NULL)
		lwp->lwp_ru.inblock++;
	CPU_STATS_ADD_K(sys, bread, 1);
	(void) biowait(bp);
	return (bp);
}
Exemple #6
0
caddr_t
dadk_iob_xfer(opaque_t objp, struct tgdk_iob *iobp, int rw)
{
	struct dadk	*dadkp = (struct dadk *)objp;
	struct buf	*bp;
	int		err;

	bp = iobp->b_bp;
	if (dadkp->dad_rdonly && !(rw & B_READ)) {
		bioerror(bp, EROFS);
		return (NULL);
	}

	bp->b_flags |= (B_BUSY | rw);
	bp->b_bcount = iobp->b_pbytecnt;
	SET_BP_SEC(bp, iobp->b_psec);
	bp->av_back = (struct buf *)0;
	bp->b_resid = 0;

	/* call flow control */
	mutex_enter(&dadkp->dad_cmd_mutex);
	dadkp->dad_cmd_count++;
	mutex_exit(&dadkp->dad_cmd_mutex);
	FLC_ENQUE(dadkp->dad_flcobjp, bp);
	err = biowait(bp);

	bp->b_bcount = iobp->b_xfer;
	bp->b_flags &= ~(B_DONE|B_BUSY);

	if (err)
		return (NULL);

	return (bp->b_un.b_addr+iobp->b_pbyteoff);
}
Exemple #7
0
static int
mtcommand(dev_t dev, int cmd, int cnt)
{
	struct mt_softc *sc = device_lookup_private(&mt_cd,UNIT(dev));
	struct buf *bp = &sc->sc_bufstore;
	int error = 0;

#if 1
	if (bp->b_cflags & BC_BUSY)
		return EBUSY;
#endif
	bp->b_cmd = cmd;
	bp->b_dev = dev;
	do {
		bp->b_cflags = BC_BUSY;
		bp->b_flags = B_CMD;
		mtstrategy(bp);
		biowait(bp);
		if (bp->b_error != 0) {
			error = bp->b_error;
			break;
		}
	} while (--cnt > 0);
#if 0
	bp->b_flags = 0 /*&= ~BC_BUSY*/;
#else
	bp->b_flags &= ~BC_BUSY;
#endif
	return error;
}
Exemple #8
0
int
mtcommand(dev_t dev, int cmd, int cnt)
{
	struct mt_softc *sc;
	struct buf *bp;
	int error = 0;

	sc = device_lookup_private(&mt_cd, MTUNIT(dev));
	bp = &sc->sc_bufstore;

	if (bp->b_cflags & BC_BUSY)
		return (EBUSY);

	bp->b_cmd = cmd;
	bp->b_dev = dev;
	bp->b_objlock = &buffer_lock;
	do {
		bp->b_cflags = BC_BUSY;
		bp->b_flags = B_CMD;
		bp->b_oflags = 0;
		mtstrategy(bp);
		biowait(bp);
		if (bp->b_error != 0) {
			error = (int) (unsigned) bp->b_error;
			break;
		}
	} while (--cnt > 0);
#if 0
	bp->b_cflags = 0 /*&= ~BC_BUSY*/;
#else
	bp->b_cflags &= ~BC_BUSY;
#endif
	return (error);
}
Exemple #9
0
/*
 * Perform a synchronous indirect write of the given block number
 * on the given device, using the given fbuf.  Upon return the fbp
 * is invalid.
 */
int
fbiwrite(struct fbuf *fbp, vnode_t *devvp, daddr_t bn, int bsize)
{
	struct buf *bp;
	int error, fberror;

	/*
	 * Allocate a temp bp using pageio_setup, but then use it
	 * for physio to the area mapped by fbuf which is currently
	 * all locked down in place.
	 *
	 * XXX - need to have a generalized bp header facility
	 * which we build up pageio_setup on top of.  Other places
	 * (like here and in device drivers for the raw I/O case)
	 * could then use these new facilities in a more straight
	 * forward fashion instead of playing all these games.
	 */
	bp = pageio_setup((struct page *)NULL, fbp->fb_count, devvp, B_WRITE);
	bp->b_flags &= ~B_PAGEIO;		/* XXX */
	bp->b_un.b_addr = fbp->fb_addr;

	bp->b_blkno = bn * btod(bsize);
	bp->b_dev = cmpdev(devvp->v_rdev);	/* store in old dev format */
	bp->b_edev = devvp->v_rdev;
	bp->b_proc = NULL;			/* i.e. the kernel */

	(void) bdev_strategy(bp);
	error = biowait(bp);
	pageio_done(bp);

	/*CSTYLED*/
	FBCOMMON(fbp, S_OTHER, 0, fberror = )

	return (error ? error : fberror);
}
Exemple #10
0
int
vdev_disk_ldi_physio(ldi_handle_t vd_lh, caddr_t data,
    size_t size, uint64_t offset, int flags)
{
#ifdef illumos
	buf_t *bp;
#else
	ldi_buf_t *bp;
#endif
	int error = 0;

	if (vd_lh == NULL)
		return (SET_ERROR(EINVAL));

	ASSERT(flags & B_READ || flags & B_WRITE);

	bp = getrbuf(KM_SLEEP);
	bp->b_flags = flags | B_BUSY | B_NOCACHE | B_FAILFAST;
	bp->b_bcount = size;
	bp->b_un.b_addr = (void *)data;
	bp->b_lblkno = lbtodb(offset);
	bp->b_bufsize = size;

	error = ldi_strategy(vd_lh, bp);
	ASSERT(error == 0);

	if ((error = biowait(bp)) == 0 && bp->b_resid != 0)
		error = SET_ERROR(EIO);
	freerbuf(bp);

	return (error);
}
/*
 * NAMES:	raid_pw_read
 * DESCRIPTION: issue a syncronous read to read a pre-write entry
 * PARAMETERS:	mr_unit_t	*un    - pointer to the unit structure
 *		int		column - column number for the pre-write entry
 *		u_int		slot   - pre-write entry slot number
 *		raid_rplybuf_t	*bufp  - pointer to the replay buffer structure
 * RETURNS:
 */
static int
raid_pw_read(mr_unit_t *un, int column, uint_t slot, raid_rplybuf_t *bufp)
{
	buf_t	*bp;
	int	error;
	uint_t	blkcnt  = un->un_iosize;
	uint_t	bytecnt = blkcnt * DEV_BSIZE;

	/* if this column is no longer accessible, return */
	if (!COLUMN_ISUP(un, column))
		return (RAID_RPLY_COMPREPLAY);

	/* set up pointers from raid_rplybuf_t *bufp */
	bp = (buf_t *)bufp->rpl_buf;

	/* calculate the data address or block number */
	bp->b_un.b_addr = bufp->rpl_data;
	bp->b_bufsize = bytecnt;
	bp->b_bcount = bytecnt;
	bp->b_flags = (B_READ | B_BUSY);
	bp->b_edev = md_dev64_to_dev(un->un_column[column].un_dev);
	bp->b_lblkno = un->un_column[column].un_pwstart + (slot * blkcnt);
	bp->b_iodone = pw_read_done;
	(void) md_call_strategy(bp, 0, NULL);
	if (biowait(bp)) {
		error = raid_replay_error(un, column);
		return (error);
	}
	return (0);
}
/*
 * NAMES:	raid_pw_write
 * DESCRIPTION: issue a syncronous write to write a pre-write entry
 * PARAMETERS:	mr_unit_t *un - pointer to the unit structure
 *		int	column	- column number for the pre-write entry
 *		raid_pwhdr_t   *pwhp - needed for some infos about the pw header
 *		raid_rplybuf_t *bufp - pointer to the replay buffer structure
 * RETURNS:
 */
static int
raid_pw_write(mr_unit_t *un, int column, raid_pwhdr_t *pwhp,
    raid_rplybuf_t *bufp)
{
	buf_t	 *bp;
	int	 error;

	/* if this column is no longer accessible, return */
	if (!COLUMN_ISUP(un, column))
		return (RAID_RPLY_COMPREPLAY);

	/* set up pointers from raid_rplybuf_t *bufp */
	bp = (buf_t *)bufp->rpl_buf;

	/* calculate the data address or block number */
	bp->b_un.b_addr = bufp->rpl_data + DEV_BSIZE;
	bp->b_bufsize = dbtob(pwhp->rpw_blkcnt);
	bp->b_bcount = dbtob(pwhp->rpw_blkcnt);
	bp->b_flags = (B_WRITE | B_BUSY);
	bp->b_edev  = md_dev64_to_dev(un->un_column[column].un_dev);
	bp->b_lblkno = un->un_column[column].un_devstart + pwhp->rpw_blkno;
	bp->b_iodone = pw_write_done;
	(void) md_call_strategy(bp, 0, NULL);
	if (biowait(bp)) {
		error = raid_replay_error(un, column);
		return (error);
	}
	return (0);
}
Exemple #13
0
/*
 * Write disk label back to device after modification.
 */
int
writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
{
	struct buf *bp = NULL;
	int error;

	/* get buffer and initialize it */
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;

	error = disklabel_bsd_to_sun(lp, (struct sun_disklabel *)bp->b_data);
	if (error)
		goto done;

	/* Write out the updated label. */
	bp->b_blkno = LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW);
	(*strat)(bp);
	error = biowait(bp);

done:
	if (bp) {
		bp->b_flags |= B_INVAL;
		brelse(bp);
	}
	disk_change = 1;
	return (error);
}
Exemple #14
0
/*
 * Write disk label back to device after modification.
 * Current label is already in clp->cd_block[]
 */
int
writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *clp)
{
	struct buf *bp;
	struct disklabel *dlp;
	int error;

	/* implant NetBSD disklabel at LABELOFFSET. */
	dlp = (struct disklabel *)(clp->cd_block + LABELOFFSET);
	*dlp = *lp; 	/* struct assignment */

	error = disklabel_bsd_to_om(lp, clp->cd_block);
	if (error)
		return (error);

	/* Get a buffer and copy the new label into it. */
	bp = geteblk((int)lp->d_secsize);
	memcpy(bp->b_data, clp->cd_block, sizeof(clp->cd_block));

	/* Write out the updated label. */
	bp->b_dev = dev;
	bp->b_blkno = LABELSECTOR;
	bp->b_cylinder = 0;
	bp->b_bcount = lp->d_secsize;
	bp->b_flags |= B_WRITE;
	(*strat)(bp);
	error = biowait(bp);
	brelse(bp, 0);

	return (error);
}
Exemple #15
0
/*
 * Write disk label back to device after modification.
 */
int
writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
{
	daddr_t partoff = -1;
	int error = EIO;
	int offset;
	struct disklabel *dlp;
	struct buf *bp = NULL;

	/* get a buffer and initialize it */
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;

	if (readdpmelabel(bp, strat, lp, &partoff, 1) == 0) {
		bp->b_blkno = partoff;
		offset = 0;
	} else if (readdoslabel(bp, strat, lp, &partoff, 1) == 0) {
		bp->b_blkno = DL_BLKTOSEC(lp, partoff + DOS_LABELSECTOR) *
		    DL_BLKSPERSEC(lp);
		offset = DL_BLKOFFSET(lp, partoff + DOS_LABELSECTOR);
	} else
		goto done;

	/* Read it in, slap the new label in, and write it back out */
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if ((error = biowait(bp)) != 0)
		goto done;

	dlp = (struct disklabel *)(bp->b_data + offset);
	*dlp = *lp;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW);
	(*strat)(bp);
	error = biowait(bp);

done:
	if (bp) {
		bp->b_flags |= B_INVAL;
		brelse(bp);
	}
	disk_change = 1;
	return (error);
}
Exemple #16
0
/*ARGSUSED*/
int
cflrw(dev_t dev, struct uio *uio, int flag)
{
	struct buf *bp;
	int i;
	int s;
	int error;

	if (uio->uio_resid == 0) 
		return (0);
	s = splconsmedia();
	while (cfltab.cfl_state == BUSY)
		(void) tsleep(&cfltab, PRIBIO, "cflbusy", 0);
	cfltab.cfl_state = BUSY;
	splx(s);

	bp = cfltab.cfl_buf;
	error = 0;
	while ((i = imin(CFL_BYTESPERSEC, uio->uio_resid)) > 0) {
		bp->b_blkno = uio->uio_offset>>7;
		if (bp->b_blkno >= CFL_MAXSEC ||
		    (uio->uio_offset & 0x7F) != 0) {
			error = EIO;
			break;
		}
		if (uio->uio_rw == UIO_WRITE) {
			error = uiomove(bp->b_data, i, uio);
			if (error)
				break;
		}
		if (uio->uio_rw == UIO_WRITE) {
			bp->b_oflags &= ~(BO_DONE);
			bp->b_flags &= ~(B_READ);
			bp->b_flags |= B_WRITE;
		} else {
			bp->b_oflags &= ~(BO_DONE);
			bp->b_flags &= ~(B_WRITE);
			bp->b_flags |= B_READ;
		}
		s = splconsmedia(); 
		cflstart();
		biowait(bp);
		splx(s);
		if (bp->b_error != 0) {
			error = bp->b_error;
			break;
		}
		if (uio->uio_rw == UIO_READ) {
			error = uiomove(bp->b_data, i, uio);
			if (error)
				break;
		}
	}
	cfltab.cfl_state = OPEN;
	wakeup((void *)&cfltab);
	return (error);
}
Exemple #17
0
/*
 * Attempt to read a disk label from a device
 * using the indicated strategy routine.
 * The label must be partly set up before this:
 * secpercyl, secsize and anything required for a block i/o read
 * operation in the driver's strategy/start routines
 * must be filled in before calling us.
 */
int
readdisklabel(dev_t dev, void (*strat)(struct buf *),
    struct disklabel *lp, int spoofonly)
{
	struct buf *bp = NULL;
	int error;

	if ((error = initdisklabel(lp)))
		goto done;

	/* get a buffer and initialize it */
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;

	if (spoofonly)
		goto doslabel;

	bp->b_blkno = LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if (biowait(bp)) {
		error = bp->b_error;
		goto done;
	}

	error = checkdisklabel(bp->b_data + LABELOFFSET, lp, 0,
	    DL_GETDSIZE(lp));
	if (error == 0)
		goto done;

doslabel:
	error = readdoslabel(bp, strat, lp, NULL, spoofonly);
	if (error == 0)
		goto done;

#if defined(CD9660)
	error = iso_disklabelspoof(dev, strat, lp);
	if (error == 0)
		goto done;
#endif
#if defined(UDF)
	error = udf_disklabelspoof(dev, strat, lp);
	if (error == 0)
		goto done;
#endif

done:
	if (bp) {
		bp->b_flags |= B_INVAL;
		brelse(bp);
	}
	disk_change = 1;
	return (error);
}
Exemple #18
0
/*
 * Write disk label back to device after modification.
 */
int
writedisklabel(dev_t dev, void (*strat)(struct buf *bp), struct disklabel *lp,
    struct cpu_disklabel *osdep)
{
	struct buf *bp;
	struct disklabel *dlp;
	int labelpart;
	int error = 0;

	labelpart = DISKPART(dev);
	if (lp->d_partitions[labelpart].p_offset != 0) {
		if (lp->d_partitions[0].p_offset != 0)
			return EXDEV;			/* not quite right */
		labelpart = 0;
	}
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = makedev(major(dev), DISKMINOR(DISKUNIT(dev), labelpart));
	bp->b_blkno = LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	bp->b_flags |= B_READ;
	(*strat)(bp);
	if ((error = biowait(bp)) != 0)
		goto done;
	for (dlp = (struct disklabel *)bp->b_data;
	    dlp <= (struct disklabel *)
	      ((char *)bp->b_data + lp->d_secsize - sizeof(*dlp));
	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
		if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
		    dkcksum(dlp) == 0) {
			*dlp = *lp;
			bp->b_oflags &= ~(BO_DONE);
			bp->b_flags &= ~(B_READ);
			bp->b_flags |= B_WRITE;
			(*strat)(bp);
			error = biowait(bp);
			goto done;
		}
	}
	error = ESRCH;
done:
	brelse(bp, 0);
	return error;
}
Exemple #19
0
/*
 * Attempt to read a disk label from a device
 * using the indicated strategy routine.
 * The label must be partly set up before this:
 * secpercyl and anything required in the strategy routine
 * (e.g., sector size) must be filled in before calling us.
 * Returns null on success and an error string on failure.
 */
const char *
readdisklabel(dev_t dev, void (*strat)(struct buf *bp), struct disklabel *lp,
    struct cpu_disklabel *osdep)
{
	struct buf *bp;
	struct disklabel *dlp;
	const char *msg = NULL;

	if (lp->d_secperunit == 0)
		lp->d_secperunit = 0x1fffffff;
	lp->d_npartitions = 1;
	if (lp->d_partitions[0].p_size == 0)
		lp->d_partitions[0].p_size = 0x1fffffff;
	lp->d_partitions[0].p_offset = 0;

	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;
	bp->b_blkno = LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	bp->b_flags |= B_READ;
	bp->b_cylinder = LABELSECTOR / lp->d_secpercyl;
	(*strat)(bp);
	if (biowait(bp)) {
		msg = "I/O error";
	} else for (dlp = (struct disklabel *)bp->b_data;
	    dlp <= (struct disklabel *)
	    ((char *)bp->b_data + DEV_BSIZE - sizeof(*dlp));
	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
			if (msg == NULL)
				msg = "no disk label";
		} else if (dlp->d_npartitions > MAXPARTITIONS ||
			   dkcksum(dlp) != 0)
			msg = "disk label corrupted";
		else {
			*lp = *dlp;
			msg = NULL;
			break;
		}
	}
	brelse(bp, 0);
	/*
	 * If no NetBSD label was found, check for an Ultrix label and
	 * construct tne incore label from the Ultrix partition information.
	 */
	if (msg != NULL) {
		msg = compat_label(dev, strat, lp, osdep);
		if (msg == NULL) {
			printf("WARNING: using Ultrix partition information\n");
			/* set geometry? */
		}
	}
/* XXX If no NetBSD label or Ultrix label found, generate default label here */
	return msg;
}
Exemple #20
0
/*
 * Write disk label back to device after modification.
 */
int
writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
{
	u_int64_t csum = 0, *p;
	struct disklabel *dlp;
	struct buf *bp = NULL;
	int error, i;

	/* get a buffer and initialize it */
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;

	bp->b_blkno = LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if ((error = biowait(bp)) != 0)
		goto done;

	/* Write it in the regular place. */
	dlp = (struct disklabel *)(bp->b_data + LABELOFFSET);
	*dlp = *lp;

	/* Alpha bootblocks require a checksum over the sector */
	for (i = 0, p = (u_int64_t *)bp->b_data; i < 63; i++)
		csum += *p++;
	*p = csum;

	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW);
	(*strat)(bp);
	error = biowait(bp);

done:
	if (bp) {
		bp->b_flags |= B_INVAL;
		brelse(bp);
	}
	disk_change = 1;
	return (error);
}
Exemple #21
0
/*
 * Try to read a standard BSD disklabel at a certain sector.
 */
const char *
readbsdlabel(struct buf *bp, void (*strat)(struct buf *), int cyl, int sec,
    int off, struct disklabel *lp, int spoofonly)
{
	struct disklabel *dlp;
	const char *msg = NULL;
	uint16_t cksum;

	/* don't read the on-disk label if we are in spoofed-only mode */
	if (spoofonly)
		return (NULL);

	bp->b_blkno = sec;
	bp->b_cylinder = cyl;
	bp->b_bcount = lp->d_secsize;
	bp->b_cflags = BC_BUSY;
	bp->b_flags = B_READ;
	bp->b_oflags = 0;
	(*strat)(bp);

	/* if successful, locate disk label within block and validate */
	if (biowait(bp)) {
		/* XXX we return the faked label built so far */
		msg = "disk label I/O error";
		return (msg);
	}

	/*
	 * If off is negative, search until the end of the sector for
	 * the label, otherwise, just look at the specific location
	 * we're given.
	 */
	dlp = (struct disklabel *)((char *)bp->b_data + (off >= 0 ? off : 0));
	do {
		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
			if (msg == NULL)
				msg = "no disk label";
		} else {
			cksum = dkcksum(dlp);
			if (dlp->d_npartitions > MAXPARTITIONS || cksum != 0) {
				msg = "disk label corrupted";
			} else {
				*lp = *dlp;
				msg = NULL;
				break;
			}
		}
		if (off >= 0)
			break;
		dlp = (struct disklabel *)((char *)dlp + sizeof(int32_t));
	} while (dlp <= (struct disklabel *)((char *)bp->b_data +
		 lp->d_secsize - sizeof(*dlp)));
	return (msg);
}
Exemple #22
0
/*
 * Read a disk block.
 * This algorithm described in Bach (p.54).
 */
int
bread(struct vnode *vp, daddr_t blkno, int size, struct buf **bpp)
{
	struct buf *bp;

	/* Get buffer for block. */
	bp = *bpp = bio_doread(vp, blkno, size, 0);

	/* Wait for the read to complete, and return result. */
	return (biowait(bp));
}
/*
 * Attempt to read a disk label from a device
 * using the indicated strategy routine.
 * The label must be partly set up before this:
 * secpercyl and anything required in the strategy routine
 * (e.g., sector size) must be filled in before calling us.
 * Returns null on success and an error string on failure.
 */
const char *
readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
    struct cpu_disklabel *osdep)
{
	struct buf *bp;
	struct disklabel *dlp;
	const char *msg = NULL;
	int i;

	if (lp->d_secsize == 0)
		lp->d_secsize = DEV_BSIZE;
	if (lp->d_secperunit == 0)
		lp->d_secperunit = 0x1fffffff;
	if (lp->d_npartitions < RAW_PART + 1)
		lp->d_npartitions = RAW_PART + 1;
	for (i = 0; i < RAW_PART; i++) {
		lp->d_partitions[i].p_size = 0;
		lp->d_partitions[i].p_offset = 0;
	}
	if (lp->d_partitions[RAW_PART].p_size == 0)
		lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
	lp->d_partitions[RAW_PART].p_offset = 0;

	lp->d_partitions[0].p_size = lp->d_partitions[RAW_PART].p_size;
	lp->d_partitions[0].p_fstype = FS_BSDFFS;

	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;
	bp->b_blkno = LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	bp->b_flags |= B_READ;
	bp->b_cylinder = LABELSECTOR / lp->d_secpercyl;
	(*strat)(bp);
	if (biowait(bp))
		msg = "I/O error";
	else for (dlp = (struct disklabel *)bp->b_data;
	    dlp <= (struct disklabel *)((char *)bp->b_data + DEV_BSIZE
	    - sizeof(*dlp));
	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
			if (msg == NULL)
				msg = "no disk label";
		} else if (dlp->d_npartitions > MAXPARTITIONS ||
			   dkcksum(dlp) != 0)
			msg = "disk label corrupted";
		else {
			*lp = *dlp;
			msg = NULL;
			break;
		}
	}
	brelse(bp, 0);
	return msg;
}
Exemple #24
0
int
disk_read_sectors(void (*strat)(struct buf *), const struct disklabel *lp,
    struct buf *bp, unsigned int sector, int count)
{
	bp->b_blkno = btodb((off_t)sector * lp->d_secsize);
	bp->b_bcount = count * lp->d_secsize;
	bp->b_flags = (bp->b_flags & ~B_WRITE) | B_READ;
	bp->b_oflags &= ~BO_DONE;
	bp->b_cylinder = sector / lp->d_secpercyl;
	(*strat)(bp);
	return biowait(bp);
}
Exemple #25
0
int
trans_wait(struct buf *cb)
{
	/*
	 * In case of panic, busy wait for completion and run md daemon queues
	 */
	if (panicstr) {
		trans_wait_panic(cb);
	}

	return (biowait(cb));
}
static int
ramd_norm_read(struct read_info *rsp)
{
	long		bytes_left;
	int		done, error;
	struct buf	*bp;
	int		dotc = 0;

	bytes_left = rsp->nbytes;
	bp         = rsp->bp;
	error      = 0;

	while (bytes_left > 0) {
		bp->b_cflags = BC_BUSY;
		bp->b_flags  = B_PHYS | B_READ;
		bp->b_oflags &= ~BO_DONE;
		bp->b_blkno  = btodb(rsp->offset);
		bp->b_bcount = min(rsp->chunk, bytes_left);
		bp->b_data   = rsp->bufp;
		bp->b_error  = 0;

		/* Initiate read */
		(*rsp->strat)(bp);

		/* Wait for results	*/
		biowait(bp);
		error = bp->b_error;

		/* Dot counter */
		printf(".");
		if (!(++dotc % 40))
			printf("\n");

		done = bp->b_bcount - bp->b_resid;

		bytes_left   -= done;
		rsp->offset  += done;
		rsp->bufp    += done;

		if (error || !done)
			break;

		if ((rsp->offset == rsp->media_sz) && (bytes_left != 0)) {
			printf("\nInsert next media and hit any key...");
			cngetc();
			printf("\n");
			rsp->offset = 0;
		}
	}
	printf("\n");
	return error;
}
/*
 * Read a maximum of 'nbyte' bytes into 'buf'.
 */
static int
md_compressed(void * buf, int nbyte, struct read_info *rsp)
{
	static int	dotc = 0;
	struct buf	*bp;
	       int	nread = 0;
	       int	done, error;


	error  = 0;
	bp     = rsp->bp;
	nbyte &= ~(DEV_BSIZE - 1);

	while (nbyte > 0) {
		bp->b_cflags = BC_BUSY;
		bp->b_flags  = B_PHYS | B_READ;
		bp->b_oflags &= ~BO_DONE;
		bp->b_blkno  = btodb(rsp->offset);
		bp->b_bcount = min(rsp->chunk, nbyte);
		bp->b_data   = buf;
		bp->b_error  = 0;

		/* Initiate read */
		(*rsp->strat)(bp);

		/* Wait for results	*/
		biowait(bp);
		error = bp->b_error;

		/* Dot counter */
		printf(".");
		if (!(++dotc % 40))
			printf("\n");

		done = bp->b_bcount - bp->b_resid;

		nbyte        -= done;
		nread        += done;
		rsp->offset  += done;

		if (error || !done)
			break;

		if ((rsp->offset == rsp->media_sz) && (nbyte != 0)) {
			printf("\nInsert next media and hit any key...");
			if (cngetc() != '\n')
				printf("\n");
			rsp->offset = 0;
		}
	}
	return nread;
}
Exemple #28
0
/*
 * Write disk label back to device after modification.
 */
int
writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
{
	int error = EIO, partoff = -1;
	struct disklabel *dlp;
	struct buf *bp = NULL;

	/* get a buffer and initialize it */
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;

	if (readliflabel(bp, strat, lp, &partoff, 1) != 0 &&
	    readdoslabel(bp, strat, lp, &partoff, 1) != 0)
		goto done;

	/* Read it in, slap the new label in, and write it back out */
	bp->b_blkno = partoff + LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if ((error = biowait(bp)) != 0)
		goto done;

	dlp = (struct disklabel *)(bp->b_data + LABELOFFSET);
	*dlp = *lp;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW);
	(*strat)(bp);
	error = biowait(bp);

done:
	if (bp) {
		bp->b_flags |= B_INVAL;
		brelse(bp);
	}
	disk_change = 1;
	return (error);
}
Exemple #29
0
/*
 * Attempt to read a disk label from a device
 * using the indicated strategy routine.
 * The label must be partly set up before this:
 * secpercyl and anything required in the strategy routine
 * (e.g., sector size) must be filled in before calling us.
 */
int
readdisklabel(dev_t dev, void (*strat)(struct buf *),
    struct disklabel *lp, int spoofonly)
{
	struct buf *bp = NULL;
	int error;

	if ((error = initdisklabel(lp)))
		goto done;

	/* get a buffer and initialize it */
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;

	/* don't read the on-disk label if we are in spoofed-only mode */
	if (spoofonly)
		goto done;

	bp->b_blkno = LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if (biowait(bp)) {
		error = bp->b_error;
		goto done;
	}

	error = cputobsdlabel(lp, (struct mvmedisklabel *)bp->b_data);
	if (error == 0)
		goto done;

#if defined(CD9660)
	error = iso_disklabelspoof(dev, strat, lp);
	if (error == 0)
		goto done;
#endif
#if defined(UDF)
	error = udf_disklabelspoof(dev, strat, lp);
	if (error == 0)
		goto done;
#endif

done:
	if (bp) {
		bp->b_flags |= B_INVAL;
		brelse(bp);
	}
	disk_change = 1;
	return (error);
}
/*
 * Attempt to read a disk label from a device.  
 *
 * Returns NULL on sucess, and an error string on failure
 */
static const char *
l32_readdisklabel(cdev_t dev, struct diskslice *sp, disklabel_t *lpp,
		struct disk_info *info)
{
	disklabel_t lpx;
	struct buf *bp;
	struct disklabel32 *dlp;
	const char *msg = NULL;
	int secsize = info->d_media_blksize;

	bp = geteblk(secsize);
	bp->b_bio1.bio_offset = (off_t)LABELSECTOR32 * secsize;
	bp->b_bio1.bio_done = biodone_sync;
	bp->b_bio1.bio_flags |= BIO_SYNC;
	bp->b_bcount = secsize;
	bp->b_flags &= ~B_INVAL;
	bp->b_cmd = BUF_CMD_READ;
	dev_dstrategy(dev, &bp->b_bio1);
	if (biowait(&bp->b_bio1, "labrd"))
		msg = "I/O error";
	else for (dlp = (struct disklabel32 *)bp->b_data;
	    dlp <= (struct disklabel32 *)((char *)bp->b_data +
	    secsize - sizeof(*dlp));
	    dlp = (struct disklabel32 *)((char *)dlp + sizeof(long))) {
		if (dlp->d_magic != DISKMAGIC32 ||
		    dlp->d_magic2 != DISKMAGIC32) {
			/*
			 * NOTE! dsreadandsetlabel() does a strcmp() on
			 * this string.
			 */
			if (msg == NULL) 
				msg = "no disk label";
		} else if (dlp->d_npartitions > MAXPARTITIONS32 ||
			   dkcksum32(dlp) != 0) {
			msg = "disk label corrupted";
		} else {
			lpx.lab32 = dlp;
			msg = l32_fixlabel(NULL, sp, lpx, FALSE);
			if (msg == NULL) {
				(*lpp).lab32 = kmalloc(sizeof(*dlp),
						       M_DEVBUF, M_WAITOK|M_ZERO);
				*(*lpp).lab32 = *dlp;
			}
			break;
		}
	}
	bp->b_flags |= B_INVAL | B_AGE;
	brelse(bp);
	return (msg);
}