I've discovered that there are three basic types of tape drives:
a) Tape drives that do not support partitions. Most QIC-style drives, DLT.
b) Tape drives that support two partitions. DAT drives, Ecrix VXA.
c) Tape drives that support "lots" of partitions (24 or more). Exabyte
Mammoth, Tandberg MLR/SLR-6 family. Maybe the AIT family (haven't had a
chance
to check that yet, but if the Mammoth does it, I'm pretty sure that AIT
does too).
There are exceptions to this partitioning schema, but mostly they are for old
and uninteresting drives ("uninteresting" because they do not hold enough data
to be useful in today's enterprise environment -- anybody seen a QIC-4GB-DC
lately?).
The current 'st.c' driver in linux/drivers/scsi/st.c only understands scheme
b), the two-partition DAT scheme. It does not understand scheme c) drives that
support "lots" of partitions. If you try issuing a partitioning command to a
drive that supports "lots" of partitions, or which supports the standard
SCSI-3 partitioning stuff out of the T-10 docs, the command fails. This is
because the 'length' field in SCSI-3 for MODE_SELECT page 0x11 (the Medium
Partition Page) must be what you read using MODE_SENSE for page 0x11.
Meanwhile, for DAT drives, the 'length' field must be 6 if you're zapping the
(second and only other) partition, and 8 if you creating the (second and only
other) partition.
I have patched the st.c driver so that it a) looks at the 'Maximum Additional
Partitions' field from the MODE_SENSE, and b) uses the SCSI-3 scheme for
generating the MODE_SELECT if 'Maximum Additional Partitions' is greater than
1 (i.e., we can have "lots" of partitions). This patch is attached. I am
tossing it out here for testing purposes prior to submitting it to whoever for
inclusion in the kernel.
To use:
Patch the driver. Re-compile your kernel or st module, reboot or
remove/reinsert
module, whatever, to get the new one going.
use 'mt -f /dev/st0 stoptions can-partition' to enable partition support
try 'mt -f /dev/st0 mkpartition 1' to create a 1mb partition (more or
less).
try 'mt -f /dev/st0 setpartition 1' to go to your new partition.
try 'mt -f /dev/st0 setpartition 0' to go back to partition 0.
try 'mt -f /dev/st0 mkpartition 0' to delete your partition (and erase all
data on the tape, sigh).
I'd appreciate if some of the more guru-ly of you would try this patch and
make sure it still works with your particular drive (or doesn't). This is
especially useful if you have an AIT, Mammoth, or SLR tape drive that
currently doesn't do partitions, but it's also a useful data point to make
sure that all known DDS DAT drives still work.
Known failure modes:
Certain older SLR drives, when using QIC-2GB-DC or QIC-4GB-DC tapes,
support only 2 partitions (i.e., M.A.P==1), but the Medium Partition Page uses
the SCSI-3 scheme. This fails there. On the other hand, nobody uses QIC-4GB-DC
tapes nowdays and I have no desire to figure out a workaround or kludge things
further by adding yet more drive-dependent code into the kernel. Those people
just won't be able to use partitions -- they can't use partitions now, with
the current code, so they're no worse off.
If a drive that supports exactly three partitions is ever produced (I know
of no such drive, and know of no plans for such a weird beast), this test
fails when there are already two partitions on the tape. Maybe. Without such a
drive existing, it's hard to check :-). On the other hand, such a tape drive
currently isn't supported by st.c, so they'd be no worse off than they are
today.
For the future:
The whole 'mkpartition' concept needs a bit of thought before the 2.6
kernel. It made sense back when the only tape drives that supported partitions
were DAT drives, and said drives only supported a maximum of two partitions.
It does not make sense today to have an interface that supports only two
partitions, when Exabyte Mammoth II drives can have up to 63 additional
partitions, and Tandberg MLR drives can have up to 35 additional partitions.
--
Eric Lee Green [EMAIL PROTECTED]
Software Engineer Visit our Web page:
Enhanced Software Technologies, Inc. http://www.estinc.com/
(602) 470-1115 voice (602) 470-1116 fax
--- linux/drivers/scsi/st.c.orig Sat May 22 14:51:26 1999
+++ linux/drivers/scsi/st.c Wed Mar 15 14:16:23 2000
@@ -2763,37 +2763,88 @@
#endif
}
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: Number of partitions %d.\n",dev,result);
+#endif
return result;
}
/* Partition the tape into two partitions if size > 0 or one partition if
size == 0 */
+
+/* Extensive changes made March 2000 by Eric Lee Green <[EMAIL PROTECTED]>
+ * in order to produce a SCSI-3-compliant Medium Partition Page in the
+ * case where we can have more than 1 additional partition (i.e., for most
+ * new tape drives, though this was tested with the Exabyte Mammoth 2).
+ * This perhaps is not the best way of detirmining whether I need to send
+ * the DAT-style medium partition page or the SCSI-3 style medium partition
+ * page, but it's the best that I can do :-(.
+ */
static int
partition_tape(struct inode * inode, int size)
{
int dev = TAPE_NR(inode->i_rdev), result;
int length;
+ int scsi3=0;
Scsi_Tape *STp;
Scsi_Cmnd * SCpnt = NULL;
unsigned char cmd[10], *bp;
- if ((result = nbr_partitions(inode)) < 0)
+ if ((result = nbr_partitions(inode)) < 0) {
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: nbr_partitions=%d\n", dev, result);
+#endif
return result;
+ }
STp = &(scsi_tapes[dev]);
/* The mode page is in the buffer. Let's modify it and write it. */
bp = &((STp->buffer)->b_data[0]);
+#if DEBUG
+ if (debugging)
+ {
+ int i,j;
+ for (i=0; i < MODE_HEADER_LENGTH+10; i++) {
+ if (i < MODE_HEADER_LENGTH) {
+ printk(ST_DEB_MSG "st%d: sense mode_header[%d]=0x%x\n",dev,i,bp[i]);
+ } else {
+ j=i-MODE_HEADER_LENGTH;
+ printk(ST_DEB_MSG "st%d: sense mode_sense[%d]=0x%x\n",dev,j,bp[i]);
+ }
+ }
+ }
+#endif
+ /* Warning: This *COULD* fail if we had a drive that could only do THREE
+ * partitions, but I know of no such drives. --E
+ if (bp[MODE_HEADER_LENGTH + 2] > 1) {
+ scsi3=1; /* true, we do scsi3.... */
+ }
+
if (size <= 0) {
- length = 8;
+ if (!scsi3) {/* we must be doing a dat or older SLR... */
+ length = 8;
+ } else {
+ length=bp[MODE_HEADER_LENGTH+1]+2; /* length field in the mode sense */
+ }
bp[MODE_HEADER_LENGTH + 3] = 0;
+ if (scsi3) { /* to zap these in SCSI 3, must have length = 0? */
+ bp[MODE_HEADER_LENGTH + 8] = 0;
+ bp[MODE_HEADER_LENGTH + 9] = 0;
+ }
#if DEBUG
if (debugging)
printk(ST_DEB_MSG "st%d: Formatting tape with one partition.\n", dev);
#endif
}
else {
- length = 10;
+ if (!scsi3) {
+ length = 10;
+ } else {
+ length=bp[MODE_HEADER_LENGTH+1]+2;
+ }
bp[MODE_HEADER_LENGTH + 3] = 1;
bp[MODE_HEADER_LENGTH + 8] = (size >> 8) & 0xff;
bp[MODE_HEADER_LENGTH + 9] = size & 0xff;
@@ -2803,6 +2854,10 @@
dev, size);
#endif
}
+#if DEBUG
+ if (debugging)
+ printk(ST_DEB_MSG "st%d: Length=%d\n",dev,length);
+#endif
bp[MODE_HEADER_LENGTH + 6] = 0;
bp[MODE_HEADER_LENGTH + 7] = 0;
bp[MODE_HEADER_LENGTH + 4] = 0x30; /* IDP | PSUM = MB */
@@ -2811,6 +2866,21 @@
bp[1] = 0;
bp[MODE_HEADER_LENGTH] &= 0x3f;
bp[MODE_HEADER_LENGTH + 1] = length - 2;
+
+#if DEBUG
+ if (debugging)
+ {
+ int i,j;
+ for (i=0; i < MODE_HEADER_LENGTH+length; i++) {
+ if (i < MODE_HEADER_LENGTH) {
+ printk(ST_DEB_MSG "st%d: mode_header[%d]=0x%x\n",dev,i,bp[i]);
+ } else {
+ j=i-MODE_HEADER_LENGTH;
+ printk(ST_DEB_MSG "st%d: mode_sense[%d]=0x%x\n",dev,j,bp[i]);
+ }
+ }
+ }
+#endif
memset(cmd, 0, 10);
cmd[0] = MODE_SELECT;