[comp.sys.mac.programmer] File System Re-entrancy

jb@aries5.uucp (11/29/89)

This may seem like a strange question but seeing the discussion on
multi-tasking, I have a related question.

Is there any reliable way to make the device manager re-entrant.
 
In other words if I do a PBRead() to a device driver can that device
driver synchronously do another PBRead() to another device driver?  

From what I have observed this is non-trivial, because the second
PBRead() will block becasue FSBusy is set.

Jim Bruyn

Gavin_Eadie@um.cc.umich.edu (Gavin Eadie) (11/29/89)

In article <924@maytag.waterloo.edu> jb@aries5.uucp writes:
> In other words if I do a PBRead() to a device driver can that device
> driver synchronously do another PBRead() to another device driver?  
> 
> From what I have observed this is non-trivial, because the second
> PBRead() will block becasue FSBusy is set.
> 
> Jim Bruyn

I wrestled with this for a while too. It turns out that, since the file 
system is not re-entrant, you have to cheat if you want to "call PBRead 
from inside PBRead". I needed to be able to do this in order to implement 
a file caching system for the Mac, actually for a Mac implementation of 
the Andrew File System (AFS), and found it to be impossible with the 
present Mac file system.

Under the AFS, an application would call RBRead to get some file stuff, 
the AFS would intercept that call (using the external file system 
mechanism - to be called the foreign file system mechanism in System 7.0), 
determine if the file was cached locally and if it was, call RBRead AGAIN 
to actually obtain the file stuff.

With the help of clever people in Developer Support at Apple, we managed 
to concoct a very small program which kinda worked. The trick was to make 
asynchronous RBRead calls and to call PBRead again in the completion 
routine. The FSBusy block is released before the completion routine is 
invoked.

This curious program was set up to read one character, then read one more 
in the completion routine of that read ad nauseam, stack overflow or eof, 
whichever came first. When run it was quite good at reversing the order of 
all the characters in a file being read! While fun to build, this has no 
real utility since it relied on the PBRead calls being asynch and for the 
mechanism to be generally useful you can't assume all applications do 
this, in fact most don't.

This won't change in System 7.0, but I suggest lobbying for a re-entrant 
file system/device manager in System 8.0. The Mac file system is due for 
an overhaul anyway - it doesn't scale up well to very large file systems. 
An ISO CDROM with a few thousand files on it takes a long time to mount 
and you should watch my Mac as it struggles to mount a distributed file 
system that covers the Universities of Michigan, CMU, MIT and Dartmouth, 
plus a few other sites, as one AppleShare volume! Would you believe 3 
minutes on a good day!!

---
Gavin Eadie, Associate Director/Software Engineer
The University of Michigan Computing Center
535 West William Street, Ann Arbor, Michigan 48109-4943
(313) 936-0816

urlichs@smurf.ira.uka.de (Matthias Urlichs) (11/30/89)

In comp.sys.mac.programmer jb@aries5.UUCP, writes:
< This may seem like a strange question but seeing the discussion on
< multi-tasking, I have a related question.
< 
< Is there any reliable way to make the device manager re-entrant.
<  
That should be the file manager..?

< In other words if I do a PBRead() to a device driver can that device
< driver synchronously do another PBRead() to another device driver?  
< 
One simple answer: No. Not even asyncronously.

I assume that you want to do something like what I tried to do a few years
back: the straight-ahead way to partition a disk would of course be to
open a file and then write a "disk driver" which simply does PB{read,write}()
calls on that file.
No such luck. Apart from the obvious (the file manager queue), the file
manager implements its own internal stack for async requests, plus state
variables and (since HFS) two special files which make this even more complex.

My hack of a solution was to allocate the file contiguously (using
AllocContig) and then, after opening the file, calculate its beginning on disk
from the information from GetVolInfo() and from the FCB (_not_ generally
recommended).
You will have to test that the file is still contiguous (if somebody copies
it, it is likely not to be anymore); this is easy because the FCB contains the
first three extents: the last two should be zero.  You will also run into the
fact that doing this right (ie. if your driver is called asynchronously; it
may well be) is not easy.
This "solution" (apart from being a hack anyway) only works on local disks
which indicates that there should be a better solution.
< 
< Jim Bruyn

I suggest that you post a note describing exactly what you want to do; then
we'll all come up with some better ideas. ;-)

NB: Some rather vague Sytem 7.0 information (reliability level and source
attribution: grapevine) says that the paging file for virtual memory will not
have to be contiguous. I wonder if Apple will do this right (ie. make the
emergency file manager call available for those who need it), or not (ie. hack
it in, using heaps of undocumented file manager features). Based on past
experience I tend to expect the latter. :-(
-- 
Matthias Urlichs

jb@aries5.uucp (12/01/89)

In article <1258@smurf.ira.uka.de> urlichs@smurf.ira.uka.de (Matthias Urlichs) writes:
>In comp.sys.mac.programmer jb@aries5.UUCP, writes:
>< This may seem like a strange question but seeing the discussion on
>< multi-tasking, I have a related question.
>< 
>< Is there any reliable way to make the device manager re-entrant.
><  
>That should be the file manager..?
>
Yes

>< In other words if I do a PBRead() to a device driver can that device
>< driver synchronously do another PBRead() to another device driver?  
>< 
>One simple answer: No. Not even asyncronously.
>
>I assume that you want to do something like what I tried to do a few years
>back: the straight-ahead way to partition a disk would of course be to
>open a file and then write a "disk driver" which simply does PB{read,write}()
>calls on that file.
>No such luck. Apart from the obvious (the file manager queue), the file
>manager implements its own internal stack for async requests, plus state
>variables and (since HFS) two special files which make this even more complex.

Here is what I was trying to do:

At the University of Waterloo we have developed a local area network for
the Macintosh - MacJANET.  This is a disk server, that essentailly partions
one or more files on the server (called disk boxes) into volumes.  Each
user is assigned there own volume, with read/write access.  Then there
are common read/only volumes, for applications.  This way you only need
to store one copy of the application on the network.  We implemented at
the workstation a device driver that sent sector read and write calls
for the network disk to the server, and the server would then read from
the file that data, and return it to the workstation.  Aiming at
education, we spent considerable effort on ease of use, particularly in
administration of userids etc.  This implementation had one problem, it
only allowed for one person to have write only access to a network disk, 
although multiple people could have read access.

With the advent of appleshare, we wanted to provide appleshare capbabilities
within the same framework.  i.e. allow the user to access a network disk
as an appleshare volume (where an appleshare disk is a partition in the
disk box (file) on the server).  The obvious solution (to me at least) was
mount that partion of the file, as a volume on the server, and then do
file manager calls to that volume (since appleshare calls map very nicely
to file manager calls - yes Apple did this right).  This means though
that I needed a device driver for the disk  (file partition) that I mount
on the server.  This device driver will be called by the file manager,
and then subsequently wants to call the real disk driver too actually
read from the disk.  

In other words the problem became how do I write a disk device driver that
takes read/write requests and calls the real disk driver - i.e. device
manager re-entrancy?

This also had one cute side-effect that I never thought of, that if the
server is running under multi-finder all the appleshare compatible volumes
that I mount multifinder will wish to access also.  So in effect I do not
have any control over who is calling my device driver.

If what I was doing was simpler, the proposed solution of calling the
other device driver from the completion routine would work.

I have come up with a solution that works but I am interested in hearing
if my original idea is feasible and/or suggestions on how it can be done.
(By the way, since I enjoy challenges "it can't be done" I don't believe).

Jim Bruyn

P.S.  Information on MacJANET can be obtained from:

WATCOM Products
415 Phillip Street
Waterloo, Ontario
N2L 3X2

(519)-886-3700

MacJANET has other features, like print spooling, tracking number of users
running an application, limitting the number of users who can use an
application concurrently, etc.