I have some questions concerning locking of pages belonging
to a user-level process.
The scenario I have is as follows: I have implemented a driver for a PCI device (as a module). All processes that wants to access the device will have to do an open on it. When the device-file is opened, some of the device's memory is mapped into the user-level application. Communiction between the application and the device either goes through this buffer, or through the in-kernel module (via ioctl). The device is also able to initiate a DMA transfer all by itself to or from the application's memory.
To be able to do this DMA transfer I will have to pin some pages to memory, do some vitual to physical mapping, and also some scatter-gather mechanism. I am somehow able to cope with all this.
The problem that I am concerned with however, is the case when a DMA operation is going on (or about to be started), and the process that is the destination or source of the DMA transfer dies. What is the best way to make sure that the pages get pinned in memory until the device driver receives a release from the dying process? When this happens, the driver will be able to pause the termination of the process if a dangerous DMA transfer is in progress. When the DMA transfer has finished, it may then free the pinned pages and continue termination.
From what I've seen of the process termination code (I'm doing this in a 2.0.30 kernel), the memory mapings are freed before the open files are released (this rules out the obvious solution). I've thought of two other solutions:
1) Using a dummy "ghost thread" associated with the module. All locking of user-level pages are also made sharable, and shared with this thread. During the termination of the process, the pinned memoryis not freed (I think) beacause the memory is also shared with this thread.
2) Making the pages "reserved" instead of locked. From what I've seen of the kernel code, reserved pages are not freed by the free_pte() function. They are however freed by the forget_pte() function which is called by the zeromap_page_range() function --- something which is only possible to do after doing an open on /dev/mem (right?).
So, marking pages as reserved should probably work ok. I am however reluctant to do this since I suspect I am abusing the whole conecpt of reserved pages.
Are there any other ways to accomplish what I am trying to do, or have I misinterpreted the whole kernel-code --- overlooked an amazingly simple fact? (I guess this is a fairly easy thing to do --- misrinterpreting the code I mean. It is afterall not what I would considered a well documented/commented piece of software.)