Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Apr 1995 18:31:35 +1000
From:      Stephen McKay <syssgm@devetir.qld.gov.au>
To:        current@FreeBSD.org
Cc:        syssgm@devetir.qld.gov.au
Subject:   fcntl F_SETLK backward compatibility kludge
Message-ID:  <199504170831.SAA27341@orion.devetir.qld.gov.au>

next in thread | raw e-mail | index | archive | help
Between 1.1.5 and 2.0, the format of one of the parameters to the fcntl()
system call changed, but neither the system call number nor the command codes
passed to it were updated to reflect this.  This causes some 1.1.5 binaries
to fail when run on 2.0 systems.  This is a proposal which should almost
totally heal this minor wart.


Old struct flock from Freebsd 1.1.5 and earlier:

 type  whence   start      length     pid   junk (because of padding)
+-----+-----+-----------+-----------+-----+ - - +
| 16  | 16  |    32     |    32     | 16  |     |
+-----+-----+-----------+-----------+-----+ - - +


New struct flock from Freebsd 2.0 and later:

	 start                   length              pid     type  whence
+-----------------------+-----------------------+-----------+-----+-----+
|          64           |          64           |    32     | 16  | 16  |
+-----------------------+-----------------------+-----------+-----+-----+


I propose that fcntl() command codes 7, 8, 9 be reserved for the backward
compatible locking calls, and new values 10, 11, 12 be allocated for use
in FreeBSD 2.1 as F_GETLK, F_SETLK and F_SETLKW.

Code bracketed by #ifdef COMPAT_43 should be added to fcntl() in kern_descrip.c
to handle the old case in the following way:  Using the fact that "type" must
be 1, 2 or 3, and "whence" must be 0, 1 or 2, an educated guess can be made
as to which of the two forms is being used by the currently executing binary.

The two possible cases of confusion are when an old style struct flock is
followed in memory by data that just happens to contain 1, 2 or 3 and 0, 1 or 2
in the right place, or when a new style struct flock specifies a start offset
with a low 32 bits of 0x00000001, 0x00000002, 0x00000003, 0x00010001,
0x00010002, 0x00010003, 0x00020001, 0x00020002, or 0x00020003.

In these cases, the old style should be assumed, possibly logging a kernel
warning message.  The assumption here is that the 2.0 binary is newer and
thus more easily recompiled to use the unambiguous 2.1 fcntl() call.

I have scanned the 2.0 source code for uses of fcntl() locking and have found
four cases.  "amd", "vi", and "sendmail" use fcntl() locking to simulate
flock() locking if that is unavailable.  "at" uses fcntl() locking, but only
with full file locking (whence = 0, start = 0, end = 0) which is correctly
detected by the above scheme.  It seems likely that most uses of fcntl()
locking are to simulate flock(), and will be correctly handled.

If added complication is desired :-) a number of other checks can be done.
It seems very unlikely that any program in this transitional situation is
going to be using files >= 2^32 bytes, and so the high 32 bits of a new
style "start" and "length" must be 0 or -1.  Thus an old style flock with
a "start" field not 0 or -1 will not be mistaken for a new style flock.
Similarly, the "pid" field and padding of an old style struct flock can
contain garbage, and be an unmistakable marker since it overlaps the high
half of a new style "length" field.  There are also some constraints on
what values "start" and "length" can have for various values of "whence".

If guessing for each call is not your idea of determinism, there are a few
spare bits in u_pcb.pcb_flags in the user struct.  A value could be
determined on the first call, and stored here to remove future guesswork.

So, how far should we go to support a few old binaries using a system call
that the man page bags so heavily?  My second favourite proposal after this
one, is to convert the old calls to simply log a kernel error message, and
return a failure code to the program.  Old binaries will then be detected
and hopefully upgraded.

I am available to implement and test either of these solutions as I currently
have both 1.1.5 and 2.0 at home.

Stephen.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199504170831.SAA27341>