Hi Kai, With the changes the I get a failure partitioning a HP DAT72 drive (DDS-5): # ./mt -f /dev/st1 stsetoption debug # ./mt -f /dev/st1 stsetoption can-partitions # ./mt -f /dev/st1 mkpartition 1000 /dev/st1: Input/output error [ 3944.387190] st: Unloaded. [ 3949.420128] st: Version 20160124, fixed bufsize 32768, s/g segs 256 [ 3949.421167] st 5:0:1:0: Attached scsi tape st0 [ 3949.421169] st 5:0:1:0: st0: try direct i/o: yes (alignment 512 B) [ 3949.422108] st 6:0:3:0: Attached scsi tape st1 [ 3949.422112] st 6:0:3:0: st1: try direct i/o: yes (alignment 512 B) [ 3955.866684] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes. [ 3955.866992] st 6:0:3:0: [st1] Mode 0 options: buffer writes: 1, async writes: 1, read ahead: 1 [ 3955.866996] st 6:0:3:0: [st1] can bsr: 1, two FMs: 0, fast mteom: 0, auto lock: 0, [ 3955.866999] st 6:0:3:0: [st1] defs for wr: 0, no block limits: 0, partitions: 0, s2 log: 0 [ 3955.867002] st 6:0:3:0: [st1] sysv: 0 nowait: 0 sili: 0 nowait_filemark:0 [ 3955.867005] st 6:0:3:0: [st1] debugging: 1 [ 3955.867010] st 6:0:3:0: [st1] Rewinding tape. [ 3961.330913] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes. [ 3961.331366] st 6:0:3:0: [st1] Mode sense. Length 11, medium 0, WBS 10, BLL 8 [ 3961.331370] st 6:0:3:0: [st1] Density 47, tape length: 0, drv buffer: 1 [ 3961.331372] st 6:0:3:0: [st1] Block size: 0, buffer size: 4096 (1 blocks). [ 3961.331384] st 6:0:3:0: [st1] Mode 0 options: buffer writes: 1, async writes: 1, read ahead: 1 [ 3961.331386] st 6:0:3:0: [st1] can bsr: 1, two FMs: 0, fast mteom: 0, auto lock: 0, [ 3961.331388] st 6:0:3:0: [st1] defs for wr: 0, no block limits: 0, partitions: 1, s2 log: 0 [ 3961.331389] st 6:0:3:0: [st1] sysv: 0 nowait: 0 sili: 0 nowait_filemark: 0 [ 3961.331391] st 6:0:3:0: [st1] debugging: 1 [ 3961.331393] st 6:0:3:0: [st1] Rewinding tape. [ 3976.387354] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes. [ 3976.387651] st 6:0:3:0: [st1] Mode sense. Length 11, medium 0, WBS 10, BLL 8 [ 3976.387653] st 6:0:3:0: [st1] Density 47, tape length: 0, drv buffer: 1 [ 3976.387655] st 6:0:3:0: [st1] Block size: 0, buffer size: 4096 (1 blocks). [ 3976.387656] st 6:0:3:0: [st1] Updating partition number in status. [ 3976.388001] st 6:0:3:0: [st1] Got tape pos. blk 0 part 0. [ 3976.388013] st 6:0:3:0: [st1] Loading tape. [ 3976.388909] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes. [ 3976.389261] st 6:0:3:0: [st1] Mode sense. Length 11, medium 0, WBS 10, BLL 8 [ 3976.389265] st 6:0:3:0: [st1] Density 47, tape length: 0, drv buffer: 1 [ 3976.389269] st 6:0:3:0: [st1] Block size: 0, buffer size: 4096 (1 blocks). [ 3976.389605] st 6:0:3:0: [st1] Partition page length is 10 bytes. [ 3976.389610] st 6:0:3:0: [st1] PP: max 1, add 0, xdp 0, psum 02, pofmetc 0, rec 03, units 00, sizes: 0 65535 [ 3976.389614] st 6:0:3:0: [st1] MP: 11 08 01 00 10 03 00 00 00 00 ff ff [ 3976.389618] st 6:0:3:0: [st1] psd_cnt 2, max.parts 1, nbr_parts 0 [ 3976.389620] st 6:0:3:0: [st1] Formatting tape with two partitions (1 = 1000 MB). [ 3976.389623] st 6:0:3:0: [st1] Sent partition page length is 12 bytes. needs_format: 0 [ 3976.389627] st 6:0:3:0: [st1] PP: max 1, add 1, xdp 1, psum 02, pofmetc 0, rec 03, units 00, sizes: 65535 1000 [ 3976.389631] st 6:0:3:0: [st1] MP: 11 0a 01 01 30 03 00 00 ff ff 03 e8 [ 3976.390727] st 6:0:3:0: [st1] Error: 8000002, cmd: 15 10 0 0 18 0 [ 3976.390731] st 6:0:3:0: [st1] Sense Key : Illegal Request [current] [ 3976.390734] st 6:0:3:0: [st1] Add. Sense: Invalid field in parameter list [ 3976.390735] st 6:0:3:0: [st1] Partitioning of tape failed. [ 3976.390806] st 6:0:3:0: [st1] Rewinding tape. Using a slightly older kernel to partition the DAT72 drive works (same 3 commands as above): [ 339.578950] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes. [ 339.579263] st 6:0:3:0: [st1] Mode 0 options: buffer writes: 1, async writes: 1, read ahead: 1 [ 339.579266] st 6:0:3:0: [st1] can bsr: 1, two FMs: 0, fast mteom: 0, auto lock: 0, [ 339.579268] st 6:0:3:0: [st1] defs for wr: 0, no block limits: 0, partitions: 0, s2 log: 0 [ 339.579269] st 6:0:3:0: [st1] sysv: 0 nowait: 0 sili: 0 nowait_filemark: 0 [ 339.579271] st 6:0:3:0: [st1] debugging: 1 [ 339.579275] st 6:0:3:0: [st1] Rewinding tape. [ 345.335252] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes. [ 345.335556] st 6:0:3:0: [st1] Mode sense. Length 11, medium 0, WBS 10, BLL 8 [ 345.335559] st 6:0:3:0: [st1] Density 47, tape length: 0, drv buffer: 1 [ 345.335562] st 6:0:3:0: [st1] Block size: 0, buffer size: 4096 (1 blocks). [ 345.335573] st 6:0:3:0: [st1] Mode 0 options: buffer writes: 1, async writes: 1, read ahead: 1 [ 345.335575] st 6:0:3:0: [st1] can bsr: 1, two FMs: 0, fast mteom: 0, auto lock: 0, [ 345.335577] st 6:0:3:0: [st1] defs for wr: 0, no block limits: 0, partitions: 1, s2 log: 0 [ 345.335579] st 6:0:3:0: [st1] sysv: 0 nowait: 0 sili: 0 nowait_filemark: 0 [ 345.335581] st 6:0:3:0: [st1] debugging: 1 [ 345.335583] st 6:0:3:0: [st1] Rewinding tape. [ 351.583495] st 6:0:3:0: [st1] Block limits 1 - 16777215 bytes. [ 351.583779] st 6:0:3:0: [st1] Mode sense. Length 11, medium 0, WBS 10, BLL 8 [ 351.583782] st 6:0:3:0: [st1] Density 47, tape length: 0, drv buffer: 1 [ 351.583783] st 6:0:3:0: [st1] Block size: 0, buffer size: 4096 (1 blocks). [ 351.583785] st 6:0:3:0: [st1] Updating partition number in status. [ 351.584184] st 6:0:3:0: [st1] Got tape pos. blk 0 part 0. [ 351.584196] st 6:0:3:0: [st1] Rewinding tape. [ 351.584906] st 6:0:3:0: [st1] Partition page length is 10 bytes. [ 351.584908] st 6:0:3:0: [st1] psd_cnt 1, max.parts 1, nbr_parts 0 [ 351.584910] st 6:0:3:0: [st1] Formatting tape with two partitions (1 = 1000 MB). [ 723.976554] st 6:0:3:0: [st1] Rewinding tape. Thanks Shane > -----Original Message----- > From: linux-scsi-owner@xxxxxxxxxxxxxxx [mailto:linux-scsi- > owner@xxxxxxxxxxxxxxx] On Behalf Of Kai Makisara > Sent: Monday, January 25, 2016 8:05 AM > To: Seymour, Shane M > Cc: Laurence Oberman; Emmanuel Florac; Laurence Oberman; linux- > scsi@xxxxxxxxxxxxxxx > Subject: RE: What partition should the MTMKPART argument specify? Was: > Re: st driver doesn't seem to grok LTO partitioning > > On Friday 2016-01-22 04:10, Seymour, Shane M wrote: > > > >> -----Original Message----- > >> From: linux-scsi-owner@xxxxxxxxxxxxxxx [mailto:linux-scsi- > >> owner@xxxxxxxxxxxxxxx] On Behalf Of "Kai Mäkisara (Kolumbus)" > >> Sent: Friday, January 22, 2016 7:59 AM > >> To: Seymour, Shane M > >> Cc: Laurence Oberman; Emmanuel Florac; Laurence Oberman; linux- > >> scsi@xxxxxxxxxxxxxxx > >> Subject: What partition should the MTMKPART argument specify? Was: > Re: > >> st driver doesn't seem to grok LTO partitioning > >> > ... > >> > >> There seem to be lot of arguments supporting both possible choices. > Should > >> we use the existing definition (1) or change it for the drives supporting > SCSI > >> level >= 3 (or supporting FORMAT MEDIUM)? The definition can’t be > >> changed later. This is why we should make a good decision. > >> > >> Opinions? > > > >How about using the fact the size is signed to indicate one slightly different > >thing? I'm not sure if you'd call this using or abusing the fact that it's signed. > > > >Make the default behavior for a positive size the same as the current > >behavior for SCSI-2 (size applies to partition 1). If the size is negative then > >the absolute value of the size applies to partition 0. That provides some > >flexibility in choosing which partition the size applies to if it worked that > >way for all devices. > > > >With that you also get consistent behavior between tape drives without > >having to know if the size will apply to partition 0 or partition 1 based on > >the tape technology and you get the benefit of being able to set an > >explicit size for partition 0 or partition 1. > > > I like this suggestion, because of the reasons you point out. I think > this is using the fact that the argument is signed. > > >You could overload the value of 0 as well to use FDP to choose the sizes > >for the partitions (assuming 0 doesn't already have a side effect in > >the code). Then you get whatever the tape drive wants to do. > > > The value zero is used to specify only one partition. The previous > patches overloaded the size 1. However, I think supporting FDP is > useless nowadays: the drives that support FDP=1 seem to end up with the > same partitioning (two wraps to partition 1) with any small number as > argument. > > Below is a test patch that implements the current behaviour with > non-negative argument (but works with LTOs etc.) and makes partition > zero size absolute value of argument (MB) if argument is negative. If > you want to test the patch, note that the current mt-st does not accept > negative numbers. A minimal patch is needed. > > Thanks, > Kai > -------------------------------8<---------------------------------------- > --- ref/drivers/scsi/st.c 2015-12-21 18:54:05.068882001 +0200 > +++ new/drivers/scsi/st.c 2016-01-24 22:36:13.250928500 +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@xxxxxxxxxxx > > Some small formal changes - aeb, 950809 > @@ -17,7 +17,7 @@ > Last modified: 18-JAN-1998 Richard Gooch <rgooch@xxxxxxxxxxxxx> Devfs > support > */ > > -static const char *verstr = "20101219"; > +static const char *verstr = "20160124"; > > #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]); > + > + 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; > + } > + > + psd_cnt = size > 0 ? 2 : 1; > + 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 */ > + } > + } else > + psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - > + PART_PAGE_FIXED_LENGTH) / 2; > + > + if (size >= 65535 || /* Does not fit into two bytes */ > + (target_partition == 0 && psd_cnt < 2)) { > + result = -EINVAL; > + goto out; > + } > > - psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - > PART_PAGE_FIXED_LENGTH) / 2; > 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 if 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; ��.n��������+%������w��{.n�����{������ܨ}���Ơz�j:+v�����w����ޙ��&�)ߡ�a����z�ޗ���ݢj��w�f