Re: The Ultra Sound Driver

Itai Nahshon (
Tue, 17 Feb 1998 01:42:49 +0200

Alessandro gives a basic implementation for mmap and vm_ops.
(off course this is outdated... the vma now holds the dentry and not the
inode pointer).

The problem is that the device release function is called when the count
on the file structure drops to 0 (last close). We need to postpone it
until the last vma which points to this inode (indirectly through the
dentry) is closed. The way that things are implemented now it cannot be
done cleanly.

The vma_close functions are called each time when a vma is unmapped,
but it is impossible to know when is the really last close. This is
when part of a vma is unmapped, it will call vma_close and immediately
vma_open. A naive counter will decrement to 0 and increment again.

IMHO, the right way to do it (but that is a major change) is to move
the file_ops pointer from the file struct to the inode (or to the
and call the device release only when the inode (dentry?) are released.
I think this will also eliminate some of the need for private file

Alternately, a simpler solution is to add a boolean parameter to
telling it if this is really the last close.


Alessandro Rubini wrote:
> > If file was closed mmaped area can still exist,
> > but I (probably wrong) free DMA buffer when file is closing (releasing).
> Yes, this *is* wrong.
> > My question is: Can I detect at which point application unmap memory
> > area? Is there any callback for it or some like this?
> There are the "virtual memory operations", that are meant just for that
> purpose: give a driver some control over its memory mapped regions.
> You can implement a usage count in virtual memory areas with code like
> this one:
> static struct vm_operations_struct simple_vm_ops = {
> simple_vma_open,
> simple_vma_close, /* no more fields */
> };
> void simple_vma_open(struct vm_area_struct * area)
> void simple_vma_close(struct vm_area_struct * area)
> int simple_mmap(struct inode *inode, struct file *filp,
> struct vm_area_struct *vma)
> {
> /* int remap_page_range(virt_add, phys_add, size, protection); */
> if (remap_page_range(vma->vm_start, vma->vm_offset,
> vma->vm_end-vma->vm_start, vma->vm_page_prot))
> return -EAGAIN;
> if (vma->vm_ops)
> return -EINVAL; /* Hmm... shouldn't happen */
> vma->vm_ops = &simple_vm_ops;
> MOD_INC_USE_COUNT; /* open(vma) wasn't called this time */
> vma->vm_inode = inode;
> inode->i_count++;
> return 0;
> }
> Best
> /alessandro
> --
> __ o Tu vuo` fa` l'americano: sient'a me chi t'o fa fa`.
> _`\<, (Renato Carosone)
> __( )/( )__ +39-382-529554
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to

Itai Nahshon

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to