On Mon, Mar 12, 2018 at 11:38:14AM +0100, Stefan Sperling wrote:
> I haven't had any feedback on the previous diff. However, I felt it
> was a bit of a hack, so I tried to come up with a cleaner solution.
Anyone? Can this go in now? I hope to get this tested across
many sparc64 machines during the 6.4 release cycle.
> The diff below opens the softraid boot chunk early on and keeps the
> handle open until a kernel has been loaded from the softraid volume.
> This means sr_strategy() does not have to worry about obtaining a
> handle from the firmware anymore.
>
> Also consolidate some repeated lines of code in sr_strategy().
>
> Tested on a T5220 ldom guest (CRYPTO) and a v240 machine (RAID1).
>
> Index: boot.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/sparc64/stand/ofwboot/boot.c,v
> retrieving revision 1.27
> diff -u -p -r1.27 boot.c
> --- boot.c 11 Sep 2016 17:53:26 -0000 1.27
> +++ boot.c 12 Mar 2018 10:26:23 -0000
> @@ -248,6 +248,8 @@ loadfile(int fd, char *args)
> close(fd);
>
> #ifdef SOFTRAID
> + if (bootdev_dip)
> + OF_close(bootdev_dip->sr_handle);
> sr_clear_keys();
> #endif
> chain(entry, args, ssym, esym);
> @@ -283,12 +285,11 @@ fail:
> }
>
> #ifdef SOFTRAID
> -/* Set bootdev_dip to the software boot volume, if specified. */
> +/* Set bootdev_dip to the softraid boot volume, if specified. */
> static int
> srbootdev(const char *bootline)
> {
> struct sr_boot_volume *bv;
> - struct diskinfo *dip;
> int unit;
>
> bootdev_dip = NULL;
> @@ -320,9 +321,23 @@ srbootdev(const char *bootline)
> return EPERM;
>
> if (bv->sbv_diskinfo == NULL) {
> + struct sr_boot_chunk *bc;
> + struct diskinfo *dip, *bc_dip;
> + int sr_handle;
> +
> + /* All reads will come from the boot chunk. */
> + bc = sr_vol_boot_chunk(bv);
> + if (bc == NULL)
> + return ENXIO;
> + bc_dip = (struct diskinfo *)bc->sbc_diskinfo;
> + sr_handle = OF_open(bc_dip->path);
> + if (sr_handle == -1)
> + return EIO;
> +
> dip = alloc(sizeof(struct diskinfo));
> bzero(dip, sizeof(*dip));
> dip->sr_vol = bv;
> + dip->sr_handle = sr_handle;
> bv->sbv_diskinfo = dip;
> }
>
> @@ -331,7 +346,8 @@ srbootdev(const char *bootline)
>
> /* Attempt to read disklabel. */
> bv->sbv_part = 'c';
> - if (sr_getdisklabel(bv, &dip->disklabel)) {
> + if (sr_getdisklabel(bv, &bootdev_dip->disklabel)) {
> + OF_close(bootdev_dip->sr_handle);
> free(bv->sbv_diskinfo, sizeof(struct diskinfo));
> bv->sbv_diskinfo = NULL;
> bootdev_dip = NULL;
> Index: disk.h
> ===================================================================
> RCS file: /cvs/src/sys/arch/sparc64/stand/ofwboot/disk.h,v
> retrieving revision 1.1
> diff -u -p -r1.1 disk.h
> --- disk.h 26 Nov 2014 20:30:41 -0000 1.1
> +++ disk.h 12 Mar 2018 10:26:23 -0000
> @@ -36,7 +36,10 @@
> struct diskinfo {
> char path[256];
> struct disklabel disklabel;
> +
> + /* Used during softraid boot. */
> struct sr_boot_volume *sr_vol;
> + int sr_handle; /* open handle for reading from boot chunk */
>
> TAILQ_ENTRY(diskinfo) list;
> };
> Index: ofdev.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/sparc64/stand/ofwboot/ofdev.c,v
> retrieving revision 1.25
> diff -u -p -r1.25 ofdev.c
> --- ofdev.c 1 Oct 2015 16:08:20 -0000 1.25
> +++ ofdev.c 12 Mar 2018 10:26:23 -0000
> @@ -125,8 +125,8 @@ strategy(void *devdata, int rw, daddr32_
> #ifdef SOFTRAID
> /* Intercept strategy for softraid volumes. */
> if (dev->type == OFDEV_SOFTRAID)
> - return sr_strategy(bootdev_dip->sr_vol, rw,
> - blk, size, buf, rsize);
> + return sr_strategy(bootdev_dip->sr_vol, bootdev_dip->sr_handle,
> + rw, blk, size, buf, rsize);
> #endif
> if (dev->type != OFDEV_DISK)
> panic("strategy");
> Index: softraid_sparc64.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/sparc64/stand/ofwboot/softraid_sparc64.c,v
> retrieving revision 1.2
> diff -u -p -r1.2 softraid_sparc64.c
> --- softraid_sparc64.c 11 Sep 2016 17:53:26 -0000 1.2
> +++ softraid_sparc64.c 12 Mar 2018 10:26:23 -0000
> @@ -306,9 +306,25 @@ srprobe(void)
> free(md, SR_META_SIZE * DEV_BSIZE);
> }
>
> +struct sr_boot_chunk *
> +sr_vol_boot_chunk(struct sr_boot_volume *bv)
> +{
> + struct sr_boot_chunk *bc = NULL;
> +
> + if (bv->sbv_level == 1 || bv->sbv_level == 'C' ) { /* RAID1 or CRYPTO */
> + /* Select first online chunk. */
> + SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link)
> + if (bc->sbc_state == BIOC_SDONLINE)
> + break;
> + }
> +
> + return bc;
> +}
> +
> +
> int
> -sr_strategy(struct sr_boot_volume *bv, int rw, daddr32_t blk, size_t size,
> - void *buf, size_t *rsize)
> +sr_strategy(struct sr_boot_volume *bv, int sr_handle, int rw, daddr32_t blk,
> + size_t size, void *buf, size_t *rsize)
> {
> struct diskinfo *sr_dip, *dip;
> struct partition *pp;
> @@ -320,7 +336,6 @@ sr_strategy(struct sr_boot_volume *bv, i
> u_char iv[8];
> u_char *bp;
> int err;
> - int ihandle;
>
> /* We only support read-only softraid. */
> if (rw != F_READ)
> @@ -331,55 +346,28 @@ sr_strategy(struct sr_boot_volume *bv, i
> blk +=
> DL_GETPOFFSET(&sr_dip->disklabel.d_partitions[bv->sbv_part - 'a']);
>
> + bc = sr_vol_boot_chunk(bv);
> + if (bc == NULL)
> + return ENXIO;
> +
> + dip = (struct diskinfo *)bc->sbc_diskinfo;
> + pp = &dip->disklabel.d_partitions[bc->sbc_part - 'a'];
> + bzero(&ofdev, sizeof(ofdev));
> + ofdev.handle = sr_handle;
> + ofdev.type = OFDEV_DISK;
> + ofdev.bsize = DEV_BSIZE;
> + ofdev.partoff = DL_GETPOFFSET(pp);
> +
> if (bv->sbv_level == 0) {
> return ENOTSUP;
> } else if (bv->sbv_level == 1) {
> -
> - /* Select first online chunk. */
> - SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link)
> - if (bc->sbc_state == BIOC_SDONLINE)
> - break;
> - if (bc == NULL)
> - return EIO;
> -
> - dip = (struct diskinfo *)bc->sbc_diskinfo;
> - pp = &dip->disklabel.d_partitions[bc->sbc_part - 'a'];
> blk += bv->sbv_data_blkno;
>
> /* XXX - If I/O failed we should try another chunk... */
> - ihandle = OF_open(dip->path);
> - if (ihandle == -1)
> - return EIO;
> - bzero(&ofdev, sizeof(ofdev));
> - ofdev.handle = ihandle;
> - ofdev.type = OFDEV_DISK;
> - ofdev.bsize = DEV_BSIZE;
> - ofdev.partoff = DL_GETPOFFSET(pp);
> err = strategy(&ofdev, rw, blk, size, buf, rsize);
> - OF_close(ihandle);
> return err;
>
> } else if (bv->sbv_level == 'C') {
> -
> - /* Select first online chunk. */
> - SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link)
> - if (bc->sbc_state == BIOC_SDONLINE)
> - break;
> - if (bc == NULL)
> - return EIO;
> -
> - dip = (struct diskinfo *)bc->sbc_diskinfo;
> - pp = &dip->disklabel.d_partitions[bc->sbc_part - 'a'];
> -
> - ihandle = OF_open(dip->path);
> - if (ihandle == -1)
> - return EIO;
> - bzero(&ofdev, sizeof(ofdev));
> - ofdev.handle = ihandle;
> - ofdev.type = OFDEV_DISK;
> - ofdev.bsize = DEV_BSIZE;
> - ofdev.partoff = DL_GETPOFFSET(pp);
> -
> /* XXX - select correct key. */
> aes_xts_setkey(&ctx, (u_char *)bv->sbv_keys, 64);
>
> @@ -395,7 +383,6 @@ sr_strategy(struct sr_boot_volume *bv, i
> printf("Read from crypto volume failed "
> "(read %d bytes): %s\n", *rsize,
> strerror(err));
> - OF_close(ihandle);
> return err;
> }
> bcopy(&blkno, iv, sizeof(blkno));
> @@ -404,7 +391,6 @@ sr_strategy(struct sr_boot_volume *bv, i
> aes_xts_decrypt(&ctx, bp + j);
> }
> *rsize = nsect * DEV_BSIZE;
> - OF_close(ihandle);
> return err;
>
> } else
> Index: softraid_sparc64.h
> ===================================================================
> RCS file: /cvs/src/sys/arch/sparc64/stand/ofwboot/softraid_sparc64.h,v
> retrieving revision 1.3
> diff -u -p -r1.3 softraid_sparc64.h
> --- softraid_sparc64.h 11 Sep 2016 17:53:26 -0000 1.3
> +++ softraid_sparc64.h 12 Mar 2018 10:26:23 -0000
> @@ -21,8 +21,9 @@
>
> void srprobe(void);
>
> +struct sr_boot_chunk *sr_vol_boot_chunk(struct sr_boot_volume *);
> const char *sr_getdisklabel(struct sr_boot_volume *, struct disklabel *);
> -int sr_strategy(struct sr_boot_volume *, int, daddr32_t, size_t,
> +int sr_strategy(struct sr_boot_volume *, int, int, daddr32_t, size_t,
> void *, size_t *);
>
> #endif /* _SOFTRAID_SPARC64_H */
> Index: vers.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/sparc64/stand/ofwboot/vers.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 vers.c
> --- vers.c 18 Sep 2016 16:36:09 -0000 1.10
> +++ vers.c 12 Mar 2018 10:26:23 -0000
> @@ -1 +1 @@
> -const char version[] = "1.9";
> +const char version[] = "1.10";
>