From owner-freebsd-scsi@FreeBSD.ORG Mon Jun 2 03:45:38 2003 Return-Path: Delivered-To: freebsd-scsi@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 49EC037B401 for ; Mon, 2 Jun 2003 03:45:38 -0700 (PDT) Received: from matou.sibbald.com (matou.sibbald.com [195.202.201.48]) by mx1.FreeBSD.org (Postfix) with ESMTP id A91A643FA3 for ; Mon, 2 Jun 2003 03:45:36 -0700 (PDT) (envelope-from kern@sibbald.com) Received: from [192.168.68.112] (rufus [192.168.68.112]) by matou.sibbald.com (8.11.6/8.11.6) with ESMTP id h52AjQv04974; Mon, 2 Jun 2003 12:45:26 +0200 From: Kern Sibbald To: "Justin T. Gibbs" In-Reply-To: <2846020000.1054498114@aslan.scsiguy.com> References: <1054490081.1582.1685.camel@rufus> <2846020000.1054498114@aslan.scsiguy.com> Content-Type: text/plain Organization: Message-Id: <1054550725.1582.1859.camel@rufus> Mime-Version: 1.0 X-Mailer: Ximian Evolution 1.2.4 Date: 02 Jun 2003 12:45:26 +0200 Content-Transfer-Encoding: 7bit cc: freebsd-scsi@freebsd.org cc: mjacob@feral.com Subject: Differences between Solaris/Linux and FreeBSD X-BeenThere: freebsd-scsi@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: SCSI subsystem List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 02 Jun 2003 10:45:38 -0000 On Sun, 2003-06-01 at 22:08, Justin T. Gibbs wrote: > > Hello, > > > > I'm the author of a GPL'ed network backup program called > > Bacula (www.bacula.org). For the last three years, it > > has been working flawlessly on Solaris and Linux systems. > > When users attempted to use it recently on FreeBSD, > > it did not work. I subsequently modified Bacula so that > > it would work on FreeBSD -- basically, I had to program > > around some important differences in the way FreeBSD > > handles EOFs compared to Solaris and Linux. At some point > > in the future, I would like to discuss the problems > > I had in detail, if that interests you. > > I would be interested as I'm sure would other readers of this > list. ... As promised, in this email, I will try my best to describe the differences I found between Solaris/Linux and FreeBSD concerning tape handling. There were five separate areas where I noticed differences: 1. On Solaris/Linux, the default behavior for ioctl(MTEOM) is to run in what they call slow mode. In this mode, the tape is positioned to the end of the data, and the driver returns the correct file number in the MTIOCGET packet. It is possible to enable fast-EOM, but no one uses it to my knowledge. On FreeBSD, you apparently always use the fast-EOM so that the tape position is unknown after the ioctl(). Bacula always knows how many files are on a tape, and when appending to a tape that is already written and newly opened, it MUST know where it is on the tape. As a consequence, on FreeBSD, I must explicitly use MTFSF with read()s in between to position to the end of the tape -- a fairly slow affair. Note, on FreeBSD, the user must explicitly tell Bacula not to use the MTEOM function with a special configuration statement. 2. Your handling of EOM differs from Solaris/Linux. On both of those systems, when the Bacula reads the first EOF, the driver returns 0 bytes read. On reading the second EOF, the driver returns 0 bytes read, but before returning backspaces over the EOF, leaving you positioned correctly for appending to the tape and having told you you are at the end of the tape by giving two consecutive 0 byte read. Any further read() request return an I/O error. On FreeBSD, reading the first EOF returns 0 bytes, reading the second EOF also returns 0 bytes (sometimes, I apparently get "Illegal operation"). However, the tape is left positioned after the second EOF, so appending from that point effectively "loses" the data. To handle this correctly the FreeBSD user must add a configuration statement to Bacula telling him to backspace file at EOM. 3. I have previously described this but will do so again for completeness here. On Solaris/Linux when Bacula does: write(); ioctl(MTEOF); ioctl(MTEOF) ioctl(MTBSF); ioctl(MTBSF); ioctl(MTBSR); read(); the read() re-reads the last write. On FreeBSD, the read returns 0 bytes (there is also a problem of freezing the tape wrapped into this example if I am not mistaken). Apparently the 0 bytes read is because FreeBSD adds an additional EOF mark (not necessary) and leaves the drive positioned *after* the mark thus re-reading the last record fails when it logically should not. 4. Tape freezing: On Solaris/Linux, the tape never "freezes". On FreeBSD it does freeze. As best I can determine, you freeze the drive when you lose track of where you are. Typically, this occurs when I do a MTBSR to re-read the last record. On Solaris/Linux the tape is never frozen, but when they don't know the position, they simply return -s in the MTIOCGET packet, which is fine with me because Bacula only uses that info when initially reading a tape to append to it. Freezing the tape causes all sorts of problems because it generates a flood of unexpected errors. Within a large complicated program like Bacula, when a low level routine re-reads a record during writing and the tape freezes, it cannot simply rewind the drive as this could cause chaos and possible overwriting of the beginning of the drive. I've attempted to overcome tape freezing by providing the user a means to turn off MTBSR (but they don't always do so), and by issuing ioctl(MTIOCERRSTAT) after every return of -1 from any I/O request. I recommend that you do away with freezing the drive -- it seems to me that it only causes more problems. In saying that I have to that I really do not understand tape freezing or why you do it since I found no documentation on it, and everything I write above I have deduced from what Dan has reported back to me. 5. I am quite fuzzy on this point because I forget exactly what happened and what I did about it. It seems to me that on Linux, if I read a block but specify a number of bytes less than the number actually in the block on the tape, the driver returns the data anyway. I then check if the block is internally complete and if not, increase my record size to the size indicated in the data received, backspace one record, and re-read it. If I am not mistaken, on FreeBSD, the first read returns an error, and Bacula just immediately gives up. Your documentation specifies that one can never read a partial record from a tape, but it does not specify what error code is generated. As a consequence, rather than recovering and re-reading the record, Bacula has to assume it was a fatal error. I hope these points are clear. If not please don't hesitate to ask. Best regards, Kern