The following diff factors out the block I/O code that is used within
softraid(4) and also allows it to handle I/Os that exceeds MAXPHYS in
size. This is necessary for some upcoming work.
This diff needs extensive testing since the main purpose is to read and
write the softraid metadata. Bugs in this area will eat softraid metadata
and therefore destroy softraid volumes. If you are testing please ensure
that you have backed up your data or that the volume does not have
critical information. Please report test successes/failures directly to me.
Index: softraidvar.h
===================================================================
RCS file: /cvs/src/sys/dev/softraidvar.h,v
retrieving revision 1.96
diff -u -p -r1.96 softraidvar.h
--- softraidvar.h 6 Nov 2010 23:01:56 -0000 1.96
+++ softraidvar.h 6 Jan 2011 12:41:26 -0000
@@ -624,6 +624,8 @@ int sr_check_io_collision(struct sr_wo
void sr_scsi_done(struct sr_discipline *,
struct scsi_xfer *);
int sr_chunk_in_use(struct sr_softc *, dev_t);
+int sr_rw(struct sr_softc *, dev_t, char *, size_t,
+ daddr64_t, long);
/* discipline functions */
int sr_raid_inquiry(struct sr_workunit *);
Index: softraid.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid.c,v
retrieving revision 1.217
diff -u -p -r1.217 softraid.c
--- softraid.c 20 Dec 2010 17:47:48 -0000 1.217
+++ softraid.c 6 Jan 2011 12:41:26 -0000
@@ -387,57 +387,93 @@ sr_meta_getdevname(struct sr_softc *sc,
}
int
-sr_meta_rw(struct sr_discipline *sd, dev_t dev, void *md, size_t sz,
- daddr64_t ofs, long flags)
+sr_rw(struct sr_softc *sc, dev_t dev, char *buf, size_t size, daddr64_t
offset,
+ long flags)
{
- struct sr_softc *sc = sd->sd_sc;
+ struct vnode *vp;
struct buf b;
+ size_t bufsize;
int rv = 1;
- DNPRINTF(SR_D_META, "%s: sr_meta_rw(0x%x, %p, %d, %llu 0x%x)\n",
- DEVNAME(sc), dev, md, sz, ofs, flags);
-
- bzero(&b, sizeof(b));
+ DNPRINTF(SR_D_MISC, "%s: sr_rw(0x%x, %p, %d, %llu 0x%x)\n",
+ DEVNAME(sc), dev, buf, size, offset, flags);
- if (md == NULL) {
- printf("%s: read invalid metadata pointer\n", DEVNAME(sc));
+ if (bdevvp(dev, &vp)) {
+ printf("%s: sr_rw: failed to allocate vnode\n", DEVNAME(sc));
goto done;
}
- b.b_flags = flags | B_PHYS;
- b.b_blkno = ofs;
- b.b_bcount = sz;
- b.b_bufsize = sz;
- b.b_resid = sz;
- b.b_data = md;
- b.b_error = 0;
- b.b_proc = curproc;
- b.b_dev = dev;
- b.b_iodone = NULL;
- if (bdevvp(dev, &b.b_vp)) {
- printf("%s: sr_meta_rw: can't allocate vnode\n", DEVNAME(sc));
- goto done;
- }
- if ((b.b_flags & B_READ) == 0)
- b.b_vp->v_numoutput++;
-
- LIST_INIT(&b.b_dep);
- VOP_STRATEGY(&b);
- biowait(&b);
-
- if (b.b_flags & B_ERROR) {
- printf("%s: 0x%x i/o error on block %llu while reading "
- "metadata %d\n", DEVNAME(sc), dev, b.b_blkno, b.b_error);
- goto done;
+
+ while (size > 0) {
+
+ DNPRINTF(SR_D_MISC, "%s: buf %p, size %d, offset %llu)\n",
+ DEVNAME(sc), buf, size, offset);
+
+ bufsize = (size > MAXPHYS) ? MAXPHYS : size;
+
+ bzero(&b, sizeof(b));
+
+ b.b_flags = flags | B_PHYS;
+ b.b_proc = curproc;
+ b.b_dev = dev;
+ b.b_iodone = NULL;
+ b.b_error = 0;
+ b.b_blkno = offset;
+ b.b_data = buf;
+ b.b_bcount = bufsize;
+ b.b_bufsize = bufsize;
+ b.b_resid = bufsize;
+ b.b_vp = vp;
+
+ if ((b.b_flags & B_READ) == 0)
+ vp->v_numoutput++;
+
+ LIST_INIT(&b.b_dep);
+ VOP_STRATEGY(&b);
+ biowait(&b);
+
+ if (b.b_flags & B_ERROR) {
+ printf("%s: I/O error %d on dev 0x%x at block %llu\n",
+ DEVNAME(sc), b.b_error, dev, b.b_blkno);
+ goto done;
+ }
+
+ size -= bufsize;
+ buf += bufsize;
+ offset += howmany(bufsize, DEV_BSIZE);
+
}
+
rv = 0;
+
done:
- if (b.b_vp)
- vput(b.b_vp);
+ if (vp)
+ vput(vp);
return (rv);
}
int
+sr_meta_rw(struct sr_discipline *sd, dev_t dev, void *md, size_t size,
+ daddr64_t offset, long flags)
+{
+ int rv = 1;
+
+ DNPRINTF(SR_D_META, "%s: sr_meta_rw(0x%x, %p, %d, %llu 0x%x)\n",
+ DEVNAME(sd->sd_sc), dev, md, size, offset, flags);
+
+ if (md == NULL) {
+ printf("%s: sr_meta_rw: invalid metadata pointer\n",
+ DEVNAME(sd->sd_sc));
+ goto done;
+ }
+
+ rv = sr_rw(sd->sd_sc, dev, md, size, offset, flags);
+
+done:
+ return (rv);
+}
+
+int
sr_meta_clear(struct sr_discipline *sd)
{
struct sr_softc *sc = sd->sd_sc;
@@ -3167,7 +3203,6 @@ sr_ioctl_installboot(struct sr_softc *sc
void *bootblk = NULL, *bootldr = NULL;
struct sr_discipline *sd = NULL;
struct sr_chunk *chunk;
- struct buf b;
u_int32_t bbs, bls;
int rv = EINVAL;
int i;
@@ -3216,34 +3251,9 @@ sr_ioctl_installboot(struct sr_softc *sc
"sr_ioctl_installboot: saving boot block to %s "
"(%u bytes)\n", chunk->src_devname, bbs);
- bzero(&b, sizeof(b));
- b.b_flags = B_WRITE | B_PHYS;
- b.b_blkno = SR_BOOT_BLOCKS_OFFSET;
- b.b_bcount = bbs;
- b.b_bufsize = bbs;
- b.b_resid = bbs;
- b.b_data = bootblk;
- b.b_error = 0;
- b.b_proc = curproc;
- b.b_dev = chunk->src_dev_mm;
- b.b_vp = NULL;
- b.b_iodone = NULL;
- if (bdevvp(chunk->src_dev_mm, &b.b_vp)) {
- printf("%s: sr_ioctl_installboot: vnode allocation "
- "failed\n", DEVNAME(sc));
- goto done;
- }
- if ((b.b_flags & B_READ) == 0)
- b.b_vp->v_numoutput++;
- LIST_INIT(&b.b_dep);
- VOP_STRATEGY(&b);
- biowait(&b);
- vput(b.b_vp);
-
- if (b.b_flags & B_ERROR) {
- printf("%s: 0x%x i/o error on block %llu while "
- "writing boot block %d\n", DEVNAME(sc),
- chunk->src_dev_mm, b.b_blkno, b.b_error);
+ if (sr_rw(sc, chunk->src_dev_mm, bootblk, bbs,
+ SR_BOOT_BLOCKS_OFFSET, B_WRITE)) {
+ printf("%s: failed to write boot block\n", DEVNAME(sc));
goto done;
}
@@ -3252,34 +3262,10 @@ sr_ioctl_installboot(struct sr_softc *sc
"sr_ioctl_installboot: saving boot loader to %s "
"(%u bytes)\n", chunk->src_devname, bls);
- bzero(&b, sizeof(b));
- b.b_flags = B_WRITE | B_PHYS;
- b.b_blkno = SR_BOOT_LOADER_OFFSET;
- b.b_bcount = bls;
- b.b_bufsize = bls;
- b.b_resid = bls;
- b.b_data = bootldr;
- b.b_error = 0;
- b.b_proc = curproc;
- b.b_dev = chunk->src_dev_mm;
- b.b_vp = NULL;
- b.b_iodone = NULL;
- if (bdevvp(chunk->src_dev_mm, &b.b_vp)) {
- printf("%s: sr_ioctl_installboot: vnode alocation "
- "failed\n", DEVNAME(sc));
- goto done;
- }
- if ((b.b_flags & B_READ) == 0)
- b.b_vp->v_numoutput++;
- LIST_INIT(&b.b_dep);
- VOP_STRATEGY(&b);
- biowait(&b);
- vput(b.b_vp);
-
- if (b.b_flags & B_ERROR) {
- printf("%s: 0x%x i/o error on block %llu while "
- "writing boot blocks %d\n", DEVNAME(sc),
- chunk->src_dev_mm, b.b_blkno, b.b_error);
+ if (sr_rw(sc, chunk->src_dev_mm, bootldr, bls,
+ SR_BOOT_LOADER_OFFSET, B_WRITE)) {
+ printf("%s: failed to write boot loader\n",
+ DEVNAME(sc));
goto done;
}
--
"Stop assuming that systems are secure unless demonstrated insecure;
start assuming that systems are insecure unless designed securely."
- Bruce Schneier