Differences between Solaris/Linux and FreeBSD
Kern Sibbald
kern at sibbald.com
Mon Jun 2 03:45:38 PDT 2003
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
More information about the freebsd-scsi
mailing list