diff mbox

st driver doesn't seem to grok LTO partitioning

Message ID alpine.LSU.2.11.1512251732060.4761@xnv.znxvfnen.cevingr (mailing list archive)
State Under Review, archived
Headers show

Commit Message

Kai Mäkisara Dec. 25, 2015, 3:53 p.m. UTC
On Monday 2015-12-21 20:57, "Kai Mäkisara (Kolumbus)" wrote:

...
>I can look at the manuals during Christmas holidays and try to think about a suggestion.
>All other suggestions are, of course, welcome. My view may be somewhat theoretical
>because I don’t have access to current hardware.
>
I have had some time to look at manuals and even do some coding :-)

The partitioning is initiated with the MTMKPART operation of the 
MTIOCTOP ioctl. This has one int parameter mt_count that is used to 
specify the size in megabytes of the first partition on the tape. Note 
that, for historical reasons, the number of this partition used to be 1, 
not zero. So, the ioctls allocates the specified space to partition 1 
and the rest to partition 0. This intefarce does not allow specifying 
more than two partitions. We can make work for current drives quite 
easily. More than two partitions need a new API but do we have a real 
need for this?

The current code did not work basically because the current drives need 
a separate FORMAT MEDIUM command to do the partitioning specified by 
MODE SELECT. There are smaller details that could have also been a 
problem.

The patch at the end of this message is an attempt to make the 
partitioning work for both old and new drives. The patch is against st.c 
from the current git kernel, although I have tested it in 4.3.3. It 
seems to work with my HP DDS-4 drive. It includes some debugging printks 
and I have tried to see that the commands that would have been sent to 
newer drives are basically correct.

The patch uses the scsi level of the device to separate processing. The 
FORMAT MEDIUM command is defined in SCSI-3 and I suppose that no current 
drive is still SCSI-2. In addition to the "sane" changes using the 
method to specify partitions, the patch implements the following: if the 
size is 1, the driver tells the drive to use default partitioning for 
two partitions. For the HP Ultrium this should result in partition 0 of 
1425 GB and 1 of 37.5 GB. I don't know if this is a useful addition.


Kai

------------------------------------8<----------------------------------

Comments

Emmanuel Florac Dec. 25, 2015, 5:47 p.m. UTC | #1
Le Fri, 25 Dec 2015 17:53:46 +0200 (EET)
Kai Makisara <Kai.Makisara@kolumbus.fi> écrivait:

> The patch at the end of this message is an attempt to make the 
> partitioning work for both old and new drives. The patch is against
> st.c from the current git kernel, although I have tested it in 4.3.3.
> It seems to work with my HP DDS-4 drive. It includes some debugging
> printks and I have tried to see that the commands that would have
> been sent to newer drives are basically correct.
> 
> The patch uses the scsi level of the device to separate processing.
> The FORMAT MEDIUM command is defined in SCSI-3 and I suppose that no
> current drive is still SCSI-2. In addition to the "sane" changes
> using the method to specify partitions, the patch implements the
> following: if the size is 1, the driver tells the drive to use
> default partitioning for two partitions. For the HP Ultrium this
> should result in partition 0 of 1425 GB and 1 of 37.5 GB. I don't
> know if this is a useful addition.

Great I'll give it a try soon next week!
Emmanuel Florac Dec. 29, 2015, 4:14 p.m. UTC | #2
Le Fri, 25 Dec 2015 17:53:46 +0200 (EET)
Kai Makisara <Kai.Makisara@kolumbus.fi> écrivait:

> The patch uses the scsi level of the device to separate processing.
> The FORMAT MEDIUM command is defined in SCSI-3 and I suppose that no
> current drive is still SCSI-2. In addition to the "sane" changes
> using the method to specify partitions, the patch implements the
> following: if the size is 1, the driver tells the drive to use
> default partitioning for two partitions. For the HP Ultrium this
> should result in partition 0 of 1425 GB and 1 of 37.5 GB. I don't
> know if this is a useful addition.
> 

I didn't look much at the code, but here's what's happening when
running "mt -f /dev/st0 mkpartition 1":

Dec 29 17:01:53 shakuhachi kernel: st: Version 20151225, fixed bufsize 32768, s/g segs 256
Dec 29 17:01:53 shakuhachi kernel: st 7:0:0:0: Attached scsi tape st0
Dec 29 17:01:53 shakuhachi kernel: st 7:0:0:0: st0: try direct i/o: yes (alignment 512 B)
Dec 29 17:01:53 shakuhachi kernel: st 7:0:0:0: st0: Block limits 1 - 16777215 bytes.
Dec 29 17:01:53 shakuhachi kernel: st 7:0:0:0: st0: Mode sense. Length 11, medium 0, WBS 10, BLL 8
Dec 29 17:01:53 shakuhachi kernel: st 7:0:0:0: st0: Density 5a, tape length: 0, drv buffer: 1
Dec 29 17:01:53 shakuhachi kernel: st 7:0:0:0: st0: Block size: 0, buffer size: 4096 (1 blocks).
Dec 29 17:02:04 shakuhachi kernel: st 7:0:0:0: st0: Block limits 1 - 16777215 bytes.
Dec 29 17:02:04 shakuhachi kernel: st 7:0:0:0: st0: Mode sense. Length 11, medium 0, WBS 10, BLL 8
Dec 29 17:02:04 shakuhachi kernel: st 7:0:0:0: st0: Density 5a, tape length: 0, drv buffer: 1
Dec 29 17:02:04 shakuhachi kernel: st 7:0:0:0: st0: Block size: 0, buffer size: 4096 (1 blocks).
Dec 29 17:02:04 shakuhachi kernel: st 7:0:0:0: st0: Rewinding tape.
Dec 29 17:03:06 shakuhachi kernel: st 7:0:0:0: st0: Block limits 1 - 16777215 bytes.
Dec 29 17:03:06 shakuhachi kernel: st 7:0:0:0: st0: Mode sense. Length 11, medium 0, WBS 10, BLL 8
Dec 29 17:03:06 shakuhachi kernel: st 7:0:0:0: st0: Density 5a, tape length: 0, drv buffer: 1
Dec 29 17:03:06 shakuhachi kernel: st 7:0:0:0: st0: Block size: 0, buffer size: 4096 (1 blocks).
Dec 29 17:07:20 shakuhachi kernel: st 7:0:0:0: st0: Error: 8000002,cmd: 0 0 0 0 0 0

Note that I've simply patched my plain vanilla 3.18.25 st modules.
There doesn't seem to be any difference with newer (or older) kernels,
anyway.

Do you want me to try anything in particular? Is my mt version OK (v
1.1)?
Emmanuel Florac Dec. 29, 2015, 4:58 p.m. UTC | #3
Le Fri, 25 Dec 2015 17:53:46 +0200 (EET)
Kai Makisara <Kai.Makisara@kolumbus.fi> écrivait:

> The patch uses the scsi level of the device to separate processing.
> The FORMAT MEDIUM command is defined in SCSI-3 and I suppose that no
> current drive is still SCSI-2. In addition to the "sane" changes
> using the method to specify partitions, the patch implements the
> following: if the size is 1, the driver tells the drive to use
> default partitioning for two partitions. For the HP Ultrium this
> should result in partition 0 of 1425 GB and 1 of 37.5 GB. I don't
> know if this is a useful addition.

Still testing, with another, LTO-5 tape:

~# mt -f /dev/nst0 mkpartition 0
/dev/nst0: Invalid argument

Dec 29 17:57:38 shakuhachi kernel: st 7:0:0:0: st0: Block limits 1 - 16777215 bytes.
Dec 29 17:57:38 shakuhachi kernel: st 7:0:0:0: st0: Mode sense. Length 11, medium 0, WBS 10, BLL 8
Dec 29 17:57:38 shakuhachi kernel: st 7:0:0:0: st0: Density 58, tape length: 0, drv buffer: 1
Dec 29 17:57:38 shakuhachi kernel: st 7:0:0:0: st0: Block size: 0, buffer size: 4096 (1 blocks).
Emmanuel Florac Dec. 29, 2015, 4:59 p.m. UTC | #4
Le Fri, 25 Dec 2015 17:53:46 +0200 (EET)
Kai Makisara <Kai.Makisara@kolumbus.fi> écrivait:

> the patch implements the following: if the 
> size is 1, the driver tells the drive to use default partitioning for 
> two partitions. For the HP Ultrium this should result in partition 0
> of 1425 GB and 1 of 37.5 GB. I don't know if this is a useful
> addition.

Oh BTW I didn't check what's happening in code, but actual values
should be 37.5 GB for partition 0 and 1425 GB for partition 1, not the
other way around.
Kai Mäkisara Dec. 29, 2015, 5:18 p.m. UTC | #5
> On 29.12.2015, at 18.59, Emmanuel Florac <eflorac@intellique.com> wrote:
> 
> Le Fri, 25 Dec 2015 17:53:46 +0200 (EET)
> Kai Makisara <Kai.Makisara@kolumbus.fi> écrivait:
> 
>> the patch implements the following: if the 
>> size is 1, the driver tells the drive to use default partitioning for 
>> two partitions. For the HP Ultrium this should result in partition 0
>> of 1425 GB and 1 of 37.5 GB. I don't know if this is a useful
>> addition.
> 
> Oh BTW I didn't check what's happening in code, but actual values
> should be 37.5 GB for partition 0 and 1425 GB for partition 1, not the
> other way around.
> 

What I quoted is from the HP manual. The driver tells the drive to format
the tape according to the default of the drive (i.e., sets the FDP bit in the
mode page).

The order of partitions is an interesting question. The usual use case is
to have a small partition for the index and a large partition for the data.
The small partition should positioned so that it can be accessed fast. For
the old really linear drives this means the beginning. It was decided that
the first partition on the tape was given number one and the second
partition had the number zero. The HP LTO seems to use this numbering
for the default.

The SCSI standard does not specify how the partitions should be numbered.
Many drives use physically sequential numbering nowadays. LTO uses
wrap-wise partitioning and I don’t think locations of the partitions have any
effect on access speed.

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
Kai Mäkisara Dec. 29, 2015, 5:46 p.m. UTC | #6
> On 29.12.2015, at 18.58, Emmanuel Florac <eflorac@intellique.com> wrote:
> 
> Le Fri, 25 Dec 2015 17:53:46 +0200 (EET)
> Kai Makisara <Kai.Makisara@kolumbus.fi> écrivait:
> 
>> The patch uses the scsi level of the device to separate processing.
>> The FORMAT MEDIUM command is defined in SCSI-3 and I suppose that no
>> current drive is still SCSI-2. In addition to the "sane" changes
>> using the method to specify partitions, the patch implements the
>> following: if the size is 1, the driver tells the drive to use
>> default partitioning for two partitions. For the HP Ultrium this
>> should result in partition 0 of 1425 GB and 1 of 37.5 GB. I don't
>> know if this is a useful addition.
> 
> Still testing, with another, LTO-5 tape:
> 
> ~# mt -f /dev/nst0 mkpartition 0
> /dev/nst0: Invalid argument
> 
It seems that you have not told the st driver that your drive knows partitions. One way to set the
options is to use the stint program and proper definitions. You can also use
mtst -f /dev/nst0 stsetoption can-partitions

> Dec 29 17:57:38 shakuhachi kernel: st 7:0:0:0: st0: Block limits 1 - 16777215 bytes.
> Dec 29 17:57:38 shakuhachi kernel: st 7:0:0:0: st0: Mode sense. Length 11, medium 0, WBS 10, BLL 8
> Dec 29 17:57:38 shakuhachi kernel: st 7:0:0:0: st0: Density 58, tape length: 0, drv buffer: 1
> Dec 29 17:57:38 shakuhachi kernel: st 7:0:0:0: st0: Block size: 0, buffer size: 4096 (1 blocks).
> 
The st driver prints some debugging data to the kernel log if debugging is enabled. If the driver
is compiled with debugging (it is nowadays default but in 3.18 you should change DEBUG to 1
in st.c). The debugging output can be enabled with the command:
mtst -f /dev/nst0 stsetoption debug

Here is the debugging output when I make a 10 MB partition with my drive:
[ 2199.572546] st 4:0:5:0: [st0] Block limits 1 - 16777215 bytes.
[ 2199.573367] st 4:0:5:0: [st0] Mode sense. Length 11, medium 0, WBS 10, BLL 8
[ 2199.573375] st 4:0:5:0: [st0] Density 26, tape length: 0, drv buffer: 1
[ 2199.573380] st 4:0:5:0: [st0] Block size: 0, buffer size: 4096 (1 blocks).
[ 2199.573403] st 4:0:5:0: [st0] Rewinding tape.
[ 2199.575319] st 4:0:5:0: [st0] Partition page length is 10 bytes.
[ 2199.575328] st 4:0:5:0: [st0] PP: max 1, add 1, xdp 0, psum 02, pofmetc 0,rec 03 units 00, sizes: 100 65535
[ 2199.575333] st 4:0:5:0: [st0] psd_cnt 1, max.parts 1, nbr_parts 1
[ 2199.575338] st 4:0:5:0: [st0] Formatting tape with two partitions (1 = 10 MB).
[ 2199.575342] st 4:0:5:0: [st0] Sent partition page length is 10 bytes. needs_format: 0
[ 2199.575348] st 4:0:5:0: [st0] PP: max 1, add 1, xdp 1, psum 02, pofmetc 0,rec 03 units 00, sizes: 10 65535

Regardless whether the partitioning works with your drive, your should see at least few lines after “Rewinding tape”.
The driver first reads the partition mode page and (for testing) prints some data from the page.

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
Emmanuel Florac Dec. 29, 2015, 5:58 p.m. UTC | #7
Le Tue, 29 Dec 2015 19:46:11 +0200
"Kai Mäkisara (Kolumbus)" <kai.makisara@kolumbus.fi> écrivait:

> It seems that you have not told the st driver that your drive knows
> partitions. One way to set the options is to use the stint program
> and proper definitions. You can also use mtst -f /dev/nst0
> stsetoption can-partitions
> 

Silly me. I forgot that one.

> The st driver prints some debugging data to the kernel log if
> debugging is enabled. If the driver is compiled with debugging (it is
> nowadays default but in 3.18 you should change DEBUG to 1 in st.c).

Yup this is the output from the driver with DEBUG at 1. 

> The debugging output can be enabled with the command: mtst
> -f /dev/nst0 stsetoption debug

Ah yes, it works!

> Regardless whether the partitioning works with your drive, your
> should see at least few lines after “Rewinding tape”. The driver
> first reads the partition mode page and (for testing) prints some
> data from the page.

So here is the result of my testings so far. Alas, it fails on the
goal line!:

# mt -f /dev/st0  stsetoption debug


Dec 29 17:57:38 shakuhachi kernel: st 7:0:0:0: st0: Block limits 1 - 16777215 bytes.
Dec 29 17:57:38 shakuhachi kernel: st 7:0:0:0: st0: Mode sense. Length 11, medium 0, WBS 10, BLL 8
Dec 29 17:57:38 shakuhachi kernel: st 7:0:0:0: st0: Density 58, tape length: 0, drv buffer: 1
Dec 29 17:57:38 shakuhachi kernel: st 7:0:0:0: st0: Block size: 0, buffer size: 4096 (1 blocks).
Dec 29 18:51:45 shakuhachi kernel: st 7:0:0:0: st0: Error: 8000002, cmd: 0 0 0 0 0 0
Dec 29 18:51:45 shakuhachi kernel: st0: Sense Key : Unit Attention [current] 
Dec 29 18:51:45 shakuhachi kernel: st0: Add. Sense: Not ready to ready change, medium may have changed
Dec 29 18:51:45 shakuhachi kernel: st 7:0:0:0: st0: Block limits 1 - 16777215 bytes.
Dec 29 18:51:45 shakuhachi kernel: st 7:0:0:0: st0: Mode sense. Length 11, medium 0, WBS 10, BLL 8
Dec 29 18:51:45 shakuhachi kernel: st 7:0:0:0: st0: Density 5a, tape length: 0, drv buffer: 1
Dec 29 18:51:45 shakuhachi kernel: st 7:0:0:0: st0: Block size: 0, buffer size: 4096 (1 blocks).
Dec 29 18:51:45 shakuhachi kernel: st 7:0:0:0: st0: Mode 0 options: buffer writes: 1, async writes: 1, read ahead: 1
Dec 29 18:51:45 shakuhachi kernel: st 7:0:0:0: st0:     can bsr: 1, two FMs: 0, fast mteom: 0, auto lock: 0,
Dec 29 18:51:45 shakuhachi kernel: st 7:0:0:0: st0:     defs for wr: 0, no block limits: 0, partitions: 0, s2 log: 0
Dec 29 18:51:45 shakuhachi kernel: st 7:0:0:0: st0:     sysv: 0 nowait: 0 sili: 0 nowait_filemark: 0
Dec 29 18:51:45 shakuhachi kernel: st 7:0:0:0: st0:     debugging: 1
Dec 29 18:51:45 shakuhachi kernel: st 7:0:0:0: st0: Rewinding tape.

# tapeinfo -f /dev/sg6
Product Type: Tape Drive
Vendor ID: 'HP      '
Product ID: 'Ultrium 6-SCSI  '
Revision: '329U'
Attached Changer API: No
SerialNumber: 'HU1302U4RC'
MinBlock: 1
MaxBlock: 16777215
SCSI ID: 0
SCSI LUN: 0
Ready: yes
BufferedMode: yes
Medium Type: Not Loaded
Density Code: 0x5a
BlockSize: 0
DataCompEnabled: yes
DataCompCapable: yes
DataDeCompEnabled: yes
CompType: 0x1
DeCompType: 0x1
BOP: yes
Block Position: 0
ActivePartition: 0
EarlyWarningSize: 0
NumPartitions: 0
MaxPartitions: 3

~# mt -f /dev/st0  stsetoption can-partitions

Dec 29 18:54:04 shakuhachi kernel: st 7:0:0:0: st0: Block limits 1 - 16777215 bytes.
Dec 29 18:54:04 shakuhachi kernel: st 7:0:0:0: st0: Mode sense. Length 11, medium 0, WBS 10, BLL 8
Dec 29 18:54:04 shakuhachi kernel: st 7:0:0:0: st0: Density 5a, tape length: 0, drv buffer: 1
Dec 29 18:54:04 shakuhachi kernel: st 7:0:0:0: st0: Block size: 0, buffer size: 4096 (1 blocks).
Dec 29 18:54:04 shakuhachi kernel: st 7:0:0:0: st0: Updating partition number in status.
Dec 29 18:54:04 shakuhachi kernel: st 7:0:0:0: st0: Got tape pos. blk 0 part 0.
Dec 29 18:54:04 shakuhachi kernel: st 7:0:0:0: st0: Mode 0 options: buffer writes: 1, async writes: 1, read ahead: 1
Dec 29 18:54:04 shakuhachi kernel: st 7:0:0:0: st0:     can bsr: 1, two FMs: 0, fast mteom: 0, auto lock: 0,
Dec 29 18:54:04 shakuhachi kernel: st 7:0:0:0: st0:     defs for wr: 0, no block limits: 0, partitions: 1, s2 log: 0
Dec 29 18:54:04 shakuhachi kernel: st 7:0:0:0: st0:     sysv: 0 nowait: 0 sili: 0 nowait_filemark: 0
Dec 29 18:54:04 shakuhachi kernel: st 7:0:0:0: st0:     debugging: 1
Dec 29 18:54:04 shakuhachi kernel: st 7:0:0:0: st0: Rewinding tape.

# mt -f /dev/st0  mkpartition 1
/dev/st0: Input/output error

Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: Block limits 1 - 16777215 bytes.
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: Mode sense. Length 11, medium 0, WBS 10, BLL 8
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: Density 5a, tape length: 0, drv buffer: 1
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: Block size: 0, buffer size: 4096 (1 blocks).
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: Rewinding tape.
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: Partition page length is 16 bytes.
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: PP: max 3, add 0, xdp 1, psum 03, pofmetc 0,rec 03 units 09, sizes: 2620 0
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: psd_cnt 2, max.parts 3, nbr_parts 0
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: Formatting tape with two partitions (FDP).
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: Sent partition page length is 12 bytes. needs_format: 0
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: PP: max 3, add 1, xdp 4, psum 00, pofmetc 0,rec 03 units 00, sizes: 65535 0
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: Error: 8000002, cmd: 15 10 0 0 18 0
Dec 29 18:55:54 shakuhachi kernel: st0: Sense Key : Illegal Request [current] 
Dec 29 18:55:54 shakuhachi kernel: st0: Add. Sense: Invalid field in parameter list
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: Partitioning of tape failed.
Dec 29 18:55:54 shakuhachi kernel: st 7:0:0:0: st0: Rewinding tape.
diff mbox

Patch

--- ref/drivers/scsi/st.c	2015-12-21 18:54:05.068882001 +0200
+++ new/drivers/scsi/st.c	2015-12-25 16:49:54.345263675 +0200
@@ -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 = "20151225";
 
 #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. */
@@ -3344,7 +3347,9 @@ 
 static int partition_tape(struct scsi_tape *STp, int size)
 {
 	int result;
+	int scsi3 = STp->device->scsi_level >= SCSI_3, needs_format = 0;
 	int pgo, psd_cnt, psdo;
+	int psum = PP_MSK_PSUM_MB, units = 0;
 	unsigned char *bp;
 
 	result = read_mode_page(STp, PART_PAGE, 0);
@@ -3357,10 +3362,32 @@ 
 	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);
-
-	psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - PART_PAGE_FIXED_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] & 0x03,
+		    bp[pgo + 5],
+		    bp[pgo + PP_OFF_PART_UNITS],
+		    bp[pgo + 8] * 256 + bp[pgo + 9],
+		    bp[pgo + 10] * 256 + bp[pgo + 11]);
+
+	if (scsi3) {
+		psd_cnt = size > 0 ? 2 : 1;
+		if (size >= 65535) {
+			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)
+		return -EINVAL;
 	psdo = pgo + PART_PAGE_FIXED_LENGTH;
-	if (psd_cnt > bp[pgo + PP_OFF_MAX_ADD_PARTS]) {
+	if (scsi3 || psd_cnt > bp[pgo + PP_OFF_MAX_ADD_PARTS]) {
 		bp[psdo] = bp[psdo + 1] = 0xff;  /* Rest of the tape */
 		psdo += 2;
 	}
@@ -3375,6 +3402,11 @@ 
 		if (psd_cnt <= bp[pgo + PP_OFF_MAX_ADD_PARTS])
 		    bp[pgo + MP_OFF_PAGE_LENGTH] = 6;
 		DEBC_printk(STp, "Formatting tape with one partition.\n");
+	} else if (size == 1) {
+		bp[pgo + PP_OFF_NBR_ADD_PARTS] = 1;
+		if (psd_cnt <= bp[pgo + PP_OFF_MAX_ADD_PARTS])
+		    bp[pgo + MP_OFF_PAGE_LENGTH] = 6;
+		DEBC_printk(STp, "Formatting tape with two partitions (FDP).\n");
 	} else {
 		bp[psdo] = (size >> 8) & 0xff;
 		bp[psdo + 1] = size & 0xff;
@@ -3382,13 +3414,55 @@ 
 		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) {
+		bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | psum |
+			(bp[pgo + PP_OFF_FLAGS] & 0x0F);
+		bp[pgo + PP_OFF_PART_UNITS] = units;
+	} else
+		bp[pgo + PP_OFF_FLAGS] = PP_BIT_FDP;
+	if (scsi3)
+		needs_format = (bp[pgo + PP_OFF_FLAGS] & PP_MSK_POFM) != 0;
+	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] & 0x03,
+		    bp[pgo + 5],
+		    bp[pgo + PP_OFF_PART_UNITS],
+		    bp[pgo + 8] * 256 + bp[pgo + 9],
+		    bp[pgo + 10] * 256 + bp[pgo + 11]);
 
 	result = write_mode_page(STp, PART_PAGE, 1);
+
+	if (!result && needs_format) {
+		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] = 1;
+		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;
+	}
+
 	if (result) {
 		st_printk(KERN_INFO, STp, "Partitioning of tape failed.\n");
 		result = (-EIO);