Specifications

This is the Title of the Book, eMatter Edition
Copyright © 2005 O’Reilly & Associates, Inc. All rights reserved.
The mmap Device Operation
|
427
To make these operations active for a specific mapping, it is necessary to store a
pointer to
simple_remap_vm_ops in the vm_ops field of the relevant VMA. This is usu-
ally done in the mmap method. If you turn back to the simple_remap_mmap exam-
ple, you see these lines of code:
vma->vm_ops = &simple_remap_vm_ops;
simple_vma_open(vma);
Note the explicit call to simple_vma_open. Since the open method is not invoked on
the initial mmap, we must call it explicitly if we want it to run.
Mapping Memory with nopage
Although remap_pfn_range works well for many, if not most, driver mmap imple-
mentations, sometimes it is necessary to be a little more flexible. In such situations,
an implementation using the nopage VMA method may be called for.
One situation in which the nopage approach is useful can be brought about by the
mremap system call, which is used by applications to change the bounding addresses
of a mapped region. As it happens, the kernel does not notify drivers directly when a
mapped VMA is changed by mremap. If the VMA is reduced in size, the kernel can
quietly flush out the unwanted pages without telling the driver. If, instead, the VMA
is expanded, the driver eventually finds out by way of calls to nopage when map-
pings must be set up for the new pages, so there is no need to perform a separate
notification. The nopage method, therefore, must be implemented if you want to
support the mremap system call. Here, we show a simple implementation of nopage
for the simple device.
The nopage method, remember, has the following prototype:
struct page *(*nopage)(struct vm_area_struct *vma,
unsigned long address, int *type);
When a user process attempts to access a page in a VMA that is not present in mem-
ory, the associated nopage function is called. The
address parameter contains the vir-
tual address that caused the fault, rounded down to the beginning of the page. The
nopage function must locate and return the
struct page pointer that refers to the
page the user wanted. This function must also take care to increment the usage
count for the page it returns by calling the get_page macro:
get_page(struct page *pageptr);
This step is necessary to keep the reference counts correct on the mapped pages. The
kernel maintains this count for every page; when the count goes to
0, the kernel
knows that the page may be placed on the free list. When a VMA is unmapped, the
kernel decrements the usage count for every page in the area. If your driver does not
increment the count when adding a page to the area, the usage count becomes
0 pre-
maturely, and the integrity of the system is compromised.
,ch15.13676 Page 427 Friday, January 21, 2005 11:04 AM