From patchwork Fri Dec 25 15:53:46 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Kai_M=C3=A4kisara?= X-Patchwork-Id: 7920821 Return-Path: X-Original-To: patchwork-linux-scsi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 35295BEEE5 for ; Fri, 25 Dec 2015 15:54:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 12CE7203E6 for ; Fri, 25 Dec 2015 15:54:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 942282034F for ; Fri, 25 Dec 2015 15:54:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753068AbbLYPxx (ORCPT ); Fri, 25 Dec 2015 10:53:53 -0500 Received: from vs19.mail.saunalahti.fi ([62.142.117.200]:52711 "EHLO vs19.mail.saunalahti.fi" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751425AbbLYPxw (ORCPT ); Fri, 25 Dec 2015 10:53:52 -0500 Received: from vams (localhost [127.0.0.1]) by vs19.mail.saunalahti.fi (Postfix) with SMTP id 4E935280117; Fri, 25 Dec 2015 17:53:49 +0200 (EET) Received: from gw01.mail.saunalahti.fi (gw01.mail.saunalahti.fi [195.197.172.115]) by vs19.mail.saunalahti.fi (Postfix) with ESMTP id 3A3F3280117; Fri, 25 Dec 2015 17:53:49 +0200 (EET) Received: from kai.makisara.private (a88-115-178-128.elisa-laajakaista.fi [88.115.178.128]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by gw01.mail.saunalahti.fi (Postfix) with ESMTPSA id 152EA4006A; Fri, 25 Dec 2015 17:53:46 +0200 (EET) Date: Fri, 25 Dec 2015 17:53:46 +0200 (EET) From: Kai Makisara To: Emmanuel Florac cc: linux-scsi@vger.kernel.org Subject: Re: st driver doesn't seem to grok LTO partitioning In-Reply-To: <3F0204AE-89BD-45C7-883F-D6EC3A1D34E2@kolumbus.fi> Message-ID: References: <20151218170644.24167419@harpe.intellique.com> <20151221134649.293a1a1e@harpe.intellique.com> <20151221185759.38dd21d6@harpe.intellique.com> <3F0204AE-89BD-45C7-883F-D6EC3A1D34E2@kolumbus.fi> User-Agent: Alpine 2.11 (LSU 23 2013-08-11) MIME-Version: 1.0 Content-ID: Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_TVD_MIME_EPI, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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<---------------------------------- --- 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 Devfs support */ -static const char *verstr = "20101219"; +static const char *verstr = "20151225"; #include @@ -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);