This one needs lots of testing folks.  Please oblige.

On Sat, Jan 15, 2011 at 01:22:24AM +1100, Joel Sing wrote:
> 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

Reply via email to