lkml.org 
[lkml]   [2004]   [Jun]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subjectmincore on anon mappings
Hi David,

here a first (untested) attempt to allow mincore on anon vmas too.

I heard you need this from gcc, right?

(btw, returning -ENOMEM for anon vmas was pretty bogus, -EINVAL or
even -ENOSYS would been more correct)

--- sles/mm/mincore.c.~1~ 2004-02-04 16:07:06.000000000 +0100
+++ sles/mm/mincore.c 2004-06-15 00:42:52.122127224 +0200
@@ -11,6 +11,8 @@
#include <linux/pagemap.h>
#include <linux/mm.h>
#include <linux/mman.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>

#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -22,7 +24,7 @@
* and is up to date; i.e. that no page-in operation would be required
* at this time if an application were to map and access this page.
*/
-static unsigned char mincore_page(struct vm_area_struct * vma,
+static unsigned char mincore_page_inode(struct vm_area_struct * vma,
unsigned long pgoff)
{
unsigned char present = 0;
@@ -38,16 +40,74 @@ static unsigned char mincore_page(struct
return present;
}

+/*
+ * Careful this only works with anon-vma for the vma->vm_pgoff settings.
+ */
+static unsigned char mincore_page_anon(struct vm_area_struct * vma,
+ unsigned long pgoff)
+{
+ unsigned char present = 0;
+ struct page * page;
+ struct mm_struct *mm = vma->vm_mm;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+ unsigned long address;
+
+ address = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
+ BUG_ON(address < vma->vm_start || address >= vma->vm_end);
+
+ spin_lock(&mm->page_table_lock);
+
+ pgd = pgd_offset(mm, address);
+ if (!pgd_present(*pgd))
+ goto out_unlock;
+
+ pmd = pmd_offset(pgd, address);
+ if (!pmd_present(*pmd))
+ goto out_unlock;
+
+ ptep = pte_offset_map(pmd, address);
+ pte = *ptep;
+ pte_unmap(ptep);
+
+ spin_unlock(&mm->page_table_lock);
+
+ if (pte_none(pte))
+ goto out;
+ if (!pte_present(pte)) {
+ swp_entry_t entry = pte_to_swp_entry(pte);
+ page = lookup_swap_cache(entry);
+ if (page) {
+ present = PageUptodate(page);
+ page_cache_release(page);
+ }
+ } else
+ present = 1;
+
+ out:
+ return present;
+
+ out_unlock:
+ spin_unlock(&mm->page_table_lock);
+ goto out;
+}
+
+static unsigned char mincore_page(struct vm_area_struct * vma,
+ unsigned long pgoff)
+{
+ if (vma->vm_file)
+ return mincore_page_inode(vma, pgoff);
+ else
+ return mincore_page_anon(vma, pgoff);
+}
+
static long mincore_vma(struct vm_area_struct * vma,
unsigned long start, unsigned long end, unsigned char __user * vec)
{
long error, i, remaining;
unsigned char * tmp;

- error = -ENOMEM;
- if (!vma->vm_file)
- return error;
-
start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
if (end > vma->vm_end)
end = vma->vm_end;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 14:03    [W:0.097 / U:0.128 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site