Paul,
I too looked at this over the weekend. Here's what I
discovered:
- linux 2.6 and later linux 2.4 kernels provide 32-bit to 64-bit ioctl
conversions. Earlier linux 2.4 kernels provide some 32 to 64 bit
ioctl conversions on a architecture by architecture basis, but the
supported ioctl list is sparse.
- the legacy CDROM driver ioctl interface uses 'S' as the magic number
for its ioctls. The SCSI driver also uses 'S' as the magic number of
some of its ioctls. Some CDROM driver ioctls conflict even with SCSI
ioctls.
- register_ioctl32_conversion and unregister_ioctl32_conversion was
added somewhere between 2.4.18 and 2.4.20. CDROM ioctls were also
added somewhere between 2.4.18 and 2.4.20. All 2.6 kernel have it.
The functions refuse to register a conversion that has already been
specified and refuse to unregister a "base" definition (one specified
for the architecture in the kernel, such as the CDROM conversions).
- as of 2.6.11, a new file operation (compat_ioctl) was added to
perform device specific 32 to 64 bit conversions.
Here is a little precedent for the use of 'S':
- STR is defined as ('S'<<8) in Fourth edition of the i386 ABI.
("System V Application Binary Interface -- Intel386(TM) Architecture
Processor Supplement")
- STR is defined as ('S'<<8) in the Third edition of the MIPS ABI.
("System V Application Binary Interface -- MIPS(R) RISC Processor
Supplement").
- The ARM ABI follows i386 in this regard.
- The X86_64 ABI ("System V Application Binary Interface -- x86_64(TM)
Architecture Processor Supplement") indicates that the 32-bit CAE
must conform to the i386 ABI and regarding the stropts.h header, that
it is unchanged from the i386 ABI.
- GNU glibc header files <sys/stropts.h> conforms to these ABIs and in
fact provides ('S'<<8) for all architectures including S390.
- Original AT&T SVR4 header (of course) use 'S'.
- OSF/1 Release 1.1 headers use 'S'.
- OSF/1 Release 1.2 headers use 'S'.
- Solaris 2.6 headers use 'S'.
- Solaris 2.7 headers use 'S'.
- SUSv3/POSIX 2003 does not specify a magic number
- It is noted in the iBCS (now LinuxABI) package that 'S' is used for
all architectures, but that SCO 3.2.x (x<4) set the high bit in a
conflicting ioctl. (You say that you cannot remember why you chose
0xdc. Probably 0xd3 would have been a better choice: it is 'S'
(0x53) with the high bit set.)
With regard to the current state of S390X ifdefs in 2.18.0 (that your
patch suggests also be applied to x86_64):
- The list of registered ioctls currently includes I_SETSIG, I_SRDOPT,
I_PUSH, I_LINK, I_UNLINK, and I_STR. (head/linux-mdep.c) All but
I_STR simply call sys_ioctl (i.e. no conversion).
- 2.4 kernels without register_ioctl32_conversion will fail to build.
(But then older 2.4 kernels don't really support 32 over 64 anyway.)
- The conversion registration will always fail if STR is defined as
('S'<<8) because the CDROM/SCSI ioctls using 'S' conflict with almost
all standard STREAMS ioctls.
- 2.4 kernels with register_ioctl32_conversion and 2.6 kernels will
fail [EINVAL] on all ioctls other than the six listed above, because
the default is to fail. This means that the following ioctls will
fail (even with STR defined to 0xdc):
I_NREAD, I_POP, I_LOOK, I_FLUSH, I_GRDOPT, I_GETSIG, I_FIND,
I_ISASTREAM, I_RECVFD, I_PEEK, I_FDINSERT, I_SENDFD, I_E_RECVFD,
I_SWROPT, I_GWROPT, I_LIST, I_PLINK, I_PUNLINK, I_FLUSHBAND,
I_CKBAND, I_GETBAND, I_ATMARK, I_SETCLTIME, I_GETCLTIME, I_CANPUT,
I_SERROPT, I_GERROPT, I_ANCHOR, I_ESETSIG, I_EGETSIG, I_S_RECVFD,
I_STATS, I_BIGPIPE, I_GETTP, I_TILDE, I_GETMSG, I_PUTMSG, I_GETPMSG,
I_PUTPMSG, I_PIPE, I_FIFO, I_POLL, I_SETDELAY, I_GETDELAY,
I_RUN_QUEUES, I_AUTOPUSH, I_HEAD_REPORT, I_FATTACH, I_FDETACH,
I_LIS_PIPE, I_LIS_FATTACH, I_LIS_FDETACH, I_LIS_GETPMSG,
I_LIS_PUTPMSG, I_LIS_SEMTIME, I_LIS_LOCKS, I_LIS_SDBGMSK2,
I_LIS_QRUN_STATS, I_LIS_PRNTQUEUES, I_LIS_PRNTSPL,
I_LIS_GET_MAXMSGMEM, I_LIS_SET_MAXMSGMEM, I_LIS_GET_MAXMEM,
I_LIS_SET_MAXMEM, I_LIS_GETSTATS, I_LIS_PRNTSTRM, I_LIS_PRNTMEM,
I_LIS_SDBGMSK.
Many of these are required for standard operation as well as required
for proper operation of 32 bit applications programs using the
STREAMS ioctl(2p) interface.
Even getmsg/putmsg will break on 2.6.11+ kernels because the ioctl
interface must be used for getpmsg/putpmsg instead of the read/write
interface. isastream() will also report that a Stream is not a
Stream (because it uses I_CANPUT, which will fail).
Changing STR from ('S'<<8) to 0xdc for x86_64 has the following
consequences:
- STREAMS will no longer comply with the SVID, i386 or x86_64 ABIs.
This means that any legacy applications will fail to run. Also,
any applications compiled against standard headers <stropts.h> will
also fail.
- Any driver that passes STREAMS messages to peripheral hardware (or
directly to another system) based on a standard STREAMS
implementation will also fail.
(This was the major reason for changing the message type number
(M_PROTO, M_DATA, etc.) in 2.18.0 which I notice that your patch
LiS-2.18.0-A changes back to 2.16 LiS numbering for some reason. The
numbering of message types in 2.18.0 was placed as close to other
STREAMS implementations as possible to permit STREAMS message to be
passed directly between systems.)
- For kernels 2.6.11 and greater, there is no need to change STR
because compat_ioctl file operation can do device specific conversion
and there will be no conflict with the legacy base CDROM/SCSI ioctls.
There is just too much precedent for 'S'. Therefore, I propose the
following for the next LiS (LiS-2.18.3) and Linux Fast-STREAMS
(streams-0.7a.5) release:
- For LiS I will rip the ioctl conversion hash table and the cdrom
conversion functions from the system map and override the CDROM
ioctls with a function that checks for character or block device and
then either calls the CDROM conversion or calls the STREAMS
conversions.
- For Linux Fast-STREAMS I will take the same approach before kernel
2.6.11. For kernel 2.6.11 and beyond I will define the compat_ioctl
file operation to perform device specific conversions. (LiS cannot
handle unlocked ioctls so this approach is pointless for LiS.)
- Using either approach, I will define conversions for ALL defined
ioctls, not just the six.
How does that sound?
--brian
Post by Paul LandayI found a RHEL4-x86_64 system to try this one and my
memory was (mostly) correct. The change to __SID in
LiS/include/sys/gnu.stropts.h and LiS/include/sys/stropts.h
in the patches I sent 03 Feb 2006 08:25:05 does fix
this issue. The part I forgot was that you should have
the stropts.h '#define STR' match that of the __SID values.
"include/sys/stropts.h"
#define __SID (0xdc<<8) /* for GNU libc
#define STR (0xdc<<8) /* for UnixWare
"include/sys/gnu.stropts.h"
#define __SID (0xdc<< 8)
I don't recall how we selected the 0xdc base offset value,
but it has proven to work for rhel3,rhel4,sles8,sles8 on
i686,s390,s390x,ppc64,x86_64.
This change means you to have to recompile any of your LiS
dependent code, but since x86_64 is new for you that should
not be a big problem. If you need to maintain binary
compatibility with old modules on old platforms you can
#ifdef the '#define _SID' and '#define STR' to use different
values for different platforms.
Paul Landay
_______________________________________________
Linux-streams mailing list
http://gsyc.escet.urjc.es/mailman/listinfo/linux-streams
--
Brian F. G. Bidulock ¦ The reasonable man adapts himself to the ¦
***@openss7.org ¦ world; the unreasonable one persists in ¦
http://www.openss7.org/ ¦ trying to adapt the world to himself. ¦
¦ Therefore all progress depends on the ¦
¦ unreasonable man. -- George Bernard Shaw ¦