/* * 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); }
/* * 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); }
/* * 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); } }
/* * 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); }
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); }
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; }
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); }
/* * 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); }
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); }
/* * 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); }
/* * 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); }
/* * 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); }
/*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); }
/* * 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); }
/* * 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; }
/* * 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; }
/* * 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); }
/* * 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); }
/* * 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; }
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); }
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; }
/* * 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); }
/* * 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); }