[comp.unix.internals] SCO UNIX *double* device driver

hendrik@zeusa.UUCP (Hendrik Vermooten) (03/19/91)

SCO Xenix/UNIX, PC type hardware.

In short, the problem is the following:

I need to "channel" all I/O going to and from a device, through my own
handler routine (this routine itself uses hardware to do its job).

Examples of this application : Disk Mirroring, Disk Encryption, UNIX
disk I/O monitoring, maybe even compression.

A picture tells a thousand words:

NORMAL DISK        ==============                ==============
 INPUT &     <---- | MY DEVICE  | <------------- | ACTUAL     |
 OUTPUT      ----> | & DRIVER   | -------------> | DISK DRV   |
                   ==============                ==============

All normal disk I/O must go through MYDRIVER software that uses
hardware to do it's job (so must itself be a device driver?) to the
STANDARD disk device driver.

I don't want to change the disk device driver, because I don't want to
have to support all the different types of disks out there!

At first this seemed like a perfect application for STREAMS, but I
cannot find enough documentation to clearly indicate that what I need
to do is possible using STREAMS.

-----------------------------------------------------------------------
Jaco Oosthuyzen, ZEUS systems    TEL +27 12 64-5507, FAX +27 12 64-8382
Bang: ..!uunet!ddsw1!olsa99!zeusa!jaco     or        jaco@zeusa.UUCP
-----------------------------------------------------------------------
-- 
-------- Opinions expressed here are my own when not inebriated ----------
Hendrik Vermooten, ZEUS software    TEL +27 12 64-5507, FAX +27 12 64-8382
Bang: ..!uunet!ddsw1!olsa99!zeusa!hendrik     or        hendrik@zeusa.UUCP
--- Confucious say: he who use GNU Emacs GNUs he's on to a GNUd thing ----

mwarren@rws1.ma30.bull.com (Mark Warren) (03/20/91)

hendrik@zeusa.UUCP (Hendrik Vermooten) writes:


>I need to "channel" all I/O going to and from a device, through my own
>handler routine (this routine itself uses hardware to do its job).

>Examples of this application : Disk Mirroring, Disk Encryption, UNIX
>disk I/O monitoring, maybe even compression.

>A picture tells a thousand words:

>NORMAL DISK        ==============                ==============
> INPUT &     <---- | MY DEVICE  | <------------- | ACTUAL     |
> OUTPUT      ----> | & DRIVER   | -------------> | DISK DRV   |
>                   ==============                ==============

I have done this before, and I have seen other implementations.
I suspect that what you want is a driver interface that looks
programmatically identical to a real disk driver.  If you want the
kernel to be abke to mount this device as a file system, that must
be the case.  Forget streams and just write a new disk driver that
in turn calls on the bdevsw routines to eventually call the real
disk driver.  If you have means to do so, look at OSF's LVM (Logical
Volume Manager) source code or documentation or Mips virtual disk driver.

>I don't want to change the disk device driver, because I don't want to
>have to support all the different types of disks out there!

You shouldn't, and don't need to.  All the implementations I know of
work with unmodified disk drivers.

>At first this seemed like a perfect application for STREAMS, but I
>cannot find enough documentation to clearly indicate that what I need
>to do is possible using STREAMS.

Wrong.  Streams is not the right mechanism to deal with a block device
interface, especially considering the comment about mounted filesystems
above.  Make it a block device driver.
--

 == Mark Warren                      Bull HN Information Systems Inc. ==
 == (508) 294-3171 (FAX 294-3020)    300 Concord Road     MS852A      ==
 == Mark.Warren@bull.com             Billerica, MA 01821              ==

mark@segue.segue.com (Mark Kampe) (03/20/91)

In answer to the question "How can I filter all the data going to and from
a device driver" ...

In some cases you may be able to use STREAMS, but these are not available
in all flavors (and configurations) of UNIX.  If you are willing to put 
your immortal soul in perril however, there is a pretty easy, efficient,
and sure-fire  way to address your problem.

All calls to a device driver (resulting from system calls or internal I/O
requests) are made through some variation of the device driver switch.
Some systems have one such table, some two, and a few have three.  The
entry points also vary from system to system, but they all have open,
close, read, write, ioctl and strategy.  The principle calls to the driver
that don't go through the device driver switch are interrupts (and some
kernels even pass those through the driver switch).

If you know which driver you want to filter for, you can modify the 
appropriate devsw/bdevsw/cdevsw/intrsw/... entries to point to your
driver (rather than the real driver).  Once this is done, you will get
control everytime anybody tries to do anything with the intercepted driver
(with the possible exception of interrupts).  You can do what ever processing
you intended to do, and then pass the operations on to the real driver.

Note however that this feat should only be attempted by trained professionals
and kids should not try this one at home.  More specifically:

	(1) depending on what you do, you may introduce horrible
	    performance problems into your system - particularly if
	    you use this trick (as suggested) to "mirror disks".

	(2) unless you are EXTREMELY CONFIDENT about your understanding
	    of locking, synchronization, interrupt enabling and other
	    such assorted "house keeping" chores, you are likely to 
	    unleash a Pandora's Box of horrible bugs in your system.

	(3) you may face derision from your peers and the loss of your
	    technical soul.

---mark---

boyd@necisa.ho.necisa.oz.au (Boyd Roberts) (03/21/91)

In article <905@zeusa.UUCP> hendrik@zeusa.UUCP (Hendrik Vermooten) writes:
>
>I need to "channel" all I/O going to and from a device, through my own
>handler routine (this routine itself uses hardware to do its job).
>

Trivial.  Write your driver so it calls the other driver through the bdevsw.
Make the appropriate devices in dev to reference your driver.  Use these
instead of the ones referencing the device you're overlaying.  Problem solved.

You may have to be a bit careful about handling wakeups to prevent the wrong
thing from happening, but it's not too hard.  Just think about it carefully.

Your driver is just a pseudo-device that manipulates another driver.


Boyd Roberts			boyd@necisa.ho.necisa.oz.au

``When the going gets wierd, the weird turn pro...''

theo@rascal.UUCP (T. Kramer) (03/21/91)

In article <905@zeusa.UUCP> hendrik@zeusa.UUCP (Hendrik Vermooten) writes:
>
>SCO Xenix/UNIX, PC type hardware.
>
>I need to "channel" all I/O going to and from a device, through my own
>handler routine (this routine itself uses hardware to do its job).
>

How about the following:-

#define fopen hvfopen
#define fclose hvfclose
  :              :

Etc. for all required system calls, and then do in your function calls
what you want to do.

+--------------------------------+------------------------------------------+
| theo@rascal                    | Got nuthin else to say                   |
+--------------------------------+------------------------------------------+

guy@auspex.auspex.com (Guy Harris) (03/24/91)

>At first this seemed like a perfect application for STREAMS,

Given that disk drivers rarely, if ever, use STREAMS (there's no way to
do an "lseek()" on a stream, and have it do something meaningful, for
example, unless your system has been rewhacked to send some funny
message downstream on a seek), it seems like a perfectly lousy
application for STREAMS....

The right way to do this is probably to have a pseudo-disk driver that
has the standard block-device and character-device interfaces that a
real disk driver does, that also has special "ioctl"s to tell it which
pseudo-disk devices talk to which real disk devices, and that ends up
directly calling the device driver entries of the real disk driver or
drivers.

guy@auspex.auspex.com (Guy Harris) (03/27/91)

>#define fopen hvfopen
>#define fclose hvfclose
>  :              :
>
>Etc. for all required system calls, and then do in your function calls
>what you want to do.

Doesn't help very much if he doesn't have source to all programs that
might want to use the virtual disk.  Doesn't even help much if he
*does*, because the programs generally won't access the disk directly,
they'll do it through the file system; the file system just goes through
the device driver switch, rather than specifically calling the routines
from some particular driver, so a #define trick like that won't help,
even if he *does* have the source to the OS kernel....