3

Basically, I need to identify the process or task using a page, and accordingly make some decisions regarding whether to allow the page to be swapped out or not. Because the swap module in kernel AFAIK deals with mostly struct page, I was wondering whether there is some existing trick that I am missing. From include/linux/mm_types.h (v >= 2.6), the following comment:

  • Each physical page in the system has a struct page associated with
  • it to keep track of whatever it is we are using the page for at the
  • moment. Note that we have no way to track which tasks are using
  • a page, though if it is a pagecache page, rmap structures can tell us
  • who is mapping it.

suggests we can do this via some physical-to-virtual reverse mappings, but I could not figure out from the rmap functions (in mm/rmap.c) how to achieve what I am looking for.

Thanks in advance for any help, much appreciated.

2 Answers 2

2

To answer your actual question "how to get to struct vm_area_struct from struct page", there are at least two answers.

For anonymous pages you can use page_anon_vma(), which returns an anon_vma - it's stored in page->mapping with a special flag set to indicate it's not a struct address_space (to save space).

From the anon_vma you can walk the anon_vma_chain and each entry points to a vma. From the vma you can get the mm and then a task.

See page_referenced_anon() for an example.

For a file page you look at page->mapping which is a struct address_space, and from there you walk the i_mmap which is a struct prio_tree_root. See page_referenced_file().

I'm not sure that's actually going to help you implement your idea, but there you go.

Sign up to request clarification or add additional context in comments.

Comments

1

Something like this is probably what you want.

This is the prototype:

// [ http://lxr.free-electrons.com/source/include/linux/rmap.h#L27 ]
149 struct anon_vma *page_get_anon_vma(struct page *page);

This is how you might use it: // [ http://lxr.free-electrons.com/source/mm/ksm.c#L1898 ] // [...]

        anon_vma = page_get_anon_vma(page);
1902    anon_vma_lock_read(anon_vma);
1903    anon_vma_interval_tree_foreach(vmac, &anon_vma->rb_root,
1904                                                0, ULONG_MAX) {
1906                         vma = vmac->vma;
1907                         if (page_address < vma->vm_start ||
1908                             page_address >= vma->vm_end)
1909                                 continue;
[...]   }
        anon_vma_unlock_read(anon_vma);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.