NetBSD Problem Report #53890

From www@NetBSD.org  Fri Jan 18 15:17:48 2019
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 8B7757A177
	for <gnats-bugs@gnats.NetBSD.org>; Fri, 18 Jan 2019 15:17:48 +0000 (UTC)
Message-Id: <20190118151746.9874D7A270@mollari.NetBSD.org>
Date: Fri, 18 Jan 2019 15:17:46 +0000 (UTC)
From: pa0gri@amsat.org
Reply-To: pa0gri@amsat.org
To: gnats-bugs@NetBSD.org
Subject: st(4) driver for tapes not working o variable block size
X-Send-Pr-Version: www-1.0

>Number:         53890
>Category:       port-amd64
>Synopsis:       st(4) driver for tapes not working o variable block size
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    port-amd64-maintainer
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Jan 18 15:20:00 +0000 2019
>Closed-Date:    Fri Apr 10 13:11:32 +0000 2020
>Last-Modified:  Fri Apr 10 13:11:32 +0000 2020
>Originator:     Gerard J van der Grinten
>Release:        NetBSD 5.x 6.x 7.x 8.0
>Organization:
private
>Environment:
uname -a
NetBSD plato.net27.gri 8.0 NetBSD 8.0 (GENERIC) #0: Tue Jul 17 14:59:51 UTC 2018  mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/amd64/compile/GENERIC amd64

>Description:
I have tried my problem under various versions of NetBSD AMD65 and I386.
I want to read and write .TAP files (SIMH containers)on various Tape drive 
models (currently a DDS4 Drive.
To my great disappointment It works flawlessly under Debian Linux.

Here a sample session:
plato# ./mt2tap xxz
Converting tape to tap file xxz  
rc NOP ioctl = 0
rc on set block size = 0
rc on set density = 0
rc on set compression = 0
len1 = 00486 rc NOP ioctl = 0
len2 = 00486
Reading block: Invalid argument
blocks = 00002
plato# ls -l xx*
-rw-r--r--  1 root  wheel  35670660 Jan 11 14:55 xx
-rw-r--r--  1 root  wheel  35670660 Jan 11 17:11 xx.tap
-rw-r--r--  1 root  wheel     10260 Jan 13 14:26 xx1
-rw-r--r--  1 root  wheel      2068 Jan 11 16:41 xxx
-rw-r--r--  1 root  wheel  35670660 Jan 12 13:32 xxx.tap
-rw-r--r--  1 root  wheel  35670660 Jan 11 14:31 xxxx
-rw-r--r--  1 root  wheel     20008 Jan 13 14:18 xxxx.t
-rw-r--r--  1 root  wheel         0 Jan 13 13:53 xxxx.tap
-rw-r--r--  1 root  wheel       494 Jan 18 14:14 xxz
plato# ./tap2mt xx.tap
3584 65536
rc on MTREW = 0
rc on set block size = 0
rc on set density = 0
rc on set compression = 0
len = 00486
len = 00930
Error writing tape (end?) act -1 exp 930.
plato# ./tap2mt -t /dev/rst0 xx.tap
3584 65536
rc on MTREW = 0
rc on set block size = 0
rc on set density = 0
rc on set compression = 0
len = 00486
len = 00930
Error writing tape (end?) act -1 exp 930.
plato# 

Linux correctly reads and writes the tap files.
The ST I/O read and write give up after the fist record.
My record sizes vary fro 80 to 386 

My mt2tap.c and tap2mt.c follow:

===============================================
/*
 * tap2mt.c - Write a .tap file to a magnetic tape.
 *
 * Copyright 1998,1999,2000,2002,2015,2019 - G. J. van der Grinten
 * All rights reserved by G. J. van der Grinten
 *                        Pater L.A. Bleysstraat 7
 *                        5684 TR Best
 *                        Netherlands
 densityCode Format
     0	     Device default
     1	     1/2" 800 bpi
     2	     1/2" 1600 bpi
     3	     1/2" 6250 bpi
     4	     QIC-11
     5	     QIC-24
     15      QIC-120
     16      QIC-150
     17      QIC-320/525
     18      QIC-1320/1350
     19      DDS
     28      QIC-385M
     29      QIC-410M
     30      QIC-1000C
     31      QIC-2100C
     32      QIC-6GB
     33      QIC-20GB
     34      QIC-2GB
     35      QIC-875M
     36      DDS-2
     37      DDS-3
     38      DDS-4
 */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#if !defined(_WIN32)
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mtio.h>

#if defined(_WIN32)
#include "getopt.c"
#define TAPE "\\\\.\\TAPE0"
#else
#if defined(__linux__) || defined(__gnu_linux__) || defined(linux)
#define TAPE "/dev/st0"
#elif ((defined __NetBSD__) || defined (__FreeBSD__))
#define TAPE "/dev/rst0"
#endif
#endif

#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define MTSETBLK MTSETBSIZ
#define MTSETDENSITY MTSETDNSTY
#define MTCOMPRESSION MTCMPRESS
#endif

unsigned char buf[100000];

static union {
    int number;
    char bytes[4];
} endianCheck;
int endian = 0;

void init_endian()
{
    endianCheck.number = 0;
    endianCheck.bytes[3] = 1;

    endian = endianCheck.number == 1 ? 1 : 0;
}

int to_intel(int a)
{
    int _tmp;
    if (endian) {
        _tmp  = a;
        ((char *)(void *)&a)[0] = ((char *)(void *)&_tmp)[3];
        ((char *)(void *)&a)[1] = ((char *)(void *)&_tmp)[2];
        ((char *)(void *)&a)[2] = ((char *)(void *)&_tmp)[1];
        ((char *)(void *)&a)[3] = ((char *)(void *)&_tmp)[0];
    }
    return a;
}

void usage()
{
	fprintf(stderr, "Usage: tap2mt [[-d <density>] [-t <tape device>]] <tap_file> \n");
	exit(1);
}

int main(int argc, char **argv)
{
    FILE *infile;
    int mt;
    int recLen1;
    int recLen2;
    int len;
    int rc;
    int ch;
    int dens = 0;
    char *dev = TAPE;
    struct stat stbuf;
    struct mtop op;

    init_endian();

    while(( ch = getopt(argc, argv, "d:t:")) != -1) {
        switch(ch) {
            case 'd':
                dens = atoi(optarg);
                break;
            case 't':
                dev = optarg;
                break;
            default :
				usage();
        }
    }

#if !defined(_WIN32)
    argc -= optind;
    argv += optind;
#endif

    if (argc != 1) {
		usage();
	}

#if !defined(_WIN32)
#if defined __linux__
	if (!stat(dev, &stbuf) && !S_ISCHR(stbuf.st_mode)) {
#elif ((defined __NetBSD__) || defined (__FreeBSD__))
	if (!stat(dev, &stbuf) && !S_ISCHR(stbuf.st_mode)) {
#endif
		fprintf(stderr, "The tape drive '%s' is not an expected device.\n", dev);
//		exit( 1);
	}
#endif

	printf("%d %d\n", stbuf.st_rdev, stbuf.st_blksize);
    if ((mt = open(dev, O_RDWR, 0)) < 0)
        {
        perror("could not open tape drive");
        exit(1);
    }

	op.mt_op = MTREW;
	op.mt_count = 1;
	rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on MTREW = %d\n",rc);

#if ((defined __NetBSD__) || defined (__FreeBSD__))
	op.mt_op = MTSETBSIZ;
#else
	op.mt_op = MTSETBLK;
#endif
	op.mt_count = 0;       /*  blockize = 0 (variable) */
	rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on set block size = %d\n",rc);

#if ((defined __NetBSD__) || defined (__FreeBSD__))
	op.mt_op = MTSETDNSTY;
#else
	op.mt_op = MTSETDENSITY;
#endif
	op.mt_count = dens;       /* 1600 BPI */
	rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on set density = %d\n",rc);

#if ((defined __NetBSD__) || defined (__FreeBSD__))
	op.mt_op = MTCMPRESS;
#elif defined __linux__
	op.mt_op = MTCOMPRESSION;
#endif
	op.mt_count = 0;       /* no compression */
	rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on set compression = %d\n",rc);


    if ((infile = fopen(argv[0], "rb")) == NULL) {
        perror("could not open input file");
        exit(1);
    }

    while(1) {
        len = fread(&recLen1, sizeof(recLen1), 1, infile);
        if (len <= 0) {
            fprintf(stderr, "End of Information\n");
            break;
        }

        recLen1 = to_intel(recLen1);

        if (recLen1 > 0) {
            len = fread(buf, 1, recLen1, infile);
            if (recLen1 != len) {
                fprintf(stderr, "Read %d bytes, expected %d\n",len,recLen1);
                break;
            }

            len = fread(&recLen2, sizeof(recLen2), 1, infile);
            recLen2 = to_intel(recLen2);
            if (len <= 0 || recLen2 != recLen1) {
                fprintf(stderr, "Mismatch in TAP record\n");
                break;
            }
        }
#if 1
        	fprintf(stdout, "len = %05d\n", recLen1);
        	fflush(stdout);
#endif

        if (recLen1 == 0) {
            op.mt_op = MTWEOF;
            op.mt_count = 1;
            rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
            fprintf(stderr, "zero length %d\n", rc);
        } else {
            if((rc = write(mt, buf, recLen1)) != recLen1) {
               fprintf(stderr,"Error writing tape (end?) act %d exp %d.\n",rc, recLen1);
               exit(1);
            }
        }
    }

    op.mt_op = MTWEOF;
    op.mt_count = 2;
    rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
    fclose(infile);
    close(mt);
    return(0);
}
#else
int main(int argc, char **argv)
{
	printf("this program is not supported under a MsWindows OS\n");
	return(0);
}
#endif

======================================================================
/*
 * mt2tap.c - Read a magntic tape to a .tap file.
 *
 * Copyright 1998,1999,2000,2002,2015,2019 - G. J. van der Grinten
 * All rights reserved by G. J. van der Grinten
 *                        Pater L.A. Bleysstraat 7
 *                        5684 TR Best
 *                        Netherlands
 */
 // #elif defined(__GNUC__) && (defined(__linux__) || defined(__SunOS) || defined (__FreeBSD__))
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#if !defined(_WIN32)
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/mtio.h>
#include <fcntl.h>

#if defined(_WIN32)
#include "getopt.c"
#define TAPE "\\\\.\\TAPE0"
#else
#if defined(__linux__) || defined(__gnu_linux__) || defined(linux)
#define TAPE "/dev/st0"
#elif ((defined __NetBSD__) || defined (__FreeBSD__)) || defined(__OpenBSD__)
#define TAPE "/dev/rst0"
#endif
#endif

unsigned char buf[20000];

static union {
    int number;
    char bytes[4];
} endianCheck;
int endian = 0;

void init_endian()
{
    endianCheck.number = 0;
    endianCheck.bytes[3] = 1;

    endian = endianCheck.number == 1 ? 1 : 0;
}

int to_intel(a)
int a;
{
    int _tmp;
    if (endian) {
        _tmp  = a;
        ((char *)(void *)&a)[0] = ((char *)(void *)&_tmp)[3];
        ((char *)(void *)&a)[1] = ((char *)(void *)&_tmp)[2];
        ((char *)(void *)&a)[2] = ((char *)(void *)&_tmp)[1];
        ((char *)(void *)&a)[3] = ((char *)(void *)&_tmp)[0];
    }
    return a;
}

void usage()
{
	fprintf(stderr, "Usage: mt2tap [[-d <density>] [-t <tape device>]] <tap_file> \n");
	exit(1);
}

int main(int argc, char **argv)
{
    FILE *tapfile;
    int mt;
    int ic;
    int oc;
    int zero = 0;
    int ch;
    int rc;
    int blocks = 0;
    int dens = 38;
    char *dev = TAPE;
    struct stat stbuf;
    struct mtop op;

    init_endian();

    while(( ch = getopt(argc, argv, "d:t:")) != -1) {
        switch(ch) {
            case 'd':
                dens = atoi(optarg);
                break;
            case 't':
                dev = optarg;
                break;
            default :
                usage();
        }
    }

#if !defined(_WIN32)
    argc -= optind;
    argv += optind;
#endif

    if (argc != 1) {
		usage();
    }

    printf("Converting tape to tap file %s  \n",argv[0]);

#if !defined(_WIN32)
#if defined __linux__
	if (!stat(dev, &stbuf) && !S_ISCHR(stbuf.st_mode)) {
#elif ((defined __NetBSD__) || defined (__FreeBSD__))
	if (!stat(dev, &stbuf) && !S_ISCHR(stbuf.st_mode)) {
#endif
		fprintf(stderr, "The tape drive '%s' is not an expected device.\n", dev);
//		exit( 1);
	}
#endif

    if ((mt = open(dev, O_RDONLY | O_NONBLOCK ,0)) < 0)
        {
        perror("could not open tape device");
        exit(1);
    }

    if ((tapfile = fopen(argv[0], "wb")) == NULL)
        {
        perror("open TAP file");
        exit(1);
    }


#if !defined(_WIN32)
	op.mt_op = MTNOP;
	op.mt_count = 0;       /* no compression */
	rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc NOP ioctl = %d\n",rc);

#endif




	op.mt_op = MTREW;
	op.mt_count = 1;
	rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));


#if ((defined __NetBSD__) || defined (__FreeBSD__))
	op.mt_op = MTSETBSIZ;
#else
	op.mt_op = MTSETBLK;
#endif
	op.mt_count = 0;       /*  blockize = 0 (variable) */
	rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on set block size = %d\n",rc);

#if ((defined __NetBSD__) || defined (__FreeBSD__))
	op.mt_op = MTSETDNSTY;
#else
	op.mt_op = MTSETDENSITY;
#endif
	op.mt_count = dens;       /* 1600 BPI */
	rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on set density = %d\n",rc);

#if ((defined __NetBSD__) || defined (__FreeBSD__))
	op.mt_op = MTCMPRESS;
#elif defined __linux__
	op.mt_op = MTCOMPRESSION;
#endif
	op.mt_count = 0;       /* no compression */
	rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on set compression = %d\n",rc);

    while ((ic = read(mt, buf, sizeof(buf))) >= 0) {
#if 1
        fprintf(stdout, "len1 = %05d ", ic);
        fflush(stdout);

	op.mt_op = MTNOP;
	op.mt_count = 0;
	rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc NOP ioctl = %d\n",rc);
#endif
		blocks++;

        if (ic == 0) {
            zero += 1;
            if (zero >= 2) {  /* write trailing EOF's */
				oc = 0;
				for (ic = 0 ; ic < 2; ic++) { /* write 2 EOF markers */
					if (fwrite(&oc, sizeof(oc), 1, tapfile) != 1) {
						perror("fwrite eoi");
						exit(1);
					}
				}
				break;
			}
        } else {
            zero = 0;
        }

        oc = to_intel(ic);

        if (fwrite(&oc, sizeof(oc), 1, tapfile) != 1) {
            perror("fwrite1");
            exit(1);
        }

        if (ic > 0) {
            if (fwrite(&buf, 1, ic, tapfile) != ic) {
                perror("fwrite2");
                exit(1);
            }
#if 1
        	fprintf(stdout, "len2 = %05d\n", ic);
        	fflush(stdout);
#endif


            if (fwrite(&oc, sizeof(oc), 1, tapfile) != 1) {
                perror("fwrite3");
                exit(1);
            }
        }

        blocks++;
    }

    if (ic < 0) {
	perror("Reading block");
#if 1
        fprintf(stdout, "blocks = %05d\n", blocks);
        fflush(stdout);
#endif
	}


    fclose(tapfile);
    close(mt);
    return(0);
}
#else
int main(int argc, char **argv)
{
	printf("this program is not supported under a MsWindows OS\n");
	return(0);
}
#endif
=========================================================


Gerard.
>How-To-Repeat:
create a few blocks and try the programs.
If I did miss somthtig , please tell me.
>Fix:
Unknown

>Release-Note:

>Audit-Trail:
From: mlelstv@serpens.de (Michael van Elst)
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: port-amd64/53890: st(4) driver for tapes not working o variable block size
Date: Fri, 18 Jan 2019 19:19:57 -0000 (UTC)

 pa0gri@amsat.org writes:

 >>Description:
 >I have tried my problem under various versions of NetBSD AMD65 and I386.
 >I want to read and write .TAP files (SIMH containers)on various Tape drive 
 >models (currently a DDS4 Drive.
 >To my great disappointment It works flawlessly under Debian Linux.

 The driver probably logs some messages that may explain why it fails.

 N.B. st_blocksize is not the blocksize of the device. NetBSD just
 returns MAXBSIZE (==MAXPHYS) for a character device which is pretty
 useless. But that's not your problem here.


 -- 
 -- 
                                 Michael van Elst
 Internet: mlelstv@serpens.de
                                 "A potential Snark may lurk in every tree."

From: "G J van der Grinten" <pa0gri@amsat.org>
To: <gnats-bugs@NetBSD.org>
Cc: <port-amd64-maintainer@netbsd.org>,
	<gnats-admin@netbsd.org>,
	<netbsd-bugs@netbsd.org>
Subject: RE: port-amd64/53890: st(4) driver for tapes not working o variable block size
Date: Fri, 18 Jan 2019 20:52:36 +0100

 Hallo Michael,

 I know the character block size is 2048. When I use that I get 2 blocks and some
 ot the 3rd.
 I use the raw device and that should do the variable bock size (as advertized)
 But on the recond read for a block I get an " Invalid argument" and that is
 invalid by itself.

 Program works on IRIX, MIPSOS and linux.

 No informative message found in DMESG output.

 Here a (partial) log on a working (linux, uch)

 Converting tape to tap file xxz  
 rc NOP ioctl = 0
 rc on set block size = 0
 rc on set density = 0
 rc on set compression = 0
 len1 = 00486 rc NOP ioctl = 0
 len2 = 00486
 len1 = 00930 rc NOP ioctl = 0
 len2 = 00930
 len1 = 00936 rc NOP ioctl = 0
 len2 = 00936
 len1 = 00826 rc NOP ioctl = 0
 len2 = 00826
 len1 = 00946 rc NOP ioctl = 0
 len2 = 00946
 len1 = 00960 rc NOP ioctl = 0
 len2 = 00960
 len1 = 00930 rc NOP ioctl = 0
 len2 = 00930
 len1 = 00952 rc NOP ioctl = 0
 len2 = 00952
 len1 = 00142 rc NOP ioctl = 0
 len2 = 00142
 len1 = 00486 rc NOP ioctl = 0
 len2 = 00486

 Regards, Gerard.

 -----Original Message-----
 From: Michael van Elst [mailto:mlelstv@serpens.de] 
 Sent: Friday, January 18, 2019 8:25 PM
 To: port-amd64-maintainer@netbsd.org; gnats-admin@netbsd.org;
 netbsd-bugs@netbsd.org; pa0gri@amsat.org
 Subject: Re: port-amd64/53890: st(4) driver for tapes not working o variable
 block size

 The following reply was made to PR port-amd64/53890; it has been noted by GNATS.

 From: mlelstv@serpens.de (Michael van Elst)
 To: gnats-bugs@netbsd.org
 Cc: 
 Subject: Re: port-amd64/53890: st(4) driver for tapes not working o variable
 block size
 Date: Fri, 18 Jan 2019 19:19:57 -0000 (UTC)

  pa0gri@amsat.org writes:

  >>Description:
  >I have tried my problem under various versions of NetBSD AMD65 and I386.
  >I want to read and write .TAP files (SIMH containers)on various Tape drive 
  >models (currently a DDS4 Drive.
  >To my great disappointment It works flawlessly under Debian Linux.

  The driver probably logs some messages that may explain why it fails.

  N.B. st_blocksize is not the blocksize of the device. NetBSD just
  returns MAXBSIZE (==MAXPHYS) for a character device which is pretty
  useless. But that's not your problem here.


  -- 
  -- 
                                  Michael van Elst
  Internet: mlelstv@serpens.de
                                  "A potential Snark may lurk in every tree."


From: mlelstv@serpens.de (Michael van Elst)
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: port-amd64/53890: st(4) driver for tapes not working o variable block size
Date: Sat, 19 Jan 2019 14:42:42 -0000 (UTC)

 pa0gri@amsat.org ("G J van der Grinten") writes:

 >But on the recond read for a block I get an " Invalid argument" and that is
 >invalid by itself.

 Looks like this is not the tape driver itself. The kernel physio() routine
 does a sanity check on the I/O byte offset to be a multiple of DEV_BSIZE
 (== 512 bytes) and returns EINVAL if that's false. That's why the
 second read or write fails (the first starts at offset 0).

 That sanity check doesn't make sense for a tape and might not even be needed
 for e.g. a disk, the disk drivers do their own checks.

 -- 
 -- 
                                 Michael van Elst
 Internet: mlelstv@serpens.de
                                 "A potential Snark may lurk in every tree."

From: "G J van der Grinten" <pa0gri@amsat.org>
To: <gnats-bugs@NetBSD.org>,
	<port-amd64-maintainer@netbsd.org>,
	<gnats-admin@netbsd.org>,
	<netbsd-bugs@netbsd.org>
Cc: 
Subject: RE: port-amd64/53890: st(4) driver for tapes not working o variable block size
Date: Sat, 19 Jan 2019 15:57:49 +0100

 Hello Michael,

 That is a very logical explanation.

 For TAPE files -as long a I worked with them (52 years) they Always are odd
 sized.
 (besides the inter-system tapes - they had precise formats)

 Now a patch and I will be happy.
 I am and long time standing - 386BSD user.

 Regards, Gerard.

 PS, being careful is fine but not always...


 -----Original Message-----
 From: Michael van Elst [mailto:mlelstv@serpens.de] 
 Sent: Saturday, January 19, 2019 3:45 PM
 To: port-amd64-maintainer@netbsd.org; gnats-admin@netbsd.org;
 netbsd-bugs@netbsd.org; pa0gri@amsat.org
 Subject: Re: port-amd64/53890: st(4) driver for tapes not working o variable
 block size

 The following reply was made to PR port-amd64/53890; it has been noted by GNATS.

 From: mlelstv@serpens.de (Michael van Elst)
 To: gnats-bugs@netbsd.org
 Cc: 
 Subject: Re: port-amd64/53890: st(4) driver for tapes not working o variable
 block size
 Date: Sat, 19 Jan 2019 14:42:42 -0000 (UTC)

  pa0gri@amsat.org ("G J van der Grinten") writes:

  >But on the recond read for a block I get an " Invalid argument" and that is
  >invalid by itself.

  Looks like this is not the tape driver itself. The kernel physio() routine
  does a sanity check on the I/O byte offset to be a multiple of DEV_BSIZE
  (== 512 bytes) and returns EINVAL if that's false. That's why the
  second read or write fails (the first starts at offset 0).

  That sanity check doesn't make sense for a tape and might not even be needed
  for e.g. a disk, the disk drivers do their own checks.

  -- 
  -- 
                                  Michael van Elst
  Internet: mlelstv@serpens.de
                                  "A potential Snark may lurk in every tree."


From: mlelstv@serpens.de (Michael van Elst)
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: port-amd64/53890: st(4) driver for tapes not working o variable block size
Date: Sat, 19 Jan 2019 16:27:38 -0000 (UTC)

 mlelstv@serpens.de (Michael van Elst) writes:

 > Looks like this is not the tape driver itself. The kernel physio() routine
 > does a sanity check on the I/O byte offset to be a multiple of DEV_BSIZE
 > (== 512 bytes) and returns EINVAL if that's false. That's why the
 > second read or write fails (the first starts at offset 0).

 The sanity check is done because physio() may issue concurrent
 partial I/O requests and keeps track of the individual parts
 by their block number. The block number addresses DEV_BSIZE
 blocks, so the algorithm only works for multiples of 512 bytes.

 A simple solution would be to not track absolute but relative
 offsets. This would still fail when physio has to handle I/O of
 multiple memory blocks (the second might be unaligned again),
 but the tape driver only starts I/O for a single block.

 -- 
 -- 
                                 Michael van Elst
 Internet: mlelstv@serpens.de
                                 "A potential Snark may lurk in every tree."

From: "G J van der Grinten" <pa0gri@amsat.org>
To: <gnats-bugs@NetBSD.org>,
	<port-amd64-maintainer@netbsd.org>,
	<gnats-admin@netbsd.org>,
	<netbsd-bugs@netbsd.org>
Cc: 
Subject: RE: port-amd64/53890: st(4) driver for tapes not working o variable block size
Date: Sat, 19 Jan 2019 19:03:13 +0100

 Hello Michael,

 That is why TAR and family work as they use 20 *DEV_BSIZE blocks.

 The check could thus be skipped for real reel tape devices.
 But indeed if tape i/o is a single operation and does not conflict with other
 operations.

 Thanks for the update.

 Regards, Gerard

 -----Original Message-----
 From: Michael van Elst [mailto:mlelstv@serpens.de] 
 Sent: Saturday, January 19, 2019 5:30 PM
 To: port-amd64-maintainer@netbsd.org; gnats-admin@netbsd.org;
 netbsd-bugs@netbsd.org; pa0gri@amsat.org
 Subject: Re: port-amd64/53890: st(4) driver for tapes not working o variable
 block size

 The following reply was made to PR port-amd64/53890; it has been noted by GNATS.

 From: mlelstv@serpens.de (Michael van Elst)
 To: gnats-bugs@netbsd.org
 Cc: 
 Subject: Re: port-amd64/53890: st(4) driver for tapes not working o variable
 block size
 Date: Sat, 19 Jan 2019 16:27:38 -0000 (UTC)

  mlelstv@serpens.de (Michael van Elst) writes:

  > Looks like this is not the tape driver itself. The kernel physio() routine
  > does a sanity check on the I/O byte offset to be a multiple of DEV_BSIZE
  > (== 512 bytes) and returns EINVAL if that's false. That's why the
  > second read or write fails (the first starts at offset 0).

  The sanity check is done because physio() may issue concurrent
  partial I/O requests and keeps track of the individual parts
  by their block number. The block number addresses DEV_BSIZE
  blocks, so the algorithm only works for multiples of 512 bytes.

  A simple solution would be to not track absolute but relative
  offsets. This would still fail when physio has to handle I/O of
  multiple memory blocks (the second might be unaligned again),
  but the tape driver only starts I/O for a single block.

  -- 
  -- 
                                  Michael van Elst
  Internet: mlelstv@serpens.de
                                  "A potential Snark may lurk in every tree."


From: Michael van Elst <mlelstv@serpens.de>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: port-amd64/53890 st(4) driver for tapes not working o variable
 block size
Date: Sat, 23 Mar 2019 12:23:33 +0100

 I've prepared a patch for the physio routine:

 http://ftp.netbsd.org/pub/NetBSD/misc/mlelstv/kern_physio.diff

 With this patch I can read and write tapes with e.g. 128 byte blocks.


 Greetings,
 -- 
                                 Michael van Elst
 Internet: mlelstv@serpens.de
                                 "A potential Snark may lurk in every tree."

From: "G J van der Grinten" <pa0gri@amsat.org>
To: <gnats-bugs@netbsd.org>,
	<mlelstv@serpens.de>
Cc: 
Subject: RE: port-amd64/53890 st(4) driver for tapes not working o variable block size
Date: Sat, 23 Mar 2019 13:29:29 +0100

 Hello Michael,

 I applied the patch and tested the tape drive.

 Both reading and writing all kinds of block sizes worked.

 Thanks, Gerard.

 -----Original Message-----
 From: Michael van Elst [mailto:mlelstv@serpens.de] 
 Sent: Saturday, March 23, 2019 12:25 PM
 To: port-amd64-maintainer@netbsd.org; gnats-admin@netbsd.org;
 netbsd-bugs@netbsd.org; pa0gri@amsat.org
 Subject: Re: port-amd64/53890 st(4) driver for tapes not working o variable
 block size

 The following reply was made to PR port-amd64/53890; it has been noted by GNATS.

 From: Michael van Elst <mlelstv@serpens.de>
 To: gnats-bugs@netbsd.org
 Cc: 
 Subject: Re: port-amd64/53890 st(4) driver for tapes not working o variable
  block size
 Date: Sat, 23 Mar 2019 12:23:33 +0100

  I've prepared a patch for the physio routine:

  http://ftp.netbsd.org/pub/NetBSD/misc/mlelstv/kern_physio.diff

  With this patch I can read and write tapes with e.g. 128 byte blocks.


  Greetings,
  -- 
                                  Michael van Elst
  Internet: mlelstv@serpens.de
                                  "A potential Snark may lurk in every tree."


State-Changed-From-To: open->closed
State-Changed-By: mlelstv@NetBSD.org
State-Changed-When: Fri, 10 Apr 2020 13:11:32 +0000
State-Changed-Why:
Issue fixed in kern_physio.c 1.95.


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.46 2020/01/03 16:35:01 leot Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2020 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.