diff mbox

What partition should the MTMKPART argument specify? Was: Re: st driver doesn't seem to grok LTO partitioning

Message ID alpine.LSU.2.11.1601291915010.22105@xnv.znxvfnen.cevingr (mailing list archive)
State Accepted, archived
Headers show

Commit Message

Kai Mäkisara (Kolumbus) Jan. 29, 2016, 5:22 p.m. UTC
On Friday 2016-01-29 01:12, Seymour, Shane M wrote:

>Date: Fri, 29 Jan 2016 01:12:41
>From: "Seymour, Shane M" <shane.seymour@hpe.com>
>To: "\"Kai Mäkisara (Kolumbus)\"" <kai.makisara@kolumbus.fi>
>Cc: Laurence Oberman <loberman@redhat.com>,
>    Emmanuel Florac <eflorac@intellique.com>,
>    Laurence Oberman <oberman.l@gmail.com>,
>    "linux-scsi@vger.kernel.org" <linux-scsi@vger.kernel.org>
>Subject: RE: What partition should the MTMKPART argument specify? Was: Re: st
>    driver doesn't seem to grok LTO partitioning
>
>Hi Kai,
>
>$ pwd
>/sys/class/scsi_tape/st1/device
>$ cat scsi_level
>4
>
OK. The previous patch set the number of partition size descriptors to 
one for HP DATs only if the SCSI level was <= SCSI_2.

The patch below uses that logic for all drives that don't need FORMAT 
MEDIUM. For the drives needing FORMAT MEDIUM the value is set to 2. 
These drives include LTOs and other modern drives.

Thanks, Kai
---------------------------------8<----------------------------------

Comments

Seymour, Shane M Feb. 1, 2016, 6:31 a.m. UTC | #1
Hi Kai,

Thanks for the changes the HPE DAT72 DDS5 drive now works as expected:

# ./mt -f /dev/st1 stsetoption debug
# ./mt -f /dev/st1 stsetoption can-partitions
# ./mt -f /dev/st1 mkpartition 1000

[  980.241139] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes.
[  980.241481] st 6:0:3:0: [st1] Mode 0 options: buffer writes: 1, async writes: 1, read ahead: 1
[  980.241487] st 6:0:3:0: [st1]     can bsr: 1, two FMs: 0, fast mteom: 0, auto lock: 0,
[  980.241490] st 6:0:3:0: [st1]     defs for wr: 0, no block limits: 0, partitions: 0, s2 log: 0
[  980.241493] st 6:0:3:0: [st1]     sysv: 0 nowait: 0 sili: 0 nowait_filemark: 0
[  980.241496] st 6:0:3:0: [st1]     debugging: 1
[  980.241502] st 6:0:3:0: [st1] Rewinding tape.
[  986.785288] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes.
[  986.785658] st 6:0:3:0: [st1] Mode sense. Length 11, medium 0, WBS 10, BLL 8
[  986.785663] st 6:0:3:0: [st1] Density 47, tape length: 0, drv buffer: 1
[  986.785666] st 6:0:3:0: [st1] Block size: 0, buffer size: 4096 (1 blocks).
[  986.785686] st 6:0:3:0: [st1] Mode 0 options: buffer writes: 1, async writes: 1, read ahead: 1
[  986.785690] st 6:0:3:0: [st1]     can bsr: 1, two FMs: 0, fast mteom: 0, auto lock: 0,
[  986.785693] st 6:0:3:0: [st1]     defs for wr: 0, no block limits: 0, partitions: 1, s2 log: 0
[  986.785696] st 6:0:3:0: [st1]     sysv: 0 nowait: 0 sili: 0 nowait_filemark: 0
[  986.785699] st 6:0:3:0: [st1]     debugging: 1
[  986.785703] st 6:0:3:0: [st1] Rewinding tape.
[  994.642650] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes.
[  994.643219] st 6:0:3:0: [st1] Mode sense. Length 11, medium 0, WBS 10, BLL 8
[  994.643225] st 6:0:3:0: [st1] Density 47, tape length: 0, drv buffer: 1
[  994.643229] st 6:0:3:0: [st1] Block size: 0, buffer size: 4096 (1 blocks).
[  994.643231] st 6:0:3:0: [st1] Updating partition number in status.
[  994.643681] st 6:0:3:0: [st1] Got tape pos. blk 0 part 0.
[  994.643699] st 6:0:3:0: [st1] Loading tape.
[  994.644655] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes.
[  994.644972] st 6:0:3:0: [st1] Mode sense. Length 11, medium 0, WBS 10, BLL 8
[  994.644976] st 6:0:3:0: [st1] Density 47, tape length: 0, drv buffer: 1
[  994.644980] st 6:0:3:0: [st1] Block size: 0, buffer size: 4096 (1 blocks).
[  994.645346] st 6:0:3:0: [st1] Partition page length is 10 bytes.
[  994.645352] st 6:0:3:0: [st1] PP: max 1, add 1, xdp 0, psum 02, pofmetc 0, rec 03, units 00, sizes: 1000 65535
[  994.645356] st 6:0:3:0: [st1] MP: 11 08 01 01 10 03 00 00 03 e8 ff ff
[  994.645359] st 6:0:3:0: [st1] psd_cnt 1, max.parts 1, nbr_parts 1
[  994.645362] st 6:0:3:0: [st1] Formatting tape with two partitions (1 = 1000 MB).
[  994.645366] st 6:0:3:0: [st1] Sent partition page length is 10 bytes. needs_format: 0
[  994.645370] st 6:0:3:0: [st1] PP: max 1, add 1, xdp 1, psum 02, pofmetc 0, rec 03, units 00, sizes: 1000 65535
[  994.645374] st 6:0:3:0: [st1] MP: 11 08 01 01 30 03 00 00 03 e8 ff ff
[ 1372.970312] st 6:0:3:0: [st1] Rewinding tape.

# ./mt -f /dev/st1 status
SCSI 2 tape drive:
File number=0, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x47 (DDS-5 or TR-5).
Soft error count since last status=0
General status bits on (41010000):
 BOT ONLINE IM_REP_EN
# ./mt -f /dev/st1 setpartition 1
# ./mt -f /dev/st1 status
SCSI 2 tape drive:
File number=0, block number=0, partition=1.
Tape block size 0 bytes. Density code 0x47 (DDS-5 or TR-5).
Soft error count since last status=0
General status bits on (41010000):
 BOT ONLINE IM_REP_EN

And since you can only set the size of partition 1 on those drives as expected using a negative size fails:

# ./mt -f /dev/st1 mkpartition -500
/dev/st1: Invalid argument

[ 3937.384419] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes.
[ 3937.384710] st 6:0:3:0: [st1] Mode sense. Length 11, medium 0, WBS 10, BLL 8
[ 3937.384715] st 6:0:3:0: [st1] Density 47, tape length: 0, drv buffer: 1
[ 3937.384718] st 6:0:3:0: [st1] Block size: 0, buffer size: 4096 (1 blocks).
[ 3937.384736] st 6:0:3:0: [st1] Loading tape.
[ 3937.385682] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes.
[ 3937.385983] st 6:0:3:0: [st1] Mode sense. Length 11, medium 0, WBS 10, BLL 8
[ 3937.385988] st 6:0:3:0: [st1] Density 47, tape length: 0, drv buffer: 1
[ 3937.385991] st 6:0:3:0: [st1] Block size: 0, buffer size: 4096 (1 blocks).
[ 3937.386443] st 6:0:3:0: [st1] Partition page length is 10 bytes.
[ 3937.386450] st 6:0:3:0: [st1] PP: max 1, add 1, xdp 0, psum 02, pofmetc 0, rec 03, units 00, sizes: 1000 65535
[ 3937.386455] st 6:0:3:0: [st1] MP: 11 08 01 01 10 03 00 00 03 e8 ff ff
[ 3937.386577] st 6:0:3:0: [st1] Rewinding tape.

As expected LTO3 fails since it cannot be partitioned:

[ 4599.012299] st 5:0:1:0: [st0] Block limits 1 - 16777215 bytes.
[ 4599.014281] st 5:0:1:0: [st0] Mode sense. Length 11, medium 0, WBS 10, BLL 8
[ 4599.014286] st 5:0:1:0: [st0] Density 44, tape length: 0, drv buffer: 1
[ 4599.014290] st 5:0:1:0: [st0] Block size: 0, buffer size: 4096 (1 blocks).
[ 4599.014356] st 5:0:1:0: [st0] Rewinding tape.
[ 4631.811295] st 5:0:1:0: [st0] Block limits 1 - 16777215 bytes.
[ 4631.813313] st 5:0:1:0: [st0] Mode sense. Length 11, medium 0, WBS 10, BLL 8
[ 4631.813318] st 5:0:1:0: [st0] Density 44, tape length: 0, drv buffer: 1
[ 4631.813321] st 5:0:1:0: [st0] Block size: 0, buffer size: 4096 (1 blocks).
[ 4631.813342] st 5:0:1:0: [st0] Mode 0 options: buffer writes: 1, async writes: 1, read ahead: 1
[ 4631.813345] st 5:0:1:0: [st0]     can bsr: 1, two FMs: 0, fast mteom: 0, auto lock: 0,
[ 4631.813348] st 5:0:1:0: [st0]     defs for wr: 0, no block limits: 0, partitions: 1, s2 log: 0
[ 4631.813351] st 5:0:1:0: [st0]     sysv: 0 nowait: 0 sili: 0 nowait_filemark: 0
[ 4631.813354] st 5:0:1:0: [st0]     debugging: 1
[ 4631.813359] st 5:0:1:0: [st0] Rewinding tape.
[ 4648.170712] st 5:0:1:0: [st0] Block limits 1 - 16777215 bytes.
[ 4648.172774] st 5:0:1:0: [st0] Mode sense. Length 11, medium 0, WBS 10, BLL 8
[ 4648.172779] st 5:0:1:0: [st0] Density 44, tape length: 0, drv buffer: 1
[ 4648.172783] st 5:0:1:0: [st0] Block size: 0, buffer size: 4096 (1 blocks).
[ 4648.172786] st 5:0:1:0: [st0] Updating partition number in status.
[ 4648.175584] st 5:0:1:0: [st0] Got tape pos. blk 0 part 0.
[ 4648.175604] st 5:0:1:0: [st0] Loading tape.
[ 4648.209689] st 5:0:1:0: [st0] Block limits 1 - 16777215 bytes.
[ 4648.212799] st 5:0:1:0: [st0] Mode sense. Length 11, medium 0, WBS 10, BLL 8
[ 4648.212804] st 5:0:1:0: [st0] Density 44, tape length: 0, drv buffer: 1
[ 4648.212808] st 5:0:1:0: [st0] Block size: 0, buffer size: 4096 (1 blocks).
[ 4648.215855] st 5:0:1:0: [st0] Partition page length is 10 bytes.
[ 4648.215861] st 5:0:1:0: [st0] PP: max 0, add 0, xdp 0, psum 03, pofmetc 0, rec 03, units 09, sizes: 400 65535
[ 4648.215866] st 5:0:1:0: [st0] MP: 11 08 00 00 18 03 09 00 01 90 ff ff
[ 4648.215869] st 5:0:1:0: [st0] psd_cnt 1, max.parts 0, nbr_parts 0
[ 4648.215872] st 5:0:1:0: [st0] Formatting tape with two partitions (1 = 1000 MB).
[ 4648.215875] st 5:0:1:0: [st0] Sent partition page length is 10 bytes. needs_format: 0
[ 4648.215879] st 5:0:1:0: [st0] PP: max 0, add 1, xdp 1, psum 03, pofmetc 0, rec 03, units 09, sizes: 65535 1
[ 4648.215883] st 5:0:1:0: [st0] MP: 11 08 00 01 38 03 09 00 ff ff 00 01
[ 4648.220140] st 5:0:1:0: [st0] Error: 8000002, cmd: 15 10 0 0 16 0
[ 4648.220145] st 5:0:1:0: [st0] Sense Key : Illegal Request [current]
[ 4648.220149] st 5:0:1:0: [st0] Add. Sense: Invalid field in parameter list
[ 4648.220153] st 5:0:1:0: [st0] Partitioning of tape failed.
[ 4648.220269] st 5:0:1:0: [st0] Rewinding tape.

I'm asking around again one final time to see if I can lay my hands on a LTO5 or greater drive so I can test LTO partitioning as well.

The only other thing I can think of (I'm not sure if this is an improvement or not) is if bp[pgo + PP_OFF_MAX_ADD_PARTS] + bp[pgo + PP_OFF_NBR_ADD_PARTS] (max.parts and nbr_parts in the debug message) is zero just return -EINVAL unless you know of any take drives that report them both as 0 but can be partitioned? That is after this:

        DEBC_printk(STp, "psd_cnt %d, max.parts %d, nbr_parts %d\n",
                    psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],
                    bp[pgo + PP_OFF_NBR_ADD_PARTS]);

add (and also turn off the can-partitions option):

	if ((bp[pgo + PP_OFF_MAX_ADD_PARTS] + bp[pgo + PP_OFF_NBR_ADD_PARTS]) == 0) {
		DEBC_printk(STp, "Drive not partitionable - max.parts+nbr_parts is 0\n");
		STp->can_partitions = 0;
		return -EINVAL;
	}

I'm not especially fussed if you don't want to add that though.

Thanks
Shane

> -----Original Message-----

> From: makisara@kai.makisara.private [mailto:makisara@kai.makisara.private]

> On Behalf Of Kai Makisara

> Sent: Saturday, January 30, 2016 4:22 AM

> To: Seymour, Shane M

> Cc: Laurence Oberman; Emmanuel Florac; Laurence Oberman; linux-

> scsi@vger.kernel.org

> Subject: RE: What partition should the MTMKPART argument specify? Was:

> Re: st driver doesn't seem to grok LTO partitioning

> 

> On Friday 2016-01-29 01:12, Seymour, Shane M wrote:

> 

> >Date: Fri, 29 Jan 2016 01:12:41

> >From: "Seymour, Shane M" <shane.seymour@hpe.com>

> >To: "\"Kai Mäkisara (Kolumbus)\"" <kai.makisara@kolumbus.fi>

> >Cc: Laurence Oberman <loberman@redhat.com>,

> >    Emmanuel Florac <eflorac@intellique.com>,

> >    Laurence Oberman <oberman.l@gmail.com>,

> >    "linux-scsi@vger.kernel.org" <linux-scsi@vger.kernel.org>

> >Subject: RE: What partition should the MTMKPART argument specify? Was:

> Re: st

> >    driver doesn't seem to grok LTO partitioning

> >

> >Hi Kai,

> >

> >$ pwd

> >/sys/class/scsi_tape/st1/device

> >$ cat scsi_level

> >4

> >

> OK. The previous patch set the number of partition size descriptors to

> one for HP DATs only if the SCSI level was <= SCSI_2.

> 

> The patch below uses that logic for all drives that don't need FORMAT

> MEDIUM. For the drives needing FORMAT MEDIUM the value is set to 2.

> These drives include LTOs and other modern drives.

> 

> Thanks, Kai

> ---------------------------------8<----------------------------------

> --- ref/drivers/scsi/st.c	2015-12-21 18:54:05.068882001 +0200

> +++ new/drivers/scsi/st.c	2016-01-29 19:12:06.139738037 +0200

> @@ -9,7 +9,7 @@

>     Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,

>     Michael Schaefer, J"org Weule, and Eric Youngdale.

> 

> -   Copyright 1992 - 2010 Kai Makisara

> +   Copyright 1992 - 2016 Kai Makisara

>     email Kai.Makisara@kolumbus.fi

> 

>     Some small formal changes - aeb, 950809

> @@ -17,7 +17,7 @@

>     Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs

> support

>   */

> 

> -static const char *verstr = "20101219";

> +static const char *verstr = "20160129";

> 

>  #include <linux/module.h>

> 

> @@ -3296,7 +3296,10 @@

>  #define PP_OFF_RESERVED        7

> 

>  #define PP_BIT_IDP             0x20

> +#define PP_BIT_FDP             0x80

>  #define PP_MSK_PSUM_MB         0x10

> +#define PP_MSK_PSUM_UNITS      0x18

> +#define PP_MSK_POFM            0x04

> 

>  /* Get the number of partitions on the tape. As a side effect reads the

>     mode page into the tape buffer. */

> @@ -3322,6 +3325,29 @@

>  }

> 

> 

> +static int format_medium(struct scsi_tape *STp, int format)

> +{

> +	int result = 0;

> +	int timeout = STp->long_timeout;

> +	unsigned char scmd[MAX_COMMAND_SIZE];

> +	struct st_request *SRpnt;

> +

> +	memset(scmd, 0, MAX_COMMAND_SIZE);

> +	scmd[0] = FORMAT_UNIT;

> +	scmd[2] = format;

> +	if (STp->immediate) {

> +		scmd[1] |= 1;		/* Don't wait for completion */

> +		timeout = STp->device->request_queue->rq_timeout;

> +	}

> +	DEBC_printk(STp, "Sending FORMAT MEDIUM\n");

> +	SRpnt = st_do_scsi(NULL, STp, scmd, 0, DMA_NONE,

> +			   timeout, MAX_RETRIES, 1);

> +	if (!SRpnt)

> +		result = STp->buffer->syscall_result;

> +	return result;

> +}

> +

> +

>  /* Partition the tape into two partitions if size > 0 or one partition if

>     size == 0.

> 

> @@ -3340,11 +3366,16 @@

>     and 10 when 1 partition is defined (information from Eric Lee Green). This is

>     is acceptable also to some other old drives and enforced if the first

> partition

>     size field is used for the first additional partition size.

> +

> +   For drives that advertize SCSI-3 or newer, use the SSC-3 methods.

>   */

>  static int partition_tape(struct scsi_tape *STp, int size)

>  {

>  	int result;

> +	int target_partition;

> +	bool scsi3 = STp->device->scsi_level >= SCSI_3, needs_format = false;

>  	int pgo, psd_cnt, psdo;

> +	int psum = PP_MSK_PSUM_MB, units = 0;

>  	unsigned char *bp;

> 

>  	result = read_mode_page(STp, PART_PAGE, 0);

> @@ -3352,16 +3383,72 @@

>  		DEBC_printk(STp, "Can't read partition mode page.\n");

>  		return result;

>  	}

> +	target_partition = 1;

> +	if (size < 0) {

> +		target_partition = 0;

> +		size = -size;

> +	}

> +

>  	/* The mode page is in the buffer. Let's modify it and write it. */

>  	bp = (STp->buffer)->b_data;

>  	pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH];

>  	DEBC_printk(STp, "Partition page length is %d bytes.\n",

>  		    bp[pgo + MP_OFF_PAGE_LENGTH] + 2);

> +	DEBC_printk(STp, "PP: max %u, add %u, xdp %u, psum %02x,

> pofmetc %u, "

> +		    "rec %02x, units %02x, sizes: %u %u\n",

> +		    bp[pgo + PP_OFF_MAX_ADD_PARTS],

> +		    bp[pgo + PP_OFF_NBR_ADD_PARTS],

> +		    (bp[pgo + PP_OFF_FLAGS] & 0xe0) >> 5,

> +		    (bp[pgo + PP_OFF_FLAGS] & 0x18) >> 3,

> +		    bp[pgo + PP_OFF_FLAGS] & 0x07,

> +		    bp[pgo + 5],

> +		    bp[pgo + PP_OFF_PART_UNITS],

> +		    bp[pgo + 8] * 256 + bp[pgo + 9],

> +		    bp[pgo + 10] * 256 + bp[pgo + 11]);

> +	DEBC_printk(STp,

> "MP: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n

> ",

> +		    bp[pgo], bp[pgo+1], bp[pgo+2], bp[pgo+3], bp[pgo+4],

> bp[pgo+5],

> +		    bp[pgo+6], bp[pgo+7], bp[pgo+8], bp[pgo+9], bp[pgo+10],

> bp[pgo+11]);

> 

>  	psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 -

> PART_PAGE_FIXED_LENGTH) / 2;

> +

> +	if (scsi3) {

> +		needs_format = (bp[pgo + PP_OFF_FLAGS] &

> PP_MSK_POFM) != 0;

> +		if (needs_format && size == 0) {

> +			/* No need to write the mode page when clearing

> partitioning */

> +			result = format_medium(STp, 0);

> +			goto out;

> +		}

> +		if (needs_format)  /* Leave the old value for HP DATs

> claiming SCSI_3 */

> +			psd_cnt = 2;

> +		if ((bp[pgo + PP_OFF_FLAGS] & PP_MSK_PSUM_UNITS) ==

> PP_MSK_PSUM_UNITS) {

> +			/* Use units scaling for large partitions if the device

> suggests

> +			   it and no precision lost. Required for IBM TS1140/50

> drives

> +			   that don't support MB units. */

> +			if (size >= 1000 && (size % 1000) == 0) {

> +				size /= 1000;

> +				psum = PP_MSK_PSUM_UNITS;

> +				units = 9; /* GB */

> +			}

> +		}

> +		/* Try it anyway if too large to specify in MB */

> +		if (psum == PP_MSK_PSUM_MB && size >= 65534) {

> +				size /= 1000;

> +				psum = PP_MSK_PSUM_UNITS;

> +				units = 9;  /* GB */

> +		}

> +	}

> +

> +	if (size >= 65535 ||  /* Does not fit into two bytes */

> +	    (target_partition == 0 && psd_cnt < 2)) {

> +		result = -EINVAL;

> +		goto out;

> +	}

> +

>  	psdo = pgo + PART_PAGE_FIXED_LENGTH;

> -	if (psd_cnt > bp[pgo + PP_OFF_MAX_ADD_PARTS]) {

> -		bp[psdo] = bp[psdo + 1] = 0xff;  /* Rest of the tape */

> +	/* The second condition is for HP DDS which use only one partition

> size

> +	   descriptor */

> +	if (target_partition > 0 && psd_cnt > bp[pgo +

> PP_OFF_MAX_ADD_PARTS]) {

> +		bp[psdo] = bp[psdo + 1] = 0xff;  /* Rest of the tape to

> partition 0 */

>  		psdo += 2;

>  	}

>  	memset(bp + psdo, 0, bp[pgo + PP_OFF_NBR_ADD_PARTS] * 2);

> @@ -3370,7 +3457,7 @@

>  		    psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],

>  		    bp[pgo + PP_OFF_NBR_ADD_PARTS]);

> 

> -	if (size <= 0) {

> +	if (size == 0) {

>  		bp[pgo + PP_OFF_NBR_ADD_PARTS] = 0;

>  		if (psd_cnt <= bp[pgo + PP_OFF_MAX_ADD_PARTS])

>  		    bp[pgo + MP_OFF_PAGE_LENGTH] = 6;

> @@ -3378,22 +3465,54 @@

>  	} else {

>  		bp[psdo] = (size >> 8) & 0xff;

>  		bp[psdo + 1] = size & 0xff;

> +		if (target_partition == 0)

> +			bp[psdo + 2] = bp[psdo + 3] = 0xff;

>  		bp[pgo + 3] = 1;

>  		if (bp[pgo + MP_OFF_PAGE_LENGTH] < 8)

>  		    bp[pgo + MP_OFF_PAGE_LENGTH] = 8;

>  		DEBC_printk(STp, "Formatting tape with two partitions "

> -			    "(1 = %d MB).\n", size);

> +			    "(1 = %d MB).\n",

> +			    units > 0 ? size * 1000 : size);

>  	}

>  	bp[pgo + PP_OFF_PART_UNITS] = 0;

>  	bp[pgo + PP_OFF_RESERVED] = 0;

> -	bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | PP_MSK_PSUM_MB;

> +	if (size != 1 || units != 0) {

> +		bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | psum |

> +			(bp[pgo + PP_OFF_FLAGS] & 0x07);

> +		bp[pgo + PP_OFF_PART_UNITS] = units;

> +	} else

> +		bp[pgo + PP_OFF_FLAGS] = PP_BIT_FDP |

> +			(bp[pgo + PP_OFF_FLAGS] & 0x1f);

> +	bp[pgo + MP_OFF_PAGE_LENGTH] = 6 + psd_cnt * 2;

> +

> +	DEBC_printk(STp, "Sent partition page length is %d bytes.

> needs_format: %d\n",

> +		    bp[pgo + MP_OFF_PAGE_LENGTH] + 2, needs_format);

> +	DEBC_printk(STp, "PP: max %u, add %u, xdp %u, psum %02x,

> pofmetc %u, "

> +		    "rec %02x, units %02x, sizes: %u %u\n",

> +		    bp[pgo + PP_OFF_MAX_ADD_PARTS],

> +		    bp[pgo + PP_OFF_NBR_ADD_PARTS],

> +		    (bp[pgo + PP_OFF_FLAGS] & 0xe0) >> 5,

> +		    (bp[pgo + PP_OFF_FLAGS] & 0x18) >> 3,

> +		    bp[pgo + PP_OFF_FLAGS] & 0x07,

> +		    bp[pgo + 5],

> +		    bp[pgo + PP_OFF_PART_UNITS],

> +		    bp[pgo + 8] * 256 + bp[pgo + 9],

> +		    bp[pgo + 10] * 256 + bp[pgo + 11]);

> +	DEBC_printk(STp,

> "MP: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n

> ",

> +		    bp[pgo], bp[pgo+1], bp[pgo+2], bp[pgo+3], bp[pgo+4],

> bp[pgo+5],

> +		    bp[pgo+6], bp[pgo+7], bp[pgo+8], bp[pgo+9], bp[pgo+10],

> bp[pgo+11]);

> 

>  	result = write_mode_page(STp, PART_PAGE, 1);

> +

> +	if (!result && needs_format)

> +		result = format_medium(STp, 1);

> +

>  	if (result) {

>  		st_printk(KERN_INFO, STp, "Partitioning of tape failed.\n");

>  		result = (-EIO);

>  	}

> 

> +out:

>  	return result;

>  }

>  


> @@ -3570,7 +3689,7 @@

>  				retval = (-EINVAL);

>  				goto out;

>  			}

> -			if ((i = st_int_ioctl(STp, MTREW, 0)) < 0 ||

> +			if ((i = do_load_unload(STp, file, 1)) < 0 ||

>  			    (i = partition_tape(STp, mtc.mt_count)) < 0) {

>  				retval = i;

>  				goto out;

> @@ -3581,7 +3700,7 @@

>  				STp->ps[i].last_block_valid = 0;

>  			}

>  			STp->partition = STp->new_partition = 0;

> -			STp->nbr_partitions = 1;	/* Bad guess ?-) */

> +			STp->nbr_partitions = mtc.mt_count > 0 ? 2 : 1;

>  			STps->drv_block = STps->drv_file = 0;

>  			retval = 0;

>  			goto out;
Kai Mäkisara (Kolumbus) Feb. 1, 2016, 6:43 p.m. UTC | #2
> On 1.2.2016, at 8.31, Seymour, Shane M <shane.seymour@hpe.com> wrote:
> 
> Hi Kai,
> 
> Thanks for the changes the HPE DAT72 DDS5 drive now works as expected:
> 
Good. Thanks for testing.

...
> 
> I'm asking around again one final time to see if I can lay my hands on a LTO5 or greater drive so I can test LTO partitioning as well.
> 
> The only other thing I can think of (I'm not sure if this is an improvement or not) is if bp[pgo + PP_OFF_MAX_ADD_PARTS] + bp[pgo + PP_OFF_NBR_ADD_PARTS] (max.parts and nbr_parts in the debug message) is zero just return -EINVAL unless you know of any take drives that report them both as 0 but can be partitioned? That is after this:
> 
>        DEBC_printk(STp, "psd_cnt %d, max.parts %d, nbr_parts %d\n",
>                    psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],
>                    bp[pgo + PP_OFF_NBR_ADD_PARTS]);
> 
> add (and also turn off the can-partitions option):
> 
> 	if ((bp[pgo + PP_OFF_MAX_ADD_PARTS] + bp[pgo + PP_OFF_NBR_ADD_PARTS]) == 0) {
> 		DEBC_printk(STp, "Drive not partitionable - max.parts+nbr_parts is 0\n");
> 		STp->can_partitions = 0;
> 		return -EINVAL;
> 	}
> 
> I'm not especially fussed if you don't want to add that though.
> 
I thought about a test like this (only test maximum number) but decided not to add it. The reason was that
I did not want to change anything that has worked before. I quite trust that the current drives return sense
data instead of crashing and the end result for the user would be the same. However, one can argue that
returning EINVAL is better than EIO but does the user notice? If the common opinion is that a test like this
should be added, I am not against it. It can be added to the code for SCSI >=3 where it does not risk
anything for the old drives.

IMHO, can_partitions should not be cleared based on the test. For example, trying to partition a LTO-4 tape
in a LTO-5 drive should not disable partitioning. (The mode page should return zero as maximum number of
partitions when a LTO-4 tape is inserted.)

Thanks,
Kai

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Laurence Oberman Feb. 1, 2016, 7:02 p.m. UTC | #3
The new patch did not work for me, but I chatted with Shane and I have his mt version. 
I will update my DAT to same firmware or newer than his and provide a second tested by.
I also expect my LTO5 to show up this week so will be ready for that.

Thanks everyone for keeping tapes alive

Laurence Oberman
Principal Software Maintenance Engineer
Red Hat Global Support Services

----- Original Message -----
From: "Kai Mäkisara (Kolumbus)" <kai.makisara@kolumbus.fi>
To: "Shane M Seymour" <shane.seymour@hpe.com>
Cc: "Laurence Oberman" <loberman@redhat.com>, "Emmanuel Florac" <eflorac@intellique.com>, "Laurence Oberman" <oberman.l@gmail.com>, linux-scsi@vger.kernel.org
Sent: Monday, February 1, 2016 1:43:26 PM
Subject: Re: What partition should the MTMKPART argument specify? Was: Re: st driver doesn't seem to grok LTO partitioning


> On 1.2.2016, at 8.31, Seymour, Shane M <shane.seymour@hpe.com> wrote:
> 
> Hi Kai,
> 
> Thanks for the changes the HPE DAT72 DDS5 drive now works as expected:
> 
Good. Thanks for testing.

...
> 
> I'm asking around again one final time to see if I can lay my hands on a LTO5 or greater drive so I can test LTO partitioning as well.
> 
> The only other thing I can think of (I'm not sure if this is an improvement or not) is if bp[pgo + PP_OFF_MAX_ADD_PARTS] + bp[pgo + PP_OFF_NBR_ADD_PARTS] (max.parts and nbr_parts in the debug message) is zero just return -EINVAL unless you know of any take drives that report them both as 0 but can be partitioned? That is after this:
> 
>        DEBC_printk(STp, "psd_cnt %d, max.parts %d, nbr_parts %d\n",
>                    psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],
>                    bp[pgo + PP_OFF_NBR_ADD_PARTS]);
> 
> add (and also turn off the can-partitions option):
> 
> 	if ((bp[pgo + PP_OFF_MAX_ADD_PARTS] + bp[pgo + PP_OFF_NBR_ADD_PARTS]) == 0) {
> 		DEBC_printk(STp, "Drive not partitionable - max.parts+nbr_parts is 0\n");
> 		STp->can_partitions = 0;
> 		return -EINVAL;
> 	}
> 
> I'm not especially fussed if you don't want to add that though.
> 
I thought about a test like this (only test maximum number) but decided not to add it. The reason was that
I did not want to change anything that has worked before. I quite trust that the current drives return sense
data instead of crashing and the end result for the user would be the same. However, one can argue that
returning EINVAL is better than EIO but does the user notice? If the common opinion is that a test like this
should be added, I am not against it. It can be added to the code for SCSI >=3 where it does not risk
anything for the old drives.

IMHO, can_partitions should not be cleared based on the test. For example, trying to partition a LTO-4 tape
in a LTO-5 drive should not disable partitioning. (The mode page should return zero as maximum number of
partitions when a LTO-4 tape is inserted.)

Thanks,
Kai

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Seymour, Shane M Feb. 1, 2016, 10:59 p.m. UTC | #4
Hi Kai,

> -----Original Message-----
> From: linux-scsi-owner@vger.kernel.org [mailto:linux-scsi-
> owner@vger.kernel.org] On Behalf Of "Kai Mäkisara (Kolumbus)"
> Sent: Tuesday, February 02, 2016 5:43 AM
> To: Seymour, Shane M
> Cc: Laurence Oberman; Emmanuel Florac; Laurence Oberman; linux-
> scsi@vger.kernel.org
> Subject: Re: What partition should the MTMKPART argument specify? Was:
> Re: st driver doesn't seem to grok LTO partitioning
> 
> 
> > On 1.2.2016, at 8.31, Seymour, Shane M <shane.seymour@hpe.com>
> wrote:
> >
> > Hi Kai,
> >
> > Thanks for the changes the HPE DAT72 DDS5 drive now works as expected:
> >
> Good. Thanks for testing.
> 
> ...
> >
> > I'm asking around again one final time to see if I can lay my hands on a LTO5
> or greater drive so I can test LTO partitioning as well.
> >
> > The only other thing I can think of (I'm not sure if this is an improvement or
> not) is if bp[pgo + PP_OFF_MAX_ADD_PARTS] + bp[pgo +
> PP_OFF_NBR_ADD_PARTS] (max.parts and nbr_parts in the debug message)
> is zero just return -EINVAL unless you know of any take drives that report
> them both as 0 but can be partitioned? That is after this:
> >
> >        DEBC_printk(STp, "psd_cnt %d, max.parts %d, nbr_parts %d\n",
> >                    psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],
> >                    bp[pgo + PP_OFF_NBR_ADD_PARTS]);
> >
> > add (and also turn off the can-partitions option):
> >
> > 	if ((bp[pgo + PP_OFF_MAX_ADD_PARTS] + bp[pgo +
> PP_OFF_NBR_ADD_PARTS]) == 0) {
> > 		DEBC_printk(STp, "Drive not partitionable -
> max.parts+nbr_parts is 0\n");
> > 		STp->can_partitions = 0;
> > 		return -EINVAL;
> > 	}
> >
> > I'm not especially fussed if you don't want to add that though.
> >
> I thought about a test like this (only test maximum number) but decided not
> to add it. The reason was that I did not want to change anything that has
> worked before. I quite trust that the current drives return sense data instead
> of crashing and the end result for the user would be the same. However, one
> can argue that returning EINVAL is better than EIO but does the user notice?
> If the common opinion is that a test like this should be added, I am not
> against it. It can be added to the code for SCSI >=3 where it does not risk
> anything for the old drives.
> 
> IMHO, can_partitions should not be cleared based on the test. For example,
> trying to partition a LTO-4 tape in a LTO-5 drive should not disable partitioning.
> (The mode page should return zero as maximum number of partitions when
> a LTO-4 tape is inserted.)

No problem, I didn't think of the case where you have a non-partitionable tape in
a drive that can do partitions. That case should have been obvious to me.

I may be able to lay my hands on a LTO5+ drive (only a small chance). Someone in
the US is checking is checking for me and will hook it up to the system I use for
testing tape stuff for me. I'll only have it for about a week if I'm able to get it.

Thanks
Shane

> 
> Thanks,
> Kai
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the
> body of a message to majordomo@vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Seymour, Shane M Feb. 3, 2016, 2:18 a.m. UTC | #5
SGkgS2FpLA0KDQpJJ3ZlIGRvbmUgbW9yZSB0ZXN0ZWQuIFNvbWUgc3R1ZmYgZGlkbid0IHdvcmsg
YW5kIEkndmUgZ290IHNvbWUgc3VnZ2VzdGVkIGNoYW5nZXMgKHRoZXJlIGFyZSB0d28gY2hhbmdl
cyB0byB0aGUgcGF0Y2ggYW5kIG9uZSBmb3IgdGhlIG10IGNvbW1hbmQpLiBUZXN0aW5nIHJlc3Vs
dHMgZmlyc3Q6DQoNCiMgZWNobyAxID4gL3N5cy9idXMvc2NzaS9kcml2ZXJzL3N0L2RlYnVnX2Zs
YWcNCiMgbXQgLWYgL2Rldi9zdDIgc3RzZXRvcHRpb24gY2FuLXBhcnRpdGlvbnMNCiMgbXQgLWYg
L2Rldi9zdDEgc3RzZXRvcHRpb24gY2FuLXBhcnRpdGlvbnMNCiMgbXQgLWYgL2Rldi9zdDAgc3Rz
ZXRvcHRpb24gY2FuLXBhcnRpdGlvbnMNCg0KRXhwZWN0IHRvIGZhaWwgTFRPMzoNCg0KIyBtdCAt
ZiAvZGV2L3N0MCBta3BhcnRpdGlvbiA1MDANCi9kZXYvc3QwOiBJbnB1dC9vdXRwdXQgZXJyb3IN
Cg0KWyAzMTk3LjkwMTU4M10gc3QgNTowOjE6MDogW3N0MF0gQmxvY2sgbGltaXRzIDEgLSAxNjc3
NzIxNSBieXRlcy4NClsgMzE5Ny45MDM2MTNdIHN0IDU6MDoxOjA6IFtzdDBdIE1vZGUgc2Vuc2Uu
IExlbmd0aCAxMSwgbWVkaXVtIDAsIFdCUyAxMCwgQkxMIDgNClsgMzE5Ny45MDM2MThdIHN0IDU6
MDoxOjA6IFtzdDBdIERlbnNpdHkgNDQsIHRhcGUgbGVuZ3RoOiAwLCBkcnYgYnVmZmVyOiAxDQpb
IDMxOTcuOTAzNjIyXSBzdCA1OjA6MTowOiBbc3QwXSBCbG9jayBzaXplOiAwLCBidWZmZXIgc2l6
ZTogNDA5NiAoMSBibG9ja3MpLg0KWyAzMTk3LjkwMzYyNV0gc3QgNTowOjE6MDogW3N0MF0gVXBk
YXRpbmcgcGFydGl0aW9uIG51bWJlciBpbiBzdGF0dXMuDQpbIDMxOTcuOTA2NDA2XSBzdCA1OjA6
MTowOiBbc3QwXSBHb3QgdGFwZSBwb3MuIGJsayAwIHBhcnQgMC4NClsgMzE5Ny45MDY0MjldIHN0
IDU6MDoxOjA6IFtzdDBdIExvYWRpbmcgdGFwZS4NClsgMzE5Ny45Mjk0ODRdIHN0IDU6MDoxOjA6
IFtzdDBdIEJsb2NrIGxpbWl0cyAxIC0gMTY3NzcyMTUgYnl0ZXMuDQpbIDMxOTcuOTMxNTE4XSBz
dCA1OjA6MTowOiBbc3QwXSBNb2RlIHNlbnNlLiBMZW5ndGggMTEsIG1lZGl1bSAwLCBXQlMgMTAs
IEJMTCA4DQpbIDMxOTcuOTMxNTI0XSBzdCA1OjA6MTowOiBbc3QwXSBEZW5zaXR5IDQ0LCB0YXBl
IGxlbmd0aDogMCwgZHJ2IGJ1ZmZlcjogMQ0KWyAzMTk3LjkzMTUyN10gc3QgNTowOjE6MDogW3N0
MF0gQmxvY2sgc2l6ZTogMCwgYnVmZmVyIHNpemU6IDQwOTYgKDEgYmxvY2tzKS4NClsgMzE5Ny45
MzM4NDBdIHN0IDU6MDoxOjA6IFtzdDBdIFBhcnRpdGlvbiBwYWdlIGxlbmd0aCBpcyAxMCBieXRl
cy4NClsgMzE5Ny45MzM4NDZdIHN0IDU6MDoxOjA6IFtzdDBdIFBQOiBtYXggMCwgYWRkIDAsIHhk
cCAwLCBwc3VtIDAzLCBwb2ZtZXRjIDAsIHJlYyAwMywgdW5pdHMgMDksIHNpemVzOiA0MDAgNjU1
MzUNClsgMzE5Ny45MzM4NTFdIHN0IDU6MDoxOjA6IFtzdDBdIE1QOiAxMSAwOCAwMCAwMCAxOCAw
MyAwOSAwMCAwMSA5MCBmZiBmZg0KWyAzMTk3LjkzMzg1NF0gc3QgNTowOjE6MDogW3N0MF0gcHNk
X2NudCAxLCBtYXgucGFydHMgMCwgbmJyX3BhcnRzIDANClsgMzE5Ny45MzM4NTddIHN0IDU6MDox
OjA6IFtzdDBdIEZvcm1hdHRpbmcgdGFwZSB3aXRoIHR3byBwYXJ0aXRpb25zICgxID0gNTAwIE1C
KS4NClsgMzE5Ny45MzM4NjBdIHN0IDU6MDoxOjA6IFtzdDBdIFNlbnQgcGFydGl0aW9uIHBhZ2Ug
bGVuZ3RoIGlzIDEwIGJ5dGVzLiBuZWVkc19mb3JtYXQ6IDANClsgMzE5Ny45MzM4NjVdIHN0IDU6
MDoxOjA6IFtzdDBdIFBQOiBtYXggMCwgYWRkIDEsIHhkcCAxLCBwc3VtIDAyLCBwb2ZtZXRjIDAs
IHJlYyAwMywgdW5pdHMgMDAsIHNpemVzOiA2NTUzNSA1MDANClsgMzE5Ny45MzM4NjldIHN0IDU6
MDoxOjA6IFtzdDBdIE1QOiAxMSAwOCAwMCAwMSAzMCAwMyAwMCAwMCBmZiBmZiAwMSBmNA0KWyAz
MTk3LjkzNzcwNl0gc3QgNTowOjE6MDogW3N0MF0gRXJyb3I6IDgwMDAwMDIsIGNtZDogMTUgMTAg
MCAwIDE2IDANClsgMzE5Ny45Mzc3MTJdIHN0IDU6MDoxOjA6IFtzdDBdIFNlbnNlIEtleSA6IEls
bGVnYWwgUmVxdWVzdCBbY3VycmVudF0NClsgMzE5Ny45Mzc3MTZdIHN0IDU6MDoxOjA6IFtzdDBd
IEFkZC4gU2Vuc2U6IEludmFsaWQgZmllbGQgaW4gcGFyYW1ldGVyIGxpc3QNClsgMzE5Ny45Mzc3
MTldIHN0IDU6MDoxOjA6IFtzdDBdIFBhcnRpdGlvbmluZyBvZiB0YXBlIGZhaWxlZC4NClsgMzE5
Ny45Mzc4NDddIHN0IDU6MDoxOjA6IFtzdDBdIFJld2luZGluZyB0YXBlLg0KDQpXb3JrcyBERFM1
Og0KDQojIG10IC1mIC9kZXYvc3QxIG1rcGFydGl0aW9uIDUwMA0KDQpbIDMyNDEuMzU1NDc0XSBz
dCA2OjA6MzowOiBbc3QxXSBCbG9jayBsaW1pdHMgMSAtIDE2Nzc3MjE1IGJ5dGVzLg0KWyAzMjQx
LjM1NTc3NV0gc3QgNjowOjM6MDogW3N0MV0gTW9kZSBzZW5zZS4gTGVuZ3RoIDExLCBtZWRpdW0g
MCwgV0JTIDEwLCBCTEwgOA0KWyAzMjQxLjM1NTc3OV0gc3QgNjowOjM6MDogW3N0MV0gRGVuc2l0
eSA0NywgdGFwZSBsZW5ndGg6IDAsIGRydiBidWZmZXI6IDENClsgMzI0MS4zNTU3ODNdIHN0IDY6
MDozOjA6IFtzdDFdIEJsb2NrIHNpemU6IDAsIGJ1ZmZlciBzaXplOiA0MDk2ICgxIGJsb2Nrcyku
DQpbIDMyNDEuMzU1Nzg1XSBzdCA2OjA6MzowOiBbc3QxXSBVcGRhdGluZyBwYXJ0aXRpb24gbnVt
YmVyIGluIHN0YXR1cy4NClsgMzI0MS4zNTYzODVdIHN0IDY6MDozOjA6IFtzdDFdIEdvdCB0YXBl
IHBvcy4gYmxrIDAgcGFydCAwLg0KWyAzMjQxLjM1NjM5N10gc3QgNjowOjM6MDogW3N0MV0gTG9h
ZGluZyB0YXBlLg0KWyAzMjQxLjM1NzI0OV0gc3QgNjowOjM6MDogW3N0MV0gQmxvY2sgbGltaXRz
IDEgLSAxNjc3NzIxNSBieXRlcy4NClsgMzI0MS4zNTc1NDBdIHN0IDY6MDozOjA6IFtzdDFdIE1v
ZGUgc2Vuc2UuIExlbmd0aCAxMSwgbWVkaXVtIDAsIFdCUyAxMCwgQkxMIDgNClsgMzI0MS4zNTc1
NDRdIHN0IDY6MDozOjA6IFtzdDFdIERlbnNpdHkgNDcsIHRhcGUgbGVuZ3RoOiAwLCBkcnYgYnVm
ZmVyOiAxDQpbIDMyNDEuMzU3NTQ3XSBzdCA2OjA6MzowOiBbc3QxXSBCbG9jayBzaXplOiAwLCBi
dWZmZXIgc2l6ZTogNDA5NiAoMSBibG9ja3MpLg0KWyAzMjQxLjM1Nzg4Ml0gc3QgNjowOjM6MDog
W3N0MV0gUGFydGl0aW9uIHBhZ2UgbGVuZ3RoIGlzIDEwIGJ5dGVzLg0KWyAzMjQxLjM1Nzg4N10g
c3QgNjowOjM6MDogW3N0MV0gUFA6IG1heCAxLCBhZGQgMSwgeGRwIDAsIHBzdW0gMDIsIHBvZm1l
dGMgMCwgcmVjIDAzLCB1bml0cyAwMCwgc2l6ZXM6IDUwMCA2NTUzNQ0KWyAzMjQxLjM1Nzg5Ml0g
c3QgNjowOjM6MDogW3N0MV0gTVA6IDExIDA4IDAxIDAxIDEwIDAzIDAwIDAwIDAxIGY0IGZmIGZm
DQpbIDMyNDEuMzU3ODk1XSBzdCA2OjA6MzowOiBbc3QxXSBwc2RfY250IDEsIG1heC5wYXJ0cyAx
LCBuYnJfcGFydHMgMQ0KWyAzMjQxLjM1Nzg5OF0gc3QgNjowOjM6MDogW3N0MV0gRm9ybWF0dGlu
ZyB0YXBlIHdpdGggdHdvIHBhcnRpdGlvbnMgKDEgPSA1MDAgTUIpLg0KWyAzMjQxLjM1NzkwMV0g
c3QgNjowOjM6MDogW3N0MV0gU2VudCBwYXJ0aXRpb24gcGFnZSBsZW5ndGggaXMgMTAgYnl0ZXMu
IG5lZWRzX2Zvcm1hdDogMA0KWyAzMjQxLjM1NzkwNl0gc3QgNjowOjM6MDogW3N0MV0gUFA6IG1h
eCAxLCBhZGQgMSwgeGRwIDEsIHBzdW0gMDIsIHBvZm1ldGMgMCwgcmVjIDAzLCB1bml0cyAwMCwg
c2l6ZXM6IDUwMCA2NTUzNQ0KWyAzMjQxLjM1NzkxMF0gc3QgNjowOjM6MDogW3N0MV0gTVA6IDEx
IDA4IDAxIDAxIDMwIDAzIDAwIDAwIDAxIGY0IGZmIGZmDQpbIDM0NjQuNzIxMDU4XSBzdCA2OjA6
MzowOiBbc3QxXSBSZXdpbmRpbmcgdGFwZS4NCg0KIyBtdCAtZiAvZGV2L3N0MiBta3BhcnRpdGlv
biAyMDBHDQoNCkZhaWxzIGFuZCBkb2Vzbid0IHByaW50IGFsbCBvZiB0aGUgbWVzc2FnZXMgcmVs
YXRlZCBmb3IgcGFydGl0aW9uaW5nOg0KDQpbIDM1MTQuMzA2NTgyXSBzdCA4OjA6MDowOiBbc3Qy
XSBCbG9jayBsaW1pdHMgMSAtIDE2Nzc3MjE1IGJ5dGVzLg0KWyAzNTE0LjMwNzEyNl0gc3QgODow
OjA6MDogW3N0Ml0gTW9kZSBzZW5zZS4gTGVuZ3RoIDExLCBtZWRpdW0gMCwgV0JTIDEwLCBCTEwg
OA0KWyAzNTE0LjMwNzEyOV0gc3QgODowOjA6MDogW3N0Ml0gRGVuc2l0eSA1YSwgdGFwZSBsZW5n
dGg6IDAsIGRydiBidWZmZXI6IDENClsgMzUxNC4zMDcxMzJdIHN0IDg6MDowOjA6IFtzdDJdIEJs
b2NrIHNpemU6IDAsIGJ1ZmZlciBzaXplOiA0MDk2ICgxIGJsb2NrcykuDQpbIDM1MTQuMzA3MTMz
XSBzdCA4OjA6MDowOiBbc3QyXSBVcGRhdGluZyBwYXJ0aXRpb24gbnVtYmVyIGluIHN0YXR1cy4N
ClsgMzUxNC4zMDgxMzNdIHN0IDg6MDowOjA6IFtzdDJdIEdvdCB0YXBlIHBvcy4gYmxrIDAgcGFy
dCAwLg0KWyAzNTE0LjMwODE1OV0gc3QgODowOjA6MDogW3N0Ml0gTG9hZGluZyB0YXBlLg0KWyAz
NTE0LjMyMzE3M10gc3QgODowOjA6MDogW3N0Ml0gQmxvY2sgbGltaXRzIDEgLSAxNjc3NzIxNSBi
eXRlcy4NClsgMzUxNC4zMjM2MjRdIHN0IDg6MDowOjA6IFtzdDJdIE1vZGUgc2Vuc2UuIExlbmd0
aCAxMSwgbWVkaXVtIDAsIFdCUyAxMCwgQkxMIDgNClsgMzUxNC4zMjM2MjhdIHN0IDg6MDowOjA6
IFtzdDJdIERlbnNpdHkgNWEsIHRhcGUgbGVuZ3RoOiAwLCBkcnYgYnVmZmVyOiAxDQpbIDM1MTQu
MzIzNjMyXSBzdCA4OjA6MDowOiBbc3QyXSBCbG9jayBzaXplOiAwLCBidWZmZXIgc2l6ZTogNDA5
NiAoMSBibG9ja3MpLg0KWyAzNTE0LjMyNDUwN10gc3QgODowOjA6MDogW3N0Ml0gUGFydGl0aW9u
IHBhZ2UgbGVuZ3RoIGlzIDE2IGJ5dGVzLg0KWyAzNTE0LjMyNDUxM10gc3QgODowOjA6MDogW3N0
Ml0gUFA6IG1heCAzLCBhZGQgMCwgeGRwIDEsIHBzdW0gMDMsIHBvZm1ldGMgNCwgcmVjIDAzLCB1
bml0cyAwOSwgc2l6ZXM6IDI2MjAgMA0KWyAzNTE0LjMyNDUxOF0gc3QgODowOjA6MDogW3N0Ml0g
TVA6IDExIDBlIDAzIDAwIDNjIDAzIDA5IDAwIDBhIDNjIDAwIDAwDQpbIDM1MTQuMzI0NTIxXSBz
dCA4OjA6MDowOiBbc3QyXSBTZW5kaW5nIEZPUk1BVCBNRURJVU0NClsgMzUxOS4wOTcxNDJdIHN0
IDg6MDowOjA6IFtzdDJdIFJld2luZGluZyB0YXBlLg0KDQpUaGUgb25seSB3YXkgdGhhdCBjYW4g
aGFwcGVuIGlzIGlmIGl0IHRoaW5rcyBpdCBzaG91bGQgYmUgY2xlYXJpbmcgdGhlIHBhcnRpdGlv
bnMgaW4gdGhpcyBjb2RlOg0KDQogICAgICAgIGlmIChzY3NpMykgew0KICAgICAgICAgICAgICAg
IG5lZWRzX2Zvcm1hdCA9IChicFtwZ28gKyBQUF9PRkZfRkxBR1NdICYgUFBfTVNLX1BPRk0pICE9
IDA7DQogICAgICAgICAgICAgICAgaWYgKG5lZWRzX2Zvcm1hdCAmJiBzaXplID09IDApIHsNCiAg
ICAgICAgICAgICAgICAgICAgICAgIC8qIE5vIG5lZWQgdG8gd3JpdGUgdGhlIG1vZGUgcGFnZSB3
aGVuIGNsZWFyaW5nIHBhcnRpdGlvbmluZyAqLw0KICAgICAgICAgICAgICAgICAgICAgICAgcmVz
dWx0ID0gZm9ybWF0X21lZGl1bShTVHAsIDApOw0KICAgICAgICAgICAgICAgICAgICAgICAgZ290
byBvdXQ7DQogICAgICAgICAgICAgICAgfQ0KDQpTaW5jZSB3ZSBjYW4gZm9ybWF0IGFuZCBleGl0
IGJ5IGp1bWluZyB0byBvdXQgaGVyZSB3ZSBwcm9iYWJseSBuZWVkIHRoaXMgaW4gdGhlcmUgYXMg
d2VsbCBiZWZvcmUgdGhlIGdvdG86DQoNCgkJREVCQ19wcmludGsoU1RwLCAiRm9ybWF0dGluZyB0
YXBlIHdpdGggb25lIHBhcnRpdGlvbi5cbiIpOw0KDQpTb21ldGhpbmcgYXBwZWFycyB0byBoYXZl
IGRyb3BwZWQgdGhlIHNpemUgdG8gYmUgemVyby4gU2hvdWxkIHRoZSBtdCBjb21tYW5kIGluIG10
LXN0IHJlamVjdCBhbnl0aGluZyB0aGF0IGNvdWxkIGJlY29tZSB6ZXJvIHdpdGggYW4gZXJyb3I/
IEkgaGF2ZW4ndCBsb29rZWQgYXQgdGhlIGNvbW1hbmQgdG8gc2VlIHdoeSBpdCBkcm9wcGVkIHRo
ZSB2YWx1ZSB0byAwIChJIGFtIGFzc3VtaW5nIHRoYXQncyB3aGVyZSBpdCBoYXBwZW5lZCkuIFRo
ZXJlIHNob3VsZCBwcm9iYWJseSBiZSBhbiBlcnJvciBvciBzb21ldGhpbmcgcHJpbnRlZCBvdGhl
cndpc2Ugc29tZW9uZSB3aWxsIGFzc3VtZSB0aGF0IHRoZSBwYXJ0aXRpb25pbmcgd29ya2VkIHN1
Y2Nlc3NmdWxseSB3aGVuIGluIGZhY3QgdGhlIHBhcnRpdGlvbnMgd2VyZSBjbGVhcmVkLg0KDQpJ
ZiBpbnN0ZWFkIEkgYXNrIGZvciAyMDAgaW5zdGVhZCBvZiAyMDBHIEkgZ2V0IHRoZSBmb2xsb3dp
bmc6DQoNClsgMzg3NS41ODgwMDZdIHN0IDg6MDowOjA6IFtzdDJdIEJsb2NrIGxpbWl0cyAxIC0g
MTY3NzcyMTUgYnl0ZXMuDQpbIDM4NzUuNTg4NjE3XSBzdCA4OjA6MDowOiBbc3QyXSBNb2RlIHNl
bnNlLiBMZW5ndGggMTEsIG1lZGl1bSAwLCBXQlMgMTAsIEJMTCA4DQpbIDM4NzUuNTg4NjIwXSBz
dCA4OjA6MDowOiBbc3QyXSBEZW5zaXR5IDVhLCB0YXBlIGxlbmd0aDogMCwgZHJ2IGJ1ZmZlcjog
MQ0KWyAzODc1LjU4ODYyMl0gc3QgODowOjA6MDogW3N0Ml0gQmxvY2sgc2l6ZTogMCwgYnVmZmVy
IHNpemU6IDQwOTYgKDEgYmxvY2tzKS4NClsgMzg3NS41ODg2MzhdIHN0IDg6MDowOjA6IFtzdDJd
IExvYWRpbmcgdGFwZS4NClsgMzg3NS42MDM2NTldIHN0IDg6MDowOjA6IFtzdDJdIEJsb2NrIGxp
bWl0cyAxIC0gMTY3NzcyMTUgYnl0ZXMuDQpbIDM4NzUuNjA0MTEzXSBzdCA4OjA6MDowOiBbc3Qy
XSBNb2RlIHNlbnNlLiBMZW5ndGggMTEsIG1lZGl1bSAwLCBXQlMgMTAsIEJMTCA4DQpbIDM4NzUu
NjA0MTE3XSBzdCA4OjA6MDowOiBbc3QyXSBEZW5zaXR5IDVhLCB0YXBlIGxlbmd0aDogMCwgZHJ2
IGJ1ZmZlcjogMQ0KWyAzODc1LjYwNDEyMV0gc3QgODowOjA6MDogW3N0Ml0gQmxvY2sgc2l6ZTog
MCwgYnVmZmVyIHNpemU6IDQwOTYgKDEgYmxvY2tzKS4NClsgMzg3NS42MDUwNTJdIHN0IDg6MDow
OjA6IFtzdDJdIFBhcnRpdGlvbiBwYWdlIGxlbmd0aCBpcyAxNiBieXRlcy4NClsgMzg3NS42MDUw
NThdIHN0IDg6MDowOjA6IFtzdDJdIFBQOiBtYXggMywgYWRkIDAsIHhkcCAxLCBwc3VtIDAzLCBw
b2ZtZXRjIDQsIHJlYyAwMywgdW5pdHMgMDksIHNpemVzOiAyNjIwIDANClsgMzg3NS42MDUwNjNd
IHN0IDg6MDowOjA6IFtzdDJdIE1QOiAxMSAwZSAwMyAwMCAzYyAwMyAwOSAwMCAwYSAzYyAwMCAw
MA0KWyAzODc1LjYwNTA2Nl0gc3QgODowOjA6MDogW3N0Ml0gcHNkX2NudCAyLCBtYXgucGFydHMg
MywgbmJyX3BhcnRzIDANClsgMzg3NS42MDUwNjldIHN0IDg6MDowOjA6IFtzdDJdIEZvcm1hdHRp
bmcgdGFwZSB3aXRoIHR3byBwYXJ0aXRpb25zICgxID0gMjAwIE1CKS4NClsgMzg3NS42MDUwNzJd
IHN0IDg6MDowOjA6IFtzdDJdIFNlbnQgcGFydGl0aW9uIHBhZ2UgbGVuZ3RoIGlzIDEyIGJ5dGVz
LiBuZWVkc19mb3JtYXQ6IDENClsgMzg3NS42MDUwNzZdIHN0IDg6MDowOjA6IFtzdDJdIFBQOiBt
YXggMywgYWRkIDEsIHhkcCAxLCBwc3VtIDAyLCBwb2ZtZXRjIDQsIHJlYyAwMywgdW5pdHMgMDAs
IHNpemVzOiAyMDAgMA0KWyAzODc1LjYwNTA4MF0gc3QgODowOjA6MDogW3N0Ml0gTVA6IDExIDBh
IDAzIDAxIDM0IDAzIDAwIDAwIDAwIGM4IDAwIDAwDQpbIDM4NzUuNjA1OTUyXSBzdCA4OjA6MDow
OiBbc3QyXSBFcnJvcjogODAwMDAwMiwgY21kOiAxNSAxMCAwIDAgMTggMA0KWyAzODc1LjYwNTk1
N10gc3QgODowOjA6MDogW3N0Ml0gU2Vuc2UgS2V5IDogSWxsZWdhbCBSZXF1ZXN0IFtjdXJyZW50
XQ0KWyAzODc1LjYwNTk2MV0gc3QgODowOjA6MDogW3N0Ml0gQWRkLiBTZW5zZTogSW52YWxpZCBm
aWVsZCBpbiBwYXJhbWV0ZXIgbGlzdA0KWyAzODc1LjYwNTk2NF0gc3QgODowOjA6MDogW3N0Ml0g
UGFydGl0aW9uaW5nIG9mIHRhcGUgZmFpbGVkLg0KWyAzODc1LjYwNjA4N10gc3QgODowOjA6MDog
W3N0Ml0gUmV3aW5kaW5nIHRhcGUuDQoNClNpbmNlIGEgcG9zaXRpdmUgbnVtYmVyIHNldHMgdGhl
IHNpemUgb2YgdGhlIHNlY29uZCBwYXJ0aXRpb24gSSB3b3VsZCBoYXZlIGV4cGVjdGVkIHRoZSBz
aXplcyB0byBiZSAweGZmZmYgYW5kIDIwMCBub3QgMjAwIGFuZCAwLg0KIA0KIyBtdCAtZiAvZGV2
L3N0MiBta3BhcnRpdGlvbiAyMDAwDQoNClsgMzk1Ny4zNzMxOTddIHN0IDg6MDowOjA6IFtzdDJd
IEJsb2NrIGxpbWl0cyAxIC0gMTY3NzcyMTUgYnl0ZXMuDQpbIDM5NTcuMzczNzI5XSBzdCA4OjA6
MDowOiBbc3QyXSBNb2RlIHNlbnNlLiBMZW5ndGggMTEsIG1lZGl1bSAwLCBXQlMgMTAsIEJMTCA4
DQpbIDM5NTcuMzczNzMyXSBzdCA4OjA6MDowOiBbc3QyXSBEZW5zaXR5IDVhLCB0YXBlIGxlbmd0
aDogMCwgZHJ2IGJ1ZmZlcjogMQ0KWyAzOTU3LjM3MzczNF0gc3QgODowOjA6MDogW3N0Ml0gQmxv
Y2sgc2l6ZTogMCwgYnVmZmVyIHNpemU6IDQwOTYgKDEgYmxvY2tzKS4NClsgMzk1Ny4zNzM3NTBd
IHN0IDg6MDowOjA6IFtzdDJdIExvYWRpbmcgdGFwZS4NClsgMzk1Ny4zODg1OTldIHN0IDg6MDow
OjA6IFtzdDJdIEJsb2NrIGxpbWl0cyAxIC0gMTY3NzcyMTUgYnl0ZXMuDQpbIDM5NTcuMzg5MTAw
XSBzdCA4OjA6MDowOiBbc3QyXSBNb2RlIHNlbnNlLiBMZW5ndGggMTEsIG1lZGl1bSAwLCBXQlMg
MTAsIEJMTCA4DQpbIDM5NTcuMzg5MTA0XSBzdCA4OjA6MDowOiBbc3QyXSBEZW5zaXR5IDVhLCB0
YXBlIGxlbmd0aDogMCwgZHJ2IGJ1ZmZlcjogMQ0KWyAzOTU3LjM4OTEwOF0gc3QgODowOjA6MDog
W3N0Ml0gQmxvY2sgc2l6ZTogMCwgYnVmZmVyIHNpemU6IDQwOTYgKDEgYmxvY2tzKS4NClsgMzk1
Ny4zOTAwMTJdIHN0IDg6MDowOjA6IFtzdDJdIFBhcnRpdGlvbiBwYWdlIGxlbmd0aCBpcyAxNiBi
eXRlcy4NClsgMzk1Ny4zOTAwMTVdIHN0IDg6MDowOjA6IFtzdDJdIFBQOiBtYXggMywgYWRkIDAs
IHhkcCAxLCBwc3VtIDAzLCBwb2ZtZXRjIDQsIHJlYyAwMywgdW5pdHMgMDksIHNpemVzOiAyNjIw
IDANClsgMzk1Ny4zOTAwMThdIHN0IDg6MDowOjA6IFtzdDJdIE1QOiAxMSAwZSAwMyAwMCAzYyAw
MyAwOSAwMCAwYSAzYyAwMCAwMA0KWyAzOTU3LjM5MDAyNF0gc3QgODowOjA6MDogW3N0Ml0gcHNk
X2NudCAyLCBtYXgucGFydHMgMywgbmJyX3BhcnRzIDANClsgMzk1Ny4zOTAwMjddIHN0IDg6MDow
OjA6IFtzdDJdIEZvcm1hdHRpbmcgdGFwZSB3aXRoIHR3byBwYXJ0aXRpb25zICgxID0gMjAwMCBN
QikuDQpbIDM5NTcuMzkwMDMwXSBzdCA4OjA6MDowOiBbc3QyXSBTZW50IHBhcnRpdGlvbiBwYWdl
IGxlbmd0aCBpcyAxMiBieXRlcy4gbmVlZHNfZm9ybWF0OiAxDQpbIDM5NTcuMzkwMDM1XSBzdCA4
OjA6MDowOiBbc3QyXSBQUDogbWF4IDMsIGFkZCAxLCB4ZHAgMSwgcHN1bSAwMywgcG9mbWV0YyA0
LCByZWMgMDMsIHVuaXRzIDA5LCBzaXplczogMiAwDQpbIDM5NTcuMzkwMDM5XSBzdCA4OjA6MDow
OiBbc3QyXSBNUDogMTEgMGEgMDMgMDEgM2MgMDMgMDkgMDAgMDAgMDIgMDAgMDANClsgMzk1Ny4z
OTExODRdIHN0IDg6MDowOjA6IFtzdDJdIFNlbmRpbmcgRk9STUFUIE1FRElVTQ0KWyAzOTU3LjM5
ODY2N10gc3QgODowOjA6MDogW3N0Ml0gRXJyb3I6IDgwMDAwMDIsIGNtZDogNCAwIDEgMCAwIDAN
ClsgMzk1Ny4zOTg2NzJdIHN0IDg6MDowOjA6IFtzdDJdIFNlbnNlIEtleSA6IElsbGVnYWwgUmVx
dWVzdCBbY3VycmVudF0NClsgMzk1Ny4zOTg2NzZdIHN0IDg6MDowOjA6IFtzdDJdIEFkZC4gU2Vu
c2U6IFBhcmFtZXRlciB2YWx1ZSBpbnZhbGlkDQpbIDM5NTcuMzk4Njg0XSBzdCA4OjA6MDowOiBb
c3QyXSBSZXdpbmRpbmcgdGFwZS4NCg0KQWdhaW4gSSB3b3VsZCBoYXZlIGV4cGVjdGVkIDB4ZmZm
ZiBhbmQgMiBub3QgMiBhbmQgMC4NCg0KSWYgSSBhc2sgZm9yIC0yMDAwIHRoZW4gaXQgd29ya3M6
DQoNClsgNDE5Ny45NjU2NTNdIHN0IDg6MDowOjA6IFtzdDJdIEJsb2NrIGxpbWl0cyAxIC0gMTY3
NzcyMTUgYnl0ZXMuDQpbIDQxOTcuOTY2MDg5XSBzdCA4OjA6MDowOiBbc3QyXSBNb2RlIHNlbnNl
LiBMZW5ndGggMTEsIG1lZGl1bSAwLCBXQlMgMTAsIEJMTCA4DQpbIDQxOTcuOTY2MDk0XSBzdCA4
OjA6MDowOiBbc3QyXSBEZW5zaXR5IDVhLCB0YXBlIGxlbmd0aDogMCwgZHJ2IGJ1ZmZlcjogMQ0K
WyA0MTk3Ljk2NjA5OF0gc3QgODowOjA6MDogW3N0Ml0gQmxvY2sgc2l6ZTogMCwgYnVmZmVyIHNp
emU6IDQwOTYgKDEgYmxvY2tzKS4NClsgNDE5Ny45NjYxMTldIHN0IDg6MDowOjA6IFtzdDJdIExv
YWRpbmcgdGFwZS4NClsgNDE5Ny45ODA2NzVdIHN0IDg6MDowOjA6IFtzdDJdIEJsb2NrIGxpbWl0
cyAxIC0gMTY3NzcyMTUgYnl0ZXMuDQpbIDQxOTcuOTgxMTYwXSBzdCA4OjA6MDowOiBbc3QyXSBN
b2RlIHNlbnNlLiBMZW5ndGggMTEsIG1lZGl1bSAwLCBXQlMgMTAsIEJMTCA4DQpbIDQxOTcuOTgx
MTY1XSBzdCA4OjA6MDowOiBbc3QyXSBEZW5zaXR5IDVhLCB0YXBlIGxlbmd0aDogMCwgZHJ2IGJ1
ZmZlcjogMQ0KWyA0MTk3Ljk4MTE2OV0gc3QgODowOjA6MDogW3N0Ml0gQmxvY2sgc2l6ZTogMCwg
YnVmZmVyIHNpemU6IDQwOTYgKDEgYmxvY2tzKS4NClsgNDE5Ny45ODIwODBdIHN0IDg6MDowOjA6
IFtzdDJdIFBhcnRpdGlvbiBwYWdlIGxlbmd0aCBpcyAxNiBieXRlcy4NClsgNDE5Ny45ODIwODZd
IHN0IDg6MDowOjA6IFtzdDJdIFBQOiBtYXggMywgYWRkIDAsIHhkcCAxLCBwc3VtIDAzLCBwb2Zt
ZXRjIDQsIHJlYyAwMywgdW5pdHMgMDksIHNpemVzOiAyNjIwIDANClsgNDE5Ny45ODIwOTFdIHN0
IDg6MDowOjA6IFtzdDJdIE1QOiAxMSAwZSAwMyAwMCAzYyAwMyAwOSAwMCAwYSAzYyAwMCAwMA0K
WyA0MTk3Ljk4MjA5NF0gc3QgODowOjA6MDogW3N0Ml0gcHNkX2NudCAyLCBtYXgucGFydHMgMywg
bmJyX3BhcnRzIDANClsgNDE5Ny45ODIwOTddIHN0IDg6MDowOjA6IFtzdDJdIEZvcm1hdHRpbmcg
dGFwZSB3aXRoIHR3byBwYXJ0aXRpb25zICgxID0gMjAwMCBNQikuDQpbIDQxOTcuOTgyMTAwXSBz
dCA4OjA6MDowOiBbc3QyXSBTZW50IHBhcnRpdGlvbiBwYWdlIGxlbmd0aCBpcyAxMiBieXRlcy4g
bmVlZHNfZm9ybWF0OiAxDQpbIDQxOTcuOTgyMTA1XSBzdCA4OjA6MDowOiBbc3QyXSBQUDogbWF4
IDMsIGFkZCAxLCB4ZHAgMSwgcHN1bSAwMywgcG9mbWV0YyA0LCByZWMgMDMsIHVuaXRzIDA5LCBz
aXplczogMiA2NTUzNQ0KWyA0MTk3Ljk4MjEwOF0gc3QgODowOjA6MDogW3N0Ml0gTVA6IDExIDBh
IDAzIDAxIDNjIDAzIDA5IDAwIDAwIDAyIGZmIGZmDQpbIDQxOTcuOTgzMzA2XSBzdCA4OjA6MDow
OiBbc3QyXSBTZW5kaW5nIEZPUk1BVCBNRURJVU0NClsgNDIwOC4xNTE0NjFdIHN0IDg6MDowOjA6
IFtzdDJdIFJld2luZGluZyB0YXBlLg0KDQpBcyBpdCBkaWQgc2V0IHRoZSBzaXplIG9mIHRoZSBz
ZWNvbmQgcGFydGl0aW9uIHRvIGJlIDB4ZmZmZi4NCg0KVG8gaW52ZXN0aWdhdGUgd2hhdCBpcyBo
YXBwZW5pbmcgd2l0aCBhIHBvc2l0aXZlIHNpemUgSSBjaGFuZ2VkIHRoaXMgbWVzc2FnZSB0byBw
cmludCB0aGUgdmFsdWUgb2YgdGFyZ2V0X3BhcnRpdGlvbjoNCg0KICAgICAgICAgICAgICAgIERF
QkNfcHJpbnRrKFNUcCwgIkZvcm1hdHRpbmcgdGFwZSB3aXRoIHR3byBwYXJ0aXRpb25zICINCiAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAiKCVpID0gJWQgTUIpLlxuIiwgdGFyZ2V0X3BhcnRp
dGlvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0cyA+IDAgPyBzaXplICogMTAw
MCA6IHNpemUpOw0KDQpSdW5uaW5nIHdpdGggMjAwMCBpdCBhcHBlYXJzIHRvIGhhdmUgd29ya2Vk
IGJ1dCBub3QgYmVjYXVzZSB0aGUgdmFsdWVzIGFyZSBjb3JyZWN0IHNpbmNlIHRoZSB0YXJnZXQg
cGFydGl0aW9uIGlzIDEgdGhlIDIgc2hvdWxkIGhhdmUgYmVlbiBzZXQgaW4gdGhlIHNlY29uZCBw
YXJ0aXRpb24gc2l6ZSBhbmQgdGhlIGZpcnN0IHBhcnRpdGlvbiBzaXplIHNldCB0byBiZSAweGZm
ZmY6DQoNClsgNDgyNi45Njg2ODJdIHN0IDg6MDowOjA6IFtzdDJdIEJsb2NrIGxpbWl0cyAxIC0g
MTY3NzcyMTUgYnl0ZXMuDQpbIDQ4MjYuOTY5MjU3XSBzdCA4OjA6MDowOiBbc3QyXSBNb2RlIHNl
bnNlLiBMZW5ndGggMTEsIG1lZGl1bSAwLCBXQlMgMTAsIEJMTCA4DQpbIDQ4MjYuOTY5MjYxXSBz
dCA4OjA6MDowOiBbc3QyXSBEZW5zaXR5IDVhLCB0YXBlIGxlbmd0aDogMCwgZHJ2IGJ1ZmZlcjog
MQ0KWyA0ODI2Ljk2OTI2NV0gc3QgODowOjA6MDogW3N0Ml0gQmxvY2sgc2l6ZTogMCwgYnVmZmVy
IHNpemU6IDQwOTYgKDEgYmxvY2tzKS4NClsgNDgyNi45NjkyNjhdIHN0IDg6MDowOjA6IFtzdDJd
IFVwZGF0aW5nIHBhcnRpdGlvbiBudW1iZXIgaW4gc3RhdHVzLg0KWyA0ODI2Ljk3MDIwMl0gc3Qg
ODowOjA6MDogW3N0Ml0gR290IHRhcGUgcG9zLiBibGsgMCBwYXJ0IDAuDQpbIDQ4MjYuOTcwMjI1
XSBzdCA4OjA6MDowOiBbc3QyXSBMb2FkaW5nIHRhcGUuDQpbIDQ4MjYuOTg1MTU2XSBzdCA4OjA6
MDowOiBbc3QyXSBCbG9jayBsaW1pdHMgMSAtIDE2Nzc3MjE1IGJ5dGVzLg0KWyA0ODI2Ljk4NTYx
OF0gc3QgODowOjA6MDogW3N0Ml0gTW9kZSBzZW5zZS4gTGVuZ3RoIDExLCBtZWRpdW0gMCwgV0JT
IDEwLCBCTEwgOA0KWyA0ODI2Ljk4NTYyM10gc3QgODowOjA6MDogW3N0Ml0gRGVuc2l0eSA1YSwg
dGFwZSBsZW5ndGg6IDAsIGRydiBidWZmZXI6IDENClsgNDgyNi45ODU2MjZdIHN0IDg6MDowOjA6
IFtzdDJdIEJsb2NrIHNpemU6IDAsIGJ1ZmZlciBzaXplOiA0MDk2ICgxIGJsb2NrcykuDQpbIDQ4
MjYuOTg2ODAyXSBzdCA4OjA6MDowOiBbc3QyXSBQYXJ0aXRpb24gcGFnZSBsZW5ndGggaXMgMTYg
Ynl0ZXMuDQpbIDQ4MjYuOTg2ODA5XSBzdCA4OjA6MDowOiBbc3QyXSBQUDogbWF4IDMsIGFkZCAx
LCB4ZHAgMSwgcHN1bSAwMywgcG9mbWV0YyA0LCByZWMgMDMsIHVuaXRzIDA5LCBzaXplczogMzgg
MjU0Mw0KWyA0ODI2Ljk4NjgxM10gc3QgODowOjA6MDogW3N0Ml0gTVA6IDExIDBlIDAzIDAxIDNj
IDAzIDA5IDAwIDAwIDI2IDA5IGVmDQpbIDQ4MjYuOTg2ODE3XSBzdCA4OjA6MDowOiBbc3QyXSBw
c2RfY250IDIsIG1heC5wYXJ0cyAzLCBuYnJfcGFydHMgMQ0KWyA0ODI2Ljk4NjgyMF0gc3QgODow
OjA6MDogW3N0Ml0gRm9ybWF0dGluZyB0YXBlIHdpdGggdHdvIHBhcnRpdGlvbnMgKDEgPSAyMDAw
IE1CKS4NClsgNDgyNi45ODY4MjNdIHN0IDg6MDowOjA6IFtzdDJdIFNlbnQgcGFydGl0aW9uIHBh
Z2UgbGVuZ3RoIGlzIDEyIGJ5dGVzLiBuZWVkc19mb3JtYXQ6IDENClsgNDgyNi45ODY4MjddIHN0
IDg6MDowOjA6IFtzdDJdIFBQOiBtYXggMywgYWRkIDEsIHhkcCAxLCBwc3VtIDAzLCBwb2ZtZXRj
IDQsIHJlYyAwMywgdW5pdHMgMDksIHNpemVzOiAyIDI1NDMNClsgNDgyNi45ODY4MzFdIHN0IDg6
MDowOjA6IFtzdDJdIE1QOiAxMSAwYSAwMyAwMSAzYyAwMyAwOSAwMCAwMCAwMiAwOSBlZg0KWyA0
ODI2Ljk4ODE3NF0gc3QgODowOjA6MDogW3N0Ml0gU2VuZGluZyBGT1JNQVQgTUVESVVNDQpbIDQ4
MjYuOTk1Mjk1XSBzdCA4OjA6MDowOiBbc3QyXSBSZXdpbmRpbmcgdGFwZS4NCg0KVGhpcyBjb2Rl
IGFwcGVhcnMgdG8gYmUgd3Jvbmc6DQoNCiAgICAgICAgICAgICAgICBicFtwc2RvXSA9IChzaXpl
ID4+IDgpICYgMHhmZjsNCiAgICAgICAgICAgICAgICBicFtwc2RvICsgMV0gPSBzaXplICYgMHhm
ZjsNCiAgICAgICAgICAgICAgICBpZiAodGFyZ2V0X3BhcnRpdGlvbiA9PSAwKQ0KICAgICAgICAg
ICAgICAgICAgICAgICAgYnBbcHNkbyArIDJdID0gYnBbcHNkbyArIDNdID0gMHhmZjsNCg0KSSBj
aGFuZ2VkIGl0IHRvIGJlOg0KDQovKg0KICogRm9yIFNTQy0zIGRldmljZXMgdGhlIG1vZGUgcGFn
ZSBzaG91bGQgYmUgbW9yZSB0aGFuIDEwIGJ5dGVzDQogKiBsb25nIHNvIEREUyBkcml2ZXMgd29u
J3Qgc2VlIHRoZXNlIGNoYW5nZXMuDQogKi8NCiAgICAgICAgICAgICAgICBpZiAoYnBbcGdvICsg
TVBfT0ZGX1BBR0VfTEVOR1RIXSArIDIgPiAxMCkgew0KICAgICAgICAgICAgICAgICAgICAgICAg
aWYgKHRhcmdldF9wYXJ0aXRpb24gPT0gMCkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICBicFtwc2RvXSA9IChzaXplID4+IDgpICYgMHhmZjsNCiAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgYnBbcHNkbyArIDFdID0gc2l6ZSAmIDB4ZmY7DQogICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgIGJwW3BzZG8gKyAyXSA9IGJwW3BzZG8gKyAzXSA9IDB4ZmY7DQogICAg
ICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICBicFtwc2RvICsgMl0gPSAoc2l6ZSA+PiA4KSAmIDB4ZmY7DQogICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgIGJwW3BzZG8gKyAzXSA9IHNpemUgJiAweGZmOw0KICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICBicFtwc2RvXSA9IGJwW3BzZG8gKyAxXSA9IDB4ZmY7DQogICAg
ICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAg
ICAgICAgICAgICAgICAgIGJwW3BzZG9dID0gKHNpemUgPj4gOCkgJiAweGZmOw0KICAgICAgICAg
ICAgICAgICAgICAgICAgYnBbcHNkbyArIDFdID0gc2l6ZSAmIDB4ZmY7DQogICAgICAgICAgICAg
ICAgICAgICAgICBpZiAodGFyZ2V0X3BhcnRpdGlvbiA9PSAwKQ0KICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICBicFtwc2RvICsgMl0gPSBicFtwc2RvICsgM10gPSAweGZmOw0KICAgICAg
ICAgICAgICAgIH0NCg0KWW91IG1heSBiZSBhYmxlIHRvIHRoaW5rIG9mIGEgYmV0dGVyIGNvbmRp
dGlvbiB0aGF0IHdlIGNhbiBndWFyYW50ZWUgd2lsbCB3b3JrIHdpdGggb3RoZXIgZHJpdmVzIGFu
ZCBzdGlsbCBub3QgY2F1c2UgaXNzdWVzIGZvciBERFMgYnV0IGZvciBteSBIUEUgRERTIGFuZCBM
VE82IGRyaXZlcyB0aGF0IGZpcnN0IHRlc3Qgd29ya3Mgc2luY2UgSFBFIEREUyBkcml2ZXMgb25s
eSBoYXZlIGEgcGFydGl0aW9uIGZvcm1hdCBtb2RlIHBhZ2UgbGVuZ3RoIG9mIDEwLg0KDQpBbmQg
dGhlIGRlYnVnIG91dHB1dCBub3cgbG9va3MgbGlrZToNCg0KIyBtdCAtZiAvZGV2L3N0MiBta3Bh
cnRpdGlvbiAyMDAwMA0KDQpbIDU2OTAuMjYxNjg5XSBzdCA4OjA6MDowOiBbc3QyXSBCbG9jayBs
aW1pdHMgMSAtIDE2Nzc3MjE1IGJ5dGVzLg0KWyA1NjkwLjI2MjMxMV0gc3QgODowOjA6MDogW3N0
Ml0gTW9kZSBzZW5zZS4gTGVuZ3RoIDExLCBtZWRpdW0gMCwgV0JTIDEwLCBCTEwgOA0KWyA1Njkw
LjI2MjMxNV0gc3QgODowOjA6MDogW3N0Ml0gRGVuc2l0eSA1YSwgdGFwZSBsZW5ndGg6IDAsIGRy
diBidWZmZXI6IDENClsgNTY5MC4yNjIzMTldIHN0IDg6MDowOjA6IFtzdDJdIEJsb2NrIHNpemU6
IDAsIGJ1ZmZlciBzaXplOiA0MDk2ICgxIGJsb2NrcykuDQpbIDU2OTAuMjYyMzIxXSBzdCA4OjA6
MDowOiBbc3QyXSBVcGRhdGluZyBwYXJ0aXRpb24gbnVtYmVyIGluIHN0YXR1cy4NClsgNTY5MC4y
NjMyMzBdIHN0IDg6MDowOjA6IFtzdDJdIEdvdCB0YXBlIHBvcy4gYmxrIDAgcGFydCAwLg0KWyA1
NjkwLjI2MzI0N10gc3QgODowOjA6MDogW3N0Ml0gTG9hZGluZyB0YXBlLg0KWyA1NjkwLjI3ODA3
Ml0gc3QgODowOjA6MDogW3N0Ml0gQmxvY2sgbGltaXRzIDEgLSAxNjc3NzIxNSBieXRlcy4NClsg
NTY5MC4yNzg3ODBdIHN0IDg6MDowOjA6IFtzdDJdIE1vZGUgc2Vuc2UuIExlbmd0aCAxMSwgbWVk
aXVtIDAsIFdCUyAxMCwgQkxMIDgNClsgNTY5MC4yNzg3ODZdIHN0IDg6MDowOjA6IFtzdDJdIERl
bnNpdHkgNWEsIHRhcGUgbGVuZ3RoOiAwLCBkcnYgYnVmZmVyOiAxDQpbIDU2OTAuMjc4NzkwXSBz
dCA4OjA6MDowOiBbc3QyXSBCbG9jayBzaXplOiAwLCBidWZmZXIgc2l6ZTogNDA5NiAoMSBibG9j
a3MpLg0KWyA1NjkwLjI3OTk4NV0gc3QgODowOjA6MDogW3N0Ml0gUGFydGl0aW9uIHBhZ2UgbGVu
Z3RoIGlzIDE2IGJ5dGVzLg0KWyA1NjkwLjI3OTk5Ml0gc3QgODowOjA6MDogW3N0Ml0gUFA6IG1h
eCAzLCBhZGQgMSwgeGRwIDEsIHBzdW0gMDMsIHBvZm1ldGMgNCwgcmVjIDAzLCB1bml0cyAwOSwg
c2l6ZXM6IDM4IDI1NDMNClsgNTY5MC4yNzk5OTZdIHN0IDg6MDowOjA6IFtzdDJdIE1QOiAxMSAw
ZSAwMyAwMSAzYyAwMyAwOSAwMCAwMCAyNiAwOSBlZg0KWyA1NjkwLjI4MDAwMF0gc3QgODowOjA6
MDogW3N0Ml0gcHNkX2NudCAyLCBtYXgucGFydHMgMywgbmJyX3BhcnRzIDENClsgNTY5MC4yODAw
MDNdIHN0IDg6MDowOjA6IFtzdDJdIEZvcm1hdHRpbmcgdGFwZSB3aXRoIHR3byBwYXJ0aXRpb25z
ICgxID0gMjAwMDAgTUIpLg0KWyA1NjkwLjI4MDAwN10gc3QgODowOjA6MDogW3N0Ml0gU2VudCBw
YXJ0aXRpb24gcGFnZSBsZW5ndGggaXMgMTIgYnl0ZXMuIG5lZWRzX2Zvcm1hdDogMQ0KWyA1Njkw
LjI4MDAxMV0gc3QgODowOjA6MDogW3N0Ml0gUFA6IG1heCAzLCBhZGQgMSwgeGRwIDEsIHBzdW0g
MDMsIHBvZm1ldGMgNCwgcmVjIDAzLCB1bml0cyAwOSwgc2l6ZXM6IDY1NTM1IDIwDQpbIDU2OTAu
MjgwMDE1XSBzdCA4OjA6MDowOiBbc3QyXSBNUDogMTEgMGEgMDMgMDEgM2MgMDMgMDkgMDAgZmYg
ZmYgMDAgMTQNClsgNTY5MC4yODExMTVdIHN0IDg6MDowOjA6IFtzdDJdIFNlbmRpbmcgRk9STUFU
IE1FRElVTQ0KWyA1NzAzLjI1NDEzOF0gc3QgODowOjA6MDogW3N0Ml0gUmV3aW5kaW5nIHRhcGUu
DQoNCiMgbXQgLWYgL2Rldi9zdDIgbWtwYXJ0aXRpb24gLTIwMDAwDQoNClsgNTc3MC44ODMyMzZd
IHN0IDg6MDowOjA6IFtzdDJdIEJsb2NrIGxpbWl0cyAxIC0gMTY3NzcyMTUgYnl0ZXMuDQpbIDU3
NzAuODgzODE5XSBzdCA4OjA6MDowOiBbc3QyXSBNb2RlIHNlbnNlLiBMZW5ndGggMTEsIG1lZGl1
bSAwLCBXQlMgMTAsIEJMTCA4DQpbIDU3NzAuODgzODIyXSBzdCA4OjA6MDowOiBbc3QyXSBEZW5z
aXR5IDVhLCB0YXBlIGxlbmd0aDogMCwgZHJ2IGJ1ZmZlcjogMQ0KWyA1NzcwLjg4MzgyNF0gc3Qg
ODowOjA6MDogW3N0Ml0gQmxvY2sgc2l6ZTogMCwgYnVmZmVyIHNpemU6IDQwOTYgKDEgYmxvY2tz
KS4NClsgNTc3MC44ODM4NDBdIHN0IDg6MDowOjA6IFtzdDJdIExvYWRpbmcgdGFwZS4NClsgNTc3
MC44OTgxODFdIHN0IDg6MDowOjA6IFtzdDJdIEJsb2NrIGxpbWl0cyAxIC0gMTY3NzcyMTUgYnl0
ZXMuDQpbIDU3NzAuODk4NzI1XSBzdCA4OjA6MDowOiBbc3QyXSBNb2RlIHNlbnNlLiBMZW5ndGgg
MTEsIG1lZGl1bSAwLCBXQlMgMTAsIEJMTCA4DQpbIDU3NzAuODk4NzMwXSBzdCA4OjA6MDowOiBb
c3QyXSBEZW5zaXR5IDVhLCB0YXBlIGxlbmd0aDogMCwgZHJ2IGJ1ZmZlcjogMQ0KWyA1NzcwLjg5
ODczNF0gc3QgODowOjA6MDogW3N0Ml0gQmxvY2sgc2l6ZTogMCwgYnVmZmVyIHNpemU6IDQwOTYg
KDEgYmxvY2tzKS4NClsgNTc3MC44OTk5MTVdIHN0IDg6MDowOjA6IFtzdDJdIFBhcnRpdGlvbiBw
YWdlIGxlbmd0aCBpcyAxNiBieXRlcy4NClsgNTc3MC44OTk5MjFdIHN0IDg6MDowOjA6IFtzdDJd
IFBQOiBtYXggMywgYWRkIDEsIHhkcCAxLCBwc3VtIDAzLCBwb2ZtZXRjIDQsIHJlYyAwMywgdW5p
dHMgMDksIHNpemVzOiAyNTQzIDM4DQpbIDU3NzAuODk5OTI2XSBzdCA4OjA6MDowOiBbc3QyXSBN
UDogMTEgMGUgMDMgMDEgM2MgMDMgMDkgMDAgMDkgZWYgMDAgMjYNClsgNTc3MC44OTk5MjldIHN0
IDg6MDowOjA6IFtzdDJdIHBzZF9jbnQgMiwgbWF4LnBhcnRzIDMsIG5icl9wYXJ0cyAxDQpbIDU3
NzAuODk5OTMyXSBzdCA4OjA6MDowOiBbc3QyXSBGb3JtYXR0aW5nIHRhcGUgd2l0aCB0d28gcGFy
dGl0aW9ucyAoMCA9IDIwMDAwIE1CKS4NClsgNTc3MC44OTk5MzVdIHN0IDg6MDowOjA6IFtzdDJd
IFNlbnQgcGFydGl0aW9uIHBhZ2UgbGVuZ3RoIGlzIDEyIGJ5dGVzLiBuZWVkc19mb3JtYXQ6IDEN
ClsgNTc3MC44OTk5NDBdIHN0IDg6MDowOjA6IFtzdDJdIFBQOiBtYXggMywgYWRkIDEsIHhkcCAx
LCBwc3VtIDAzLCBwb2ZtZXRjIDQsIHJlYyAwMywgdW5pdHMgMDksIHNpemVzOiAyMCA2NTUzNQ0K
WyA1NzcwLjg5OTk0NF0gc3QgODowOjA6MDogW3N0Ml0gTVA6IDExIDBhIDAzIDAxIDNjIDAzIDA5
IDAwIDAwIDE0IGZmIGZmDQpbIDU3NzAuOTAxMTQ0XSBzdCA4OjA6MDowOiBbc3QyXSBTZW5kaW5n
IEZPUk1BVCBNRURJVU0NClsgNTc4MS4wNTEyMjldIHN0IDg6MDowOjA6IFtzdDJdIFJld2luZGlu
ZyB0YXBlLg0KDQpUaGF0IG1ha2VzIGl0IHdvcmsgaW4gdGhlIHdheSBJJ2QgZXhwZWN0IGl0IHRv
IHdvcmsgZm9yIExUTyBhbmQgZGRzIHN0aWxsIHdvcmtzIGFmdGVyIHRoZSBjaGFuZ2U6DQoNCiMg
bXQgLWYgL2Rldi9zdDEgbWtwYXJ0aXRpb24gNTAwDQoNClsgNTgzNi4yMzk4NTRdIHN0IDY6MDoz
OjA6IFtzdDFdIEJsb2NrIGxpbWl0cyAxIC0gMTY3NzcyMTUgYnl0ZXMuDQpbIDU4MzYuMjQwMTU0
XSBzdCA2OjA6MzowOiBbc3QxXSBNb2RlIHNlbnNlLiBMZW5ndGggMTEsIG1lZGl1bSAwLCBXQlMg
MTAsIEJMTCA4DQpbIDU4MzYuMjQwMTU4XSBzdCA2OjA6MzowOiBbc3QxXSBEZW5zaXR5IDQ3LCB0
YXBlIGxlbmd0aDogMCwgZHJ2IGJ1ZmZlcjogMQ0KWyA1ODM2LjI0MDE2Ml0gc3QgNjowOjM6MDog
W3N0MV0gQmxvY2sgc2l6ZTogMCwgYnVmZmVyIHNpemU6IDQwOTYgKDEgYmxvY2tzKS4NClsgNTgz
Ni4yNDAxNjVdIHN0IDY6MDozOjA6IFtzdDFdIFVwZGF0aW5nIHBhcnRpdGlvbiBudW1iZXIgaW4g
c3RhdHVzLg0KWyA1ODM2LjI0MDY2MF0gc3QgNjowOjM6MDogW3N0MV0gR290IHRhcGUgcG9zLiBi
bGsgMCBwYXJ0IDAuDQpbIDU4MzYuMjQwNjgwXSBzdCA2OjA6MzowOiBbc3QxXSBMb2FkaW5nIHRh
cGUuDQpbIDU4MzYuMjQxNTY2XSBzdCA2OjA6MzowOiBbc3QxXSBCbG9jayBsaW1pdHMgMSAtIDE2
Nzc3MjE1IGJ5dGVzLg0KWyA1ODM2LjI0MTg3N10gc3QgNjowOjM6MDogW3N0MV0gTW9kZSBzZW5z
ZS4gTGVuZ3RoIDExLCBtZWRpdW0gMCwgV0JTIDEwLCBCTEwgOA0KWyA1ODM2LjI0MTg4MV0gc3Qg
NjowOjM6MDogW3N0MV0gRGVuc2l0eSA0NywgdGFwZSBsZW5ndGg6IDAsIGRydiBidWZmZXI6IDEN
ClsgNTgzNi4yNDE4ODVdIHN0IDY6MDozOjA6IFtzdDFdIEJsb2NrIHNpemU6IDAsIGJ1ZmZlciBz
aXplOiA0MDk2ICgxIGJsb2NrcykuDQpbIDU4MzYuMjQyMjE3XSBzdCA2OjA6MzowOiBbc3QxXSBQ
YXJ0aXRpb24gcGFnZSBsZW5ndGggaXMgMTAgYnl0ZXMuDQpbIDU4MzYuMjQyMjIyXSBzdCA2OjA6
MzowOiBbc3QxXSBQUDogbWF4IDEsIGFkZCAxLCB4ZHAgMCwgcHN1bSAwMiwgcG9mbWV0YyAwLCBy
ZWMgMDMsIHVuaXRzIDAwLCBzaXplczogNTAwIDY1NTM1DQpbIDU4MzYuMjQyMjI2XSBzdCA2OjA6
MzowOiBbc3QxXSBNUDogMTEgMDggMDEgMDEgMTAgMDMgMDAgMDAgMDEgZjQgZmYgZmYNClsgNTgz
Ni4yNDIyMzBdIHN0IDY6MDozOjA6IFtzdDFdIHBzZF9jbnQgMSwgbWF4LnBhcnRzIDEsIG5icl9w
YXJ0cyAxDQpbIDU4MzYuMjQyMjMzXSBzdCA2OjA6MzowOiBbc3QxXSBGb3JtYXR0aW5nIHRhcGUg
d2l0aCB0d28gcGFydGl0aW9ucyAoMSA9IDUwMCBNQikuDQpbIDU4MzYuMjQyMjM2XSBzdCA2OjA6
MzowOiBbc3QxXSBTZW50IHBhcnRpdGlvbiBwYWdlIGxlbmd0aCBpcyAxMCBieXRlcy4gbmVlZHNf
Zm9ybWF0OiAwDQpbIDU4MzYuMjQyMjQwXSBzdCA2OjA6MzowOiBbc3QxXSBQUDogbWF4IDEsIGFk
ZCAxLCB4ZHAgMSwgcHN1bSAwMiwgcG9mbWV0YyAwLCByZWMgMDMsIHVuaXRzIDAwLCBzaXplczog
NTAwIDY1NTM1DQpbIDU4MzYuMjQyMjQ0XSBzdCA2OjA6MzowOiBbc3QxXSBNUDogMTEgMDggMDEg
MDEgMzAgMDMgMDAgMDAgMDEgZjQgZmYgZmYNClsgNjA2Mi40NDExOThdIHN0IDY6MDozOjA6IFtz
dDFdIFJld2luZGluZyB0YXBlLg0KDQpGb3IgcG9zdGVyaXR5IGluIGNhc2UgYW55b25lIHJlYWRz
IHRoaXMgYXQgYSBsYXRlciBwb2ludCBqdXN0IHRvIGV4cGxhaW4gdGhlIHNpemUgdmFsdWVzIGZv
ciBERFMgLSB3aGlsZSB0aGUgRERTIHNpemVzIG1heSBsb29rIHdyb25nIHRoZXkgYXJlIG5vdC4g
VGhlIHNlY29uZCBzaXplIHZhbHVlIGlzIG5vdCBzZW50IHRvIHRoZSB0YXBlIGRyaXZlIG9ubHkg
dGhlIGZpcnN0IHNpemUgaXMgc2luY2UgbW9zdCAoYWxsPykgRERTIGRyaXZlcyBvbmx5IHN1cHBv
cnQgc2V0dGluZyBhbiBleHBsaWNpdCBzaXplIGZvciB0aGUgc2Vjb25kIHBhcnRpdGlvbiBvbmx5
IGFuZCBwYXJ0aXRpb24gMCBhdXRvbWF0aWNhbGx5IGdldHMgdGhlIHJlc3Qgb2YgdGhlIHRhcGUu
DQoNCklmIHRoZSBjaGFuZ2VzIGFyZSBjb3JyZWN0IGFuZCBuZWVkZWQgYW5kIHlvdSB3YW50IHRv
IGFkZCB0aG9zZSB0d28gY2hhbmdlcyBwbGVhc2UgZG8gc28uIEkndmUgYmVlbiBsb29raW5nIHZl
cnkgY2FyZWZ1bGx5IGF0IHRoZSBjb2RlIGNoYW5nZXMgYXMgcGFydCBvZiB0aGUgdGVzdGluZyBl
ZmZvcnQgYW5kIGhhcHB5IHRvIGFkZCBhbnkgY29tYmluYXRpb24gb2YgcmV2aWV3ZWQtYnkgYW5k
IHRlc3RlZC1ieSB0byB0aGUgcGF0Y2guIElmIHJlcXVpcmVkIGZlZWwgZnJlZSB0byBjaGFuZ2Ug
aXQgYXMgbmVlZGVkLiBJJ2xsIHJldGVzdCBhIGNvbnNvbGlkYXRlZCB2ZXJzaW9uIG9mIHRoZSBw
YXRjaCBpZiB5b3UgYWRkIHRoZSBjaGFuZ2VzIGFuZCBzZW5kIGl0IG91dC4NCg0KTGF1cmVuY2Us
IHdoZW4geW91IGdldCB5b3VyIExUTyBkcml2ZSB0ZXN0IHdpdGhvdXQgbXkgY2hhbmdlcyBpbiB0
byBtYWtlIHN1cmUgeW91IHNlZSB0aGUgc2FtZSBpc3N1ZSBhbmQgdGhlbiBpZiB5b3UgZG8gdGVz
dCB3aXRoIHRoZSBjaGFuZ2VzIEkgYWRkZWQgYWJvdmUuIFRoYXQncyBqdXN0IHRvIGRvdWJsZSBj
aGVjayB0aGF0IHRoZXJlJ3Mgbm90aGluZyB3cm9uZyB3aXRoIG15IHNldHVwIGFuZCB0aGUgY29k
ZSBjaGFuZ2VzIGFyZSByZXF1aXJlZC4NCg0KVGhhbmtzDQpTaGFuZQ0K
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Laurence Oberman Feb. 3, 2016, 3:40 a.m. UTC | #6
Hello

Finally got my firmware on my DAT updated.
Using Kai's latest patch I validated the patch on my DAT driver as well
Thanks to Shane for providing the correct mt code, as that was also one of my problems besides firmware.

[root@srp-server mt-st-1.1-patched]# ./mt -f /dev/st0 stsetoption can-partitions
[root@srp-server mt-st-1.1-patched]# ./mt -f /dev/st0 mkpartition 1000

Took almost 6 minutes to partition this old DDS

Feb 02 22:25:10 srp-server kernel: st 6:0:1:0: [st0] Mode sense. Length 11, medium 0, WBS 10, BLL 8
Feb 02 22:25:10 srp-server kernel: st 6:0:1:0: [st0] Density 47, tape length: 0, drv buffer: 1
Feb 02 22:25:10 srp-server kernel: st 6:0:1:0: [st0] Block size: 0, buffer size: 4096 (1 blocks).
Feb 02 22:25:10 srp-server kernel: st 6:0:1:0: [st0] Mode 0 options: buffer writes: 1, async writes: 1, read ahead: 1
Feb 02 22:25:10 srp-server kernel: st 6:0:1:0: [st0]     can bsr: 1, two FMs: 0, fast mteom: 0, auto lock: 0,
Feb 02 22:25:10 srp-server kernel: st 6:0:1:0: [st0]     defs for wr: 0, no block limits: 0, partitions: 1, s2 log: 0
Feb 02 22:25:10 srp-server kernel: st 6:0:1:0: [st0]     sysv: 0 nowait: 0 sili: 0 nowait_filemark: 0
Feb 02 22:25:10 srp-server kernel: st 6:0:1:0: [st0]     debugging: 1
Feb 02 22:25:10 srp-server kernel: st 6:0:1:0: [st0] Rewinding tape.

Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Block limits 1 - 16777215 bytes.
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Mode sense. Length 11, medium 0, WBS 10, BLL 8
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Density 47, tape length: 0, drv buffer: 1
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Block size: 0, buffer size: 4096 (1 blocks).
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Updating partition number in status.
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Got tape pos. blk 0 part 0.
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Loading tape.
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Error: 8000002, cmd: 0 0 0 0 0 0
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Sense Key : Unit Attention [current] 
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Add. Sense: Not ready to ready change, medium may have changed
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Block limits 1 - 16777215 bytes.
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Mode sense. Length 11, medium 0, WBS 10, BLL 8
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Density 47, tape length: 0, drv buffer: 1
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Block size: 0, buffer size: 4096 (1 blocks).
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Partition page length is 10 bytes.
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] PP: max 1, add 0, xdp 0, psum 02, pofmetc 0, rec 03, units 00, sizes: 0 65535
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] MP: 11 08 01 00 10 03 00 00 00 00 ff ff
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] psd_cnt 1, max.parts 1, nbr_parts 0
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Formatting tape with two partitions (1 = 1000 MB).
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] Sent partition page length is 10 bytes. needs_format: 0
Feb 02 22:25:24 srp-server kernel: st 6:0:1:0: [st0] PP: max 1, add 1, xdp 1, psum 02, pofmetc 0, rec 03, units 00, sizes: 1000 65535
Feb 02 22:31:45 srp-server kernel: st 6:0:1:0: [st0] Rewinding tape.

I will retest with Shane's latest additions he just sent after first testing with Kai's latest patch on my LTO5.
(here's hoping I dont have to update the f/w on that one)


Laurence Oberman
Principal Software Maintenance Engineer
Red Hat Global Support Services

----- Original Message -----
From: "Kai Mäkisara (Kolumbus)" <kai.makisara@kolumbus.fi>
To: "Shane M Seymour" <shane.seymour@hpe.com>
Cc: "Laurence Oberman" <loberman@redhat.com>, "Emmanuel Florac" <eflorac@intellique.com>, "Laurence Oberman" <oberman.l@gmail.com>, linux-scsi@vger.kernel.org
Sent: Monday, February 1, 2016 1:43:26 PM
Subject: Re: What partition should the MTMKPART argument specify? Was: Re: st driver doesn't seem to grok LTO partitioning


> On 1.2.2016, at 8.31, Seymour, Shane M <shane.seymour@hpe.com> wrote:
> 
> Hi Kai,
> 
> Thanks for the changes the HPE DAT72 DDS5 drive now works as expected:
> 
Good. Thanks for testing.

...
> 
> I'm asking around again one final time to see if I can lay my hands on a LTO5 or greater drive so I can test LTO partitioning as well.
> 
> The only other thing I can think of (I'm not sure if this is an improvement or not) is if bp[pgo + PP_OFF_MAX_ADD_PARTS] + bp[pgo + PP_OFF_NBR_ADD_PARTS] (max.parts and nbr_parts in the debug message) is zero just return -EINVAL unless you know of any take drives that report them both as 0 but can be partitioned? That is after this:
> 
>        DEBC_printk(STp, "psd_cnt %d, max.parts %d, nbr_parts %d\n",
>                    psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],
>                    bp[pgo + PP_OFF_NBR_ADD_PARTS]);
> 
> add (and also turn off the can-partitions option):
> 
> 	if ((bp[pgo + PP_OFF_MAX_ADD_PARTS] + bp[pgo + PP_OFF_NBR_ADD_PARTS]) == 0) {
> 		DEBC_printk(STp, "Drive not partitionable - max.parts+nbr_parts is 0\n");
> 		STp->can_partitions = 0;
> 		return -EINVAL;
> 	}
> 
> I'm not especially fussed if you don't want to add that though.
> 
I thought about a test like this (only test maximum number) but decided not to add it. The reason was that
I did not want to change anything that has worked before. I quite trust that the current drives return sense
data instead of crashing and the end result for the user would be the same. However, one can argue that
returning EINVAL is better than EIO but does the user notice? If the common opinion is that a test like this
should be added, I am not against it. It can be added to the code for SCSI >=3 where it does not risk
anything for the old drives.

IMHO, can_partitions should not be cleared based on the test. For example, trying to partition a LTO-4 tape
in a LTO-5 drive should not disable partitioning. (The mode page should return zero as maximum number of
partitions when a LTO-4 tape is inserted.)

Thanks,
Kai

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

--- ref/drivers/scsi/st.c	2015-12-21 18:54:05.068882001 +0200
+++ new/drivers/scsi/st.c	2016-01-29 19:12:06.139738037 +0200
@@ -9,7 +9,7 @@ 
    Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,
    Michael Schaefer, J"org Weule, and Eric Youngdale.
 
-   Copyright 1992 - 2010 Kai Makisara
+   Copyright 1992 - 2016 Kai Makisara
    email Kai.Makisara@kolumbus.fi
 
    Some small formal changes - aeb, 950809
@@ -17,7 +17,7 @@ 
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static const char *verstr = "20101219";
+static const char *verstr = "20160129";
 
 #include <linux/module.h>
 
@@ -3296,7 +3296,10 @@ 
 #define PP_OFF_RESERVED        7
 
 #define PP_BIT_IDP             0x20
+#define PP_BIT_FDP             0x80
 #define PP_MSK_PSUM_MB         0x10
+#define PP_MSK_PSUM_UNITS      0x18
+#define PP_MSK_POFM            0x04
 
 /* Get the number of partitions on the tape. As a side effect reads the
    mode page into the tape buffer. */
@@ -3322,6 +3325,29 @@ 
 }
 
 
+static int format_medium(struct scsi_tape *STp, int format)
+{
+	int result = 0;
+	int timeout = STp->long_timeout;
+	unsigned char scmd[MAX_COMMAND_SIZE];
+	struct st_request *SRpnt;
+
+	memset(scmd, 0, MAX_COMMAND_SIZE);
+	scmd[0] = FORMAT_UNIT;
+	scmd[2] = format;
+	if (STp->immediate) {
+		scmd[1] |= 1;		/* Don't wait for completion */
+		timeout = STp->device->request_queue->rq_timeout;
+	}
+	DEBC_printk(STp, "Sending FORMAT MEDIUM\n");
+	SRpnt = st_do_scsi(NULL, STp, scmd, 0, DMA_NONE,
+			   timeout, MAX_RETRIES, 1);
+	if (!SRpnt)
+		result = STp->buffer->syscall_result;
+	return result;
+}
+
+
 /* Partition the tape into two partitions if size > 0 or one partition if
    size == 0.
 
@@ -3340,11 +3366,16 @@ 
    and 10 when 1 partition is defined (information from Eric Lee Green). This is
    is acceptable also to some other old drives and enforced if the first partition
    size field is used for the first additional partition size.
+
+   For drives that advertize SCSI-3 or newer, use the SSC-3 methods.
  */
 static int partition_tape(struct scsi_tape *STp, int size)
 {
 	int result;
+	int target_partition;
+	bool scsi3 = STp->device->scsi_level >= SCSI_3, needs_format = false;
 	int pgo, psd_cnt, psdo;
+	int psum = PP_MSK_PSUM_MB, units = 0;
 	unsigned char *bp;
 
 	result = read_mode_page(STp, PART_PAGE, 0);
@@ -3352,16 +3383,72 @@ 
 		DEBC_printk(STp, "Can't read partition mode page.\n");
 		return result;
 	}
+	target_partition = 1;
+	if (size < 0) {
+		target_partition = 0;
+		size = -size;
+	}
+
 	/* The mode page is in the buffer. Let's modify it and write it. */
 	bp = (STp->buffer)->b_data;
 	pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH];
 	DEBC_printk(STp, "Partition page length is %d bytes.\n",
 		    bp[pgo + MP_OFF_PAGE_LENGTH] + 2);
+	DEBC_printk(STp, "PP: max %u, add %u, xdp %u, psum %02x, pofmetc %u, "
+		    "rec %02x, units %02x, sizes: %u %u\n",
+		    bp[pgo + PP_OFF_MAX_ADD_PARTS],
+		    bp[pgo + PP_OFF_NBR_ADD_PARTS],
+		    (bp[pgo + PP_OFF_FLAGS] & 0xe0) >> 5,
+		    (bp[pgo + PP_OFF_FLAGS] & 0x18) >> 3,
+		    bp[pgo + PP_OFF_FLAGS] & 0x07,
+		    bp[pgo + 5],
+		    bp[pgo + PP_OFF_PART_UNITS],
+		    bp[pgo + 8] * 256 + bp[pgo + 9],
+		    bp[pgo + 10] * 256 + bp[pgo + 11]);
+	DEBC_printk(STp, "MP: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		    bp[pgo], bp[pgo+1], bp[pgo+2], bp[pgo+3], bp[pgo+4], bp[pgo+5],
+		    bp[pgo+6], bp[pgo+7], bp[pgo+8], bp[pgo+9], bp[pgo+10], bp[pgo+11]);
 
 	psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - PART_PAGE_FIXED_LENGTH) / 2;
+
+	if (scsi3) {
+		needs_format = (bp[pgo + PP_OFF_FLAGS] & PP_MSK_POFM) != 0;
+		if (needs_format && size == 0) {
+			/* No need to write the mode page when clearing partitioning */
+			result = format_medium(STp, 0);
+			goto out;
+		}
+		if (needs_format)  /* Leave the old value for HP DATs claiming SCSI_3 */
+			psd_cnt = 2;
+		if ((bp[pgo + PP_OFF_FLAGS] & PP_MSK_PSUM_UNITS) == PP_MSK_PSUM_UNITS) {
+			/* Use units scaling for large partitions if the device suggests
+			   it and no precision lost. Required for IBM TS1140/50 drives
+			   that don't support MB units. */
+			if (size >= 1000 && (size % 1000) == 0) {
+				size /= 1000;
+				psum = PP_MSK_PSUM_UNITS;
+				units = 9; /* GB */
+			}
+		}
+		/* Try it anyway if too large to specify in MB */
+		if (psum == PP_MSK_PSUM_MB && size >= 65534) {
+				size /= 1000;
+				psum = PP_MSK_PSUM_UNITS;
+				units = 9;  /* GB */
+		}
+	}
+
+	if (size >= 65535 ||  /* Does not fit into two bytes */
+	    (target_partition == 0 && psd_cnt < 2)) {
+		result = -EINVAL;
+		goto out;
+	}
+
 	psdo = pgo + PART_PAGE_FIXED_LENGTH;
-	if (psd_cnt > bp[pgo + PP_OFF_MAX_ADD_PARTS]) {
-		bp[psdo] = bp[psdo + 1] = 0xff;  /* Rest of the tape */
+	/* The second condition is for HP DDS which use only one partition size
+	   descriptor */
+	if (target_partition > 0 && psd_cnt > bp[pgo + PP_OFF_MAX_ADD_PARTS]) {
+		bp[psdo] = bp[psdo + 1] = 0xff;  /* Rest of the tape to partition 0 */
 		psdo += 2;
 	}
 	memset(bp + psdo, 0, bp[pgo + PP_OFF_NBR_ADD_PARTS] * 2);
@@ -3370,7 +3457,7 @@ 
 		    psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],
 		    bp[pgo + PP_OFF_NBR_ADD_PARTS]);
 
-	if (size <= 0) {
+	if (size == 0) {
 		bp[pgo + PP_OFF_NBR_ADD_PARTS] = 0;
 		if (psd_cnt <= bp[pgo + PP_OFF_MAX_ADD_PARTS])
 		    bp[pgo + MP_OFF_PAGE_LENGTH] = 6;
@@ -3378,22 +3465,54 @@ 
 	} else {
 		bp[psdo] = (size >> 8) & 0xff;
 		bp[psdo + 1] = size & 0xff;
+		if (target_partition == 0)
+			bp[psdo + 2] = bp[psdo + 3] = 0xff;
 		bp[pgo + 3] = 1;
 		if (bp[pgo + MP_OFF_PAGE_LENGTH] < 8)
 		    bp[pgo + MP_OFF_PAGE_LENGTH] = 8;
 		DEBC_printk(STp, "Formatting tape with two partitions "
-			    "(1 = %d MB).\n", size);
+			    "(1 = %d MB).\n",
+			    units > 0 ? size * 1000 : size);
 	}
 	bp[pgo + PP_OFF_PART_UNITS] = 0;
 	bp[pgo + PP_OFF_RESERVED] = 0;
-	bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | PP_MSK_PSUM_MB;
+	if (size != 1 || units != 0) {
+		bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | psum |
+			(bp[pgo + PP_OFF_FLAGS] & 0x07);
+		bp[pgo + PP_OFF_PART_UNITS] = units;
+	} else
+		bp[pgo + PP_OFF_FLAGS] = PP_BIT_FDP |
+			(bp[pgo + PP_OFF_FLAGS] & 0x1f);
+	bp[pgo + MP_OFF_PAGE_LENGTH] = 6 + psd_cnt * 2;
+
+	DEBC_printk(STp, "Sent partition page length is %d bytes. needs_format: %d\n",
+		    bp[pgo + MP_OFF_PAGE_LENGTH] + 2, needs_format);
+	DEBC_printk(STp, "PP: max %u, add %u, xdp %u, psum %02x, pofmetc %u, "
+		    "rec %02x, units %02x, sizes: %u %u\n",
+		    bp[pgo + PP_OFF_MAX_ADD_PARTS],
+		    bp[pgo + PP_OFF_NBR_ADD_PARTS],
+		    (bp[pgo + PP_OFF_FLAGS] & 0xe0) >> 5,
+		    (bp[pgo + PP_OFF_FLAGS] & 0x18) >> 3,
+		    bp[pgo + PP_OFF_FLAGS] & 0x07,
+		    bp[pgo + 5],
+		    bp[pgo + PP_OFF_PART_UNITS],
+		    bp[pgo + 8] * 256 + bp[pgo + 9],
+		    bp[pgo + 10] * 256 + bp[pgo + 11]);
+	DEBC_printk(STp, "MP: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		    bp[pgo], bp[pgo+1], bp[pgo+2], bp[pgo+3], bp[pgo+4], bp[pgo+5],
+		    bp[pgo+6], bp[pgo+7], bp[pgo+8], bp[pgo+9], bp[pgo+10], bp[pgo+11]);
 
 	result = write_mode_page(STp, PART_PAGE, 1);
+
+	if (!result && needs_format)
+		result = format_medium(STp, 1);
+
 	if (result) {
 		st_printk(KERN_INFO, STp, "Partitioning of tape failed.\n");
 		result = (-EIO);
 	}
 
+out:
 	return result;
 }
 
@@ -3570,7 +3689,7 @@ 
 				retval = (-EINVAL);
 				goto out;
 			}
-			if ((i = st_int_ioctl(STp, MTREW, 0)) < 0 ||
+			if ((i = do_load_unload(STp, file, 1)) < 0 ||
 			    (i = partition_tape(STp, mtc.mt_count)) < 0) {
 				retval = i;
 				goto out;
@@ -3581,7 +3700,7 @@ 
 				STp->ps[i].last_block_valid = 0;
 			}
 			STp->partition = STp->new_partition = 0;
-			STp->nbr_partitions = 1;	/* Bad guess ?-) */
+			STp->nbr_partitions = mtc.mt_count > 0 ? 2 : 1;
 			STps->drv_block = STps->drv_file = 0;
 			retval = 0;
 			goto out;