We've been doing some thinking about a more general way to enable access to CP system services from Linux, and I'd like to get some opinions on one approach we've considered.
One of the useful ideas in Plan 9 (the OS that the Bell Labs people started working on when they got bored with Unix) is the idea of representing *everything* as a filesystem-like structure (much along the lines of the way /proc is done) -- network connections, serial ports, etc. Configuration is done by writing text strings to specially named files, which cause changes to be made, and data is returned via pseudofiles. There's a excellent paper available from http://www.cs.bell-labs.com/sys/doc/net/net.pdf on how Plan 9 represents network connections that explains this better -- check out pages 3 and 4 for the most interesting part of the discussion. Here's the idea for DIAGnoses: IMHO, there's 4 steps to this: - create a Linux-referencable connection to reserve workspace and set up the call to the DIAGnose - supplying requests to the DIAGnose - getting the data back from the DIAGnose - destroying the Linux-referencable connection to the service when you're done with it. 1) Creating a connection to a DIAGnose: The idea we had was to create a similar structure for IUCV and DIAG functions (provisionally /cp/iucv and /cp/diag). Each of these would have a clone "file" (example /cp/iucv/clone). Opening the clone pseudofile and reading from it would create a new kernel connection buffer (in the case of IUCV) or buffer for the DIAG, create a new pseudofile directory entry and some special files within the directory pointing to the new entry, and return a "connection number" to the reading process indicating where in the /cp/iucv or /cp/diag tree to go next, eg: program opens /cp/diag/clone using fopen() and issues fread on the file pointer returned by fopen(). Kernel creates buffer for DIAG, looks through it's tables and determines that the next free pseudofile # is 2, creates /cp/diag/2 , /cp/diag/2/ctl and /cp/diag/2/data, and returns "2" to the fread call. program then knows that it can interact with the CP service via the pseudofiles in /cp/diag/2. 2) Supplying requests to the CP service As part of the connection creation, we created two pseudofiles: ctl and data. The ctl pseudofile supplies information to the service. In the example above, let's say we want to do a DIAG 8 and execute CP QUERY USERID. We could then open /cp/diag/2/ctl, write "8,CP QUERY USERID" and close /cp/diag/2/ctl using normal file I/O calls. The act of writing to the ctl pseudofile causes the DIAG 8 to be executed, and the error code returned on the write can indicate success or failure. closing the ctl file causes the output to be transferred to the data buffer for the pseudodevice. Note that the driver for /cp/diag/2/ctl could potentially also do authentication inside the kernel, thus allowing ACL control over what DIAGs can be executed from what Linux users. 3) getting the data back from the CP service To get the data back, we read from /cp/diag/2/data until EOF. fstat(/cp/diag/2/data) would return the amount of data in the buffer. Since the close of the /cp/diag/2/ctl file establishes the buffer as stable, you can read the /cp/diag/2/data file as many times as you want (until you do a new write to /cp/diag/2/ctl, which clears the buffer and places the new output as the stable value). 4) destroying the Linux reference to the DIAGnose: To terminate the connection and free the kernel buffer, write "TERMINATE" to /cp/diag/2/ctl. The psuedofile entries are deleted, the connection number is marked as available, and the kernel buffer is released. /cp/iucv can be handled in a similar manner (more complex psuedofile structure to allow more control, but the same idea). My questions to the list are: a) does this sound like a usable paradigm? b) is it worth implementing? c) what am I missing? I haven't started implementing yet, but I'd like to get as many reactions as possible. Discuss...8-) -- db David Boyes Sine Nomine Associates
