Q: Does anyone make use of an intercepting completion-routine for a
block-storage-device driver?
If so, do you have any suggestions for how best to properly access the
IOMemoryDescriptor buffer contents from within that completion routine
as I have a situation where it appears (to me) I am doing nothing wrong
but can pretty reliably create a panic. This error occurs in both
10.2.8 and 10.3.X
// ----------------------------------------------------------
Briefly - here's the situation:
A) My generic block driver overrides a variety of
'IOBlockStorageDriver' that matches my media.
B) My app places vanilla, synchronous, device-calls like 'read(fd, buf,
siz)' commands to the OS
C) The driver may decide to manipulate some of the data on it's way
back from the lower level drivers. If so, my driver driver redirects
the completion call to itself.
D) In the completion call of my driver, data is read from and written
to the buffers of existing IOMemoryDescriptors. There is never an
'out-of-range' access or error. Prior to the panic, the data is
always successfully accessed, modified, and returned intact to my app.
There is never an exception incurred as part of the execution of my
completion routine.
E) At the end of my completion routine, the original completion routine
struct is passed on.
F) At some cumulative point - where I may have transferred a few
hundred megabytes of data thru this mechanism - a kernel panic occurs.
Depending on how quickly I might make calls, this can occur in a couple
of minutes or a couple of hours.
If curious about the specifics: In my driver's 'read' call, I do the
following to prepare to service the returned data via my completion
routine:
// *** SETUP FOR COMPLETION CALL ***
// -----------------------------------------------------------
// static array of original completion routine struct contents
sSavedStorageCompletion[mStorageCompletionIndex] = completion;
// save off IOMemoryDescriptor* from original read-call args
sIOMDBuffers[mStorageCompletionIndex] = buffer;
// substitute local completion address into struct
completion.action = MyStorageCompletion; // call here when done
completion.target = (void*) this; // pass in ptr to this obj
completion.parameter = (void*)(mStorageCompletionIndex); // index to
saved data
mStorageCompletionIndex++; // maintain index for use with next
call
if( mStorageCompletionIndex >= kIOStorageCompletionMax)
mStorageCompletionIndex = 0;
I then send the substitute 'completion' struct off to the super to
actually read the data
bytesRead = memoryDesc->readBytes(0, (void*)mybuf, bufrlen));
<do reads and writes to data in IOMemoryDescriptor buffer>
bytesWritten = memoryDesc->writeBytes(bytesRead, mybuf, bytesRead);